react-dnd-html5-backend#HTML5Backend JavaScript Examples

The following examples show how to use react-dnd-html5-backend#HTML5Backend. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: index.js    From h5-Dooring with GNU General Public License v3.0 6 votes vote down vote up
function BasicLayout(props) {
  return (
    <div className={styles.layout}>
      <DndProvider backend={HTML5Backend}>
        <Container {...props} />
      </DndProvider>
    </div>
  );
}
Example #2
Source File: index.js    From ant-simple-pro with MIT License 6 votes vote down vote up
Index = memo(function Index(props) {
  return (
    <PageLayout>
      <p style={{ textAlign: 'center', padding: '10px 0' }}>
        实现一个简单的可视化页面生成器
        <code>
          (简易版本,大致的架子,要想开发完整的,请查看这个项目
          <a href="https://github.com/lgf196/ant-simple-draw">
            ant-simple-draw
          </a>
          )
        </code>
      </p>
      <DndProvider backend={HTML5Backend}>
        <Container />
      </DndProvider>
    </PageLayout>
  );
})
Example #3
Source File: QueueCard.test.js    From qasong with ISC License 6 votes vote down vote up
describe("<QueueCard />", () => {
  it("renders a div", () => {
    const wrapper = shallow(
      <DndProvider backend={HTML5Backend}>
        <QueueCard title={"Hello Test"} />
      </DndProvider>
    );
    expect(wrapper);
  });
});
Example #4
Source File: custom-tab-bar-node.jsx    From virtuoso-design-system with MIT License 6 votes vote down vote up
render() {
    const { order } = this.state;
    const { children } = this.props;

    const tabs = [];
    React.Children.forEach(children, c => {
      tabs.push(c);
    });

    const orderTabs = tabs.slice().sort((a, b) => {
      const orderA = order.indexOf(a.key);
      const orderB = order.indexOf(b.key);

      if (orderA !== -1 && orderB !== -1) {
        return orderA - orderB;
      }
      if (orderA !== -1) {
        return -1;
      }
      if (orderB !== -1) {
        return 1;
      }

      const ia = tabs.indexOf(a);
      const ib = tabs.indexOf(b);

      return ia - ib;
    });

    return (
      <DndProvider backend={HTML5Backend}>
        <Tabs renderTabBar={this.renderTabBar} {...this.props}>
          {orderTabs}
        </Tabs>
      </DndProvider>
    );
  }
Example #5
Source File: LicenseField.js    From react-invenio-deposit with MIT License 5 votes vote down vote up
render() {
    const {
      label,
      labelIcon,
      fieldPath,
      uiFieldPath,
      form: { values, errors },
      move: formikArrayMove,
      push: formikArrayPush,
      remove: formikArrayRemove,
      replace: formikArrayReplace,
      required,
    } = this.props;

    const uiRights = getIn(values, uiFieldPath, []);

    return (
      <DndProvider backend={HTML5Backend}>
        <Form.Field required={required}>
          <FieldLabel
            htmlFor={fieldPath}
            icon={labelIcon}
            label={label}
          />
          <List>
            {getIn(values, fieldPath, []).map((value, index) => {
              const license = new VisibleLicense(uiRights, value, index);
              return (
                <LicenseFieldItem
                  key={license.key}
                  license={license}
                  moveLicense={formikArrayMove}
                  replaceLicense={formikArrayReplace}
                  removeLicense={formikArrayRemove}
                  searchConfig={this.props.searchConfig}
                  serializeLicenses={this.props.serializeLicenses}
                />
              );
            })}
            <LicenseModal
              searchConfig={this.props.searchConfig}
              trigger={
                <Button type="button" key="standard" icon labelPosition="left">
                  <Icon name="add" />
                  {i18next.t('Add standard')}
                </Button>
              }
              onLicenseChange={(selectedLicense) => {
                formikArrayPush(selectedLicense);
              }}
              mode="standard"
              action="add"
              serializeLicenses={this.props.serializeLicenses}
            />
            <LicenseModal
              searchConfig={this.props.searchConfig}
              trigger={
                <Button type="button" key="custom" icon labelPosition="left">
                  <Icon name="add" />
                  {i18next.t('Add custom')}
                </Button>
              }
              onLicenseChange={(selectedLicense) => {
                formikArrayPush(selectedLicense);
              }}
              mode="custom"
              action="add"
            />
          </List>
        </Form.Field>
      </DndProvider>
    );
  }
Example #6
Source File: PrepareDocContainer.js    From signdocs with MIT License 5 votes vote down vote up
PrepareDocContainer = () => {
  const [currSignatory, setCurrSignatory] = useState('');

  const history = useHistory();
  const { docId } = useParams();

  const { docErrors, doc, loading } = useFetchDoc({ docId });
  const signatories = useSelector(getSignatories(docId));

  const breadCrumbsHistory = [
    {
      to: '/documents',
      title: 'Documents',
    },
    {
      to: `/documents/${doc.id}`,
      title: doc.title,
    },
    {
      to: `/documents/${doc.id}/prepare`,
      title: 'Prepare',
    },
  ];

  if (loading || !doc || doc === undefined) return <div>Loading...</div>;
  if (docErrors?.status === 404)
    return <FourOhFour from={history.location.pathname} errors={docErrors} />;

  return (
    <div id="prep-doc-container">
      <BreadCrumbs history={breadCrumbsHistory} />

      <h1>Prepare your document for signatures</h1>
      <div className="scroll-container">
        <div className="pdf-drag-container">
          <DndProvider backend={HTML5Backend} displayName="DndProvider">
            <div className="side-bar">
              <Signatories
                currSignatory={currSignatory}
                signatories={signatories}
                onChangeSignatory={(sigId) => setCurrSignatory(sigId)}
              />
              <Fields currSignatory={currSignatory} />
              <CallToSignDoc docId={doc.id} status={doc.status} />
            </div>
            {doc && doc.fileUrl && (
              <div id="pdf-document-container">
                <PrepPDF doc={doc} />
              </div>
            )}
          </DndProvider>
        </div>
      </div>
    </div>
  );
}
Example #7
Source File: SignDocContainer.js    From signdocs with MIT License 5 votes vote down vote up
SignDocContainer = () => {
  const [_currSignatory, setCurrSignatory] = useState('');
  const history = useHistory();
  const { docId } = useParams();

  const { docErrors, doc, loading } = useFetchDoc({ docId });
  const signatories = useSelector(getSignatories(docId));
  const currentUser = useSelector(getCurrentUser);

  const allCFs = useSelector(getArrayOfContentFieldsByDocId(docId));
  const allCFsAreSigned = allCFs.every((cf) => !!cf.type.match(/^FILLED/));

  const myCFs = allCFs.filter((cf) => cf.signatoryId === currentUser.id);
  const allMyCFsAreSigned = myCFs.every((cf) => !!cf.type.match(/^FILLED/));

  const isOwner = doc?.ownerId === currentUser.id;

  const breadCrumbsHistory = [
    {
      to: '/documents',
      title: 'Documents',
    },
    {
      to: `/documents/${docId}`,
      title: doc.title,
    },
    {
      to: `/documents/${docId}/sign`,
      title: 'Sign',
    },
  ];

  if (loading || !doc || doc === undefined) return <div>Loading...</div>;
  if (docErrors?.status === 404)
    return <FourOhFour from={history.location.pathname} errors={docErrors} />;

  return (
    <div id="sign-doc-container">
      <BreadCrumbs history={breadCrumbsHistory} />

      <h1>Sign your document</h1>
      <div className="scroll-container">
        <div className="pdf-drag-container">
          <DndProvider backend={HTML5Backend}>
            <div className="side-bar">
              <Signatories
                signatories={signatories}
                onChangeSignatory={(sigId) => setCurrSignatory(sigId)}
              />
              {allMyCFsAreSigned && (
                <CallToFinalize
                  docId={docId}
                  allCFsAreSigned={allCFsAreSigned}
                  isOwner={isOwner}
                />
              )}
            </div>
            {doc && doc.fileUrl && (
              <div id="pdf-document-container">
                <SignPDF doc={doc} signatories={signatories} />
              </div>
            )}
          </DndProvider>
        </div>
      </div>
    </div>
  );
}
Example #8
Source File: drag-sorting.jsx    From virtuoso-design-system with MIT License 5 votes vote down vote up
DragSortingTable = () => {
  const [data, setData] = useState([
    {
      key: '1',
      name: 'John Brown',
      age: 32,
      address: 'New York No. 1 Lake Park',
    },
    {
      key: '2',
      name: 'Jim Green',
      age: 42,
      address: 'London No. 1 Lake Park',
    },
    {
      key: '3',
      name: 'Joe Black',
      age: 32,
      address: 'Sidney No. 1 Lake Park',
    },
  ]);

  const components = {
    body: {
      row: DragableBodyRow,
    },
  };

  const moveRow = useCallback(
    (dragIndex, hoverIndex) => {
      const dragRow = data[dragIndex];
      setData(
        update(data, {
          $splice: [
            [dragIndex, 1],
            [hoverIndex, 0, dragRow],
          ],
        }),
      );
    },
    [data],
  );

  return (
    <DndProvider backend={HTML5Backend}>
      <Table
        columns={columns}
        dataSource={data}
        components={components}
        onRow={(record, index) => ({
          index,
          moveRow,
        })}
      />
    </DndProvider>
  );
}
Example #9
Source File: drag-sorting.jsx    From virtuoso-design-system with MIT License 5 votes vote down vote up
DragSortingUpload = () => {
  const [fileList, setFileList] = useState([
    {
      uid: '-1',
      name: 'image1.png',
      status: 'done',
      url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
    },
    {
      uid: '-2',
      name: 'image2.png',
      status: 'done',
      url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
    },
    {
      uid: '-3',
      name: 'image3.png',
      status: 'done',
      url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
    },
    {
      uid: '-4',
      name: 'image4.png',
      status: 'done',
      url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
    },
    {
      uid: '-5',
      name: 'image.png',
      status: 'error',
    },
  ]);

  const moveRow = useCallback(
    (dragIndex, hoverIndex) => {
      const dragRow = fileList[dragIndex];
      setFileList(
        update(fileList, {
          $splice: [
            [dragIndex, 1],
            [hoverIndex, 0, dragRow],
          ],
        }),
      );
    },
    [fileList],
  );

  const onChange = ({ fileList: newFileList }) => {
    setFileList(newFileList);
  };

  return (
    <DndProvider backend={HTML5Backend}>
      <Upload
        action="https://www.mocky.io/v2/5cc8019d300000980a055e76"
        fileList={fileList}
        onChange={onChange}
        itemRender={(originNode, file, currFileList) => (
          <DragableUploadListItem
            originNode={originNode}
            file={file}
            fileList={currFileList}
            moveRow={moveRow}
          />
        )}
      >
        <Button icon={<UploadOutlined />}>Click to Upload</Button>
      </Upload>
    </DndProvider>
  );
}
Example #10
Source File: CollectionView.js    From acsys with MIT License 4 votes vote down vote up
CollectionView = (props) => {
  const context = useContext(AcsysContext);
  const [content_id, setContentId] = useState('');
  const [viewId, setViewId] = useState(0);
  const [initialViews, setInitialViews] = useState([]);
  const [documentDetails, setDocumentDetails] = useState([]);
  const [acsysView, setAcsysView] = useState([]);
  const [tableData, setTableData] = useState([]);
  const [apiCall, setApiCall] = useState('');
  const [totalRows, setTotalRows] = useState(0);
  const [page, setPage] = useState(1);
  const [orderDir, setOrderDir] = useState('');
  const [locked, setLocked] = useState(true);
  const [reset, setReset] = useState(false);
  const [view, setView] = useState(false);
  const [loading, setLoading] = useState(false);
  const [openKeyMessage, setOpenKeyMessage] = useState(false);
  const [setOpen, setSetOpen] = useState(false);
  const [setDetailOpen, setSetDetailOpen] = useState(false);
  const [setViewOpen, setSetViewOpen] = useState(false);
  const [filterLoading, setFilterLoading] = useState(false);
  const [view_order, setViewOrder] = useState(false);
  const [messageTitle, setMessageTitle] = useState('');
  const [message, setMessage] = useState('');
  const [deleteLoading, setDeleteLoading] = useState(false);

  const copy = () => {
    const el = document.createElement('textarea');
    el.value = apiCall;
    document.body.appendChild(el);
    el.select();
    document.execCommand('copy');
    document.body.removeChild(el);
  };

  const openKeyMessageFunc = () => {
    setOpenKeyMessage(true);
    setMessageTitle('Error');
    setMessage('No keys set Please setUnique key for data.');
  };

  const closeKeyMessage = () => {
    setOpenKeyMessage(false);
  };

  const handleViewChange = (value) => {
    published = value;
    let acsys_id = '';
    if (published) {
      acsys_id = props.match.params.acsys_id;
    } else {
      acsys_id = 'acsys_' + props.match.params.acsys_id;
    }
    context.setPageData(
      acsys_id,
      context.getKeys(),
      row_num,
      view_order,
      orderDir
    );
    context.setPage(1);
    mount();
  };

  const handleClickOpen = (id) => {
    setViewId(id);
    setSetOpen(true);
  };

  const handleClose = () => {
    setSetOpen(false);
  };

  const handleViewOpen = () => {
    setSetViewOpen(true);
  };

  const handleViewClose = () => {
    setSetViewOpen(false);
  };

  const handleDetailOpen = () => {
    setSetDetailOpen(true);
  };

  const handleDetailClose = () => {
    setSetDetailOpen(false);
  };

  const toggleTable = async (value) => {
    if (!value) {
      await Acsys.unlockTable(documentDetails[0].collection);
      setLocked(false);
    } else {
      Acsys.lockTable(documentDetails[0].collection);
      setLocked(true);
    }
  };

  const setLockedValue = (value) => {
    lockedValue = value;
  };

  const setOrderField = (field) => {
    view_orderField = field;
  };

  const setOrder = (order) => {
    view_order = order;
  };

  const setEntriesPerPage = (value) => {
    row_num = value;
  };

  const setUpdateOnly = (value) => {
    is_removable = value;
  };

  const saveViewsetTings = async () => {
    setLoading(true);
    let tempView = acsysView;
    if (view_orderField === 'none') {
      tempView['order_by'] = '';
      tempView['view_order'] = '';
    } else {
      tempView['order_by'] = view_orderField;
      tempView['view_order'] = view_order;
    }
    tempView['is_removable'] = is_removable;
    tempView['row_num'] = row_num;
    toggleTable(lockedValue);
    context.setHeld(false);
    await Acsys.updateData('acsys_views', tempView, [
      ['acsys_id', '=', tempView.acsys_id],
    ]);
    setSetViewOpen(false);
    setReset(True);
    setTotalRows(0);
    setPage(1);
    table_keys = [];
    mount();
  };

  const showPopUp = () => {
    return <div>{Object.values(tableData).map((value, index) => {})}</div>;
  };

  const deleteView = async () => {
    setDeleteLoading(true);

    if (table_keys[viewId]) {
      let keys = [];
      for (let i = 0; i < table_keys[viewId].length; i++) {
        let tKeys = [
          table_keys[viewId][i].field,
          '=',
          table_keys[viewId][i].value,
        ];
        keys.push(tKeys);
      }

      await Acsys.getData(documentDetails[0].collection, keys)
        .then(async (result) => {
          if (result.length < 1) {
            await Acsys.deleteData(
              'acsys_' + documentDetails[0].collection,
              keys
            );
          } else {
            await Acsys.deleteData(documentDetails[0].collection, keys);
          }
        })
        .catch(async () => {});
    } else {
      openKeyMessageFunc();
    }

    handleClose();
    setReset(True);
    table_keys = [];
    mount();
    setDeleteLoading(false);
  };

  const handleChangePrevPage = async () => {
    setLoading(true);
    let keys = [];
    for (let i = 0; i < table_keys[table_keys.length - 1].length; i++) {
      keys.push([table_keys[0][i].field, '=', table_keys[0][i].value]);
    }
    const currentData = await Acsys.getPage(
      tempDetails[0].collection,
      keys,
      row_num,
      view_order,
      orderDir,
      'prev',
      page
    );
    const apiCall = await Acsys.getOpenPageUrl(
      tempDetails[0].collection,
      keys,
      row_num,
      view_order,
      orderDir,
      'prev',
      page
    );
    setLoading(false);
    setTableData(currentData);
    setApiCall(apiCall);
    setPage(page - 1);
    context.setHeld(true);
    context.setPage(page);
    context.setPageData(
      tempDetails[0].collection,
      keys,
      row_num,
      view_order,
      orderDir
    );
    context.setPageDirection('prev');
    window.scrollTo(0, 0);
  };

  const handleChangeNextPage = async () => {
    setLoading(true);
    let keys = [];
    for (let i = 0; i < table_keys[table_keys.length - 1].length; i++) {
      keys.push([
        table_keys[table_keys.length - 1][i].field,
        '=',
        table_keys[table_keys.length - 1][i].value,
      ]);
    }
    const currentData = await Acsys.getPage(
      tempDetails[0].collection,
      keys,
      row_num,
      view_order,
      orderDir,
      'next',
      page
    );
    const apiCall = await Acsys.getOpenPageUrl(
      tempDetails[0].collection,
      keys,
      row_num,
      view_order,
      orderDir,
      'next',
      page
    );
    setLoading(false);
    setTableData(currentData);
    setApiCall(apiCall);
    setPage(page + 1);
    context.setHeld(true);
    context.setPage(page);
    context.setPageData(
      tempDetails[0].collection,
      keys,
      row_num,
      view_order,
      orderDir
    );
    context.setPageDirection('next');
    window.scrollTo(0, 0);
  };

  const savesetTings = async () => {
    setFilterLoading(true);
    table_keys = [];
    for (var i = 0; i < tempDetails.length; i++) {
      tempDetails[i].view_order = i;
      await Acsys.updateData('acsys_document_details', tempDetails[i], [
        ['acsys_id', '=', tempDetails[i].acsys_id],
      ]);
    }
    setFilterLoading(false);
    handleDetailClose();
  };

  const scan = async () => {
    setLoading(true);
    Acsys.deleteData('acsys_document_details', [
      ['content_id', '=', content_id],
    ])
      .then(async () => {
        mount();
      })
      .catch(() => {
        setLoading(false);
      });
  };

  useEffect(() => {
    if (content_id !== props.match.params.content_id && !loading) {
      mount();
    }
  }, [content_id, props.match.params.content_id, loading]);

  useEffect(() => {
    props.setHeader('Content');
    published = true;
    table_keys = [];
    setLoading(true);
    mount();
  }, []);

  const mount = async () => {
    let acsysView;
    let locked = true;
    let details = [];
    let currentData;
    let apiCall;
    let order = [];
    let orderDir = 'asc';
    lockedValue = true;
    is_removable = true;
    view_orderField = 'none';
    // view_order = 'asc';
    row_num = 10;
    if (!reset) {
      table_keys = props.location.state.table_keys;
    }
    let acsys_id = '';
    if (published) {
      acsys_id = props.match.params.acsys_id;
    } else {
      acsys_id = 'acsys_' + props.match.params.acsys_id;
    }

    const content_id = props.match.params.content_id;

    const totalRows = await Acsys.getTableSize(acsys_id);

    try {
      acsysView = await Acsys.getData('acsys_views', [
        ['acsys_id', '=', content_id],
      ]);
      is_removable = acsysView[0].is_removable;
      row_num = acsysView[0].row_num;
      if (acsysView[0].order_by.length > 0) {
        view_orderField = acsysView[0].order_by;
        view_order = acsysView[0].view_order;
      }

      let keys = [];

      try {
        for (let i = 0; i < table_keys.length; i++) {
          keys.push([table_keys[i].field, '=', table_keys[i].value]);
        }
      } catch (error) {}

      details = await Acsys.getData('acsys_document_details', [
        ['content_id', '=', content_id],
      ]);

      await Acsys.getData('acsys_open_tables', [['table_name', '=', acsys_id]])
        .then((result) => {
          if (result[0].table_name === acsys_id) {
            locked = false;
            lockedValue = false;
          }
        })
        .catch(() => {});

      if (details.length > 0) {
        details.sort((a, b) => (a.view_order > b.view_order ? 1 : -1));
        if (acsysView[0].order_by.length > 0) {
          order.push(acsysView[0].order_by);
          orderDir = acsysView[0].view_order;
        }
        for (let i = 0; i < details.length; i++) {
          if (Boolean(details[i].is_key)) {
            order.push(details[i].field_name);
          }
        }
        if (context.isHeld()) {
          let direction = 'none';
          const dbType = await Acsys.getDatabaseType();
          if (dbType === 'firestore') {
            direction = context.getPageDirection();
          }
          currentData = await Acsys.getPage(
            context.getTable(),
            context.getKeys(),
            context.getRowsPerPage(),
            context.getOrder(),
            context.getDirection(),
            direction,
            context.getPage()
          );
          setPage(context.getPage());
        } else {
          currentData = await Acsys.getData(
            acsys_id,
            [],
            row_num,
            order,
            orderDir
          );
          apiCall = await Acsys.getOpenUrl(
            acsys_id,
            [],
            row_num,
            order,
            orderDir
          );
        }
      } else {
        currentData = await Acsys.getData(acsys_id, keys, row_num);
        apiCall = await Acsys.getOpenUrl(acsys_id, keys, row_num);
        await Promise.all(
          Object.keys(currentData[0]).map(async (value, index) => {
            let collectionDetails = {
              acsys_id: uniqid(),
              content_id: content_id,
              collection: acsys_id,
              control: 'none',
              field_name: value,
              is_visible_on_page: true,
              is_visible_on_table: true,
              type: typeof currentData[0][value],
              is_key: false,
              view_order: index,
              width: 12,
            };
            await Acsys.insertData(
              'acsys_document_details',
              collectionDetails
            ).then(() => {
              details.push(collectionDetails);
            });
          })
        ).then(() => {
          details.sort((a, b) => (a.view_order > b.view_order ? 1 : -1));
        });
      }
    } catch (error) {
      console.log(error);
    }

    setReset(false);
    setView(props.location.state.view);
    setLoading(false);
    setLocked(locked);
    setContentId(content_id);
    setInitialViews(currentData);
    setTableData(currentData);
    setApiCall(apiCall);
    setAcsysView(acsysView[0]);
    setPage(page);
    setDocumentDetails(details);
    setTotalRows(totalRows);
    setViewOrder(order);
    setOrderDir(orderDir);
  };

  const renderHeader = () => {
    const details = documentDetails;
    if (details.length > 0) {
      return (
        <TableRow>
          {Object.values(details).map((value) => {
            if (value.is_visible_on_table) {
              return (
                <TableCell
                  style={{
                    paddingLeft: 16,
                    paddingRight: 16,
                    paddingTop: 5,
                    paddingBottom: 5,
                  }}
                >
                  {value.field_name.toUpperCase()}
                </TableCell>
              );
            }
          })}
          <TableCell
            style={{
              paddingLeft: 16,
              paddingRight: 16,
              paddingTop: 5,
              paddingBottom: 5,
            }}
            align="right"
          >
            ACTIONS
          </TableCell>
        </TableRow>
      );
    }
  };

  const renderCellData = (rowData) => {
    return rowData.map((column) => {
      return <TableCell>{column}</TableCell>;
    });
  };
  const renderTableData = () => {
    return tableData.map((tableData, rowIndex) => {
      let tempKey = [];
      return (
        <TableRow>
          {Object.values(documentDetails).map((details) => {
            let returnValue = '';
            Object.values(tableData).map((value, index) => {
              if (Object.keys(tableData)[index] == details.field_name) {
                if (Boolean(details.is_key) && value !== undefined) {
                  let tempObj = {
                    field: details.field_name,
                    value: value,
                  };
                  tempKey.push(tempObj);
                  table_keys[rowIndex] = tempKey;
                }
                if (details.is_visible_on_table) {
                  if (details.control == 'dateTimePicker') {
                    const date = new Date(value);
                    const printDate =
                      ('0' + (date.getMonth() + 1)).slice(-2) +
                      '/' +
                      ('0' + date.getDate()).slice(-2) +
                      '/' +
                      date.getFullYear();
                    returnValue = printDate;
                  } else if (details.control == 'booleanSelect') {
                    const tmpElement = document.createElement('DIV');
                    tmpElement.innerHTML = Boolean(value);
                    const stringLimit = 100;
                    let valueString = tmpElement.innerText;
                    if (valueString.length >= stringLimit) {
                      valueString = valueString.substr(0, stringLimit) + '...';
                    }
                    returnValue = valueString;
                  } else {
                    const tmpElement = document.createElement('DIV');
                    tmpElement.innerHTML = value;
                    const stringLimit = 100;
                    let valueString = tmpElement.innerText;
                    if (valueString.length >= stringLimit) {
                      valueString = valueString.substr(0, stringLimit) + '...';
                    }
                    returnValue = valueString;
                  }
                }
              }
            });
            if (details.is_visible_on_table) {
              return acsysView.link_view_id.length > 0 ? (
                <TableCell
                  to={{
                    pathname:
                      '/CollectionView/' +
                      acsysView.link_table +
                      '/' +
                      acsysView.link_view_id,
                    state: {
                      table_keys: table_keys[rowIndex],
                    },
                  }}
                  component={Link}
                  style={{ overflow: 'hidden', textOverflow: 'ellipsis' }}
                >
                  {returnValue}
                </TableCell>
              ) : (
                <TableCell
                  style={{ overflow: 'hidden', textOverflow: 'ellipsis' }}
                >
                  {returnValue}
                </TableCell>
              );
            }
          })}
          <TableCell align="right" style={{ minWidth: 100 }}>
            {table_keys.length > 0 ? (
              <Tooltip title="Edit Entry">
                <IconButton
                  edge="start"
                  color="inherit"
                  aria-label="edit"
                  to={{
                    pathname: '/DocumentView',
                    state: {
                      mode: 'update',
                      is_removable: is_removable,
                      table_keys: table_keys[rowIndex],
                      routed: false,
                      viewId: documentDetails[0].content_id,
                    },
                  }}
                  component={Link}
                  style={{ marginRight: 10 }}
                >
                  <CreateIcon />
                </IconButton>
              </Tooltip>
            ) : (
              <Tooltip title="Edit Entry">
                <IconButton
                  edge="start"
                  color="inherit"
                  aria-label="edit"
                  onClick={() => openKeyMessageFunc()}
                  style={{ marginRight: 10 }}
                >
                  <CreateIcon />
                </IconButton>
              </Tooltip>
            )}
            {Acsys.getMode() !== 'Viewer' && is_removable ? (
              <Tooltip title="Delete Entry">
                <IconButton
                  edge="start"
                  color="inherit"
                  aria-label="delete"
                  onClick={(event) => {
                    event.stopPropagation();
                    handleClickOpen(rowIndex);
                  }}
                >
                  <DeleteIcon />
                </IconButton>
              </Tooltip>
            ) : (
              <div />
            )}
          </TableCell>
        </TableRow>
      );
    });
  };
  const renderPagination = (paginate) => {
    let startingElement = 0;
    if (totalRows > 0) {
      startingElement = page * row_num - row_num + 1;
    }
    const endingElement = page * row_num - row_num + 1 + tableData.length - 1;
    return paginate ? (
      <Grid style={{ width: 190, float: 'right' }} container>
        <Grid style={{ float: 'right' }} item xs>
          <Typography variant={'body2'} style={{ margin: '10px auto' }}>
            {startingElement}-{endingElement} of {totalRows}
          </Typography>
        </Grid>
        <Grid item xs={6}>
          {page > 1 ? (
            <IconButton onClick={() => handleChangePrevPage()}>
              <KeyboardArrowLeft color="inherit" />
            </IconButton>
          ) : (
            <IconButton>
              <KeyboardArrowLeft
                color="disabled"
                style={{ cursor: 'default' }}
              />
            </IconButton>
          )}
          {page * row_num < totalRows ? (
            <IconButton onClick={() => handleChangeNextPage()}>
              <KeyboardArrowRight color="inherit" />
            </IconButton>
          ) : (
            <IconButton>
              <KeyboardArrowRight
                color="disabled"
                style={{ cursor: 'default' }}
              />
            </IconButton>
          )}
        </Grid>
      </Grid>
    ) : (
      <div>
        <Typography style={{ height: 30, marginTop: 8 }}>
          Please setKeys for pagination.
        </Typography>
      </div>
    );
  };
  const renderTable = (paginate) => {
    let tableDetails = '';
    try {
      tableDetails = tableData.details;
    } catch (error) {}
    if (tableDetails) {
      return <div style={{ margin: 30, overflow: 'auto' }}>{tableDetails}</div>;
    } else {
      try {
        return (
          <div>
            <div style={{ margin: 'auto', overflow: 'auto' }}>
              <Table>
                <TableHead style={{ backgroundColor: '#fafafa' }}>
                  {renderHeader()}
                </TableHead>
                <TableBody>{renderTableData()}</TableBody>
              </Table>
            </div>
            {renderPagination(paginate)}
          </div>
        );
      } catch (error) {}
    }
  };
  tempDetails = documentDetails;
  let projectId = '';
  let viewTable = '';
  let tempKey = [];
  let tempKeys = [];
  let paginate = false;

  try {
    projectId = acsysView.acsys_id;
  } catch (error) {}

  try {
    viewTable = tempDetails[0].collection;
  } catch (error) {}

  for (let i = 0; i < documentDetails.length; i++) {
    if (Boolean(documentDetails[i].is_key)) {
      let tempObj = {
        field: documentDetails[i].field_name,
      };
      tempKey.push(tempObj);
      paginate = true;
    }
  }
  tempKeys[0] = tempKey;
  return (
    <div>
      <Paper
        style={{
          margin: 'auto',
          overflow: 'hidden',
          clear: 'both',
          marginBottom: 20,
        }}
      >
        <AppBar
          position="static"
          elevation={0}
          style={{
            backgroundColor: '#fafafa',
            borderBottom: '1px solid #dcdcdc',
          }}
        >
          <Toolbar style={{ margin: 4, paddingLeft: 12, paddingRight: 12 }}>
            <Grid container spacing={2}>
              <Grid item xs style={{ overflow: 'hidden' }}>
                <Typography
                  align="left"
                  variant="subtitle2"
                  noWrap
                  style={{ marginTop: 10, color: '#000000' }}
                >
                  View: {view}
                </Typography>
              </Grid>
              <Grid item>
                <Tooltip title="Choose Between Published Or Draft Rows">
                  <NativeSelect
                    onChange={(e) => handleViewChange('true' == e.target.value)}
                  >
                    <option value={true}>Published</option>
                    <option value={false}>Draft</option>
                  </NativeSelect>
                </Tooltip>
              </Grid>

              {Acsys.getMode() === 'Administrator' ? (
                <Grid item>
                  <Tooltip title="Change How Data Is Presented">
                    <Button
                      onClick={handleDetailOpen}
                      variant="contained"
                      color="primary"
                    >
                      Field Controls
                    </Button>
                  </Tooltip>
                </Grid>
              ) : (
                <div />
              )}
              {Acsys.getMode() === 'Administrator' ? (
                <Grid item>
                  <Tooltip title="Change How Data Is Organized">
                    <Button
                      onClick={handleViewOpen}
                      variant="contained"
                      color="primary"
                    >
                      View setTings
                    </Button>
                  </Tooltip>
                </Grid>
              ) : (
                <div />
              )}
              <Grid item>
                {Acsys.getMode() !== 'Viewer' && is_removable ? (
                  <Tooltip title="Add New Entry To Table">
                    <Button
                      to={{
                        pathname: '/DocumentView',
                        state: {
                          mode: 'add',
                          table_keys: tempKeys[0],
                          routed: false,
                          viewId: projectId,
                        },
                      }}
                      component={Link}
                      variant="contained"
                      color="primary"
                    >
                      New Entry
                    </Button>
                  </Tooltip>
                ) : (
                  <div />
                )}
              </Grid>
            </Grid>
          </Toolbar>
        </AppBar>
        {renderTable(paginate)}
        <LoadingDialog loading={loading} message={'Loading'} />
        <MessageDialog
          open={openKeyMessage}
          closeDialog={closeKeyMessage}
          title={messageTitle}
          message={message}
        />
        <YesNoDialog
          open={setOpen}
          closeDialog={handleClose}
          title={'Delete data?'}
          message={'Are you sure you want to delete this data?'}
          action={deleteView}
          actionProcess={deleteLoading}
        />
        <FieldControlDialog
          open={setDetailOpen}
          closeDialog={handleDetailClose}
          title={'Field Controls'}
          backend={HTML5Backend}
          component={
            <FieldDef docDetails={tempDetails} handleClick={savesetTings} />
          }
          action={savesetTings}
          actionProcess={filterLoading}
        />
        <ViewDialog
          open={setViewOpen}
          closeDialog={handleViewClose}
          viewOrderField={view_orderField}
          setOrderField={setOrderField}
          docDetails={tempDetails}
          viewOrder={view_order}
          setOrder={setOrder}
          rowNum={row_num}
          setEntriesPerPage={setEntriesPerPage}
          isRemovable={is_removable}
          setUpdateOnly={setUpdateOnly}
          viewTable={viewTable}
          locked={locked}
          setLockedValue={setLockedValue}
          action={saveViewsetTings}
          actionProcess={filterLoading}
        />
      </Paper>
      <Hidden smDown implementation="css">
        {!locked ? (
          <div style={{ clear: 'both' }}>
            API Call:{' '}
            <a className="api-url" href={apiCall} target="_blank">
              {apiCall}
            </a>
            <Tooltip title="Copy To Clipboard">
              <IconButton
                edge="start"
                color="inherit"
                aria-label="edit"
                onClick={copy}
                style={{ marginLeft: 5 }}
              >
                <CopyIcon style={{ height: 15 }} />
              </IconButton>
            </Tooltip>
          </div>
        ) : (
          <div />
        )}
      </Hidden>
    </div>
  );
}
Example #11
Source File: Database.js    From acsys with MIT License 4 votes vote down vote up
Database = (props) => {
  const context = useContext(AcsysContext);
  const [viewId, setviewId] = useState('');
  const [views, setviews] = useState([]);
  const [page, setpage] = useState(0);
  const [rowsPerPage] = useState(15);
  const [message, setmessage] = useState('');
  const [loading, setloading] = useState(false);
  const [deleting, setdeleting] = useState(false);
  const [open, setOpen] = useState(false);
  const [addLoading, setAddLoading] = useState(false);
  const [deleteLoading, setdeleteLoading] = useState(false);
  const [openMessage, setopenMessage] = useState(false);
  const [projectName] = useState('');

  const deleteTable = async () => {
    setdeleteLoading(true);
    if (viewId.length > 0) {
      await Acsys.dropTable(viewId);
    }
    handleDeleteClose();
    inDidMount();
  };

  const handleChangePage = (event, page) => {
    setpage(page);
  };

  const handleClickOpen = async () => {
    entry = [];
    entry.push({ dataType: 'string', fieldName: '', value: '' });
    setOpen(true);
  };

  const handleClose = () => {
    tableName = '';
    setOpen(false);
    setAddLoading(false);
  };

  const handleMessageClose = () => {
    setopenMessage(false);
  };

  const editView = async () => {
    await Acsys.updateData('acsys_logical_content', tempView, [
      ['acsys_id', '=', tempView.acsys_id],
    ]);
    const currentView = await Acsys.getData('acsys_logical_content');
    setviews(currentView);
  };

  const handleDeleteOpen = async (viewId) => {
    setdeleting(true);
    setviewId(viewId);
  };

  const handleDeleteClose = () => {
    setdeleting(false);
    setdeleteLoading(false);
  };

  const inDidMount = async () => {
    props.setHeader('Database');
    context.setHeld(false);
    tempView = [];
    setloading(true);
    let projectName = await Acsys.getProjectName();
    let currentView = [];
    currentView = await Acsys.getTableData();
    projectName: projectName, setloading(false);
    setAddLoading(false);
    setviews(currentView);
  };

  useEffect(() => {
    inDidMount();
  }, []);

  const setName = (name) => {
    tableName = name;
  };

  const addTable = async () => {
    setAddLoading(true);
    let error = false;
    let newEntry = {};
    entry.forEach((obj) => {
      const field = obj['fieldName'];
      const value = obj['value'];
      if (value.length < 1 || field.length < 1) {
        error = true;
      }
      if (obj['dataType'] === 'string') {
        newEntry[field] = value;
      } else if (obj['dataType'] === 'number') {
        newEntry[field] = parseInt(value);
      } else if (obj['dataType'] === 'boolean') {
        newEntry[field] = 'true' == value;
      }
    });

    if (error || tableName.length < 1) {
      setAddLoading(false);
      setopenMessage(true);
      setmessage('Allfields must be filled before submitting.');
    } else {
      await Acsys.createTable(tableName, newEntry);
      handleClose();
      inDidMount();
    }
  };

  const renderTableData = () => {
    return views
      .slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
      .map((views) => {
        const { acsys_id, table, rows } = views;
        return (
          <TableRow key={acsys_id}>
            <TableCell>{table}</TableCell>
            <TableCell style={{ width: 50 }}>{rows}</TableCell>
            <TableCell style={{ width: 100 }} align="right">
              <Tooltip title="Delete Table">
                <IconButton
                  edge="start"
                  color="inherit"
                  aria-label="delete"
                  onClick={() => handleDeleteOpen(table)}
                >
                  <DeleteIcon />
                </IconButton>
              </Tooltip>
            </TableCell>
          </TableRow>
        );
      });
  };
  try {
    return (
      <div>
        <Paper
          style={{
            margin: 'auto',
            overflow: 'hidden',
            clear: 'both',
            marginBottom: 20,
          }}
        >
          <AppBar
            position="static"
            elevation={0}
            style={{
              backgroundColor: '#fafafa',
              borderBottom: '1px solid #dcdcdc',
            }}
          >
            <Toolbar style={{ margin: 4, paddingLeft: 12, paddingRight: 12 }}>
              <Grid container spacing={1}>
                <Grid item xs style={{ overflow: 'hidden' }}>
                  <Typography
                    align="left"
                    variant="subtitle2"
                    noWrap
                    style={{ marginTop: 10, color: '#000000' }}
                  >
                    Project: {projectName}
                  </Typography>
                </Grid>
                <Grid item>
                  <Tooltip title="Create New Table">
                    <Button
                      variant="contained"
                      color="primary"
                      onClick={handleClickOpen}
                    >
                      Add Table
                    </Button>
                  </Tooltip>
                </Grid>
              </Grid>
            </Toolbar>
          </AppBar>
          <div style={{ margin: 'auto', overflow: 'auto' }}>
            <Table>
              <TableHead style={{ backgroundColor: '#fafafa' }}>
                <TableRow>
                  <TableCell
                    style={{
                      paddingLeft: 16,
                      paddingRight: 16,
                      paddingTop: 5,
                      paddingBottom: 5,
                    }}
                  >
                    TABLE NAME
                  </TableCell>
                  <TableCell
                    style={{
                      paddingLeft: 16,
                      paddingRight: 16,
                      paddingTop: 5,
                      paddingBottom: 5,
                      width: 50,
                    }}
                  >
                    ROWS
                  </TableCell>
                  <TableCell
                    style={{
                      paddingLeft: 16,
                      paddingRight: 16,
                      paddingTop: 5,
                      paddingBottom: 5,
                      width: 100,
                    }}
                    align="right"
                  >
                    ACTIONS
                  </TableCell>
                </TableRow>
              </TableHead>
              <TableBody>{renderTableData()}</TableBody>
            </Table>
          </div>
          <TablePagination
            rowsPerPageOptions={[25]}
            component="div"
            count={views.length}
            rowsPerPage={rowsPerPage}
            page={page}
            backIconButtonProps={{
              'aria-label': 'previous page',
            }}
            nextIconButtonProps={{
              'aria-label': 'next page',
            }}
            onChangePage={handleChangePage}
            // onChangeRowsPerPage={handleChangeRowsPerPage}
          />
          <LoadingDialog loading={loading} message={'Loading'} />
          <FieldControlDialog
            open={open}
            closeDialog={handleClose}
            title={'Add Table'}
            backend={HTML5Backend}
            component={<TableControl setName={setName} entry={entry} />}
            action={addTable}
            actionProcess={addLoading}
          />
          <YesNoDialog
            open={deleting}
            closeDialog={handleDeleteClose}
            title={'Delete data?'}
            message={'Are you sure you want to delete this data?'}
            action={deleteTable}
            actionProcess={deleteLoading}
          />
          <MessageDialog
            open={openMessage}
            closeDialog={handleMessageClose}
            title={'Error'}
            message={message}
          />
        </Paper>
      </div>
    );
  } catch (error) {
    alert(error);
    return (
      <div style={{ maxWidth: 1236, margin: 'auto' }}>
        <Paper style={{ height: 40 }}>
          <div style={{ padding: 10, margin: 'auto' }}>
            Please make sure database has been created.
          </div>
        </Paper>
      </div>
    );
  }
}
Example #12
Source File: DocumentView.js    From acsys with MIT License 4 votes vote down vote up
DocumentView = (props) => {
  const [collection, setCollection] = useState('');
  const [documentDetails, setdocumentDetails] = useState([]);
  const [fileMode, setfileMode] = useState('');
  const [draft, setdraft] = useState(false);
  const [views, setviews] = useState([]);
  const [apiCall, setapiCall] = useState('');
  const [keys, setkeys] = useState([]);
  const [acsysView, setacsysView] = useState([]);
  const [routed, setrouted] = useState(false);
  const [position, setPosition] = useState(0);
  const [locked, setLocked] = useState(true);
  const [loading, setloading] = useState(false);
  const [deleting, setdeleting] = useState(false);
  const [deleteLoading, setdeleteLoading] = useState(false);
  const [setOpen, setsetOpen] = useState(false);
  const [saving, setsaving] = useState(false);
  const [fileSelect, setfileSelect] = useState(false);
  const [filterLoading, setfilterLoading] = useState(false);
  const [error, setError] = useState('');
  const [control, setcontrol] = useState('');

  const copy = () => {
    const el = document.createElement('textarea');
    el.value = apiCall;
    document.body.appendChild(el);
    el.select();
    document.execCommand('copy');
    document.body.removeChild(el);
  };

  const imageHandler = async () => {
    const quill = quillRef.getEditor();
    quillIndex = quill.getSelection().index;
    openSelector('quill', 'quill');
  };

  const handleClickOpen = () => {
    setsetOpen(true);
  };

  const handleClose = () => {
    setsetOpen(false);
  };

  const handleDeleteOpen = async () => {
    setdeleting(true);
  };

  const handleDeleteClose = () => {
    setdeleting(false);
    setdeleteLoading(false);
  };

  const openSelector = (mode, control) => {
    setfileMode(mode);
    setfileSelect(true);
    setcontrol(control);
  };

  const setQuillRef = (ref) => {
    quillRef = ref;
  };

  const setQuillIndex = (index) => {
    quillIndex = index;
  };

  const setQuillURL = (url) => {
    quillURL = url;
  };

  const setReference = async (name, reference) => {
    const field = control;
    const url = await Acsys.getStorageURL(reference);
    if (fileMode === 'quill') {
      quillURL = url;
    } else if (fileMode === 'ref') {
      fileDoc[field] = reference;
      fileRefs[field] = url;
    } else {
      fileDoc[field] = url;
      fileRefs[field] = url;
    }
    setfileSelect(false);
  };

  const removeFile = (control) => {
    setloading(true);
    tempDocument[control] = '';
    fileRefs[control] = '';
    fileDoc[control] = '';
    setloading(false);
  };

  const handleSelectClose = () => {
    setfileSelect(false);
  };

  const handleChange = (key, event) => {
    tempDocument[key] = event;
  };

  const getMaxPos = async (table, field) => {
    return new Promise(async (resolve, reject) => {
      const pos = await Acsys.getData(table, '', 1, [field], 'desc')
        .then((result) => {
          resolve(result[0][field]);
        })
        .catch(() => {
          resolve(0);
        });
    });
  };

  const increment = async (table, field, start, num) => {
    return new Promise(async (resolve, reject) => {
      await Acsys.increment(table, field, start, num)
        .then(() => {
          resolve(true);
        })
        .catch(() => {
          resolve(false);
        });
    });
  };

  const saveDocument = async () => {
    setsaving(true);
    if (mode === 'update') {
      for (var i = 0; i < tempDetails.length; i++) {
        if (fileDoc[tempDetails[i].field_name] !== undefined) {
          tempDocument[tempDetails[i].field_name] =
            fileDoc[tempDetails[i].field_name];
        } else if (tempDocument[tempDetails[i].field_name] === undefined) {
          if (tempDetails[i].control === 'numberEditor') {
            tempDocument[tempDetails[i].field_name] = 0;
          } else if (tempDetails[i].control === 'booleanSelect') {
            tempDocument[tempDetails[i].field_name] = false;
          } else {
            tempDocument[tempDetails[i].field_name] = '';
          }
        }
      }
      const result = await Acsys.updateData(
        'acsys_' + collection,
        { ...tempDocument },
        keys
      );
    } else {
      for (var i = 0; i < tempDetails.length; i++) {
        if (tempDetails[i].control === 'autoGen') {
          tempDocument[tempDetails[i].field_name] = uniqid();
        } else if (fileDoc[tempDetails[i].field_name] !== undefined) {
          tempDocument[tempDetails[i].field_name] =
            fileDoc[tempDetails[i].field_name];
        } else if (tempDocument[tempDetails[i].field_name] === undefined) {
          if (tempDetails[i].control === 'numberEditor') {
            tempDocument[tempDetails[i].field_name] = 0;
          } else if (tempDetails[i].control === 'booleanSelect') {
            tempDocument[tempDetails[i].field_name] = false;
          } else {
            tempDocument[tempDetails[i].field_name] = '';
          }
        }
      }
      const result = await Acsys.insertData(
        'acsys_' + collection,
        { ...tempDocument },
        keys
      );
    }
    table_keys = [];
    for (var i = 0; i < tempDetails.length; i++) {
      if (tempDetails[i].is_key) {
        const object = {
          field: tempDetails[i].field_name,
          value: tempDocument[tempDetails[i].field_name],
        };
        table_keys.push(object);
      }
    }
    mode = 'update';
    mount();
  };

  const publishDocument = async () => {
    setsaving(true);
    if (mode === 'update') {
      for (var i = 0; i < tempDetails.length; i++) {
        if (fileDoc[tempDetails[i].field_name] !== undefined) {
          tempDocument[tempDetails[i].field_name] =
            fileDoc[tempDetails[i].field_name];
        } else if (tempDocument[tempDetails[i].field_name] === undefined) {
          if (tempDetails[i].control === 'numberEditor') {
            tempDocument[tempDetails[i].field_name] = 0;
          } else if (tempDetails[i].control === 'booleanSelect') {
            tempDocument[tempDetails[i].field_name] = false;
          } else {
            tempDocument[tempDetails[i].field_name] = '';
          }
        }
      }
      if (draft) {
        for (var i = 0; i < tempDetails.length; i++) {
          const result = await Acsys.updateData(
            'acsys_document_details',
            { ...tempDetails[i] },
            [['acsys_id', '=', tempDetails[i].acsys_id]]
          );
        }
        const result = await Acsys.insertData(
          collection,
          { ...tempDocument },
          keys
        );
        await Acsys.deleteData('acsys_' + collection, keys)
          .then(() => {
            setdraft(false);
          })
          .catch((error) => {});
      } else {
        const result = await Acsys.updateData(
          collection,
          { ...tempDocument },
          keys
        );
      }
    } else {
      for (var i = 0; i < tempDetails.length; i++) {
        if (tempDetails[i].control === 'autoGen') {
          tempDocument[tempDetails[i].field_name] = uniqid();
        } else if (fileDoc[tempDetails[i].field_name] !== undefined) {
          tempDocument[tempDetails[i].field_name] =
            fileDoc[tempDetails[i].field_name];
        } else if (tempDocument[tempDetails[i].field_name] === undefined) {
          if (tempDetails[i].control === 'numberEditor') {
            tempDocument[tempDetails[i].field_name] = 0;
          } else if (tempDetails[i].control === 'booleanSelect') {
            tempDocument[tempDetails[i].field_name] = false;
          } else {
            tempDocument[tempDetails[i].field_name] = '';
          }
        }
      }
      console.log(fileDoc);
      await Acsys.insertData(collection, {
        ...tempDocument,
      });
    }
    table_keys = [];
    for (var i = 0; i < tempDetails.length; i++) {
      if (tempDetails[i].is_key) {
        const object = {
          field: tempDetails[i].field_name,
          value: tempDocument[tempDetails[i].field_name],
        };
        table_keys.push(object);
      }
    }
    mode = 'update';
    mount();
  };

  const saveSettings = async () => {
    setfilterLoading(true);

    for (var i = 0; i < tempDetails.length; i++) {
      tempDetails[i].view_order = i;
      const result = await Acsys.updateData(
        'acsys_document_details',
        { ...tempDetails[i] },
        [['acsys_id', '=', tempDetails[i].acsys_id]]
      );
    }
    setfilterLoading(false);
    handleClose();
  };

  const saveView = async (value) => {
    setloading(true);

    var tempView = acsysView;

    if (value) {
      tempView['table_keys'] = JSON.stringify(props.location.state.table_keys);
    } else {
      tempView['table_keys'] = [];
    }

    for (var i = 0; i < tempDetails.length; i++) {
      const result = await Acsys.updateData('acsys_logical_content', tempView, [
        ['viewId', '=', props.location.state.viewId],
      ]);
    }
    setloading(false);
  };

  const deleteView = async () => {
    setdeleteLoading(true);
    let collection;
    if (draft) {
      collection = 'acsys_' + documentDetails[0].collection;
    } else {
      collection = documentDetails[0].collection;
    }
    await Acsys.deleteData(collection, keys)
      .then(() => {
        handleClose();
        setdeleteLoading(false);
        props.history.goBack();
      })
      .catch((error) => {
        handleClose();
        setError(error);
        setdeleteLoading(false);
      });
  };

  useEffect(async () => {
    initLoad = true;
    table_keys = [];
    tempDetails = [];
    tempDocument = [];
    fileDoc = [];
    fileRefs = [];
    mode = '';
    is_removable = true;
    quillRef = null;
    quillIndex = 0;
    quillURL = '';
    try {
      props.setHeader('Content');
      let tempMode = mode;
      let routedLocal = routed;
      const acsysView = await Acsys.getData('acsys_logical_content', [
        ['viewId', '=', props.location.state.viewId],
      ]);
      if (acsysView[0].table_keys.length > 0) {
        routedLocal = true;
      }
      try {
        mode = props.location.state.mode;
        is_removable = props.location.state.is_removable;
        if (routedLocal) {
          table_keys = JSON.parse(props.location.state.table_keys);
        } else {
          table_keys = props.location.state.table_keys;
        }
      } catch (error) {
        mode = tempMode;
      }
      setloading(true);
      setrouted(routedLocal);
      setacsysView(acsysView[0]);
      tempDocument = [];
      fileRefs = [];
      mount();
    } catch (error) {}
  }, [props.location.state]);

  const mount = async () => {
    let documentDetails;
    try {
      documentDetails = await Acsys.getData('acsys_document_details', [
        ['content_id', '=', props.location.state.viewId],
      ]);
    } catch (error) {
      documentDetails = documentDetails;
    }
    let table = documentDetails[0].collection;
    let draft = false;
    let keys = [];
    let apiCall;
    let position = 0;
    let open = false;
    try {
      documentDetails.sort((a, b) => (a.view_order > b.view_order ? 1 : -1));
      tempDetails = documentDetails;

      if (mode === 'update') {
        let pullView;

        for (let i = 0; i < table_keys.length; i++) {
          keys.push([table_keys[i].field, '=', table_keys[i].value]);
        }
        await Acsys.getData(table, keys)
          .then((result) => {
            pullView = result;
          })
          .catch(async () => {});
        if (pullView.length < 1) {
          await Acsys.getData('acsys_' + table, keys).then((result) => {
            pullView = result;
            draft = true;
          });
        }
        await Acsys.getData('acsys_open_tables', [['table_name', '=', table]])
          .then(async (result) => {
            if (result[0].table_name === table) {
              open = true;
            }
          })
          .catch(() => {});

        apiCall = await Acsys.getOpenUrl(table, keys);

        let currentView;

        if (pullView[0] === undefined) {
          currentView = pullView;
        } else {
          currentView = pullView[0];
        }

        for (let i = 0; i < documentDetails.length; i++) {
          if (
            documentDetails[i].control === 'imageReference' ||
            documentDetails[i].control === 'videoReference'
          ) {
            fileRefs[documentDetails[i].field_name] = await Acsys.getStorageURL(
              currentView[documentDetails[i].field_name]
            );
            fileDoc[documentDetails[i].field_name] =
              currentView[documentDetails[i].field_name];
          } else if (
            documentDetails[i].control === 'imageURL' ||
            documentDetails[i].control === 'videoURL'
          ) {
            fileRefs[documentDetails[i].field_name] =
              currentView[documentDetails[i].field_name];
            fileDoc[documentDetails[i].field_name] =
              currentView[documentDetails[i].field_name];
          }
        }

        setviews(currentView);
      } else {
        draft = true;
      }
      setloading(false);
      setdraft(draft);
      setsaving(false);
      setdocumentDetails(documentDetails);
      setLocked(!open);
      setCollection(table);
      setapiCall(apiCall);
      setkeys(keys);
      setPosition(position);
    } catch (error) {
      setloading(false);
      console.log(error);
    }
  };

  const renderData = () => {
    if (mode === 'update') {
      return <div>{renderWithId()}</div>;
    } else {
      return <div>{renderNoId()}</div>;
    }
  };

  const renderWithId = () => {
    return (
      <div class="element-container">
        <Grid container spacing={3}>
          {Object.values(documentDetails).map((details, dindex) => {
            return Object.values(views).map((value, index) => {
              let currentKey = Object.keys(views)[index];
              if (initLoad) {
                handleChange(currentKey, value);
                if (documentDetails.length - 1 === dindex) {
                  initLoad = false;
                }
              }
              if (
                currentKey == details.field_name &&
                details.is_visible_on_page
              ) {
                const date = new Date(value);
                return renderComponent(details, currentKey, date);
              }
            });
          })}
        </Grid>
      </div>
    );
  };

  const renderNoId = () => {
    return (
      <div class="element-container">
        <Grid container spacing={3}>
          {Object.values(documentDetails).map((details, dindex) => {
            let currentKey = details.field_name;
            if (details.is_visible_on_page) {
              let date;
              if (initLoad) {
                if (details.control == 'dateTimePicker') {
                  date = new Date();
                  handleChange(currentKey, date);
                }
                if (documentDetails.length - 1 === dindex) {
                  initLoad = false;
                }
              } else {
                date = tempDocument[currentKey];
              }
              return renderComponent(details, currentKey, date);
            }
          })}
        </Grid>
      </div>
    );
  };

  const renderComponent = (details, currentKey, date) => {
    if (details.control == 'autoGen') {
      return (
        <AutoGen
          width={details.width}
          field_name={details.field_name}
          defaultValue={tempDocument[currentKey]}
        />
      );
    } else if (details.control == 'textEditor') {
      return (
        <TextField
          width={details.width}
          field_name={details.field_name}
          defaultValue={tempDocument[currentKey]}
          handleChange={handleChange}
          currentKey={currentKey}
        />
      );
    } else if (details.control == 'dateTimePicker') {
      return (
        <DateTimePicker
          width={details.width}
          field_name={details.field_name}
          defaultValue={date}
          handleChange={handleChange}
          currentKey={currentKey}
        />
      );
    } else if (details.control == 'numberEditor') {
      return (
        <NumberEditor
          width={details.width}
          field_name={details.field_name}
          defaultValue={tempDocument[currentKey]}
          handleChange={handleChange}
          currentKey={currentKey}
        />
      );
    } else if (details.control == 'richTextEditor') {
      return (
        <RichTextEditor
          width={details.width}
          field_name={details.field_name}
          defaultValue={tempDocument[currentKey]}
          handleChange={handleChange}
          currentKey={currentKey}
          imageHandler={imageHandler}
          setQuillRef={setQuillRef}
          setQuillIndex={setQuillIndex}
          setQuillURL={setQuillURL}
          index={quillIndex}
          quillRef={quillRef}
          url={quillURL}
        />
      );
    } else if (details.control == 'booleanSelect') {
      return (
        <BooleanSelect
          width={details.width}
          field_name={details.field_name}
          defaultValue={tempDocument[currentKey]}
          handleChange={handleChange}
          currentKey={currentKey}
        />
      );
    } else if (details.control == 'imageReference') {
      const url = fileRefs[details.field_name];
      return (
        <ImageReference
          width={details.width}
          field_name={details.field_name}
          url={url}
          openSelector={openSelector}
          removeFile={removeFile}
        />
      );
    } else if (details.control == 'imageURL') {
      const url = fileRefs[details.field_name];
      return (
        <ImageURL
          width={details.width}
          field_name={details.field_name}
          url={url}
          openSelector={openSelector}
          removeFile={removeFile}
        />
      );
    } else if (details.control == 'videoReference') {
      const url = fileRefs[details.field_name];
      return (
        <VideoReference
          width={details.width}
          field_name={details.field_name}
          url={url}
          openSelector={openSelector}
          removeFile={removeFile}
        />
      );
    } else if (details.control == 'videoURL') {
      const url = fileRefs[details.field_name];
      return (
        <VideoURL
          width={details.width}
          field_name={details.field_name}
          url={url}
          openSelector={openSelector}
          removeFile={removeFile}
        />
      );
    }
  };

  return (
    <div style={{ minHeight: 600 }}>
      {Acsys.getMode() !== 'Viewer' ? (
        <div>
          {!props.location.state.routed && is_removable ? (
            <Tooltip title="Delete Entry">
              <Button
                style={{ float: 'right', marginBottom: 20, marginLeft: 20 }}
                variant="contained"
                color="primary"
                onClick={handleDeleteOpen}
              >
                Delete
              </Button>
            </Tooltip>
          ) : (
            <div />
          )}
          <Tooltip title="Publish Entry">
            <Button
              style={{ float: 'right', marginBottom: 20, marginLeft: 20 }}
              variant="contained"
              color="primary"
              onClick={publishDocument}
            >
              Publish
            </Button>
          </Tooltip>
          {draft ? (
            <Tooltip title="Save Entry As Draft">
              <Button
                style={{ float: 'right', marginBottom: 20, marginLeft: 20 }}
                variant="contained"
                color="primary"
                onClick={saveDocument}
              >
                Save Draft
              </Button>
            </Tooltip>
          ) : (
            <div></div>
          )}
          {Acsys.getMode() === 'Administrator' ? (
            <Tooltip title="Change How Data Is Presented">
              <Button
                style={{ float: 'right', marginBottom: 20, marginLeft: 20 }}
                variant="contained"
                color="primary"
                onClick={handleClickOpen}
              >
                Field Controls
              </Button>
            </Tooltip>
          ) : (
            <div />
          )}
          {Acsys.getMode() === 'Administrator' ? (
            <Select
              defaultValue={props.location.state.routed}
              onChange={(e) => saveView(e.target.value)}
              style={{ float: 'right', marginBottom: 20, marginLeft: 20 }}
            >
              <MenuItem value={false}>Accessed From Table</MenuItem>
              <MenuItem value={true}>Accessed From View</MenuItem>
            </Select>
          ) : (
            <div />
          )}
        </div>
      ) : (
        <div />
      )}
      <Paper style={{ margin: 'auto', clear: 'both' }}>
        <div>
          {renderData()}
          <div class="element-container">
            <div style={{ height: 40 }}></div>
          </div>
        </div>
        <LoadingDialog loading={loading} message={'Loading'} />
        <LoadingDialog loading={saving} message={'Saving'} />
        <FieldControlDialog
          open={setOpen}
          closeDialog={handleClose}
          title={'Field Controls'}
          backend={HTML5Backend}
          component={
            <FieldDef docDetails={tempDetails} handleClick={saveSettings} />
          }
          action={saveSettings}
          actionProcess={filterLoading}
        />
        <StorageDialog
          open={fileSelect}
          closeDialog={handleSelectClose}
          fileMode={fileMode}
          docDetails={tempDetails}
          control={control}
          setReference={setReference}
        />
        <YesNoDialog
          open={deleting}
          closeDialog={handleDeleteClose}
          title={'Delete data?'}
          message={'Are you sure you want to delete this entry?'}
          action={deleteView}
          actionProcess={deleteLoading}
        />
      </Paper>
      <Hidden smDown implementation="css">
        {!locked ? (
          <div style={{ clear: 'both' }}>
            API Call:{' '}
            <a className="api-url" href={apiCall} target="_blank">
              {apiCall}
            </a>
            <Tooltip title="Copy To Clipboard">
              <IconButton
                edge="start"
                color="inherit"
                aria-label="edit"
                onClick={copy}
                style={{ marginLeft: 5 }}
              >
                <CopyIcon style={{ height: 15 }} />
              </IconButton>
            </Tooltip>
          </div>
        ) : (
          <div />
        )}
      </Hidden>
    </div>
  );
}
Example #13
Source File: CreatibutorsField.js    From react-invenio-deposit with MIT License 4 votes vote down vote up
render() {
    const {
      form: { values, errors, initialErrors, initialValues },
      remove: formikArrayRemove,
      replace: formikArrayReplace,
      move: formikArrayMove,
      name: fieldPath,
      label,
      labelIcon,
      roleOptions,
      schema,
      modal,
      autocompleteNames,
      addButtonLabel,
    } = this.props;

    const creatibutorsList = getIn(values, fieldPath, []);
    const formikInitialValues = getIn(initialValues, fieldPath, []);

    const error = getIn(errors, fieldPath, null);
    const initialError = getIn(initialErrors, fieldPath, null);
    const creatibutorsError =
      error || (creatibutorsList === formikInitialValues && initialError);

    return (
      <DndProvider backend={HTML5Backend}>
        <Form.Field
          required={schema === 'creators'}
          className={creatibutorsError ? 'error' : ''}
        >
          <FieldLabel htmlFor={fieldPath} icon={labelIcon} label={label} />
          <List>
            {creatibutorsList.map((value, index, array) => {
              const key = `${fieldPath}.${index}`;
              const identifiersError =
                creatibutorsError &&
                creatibutorsError[index]?.person_or_org?.identifiers;
              const displayName = creatibutorNameDisplay(value);

              return (
                <CreatibutorsFieldItem
                  key={key}
                  identifiersError={identifiersError}
                  {...{
                    displayName,
                    index,
                    roleOptions,
                    schema,
                    compKey: key,
                    initialCreatibutor: value,
                    removeCreatibutor: formikArrayRemove,
                    replaceCreatibutor: formikArrayReplace,
                    moveCreatibutor: formikArrayMove,
                    addLabel: modal.addLabel,
                    editLabel: modal.editLabel,
                    autocompleteNames: autocompleteNames,
                  }}
                />
              );
            })}
            <CreatibutorsModal
              onCreatibutorChange={this.handleOnContributorChange}
              action="add"
              addLabel={modal.addLabel}
              editLabel={modal.editLabel}
              roleOptions={sortOptions(roleOptions)}
              schema={schema}
              autocompleteNames={autocompleteNames}
              trigger={
                <Button type="button" icon labelPosition="left">
                  <Icon name="add" />
                  {addButtonLabel}
                </Button>
              }
            />
            {creatibutorsError && typeof creatibutorsError == 'string' && (
              <Label pointing="left" prompt>
                {creatibutorsError}
              </Label>
            )}
          </List>
        </Form.Field>
      </DndProvider>
    );
  }
Example #14
Source File: FundingField.js    From react-invenio-deposit with MIT License 4 votes vote down vote up
function FundingFieldForm(props) {
  const {
    label,
    labelIcon,
    fieldPath,
    form: { values },
    move: formikArrayMove,
    push: formikArrayPush,
    remove: formikArrayRemove,
    replace: formikArrayReplace,
    required,
  } = props;

  const deserializeAward = props.deserializeAward
    ? props.deserializeAward
    : (award) => ({
        title: award?.title_l10n,
        number: award.number,
        funder: award.funder ?? '',
        id: award.id,
        ...(award.identifiers && { identifiers: award.identifiers }),
        ...(award.acronym && { acronym: award.acronym }),
      });

  const deserializeFunder = props.deserializeFunder
    ? props.deserializeFunder
    : (funder) => ({
        id: funder.id,
        name: funder.name,
        ...(funder.pid && { pid: funder.pid }),
        ...(funder.country && { country: funder.country }),
        ...(funder.identifiers && { identifiers: funder.identifiers }),
      });

  const computeFundingContents = props.computeFundingContents
    ? props.computeFundingContents
    : (funding) => {
        let headerContent,
          descriptionContent = '';
        let awardOrFunder = 'award';
        if (funding.award) {
          headerContent = funding.award.title;
        }

        if (funding.funder) {
          const funderName =
            funding?.funder?.name ??
            funding.funder?.title ??
            funding?.funder?.id ??
            '';
          descriptionContent = funderName;
          if (!headerContent) {
            awardOrFunder = 'funder';
            headerContent = funderName;
            descriptionContent = '';
          }
        }

        return { headerContent, descriptionContent, awardOrFunder };
      };
  return (
    <DndProvider backend={HTML5Backend}>
      <Form.Field required={required}>
        <FieldLabel
          htmlFor={fieldPath}
          icon={labelIcon}
          label={label}
        ></FieldLabel>
        <List>
          {getIn(values, fieldPath, []).map((value, index, array) => {
            const arrayPath = fieldPath;
            const indexPath = index;
            const key = `${arrayPath}.${indexPath}`;
            // if award does not exist or has no id, it's a custom one
            const awardType = value?.award?.id ? 'standard' : 'custom';
            return (
              <FundingFieldItem
                key={key}
                {...{
                  index,
                  compKey: key,
                  fundingItem: value,
                  awardType,
                  moveFunding: formikArrayMove,
                  replaceFunding: formikArrayReplace,
                  removeFunding: formikArrayRemove,
                  searchConfig: props.searchConfig,
                  computeFundingContents: computeFundingContents,
                  deserializeAward: deserializeAward,
                  deserializeFunder: deserializeFunder,
                }}
              />
            );
          })}
          <FundingModal
            searchConfig={props.searchConfig}
            trigger={
              <Button type="button" key="custom" icon labelPosition="left" className="mb-5">
                <Icon name="add" />
                {i18next.t('Add award')}
              </Button>
            }
            onAwardChange={(selectedFunding) => {
              formikArrayPush(selectedFunding);
            }}
            mode="standard"
            action="add"
            deserializeAward={deserializeAward}
            deserializeFunder={deserializeFunder}
            computeFundingContents={computeFundingContents}
          />
          <FundingModal
            searchConfig={props.searchConfig}
            trigger={
              <Button type="button" key="custom" icon labelPosition="left">
                <Icon name="add" />
                {i18next.t('Add custom')}
              </Button>
            }
            onAwardChange={(selectedFunding) => {
              formikArrayPush(selectedFunding);
            }}
            mode="custom"
            action="add"
            deserializeAward={deserializeAward}
            deserializeFunder={deserializeFunder}
            computeFundingContents={computeFundingContents}
          />
        </List>
      </Form.Field>
    </DndProvider>
  );
}
Example #15
Source File: Table.js    From os-league-tools with MIT License 4 votes vote down vote up
export default function Table({
    columns,
    data,
    filters = [],
    filterState,
    globalFilter,
    defaultColumn,
    initialState,
    ExpandedRow,
    customFilterProps = {},
    enableResizeColumns = true,
}) {
    const [records, setRecords] = useState(data);

    useEffect(() => {
        if (filters.length) {
            setRecords(data.filter(record => filters.every(filter => filter(record, filterState, customFilterProps))));
        } else {
            setRecords(data);
        }
    }, [filterState, data, customFilterProps]);

    const table = useTable(
        {
            initialState: { pageSize: 25, ...initialState },
            columns,
            data: records,
            defaultColumn,
            globalFilter,
            manualFilters: true,
            autoResetGlobalFilter: false,
            autoResetSortBy: false,
            autoResetPage: false,
            autoResetExpanded: false,
            getRowId: useCallback(row => row.id, []),
        },
        useFlexLayout,
        useResizeColumns,
        useGlobalFilter,
        useSortBy,
        useExpanded,
        usePagination
    );

    useEffect(() => {
        // Reset to first page when filters are changed
        table.gotoPage(0);
    }, [filterState]);

    const moveRow = (dragIndex, hoverIndex) => {
        const dragRecord = records[dragIndex];
        setRecords(
            update(records, {
                $splice: [
                    [dragIndex, 1],
                    [hoverIndex, 0, dragRecord],
                ],
            })
        );
    };

    return (
        <>
            <div className='flex flex-row flex-wrap justify-between pb-3 px-3 items-end'>
                <span className='italic text-sm'>Showing: {table.page.length} rows</span>
                <SearchBox globalFilter={table.state.globalFilter} setGlobalFilter={table.setGlobalFilter} />
            </div>
            <div className='overflow-auto px-3'>
                <DndProvider backend={HTML5Backend}>
                    <div {...table.getTableProps()} style={{ minWidth: 'min-content' }}>
                        <div>
                            {table.headerGroups.map(headerGroup => (
                                <div
                                    {...headerGroup.getHeaderGroupProps()}
                                    className='heading-accent-md leading-loose border-b border-accent w-full'
                                >
                                    {headerGroup.headers.map(column => (
                                        <div
                                            {...column.getHeaderProps(column.getSortByToggleProps())}
                                            className='relative font-bold text-center'
                                        >
                                            {column.render('Header')}
                                            {column.isSorted && (
                                                <span className='icon-base absolute'>
                                                    {column.isSortedDesc ? 'arrow_drop_down' : 'arrow_drop_up'}
                                                </span>
                                            )}
                                            {enableResizeColumns && (
                                                <span {...column.getResizerProps()} className='resizer icon-lg'>
                                                    drag_handle
                                                </span>
                                            )}
                                        </div>
                                    ))}
                                </div>
                            ))}
                        </div>
                        <div {...table.getTableBodyProps()}>
                            {table.page.map(
                                (row, index) =>
                                    table.prepareRow(row) || (
                                        <Row
                                            index={index}
                                            row={row}
                                            moveRow={moveRow}
                                            isReorderEnabled={filterState?.reorderEnabled}
                                            ExpandedRow={ExpandedRow}
                                            {...row.getRowProps()}
                                        />
                                    )
                            )}
                        </div>
                        <div className='flex flex-col justify-center text-center'>
                            <div>
                                <PageButton
                                    onClick={() => table.gotoPage(0)}
                                    disabled={!table.canPreviousPage}
                                    text='<<'
                                />
                                <PageButton
                                    onClick={() => table.previousPage()}
                                    disabled={!table.canPreviousPage}
                                    text='<'
                                />
                                <span className='text-xs'>
                                    {table.state.pageIndex + 1} of {table.pageOptions.length}
                                </span>
                                <PageButton onClick={() => table.nextPage()} disabled={!table.canNextPage} text='>' />
                                <PageButton
                                    onClick={() => table.gotoPage(table.pageCount - 1)}
                                    disabled={!table.canNextPage}
                                    text='>>'
                                />
                            </div>

                            <span className='text-xs'>
                                Show:
                                <select
                                    className='input-primary text-xs p-0 ml-1 text-center'
                                    value={table.state.pageSize}
                                    onChange={e => {
                                        table.setPageSize(Number(e.target.value));
                                    }}
                                >
                                    {[25, 50, 100, 200].map(pageSize => (
                                        <option key={pageSize} value={pageSize}>
                                            {pageSize}
                                        </option>
                                    ))}
                                </select>
                            </span>
                        </div>
                    </div>
                </DndProvider>
            </div>
        </>
    );
}
Example #16
Source File: QueueSection.js    From qasong with ISC License 4 votes vote down vote up
function QueueSection({ nowPlaying, setNowPlaying, queue, setQueue }) {
  const [displayMode, setDisplayMode] = useState("list");
  const [displaySaved, setDisplaySaved] = useState(false);
  const [confirmDialog, setConfirmDialog] = useState({
    isOpen: false,
    title: "",
    subTitle: "",
  });

  const handleClickQueueItem = (qid) => {
    setNowPlaying(queue.find((item) => item.qid === qid));
  };

  const handleClickSave = () => {
    setDisplaySaved(true);
    setTimeout(() => {
      setDisplaySaved(false);
    }, 3000);
  };

  const moveCard = useCallback(
    (dragIndex, hoverIndex) => {
      const dragCard = queue[dragIndex];
      setQueue(
        update(queue, {
          $splice: [
            [dragIndex, 1],
            [hoverIndex, 0, dragCard],
          ],
        })
      );
    },
    [queue]
  );

  if (!queue.length > 0) {
    return (
      <div style={{ maxWidth: "800px", margin: "0 auto 200px auto" }}>
        <Typography align="center">
          <i> No queue exists. </i>
          Click
          <IconButton disabled>
            <QueueIcon />
          </IconButton>
          icon to add song to your queue.
        </Typography>

        <Box m={3}>
          <Grid container alignItems="center">
            <Grid item>
              <Typography variant="h5">
                <Skeleton variant="text" width={100} height={50} />
              </Typography>
            </Grid>
            <Grid item>
              <PlayQueueButton disabled />
            </Grid>
            <Grid item>
              <ShuffleButton disabled />
            </Grid>
            <Grid item>
              <DisplayModeButton disabled />
            </Grid>
            <Grid item>
              <SaveQueueButton disabled />
            </Grid>
            <Grid item>
              <ClearButton disabled />
            </Grid>
          </Grid>
        </Box>

        {[1, 2, 3].map((index) => {
          return (
            <Grid container key={index}>
              <Grid item xs={1}>
                <IconButton disabled>
                  <PlayArrowIcon />
                </IconButton>
              </Grid>
              <Grid item xs={9}>
                <Typography>
                  <Skeleton variant="text" width={300} height={50} />
                </Typography>
              </Grid>
              <Grid item xs={1}>
                <IconButton disabled>
                  <DragHandleIcon />
                </IconButton>
              </Grid>
              <Grid item xs={1}>
                <Typography>
                  <Skeleton variant="text" width={100} height={50} />
                </Typography>
              </Grid>
            </Grid>
          );
        })}
      </div>
    );
  }

  return (
    <div style={{ maxWidth: "800px", margin: "0 auto 200px auto" }}>
      <Box m={3}>
        <Grid container alignItems="center" spacing={1}>
          <Grid item>
            <Typography variant="h5">
              {queue.length > 0 && `${queue.length} songs`}
            </Typography>
          </Grid>
          <Grid item>
            <PlayQueueButton {...{ setNowPlaying, queue }} />
          </Grid>
          <Grid item>
            <ShuffleButton {...{ queue, setQueue, setNowPlaying }} />
          </Grid>
          <Grid item>
            <DisplayModeButton {...{ displayMode, setDisplayMode }} />
          </Grid>
          <Grid item onClick={handleClickSave}>
            <SaveQueueButton {...{ queue }} />
          </Grid>
          <Grid
            item
            onClick={() => {
              setConfirmDialog({
                isOpen: true,
                title: "Are you sure you want to clear the queue?",
                subTitle: "You can't undo this operation.",
              });
            }}
          >
            <ClearButton {...{ setQueue }} />
          </Grid>
          {displaySaved ? (
            <Grid item md={5} xs={12} spacing={3}>
              <Alert severity="success" color="warning" variant="outlined">
                <i>Queue Has Been Successfully Saved</i>
              </Alert>
            </Grid>
          ) : null}
        </Grid>
        <ConfirmClearDialog
          setQueue={setQueue}
          confirmDialog={confirmDialog}
          setConfirmDialog={setConfirmDialog}
        />
      </Box>

      <DndProvider backend={isMobile ? TouchBackend : HTML5Backend}>
        {displayMode === "list" ? (
          <Grid container direction="column">
            {queue.map((item, index) => {
              return (
                <QueueRow
                  {...item}
                  key={item.qid}
                  queue={queue}
                  setQueue={setQueue}
                  index={index}
                  nowPlaying={nowPlaying}
                  onClickMusicRow={handleClickQueueItem}
                  moveCard={moveCard}
                />
              );
            })}
          </Grid>
        ) : (
          queue.map((item, index) => (
            <QueueCard
              {...item}
              key={item.qid}
              queue={queue}
              setQueue={setQueue}
              index={index}
              nowPlaying={nowPlaying}
              onClickImage={handleClickQueueItem}
              moveCard={moveCard}
            />
          ))
        )}
      </DndProvider>
    </div>
  );
}