react-sortable-hoc#sortableElement JavaScript Examples

The following examples show how to use react-sortable-hoc#sortableElement. 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: CampaignCannedResponsesForm.jsx    From Spoke with MIT License 6 votes vote down vote up
SortableItem = SortableElement(
  ({
    value: response,
    style,
    customFields,
    labels,
    onClickDelete,
    onClickItem
  }) => {
    // not editing; just display it
    const { missingFields = [] } = validateScript({
      script: response.text,
      customFields
    });

    return (
      <div style={style} className={css(styles.listItemWrapper)}>
        <CannedResponseListItem
          response={response}
          labels={labels}
          labelIds={response.labelIds || []}
          leftIcon={missingFields.length ? warningIcon : null}
          rightIconButton={
            <IconButton onClick={onClickDelete}>
              <DeleteIcon />
            </IconButton>
          }
          onClick={onClickItem}
        />
      </div>
    );
  }
)
Example #2
Source File: SortableWidgetContainer.jsx    From covid with GNU General Public License v3.0 6 votes vote down vote up
DraggableWidgetContainer = SortableElement(
  ({ Component, payload, ...props }) => {
    // Merge props from general props and from payload
    // Add first the payload values, so them cannot overwrite the ones from props
    return (
      <Grid item xs={12} sm={6} md={4} lg={3}>
        <Component {...payload} {...props} />
      </Grid>
    )
  }
)
Example #3
Source File: index.jsx    From mixbox with GNU General Public License v3.0 6 votes vote down vote up
SortableItem = SortableElement((props) => {
    const {children} = props;
    return (
        <div
            className={classNames('draggable-tabs-bar-horizontal-item', props.className)}
            style={props.style}
        >
            {/*<div className="tabs-bar-left-corner"/>*/}
            {/*<div className="tabs-bar-right-corner"/>*/}
            {children}
        </div>
    );
})
Example #4
Source File: SortableTrackContainer.jsx    From Oud with MIT License 6 votes vote down vote up
SortableTrackContainer = SortableElement((props) => {
  return (
    <Track
      id={props.id}
      idx={props.idx}
      playTrack={props.playTrack}
      playing={props.playing}
      changePlayingState={props.changePlayingState}
      toggleDropdown={props.toggleDropdown}
      data-testid="track-component"
    />
  );
})
Example #5
Source File: DraggableColorBox.js    From flat-ui-colors with MIT License 6 votes vote down vote up
DraggableColorBox = SortableElement((props) => {
  const { classes, handleClick, name, color } = props;
  return (
    <div className={props.classes.root} style={{ backgroundColor: color }}>
      <div className={classes.boxContent} style={{ backgroundColor: color }}>
        <span>{name}</span>
        <DeleteIcon className={classes.deleteIcon} onClick={handleClick} />
      </div>
    </div>
  );
})
Example #6
Source File: index.js    From ice-electron with MIT License 6 votes vote down vote up
SortableItem = SortableElement(({ element, isSorting }) => {
  return (
    <div
      className={cx({
        [styles.sortableItem]: true,
        [styles.sorting]: isSorting,
      })}
    >
      <SortableDragHandle />
      {element}
    </div>
  );
})
Example #7
Source File: BuildPageModal.js    From ice-electron with MIT License 6 votes vote down vote up
SelectedBlock = SortableElement(({
  title, screenshot, name, onNameChange, onDelete, index, isSorting,
}) => {
  return (
    <div className={cx({ [styles.item]: true, [styles.isSorting]: isSorting })}>
      <BlockDragHandle
        title={title}
        screenshot={screenshot}
      />
      <div className={styles.name}>
        <Input
          value={name}
          className={styles.input}
          onChange={(value) => onNameChange(value, index)}
        />
        <Icon className={styles.icon} type="pencil" size="small" />
      </div>
      <Icon className={styles.trash} type="trash" size="small" onClick={() => onDelete(index)} />
    </div>
  );
})
Example #8
Source File: repeater.js    From formality with GNU General Public License v3.0 6 votes vote down vote up
SortableItem = SortableElement(({value, parentValue, index, nindex, onChangeChild, template, removeText, onRemove, addOnNonEmpty}) => {
  return el('div', {className: 'repeater-row-wrapper'}, [
    el('div', {className: 'repeater-row-inner'}, template(value, (v) => {
      onChangeChild(v, nindex)
    })),
    el('div', {className: 'button-wrapper'},
      addOnNonEmpty && nindex === parentValue.length - 1 ? null : [
        el('div', {className: 'repeater-row-move'}, '' ),
        el(c.Button, {
          className: 'repeater-row-remove is-button is-default',
          onClick: () => { onRemove(nindex) }
        }, removeText ? removeText : '-')
      ]
    )
  ])
})
Example #9
Source File: basic.js    From Lynx with MIT License 5 votes vote down vote up
SortableItem = SortableElement(({value}) => <li>{value}</li>)
Example #10
Source File: index.js    From DMS_React with GNU Affero General Public License v3.0 5 votes vote down vote up
ToDoItem = SortableElement(({todo, onTodoSelect, onTodoChecked, onMarkAsStart}) => {
  let user = null;
  // if (todo.user > 0)
  //   user = users[todo.user - 1];
  return (
    <div className="module-list-item">
      <div className="module-list-icon">
            <span className="bar-icon">
              <DragHandle/>
            </span>

        <Checkbox color="primary"
                  checked={todo.selected}
                  onClick={(event) => {
                    event.stopPropagation();
                    onTodoChecked(todo);
                  }}
                  value="SelectTodo"
        />

        <IconButton className="icon-btn" onClick={() => {
          todo.starred = !todo.starred;
          onMarkAsStart(todo);
        }}>
          {todo.starred ?
            <i className="zmdi zmdi-star"/> :
            <i className="zmdi zmdi-star-outline"/>
          }

        </IconButton>
      </div>
      <div className="module-list-info" onClick={() => {
        onTodoSelect(todo);
      }}>
        <div className="row">
          <div className="module-todo-content col-9 col-sm-10 col-md-11">
            <div className={`subject ${todo.completed && 'text-muted text-strikethrough'}`}>
              {todo.title}
            </div>
            <div className="manage-margin">
              {/* {labels.map((label, index) => {
                return (todo.labels).includes(label.id) &&
                  <div key={index}
                       className={`badge text-white bg-${label.color}`}>{label.title}</div>
              })} */}
            </div>
          </div>
          <div className="module-todo-right col-3 col-sm-2 col-md-1">
            <div className="d-flex flex-row-reverse">
              {/* {user === null ? <Avatar>U</Avatar>
                : <Avatar alt={user.name}
                          src={user.thumb}/>} */}

            </div>
          </div>
        </div>
      </div>
    </div>

  )
})
Example #11
Source File: drag-handle.js    From Lynx with MIT License 5 votes vote down vote up
SortableItem = SortableElement(({value}) => {
  return (
    <li>
      <DragHandle />
      {value}
    </li>
  );
})
Example #12
Source File: infinite-list.js    From Lynx with MIT License 5 votes vote down vote up
SortableItem = SortableElement(({height, value}) => {
  return (
    <li style={{height}}>
      {value}
    </li>
  );
})
Example #13
Source File: virtual-list.js    From Lynx with MIT License 5 votes vote down vote up
SortableItem = SortableElement(({value}) => {
  return (
    <li>
      {value}
    </li>
  );
})
Example #14
Source File: virtual-table-columns.js    From Lynx with MIT License 5 votes vote down vote up
SortableHeader = SortableElement(({children, ...props}) =>
  React.cloneElement(children, props)
)
Example #15
Source File: Roster.js    From zengm-legacy with Apache License 2.0 5 votes vote down vote up
RosterRow = SortableElement(clickable(props => {
    const {clicked, editable, i, p, season, selectedPid, showTradeFor, toggleClicked} = props;
    return <tr
        key={p.pid}
        className={classNames({separator: i === 4, warning: clicked})}
        data-pid={p.pid}
    >
        {editable ? <ReorderHandle i={i} pid={p.pid} selectedPid={selectedPid} /> : null}

        <td onClick={toggleClicked}>
            <PlayerNameLabels
                pid={p.pid}
                injury={p.injury}
                skills={p.ratings.skills}
                watch={p.watch}
            >{p.name}</PlayerNameLabels>
        </td>
        <td onClick={toggleClicked}>{p.ratings.pos}</td>
        <td onClick={toggleClicked}>{p.age}</td>
        <td onClick={toggleClicked}>{p.born.loc}</td>
        <td onClick={toggleClicked}>{p.stats.yearsWithTeam}</td>
        <td onClick={toggleClicked}>{p.ratings.MMR}</td>
        <td onClick={toggleClicked}>
            <RatingWithChange change={p.ratings.dovr}>{p.ratings.ovr}</RatingWithChange>
        </td>
        <td onClick={toggleClicked}>
            <RatingWithChange change={p.ratings.dpot}>{p.ratings.pot}</RatingWithChange>
        </td>
        {season === g.season ? <td>
            {helpers.formatCurrency(p.contract.amount, 'K')} thru {p.contract.exp}
        </td> : null}
        <td onClick={toggleClicked}>{p.stats.gp}</td>
        <td onClick={toggleClicked}>{p.stats.min.toFixed(1)}</td>
        <td onClick={toggleClicked}>{p.stats.kda.toFixed(1)}</td>
        <td onClick={toggleClicked}>{p.stats.trb.toFixed(1)}</td>
        {editable ? <td onClick={toggleClicked}>
            <button
                className="btn btn-default btn-xs"
                disabled={!p.canRelease}
                onClick={() => handleRelease(p)}
            >
                Release
            </button>
        </td> : null}
        {showTradeFor ? <td onClick={toggleClicked} title={p.untradableMsg}>
            <button
                className="btn btn-default btn-xs"
                disabled={p.untradable}
                onClick={() => toWorker('actions.tradeFor', {pid: p.pid})}
            >Trade For</button>
        </td> : null}
        <td onClick={toggleClicked}>{p.ratings.languagesGrouped}</td>
        <td onClick={toggleClicked}>{p.born.country}</td>
    </tr>;
}))
Example #16
Source File: LayerItem.js    From dnd-builder with MIT License 5 votes vote down vote up
LayerItem = sortableElement(({
  icon: Icon,
  item,
  onItemChange,
  optionKey,
  setActiveElement,
}) => {
  const { id, isVisible } = item;
  const isVisib = isVisible !== undefined ? isVisible : true;
  const handleItemLock = useCallback(({ target }) => {
    onItemChange({ id }, { isVisible: target.checked });
  }, [id]);

  const itemText = passedItem => {
    if (passedItem.itemType === 'shapes') {
      return capitalize(passedItem.shapeType || 'Rectangle');
    }
    if (passedItem.itemType === 'chart') {
      return passedItem.text || 'Chart Element';
    }
    if (passedItem.itemType === 'header') {
      return passedItem.headerText || 'Click to edit header';
    }
    if (passedItem.itemType === 'text') {
      return passedItem.value ? stripHTML(passedItem.value) : 'Click to edit text';
    }
    return capitalize(passedItem.itemType || 'Page Element');
  };
  const content = (
    <div className="jfReportSelectOption">
      <div className="jfReportSelectOption-icon">
        <Icon />
      </div>
      <div className="jfReportSelectOption-text">
        {itemText(item)}
      </div>
    </div>
  );

  return (
    <div
      className={classNames('jfReportSelectOption', {
        isSelected: isVisib,
      })}
      onClick={() => setActiveElement(id, false)}
      onKeyDown={() => {}}
    >
      <div className="jfReportSelectOption-visibility">
        <label
          className="jfReportChoice isLight hasNotText"
          htmlFor={optionKey}
        >
          <input
            checked={isVisib}
            className="jfReportChoice-input"
            data-option-key={optionKey}
            id={optionKey}
            onChange={handleItemLock}
            type="checkbox"
          />
          <div className="jfReportChoice-labelIcon">
            <div className="jfReportChoice-label checkbox" />
          </div>
        </label>
      </div>
      <div
        className="jfReportSelectOption-name"
        // style={{ backgroundColor: option.color }}
      >
        <DragHandle />
        {content}
      </div>
    </div>
  );
})
Example #17
Source File: drag-sorting-handler.jsx    From virtuoso-design-system with MIT License 5 votes vote down vote up
SortableItem = sortableElement(props => <tr {...props} />)
Example #18
Source File: PropsTree.js    From react-ui-builder-editor with GNU General Public License v3.0 5 votes vote down vote up
SortableTreeItem = SortableElement(({element}) => element)
Example #19
Source File: PageTree.js    From react-ui-builder-editor with GNU General Public License v3.0 5 votes vote down vote up
SortableTreeItem = SortableElement(({element}) => element)
Example #20
Source File: SortablePageItem.js    From dnd-builder with MIT License 5 votes vote down vote up
SortablePageItem = SortableElement(({
  acceptedItems,
  additionalPageItems,
  disableInteraction,
  hashCode,
  isSelected,
  itemAccessor,
  onAnEventTrigger,
  onPageAdd,
  onPageClick,
  onPageDuplicate,
  onPageRemove,
  order,
  page,
  pageContainerStyle,
  style,
}) => {
  const onKeyDown = f => f;
  return (
    <div
      className={classNames('thumbnailWrapper d-flex a-center j-between', { isSelected })}
      data-id={page.id}
      data-order={order}
      onClick={onPageClick}
      onKeyDown={onKeyDown}
      style={style}
    >
      <div className="thumbnailOrder">{order}</div>
      <div className="thumbnailFrame o-hidden">
        <StaticPage
          acceptedItems={acceptedItems}
          additionalPageItems={additionalPageItems}
          hashCode={hashCode}
          itemAccessor={itemAccessor}
          items={page.items}
          style={pageContainerStyle}
        />
      </div>
      <PageThumbnailActions
        disableInteraction={disableInteraction}
        onAnEventTrigger={onAnEventTrigger}
        onPageAdd={onPageAdd}
        onPageDuplicate={onPageDuplicate}
        onPageRemove={onPageRemove}
        order={order}
        page={page}
      />
    </div>
  );
})
Example #21
Source File: PageItem.js    From dnd-builder with MIT License 5 votes vote down vote up
PageItem = SortableElement(({
  acceptedItems,
  additionalPageItems,
  hashCode,
  isSelected,
  itemAccessor,
  onAnEventTrigger,
  onPageAdd,
  onPageClick,
  onPageDuplicate,
  onPageRemove,
  order,
  page,
  style,
}) => {
  const onKeyDown = f => f;
  return (
    <div
      className={(
        classNames('thumbnailWrapper d-flex dir-col a-center j-center p-relative', { isSelected })
      )}
      data-id={page.id}
      data-order={order}
      onClick={onPageClick}
      onKeyDown={onKeyDown}
    >
      <div className="thumbnailOrder">{order}</div>
      <div className="thumbnailFrame o-hidden">
        <StaticPage
          acceptedItems={acceptedItems}
          additionalPageItems={additionalPageItems}
          hashCode={hashCode}
          itemAccessor={itemAccessor}
          items={page.items}
          style={style}
        />
      </div>
      <PageThumbnailActions
        onAnEventTrigger={onAnEventTrigger}
        onPageAdd={onPageAdd}
        onPageDuplicate={onPageDuplicate}
        onPageRemove={onPageRemove}
        order={order}
        page={page}
      />
    </div>
  );
})
Example #22
Source File: Ranker.js    From label-studio-frontend with Apache License 2.0 5 votes vote down vote up
SortableText = SortableElement(({ item, value }) => {
  let classNames;

  if (isMobileDevice) {
    classNames = "noselect";
  }

  const map = {
    text: v => <span className={classNames}>{v._value}</span>,
    image: v => <img src={v._value} alt="" />,
    audio: v => <audio src={v._value} />,
  };

  return (
    <div
      style={{
        padding: "1em",
        userSelect: "none",
        display: "flex",
        alignItems: "center",
        background: value.selected ? item.sortedhighlightcolor : "transparent",
      }}
      className={classNames}
      onClick={ev => {
        if (value.selected) {
          value.setSelected(false);
          item.setUpdate();
        } else {
          value.setSelected(true);
          item.setUpdate();
        }
        ev.preventDefault();
        return false;
      }}
    >
      <DragHandle />
      {map[item.elementtag.toLowerCase()](value)}
    </div>
  );
})
Example #23
Source File: List.js    From label-studio-frontend with Apache License 2.0 5 votes vote down vote up
SortableText = SortableElement(({ item, value }) => {
  let classNames;

  if (isMobileDevice) {
    classNames = "noselect";
  }

  const map = {
    text: v => <span className={classNames}>{v._value}</span>,
    image: v => <img src={v._value} alt="" />,
    audio: v => <audio src={v._value} />,
  };

  return (
    <div
      style={{
        padding: "1em",
        userSelect: "none",
        display: "flex",
        alignItems: "center",
        background: value.selected ? item.sortedhighlightcolor : "transparent",
      }}
      className={classNames}
      onClick={ev => {
        if (value.selected) {
          value.setSelected(false);
          item.setUpdate();
        } else {
          value.setSelected(true);
          item.setUpdate();
        }
        ev.preventDefault();
        return false;
      }}
    >
      <DragHandle />
      {map[item.elementtag.toLowerCase()](value)}
    </div>
  );
})
Example #24
Source File: index.jsx    From mixbox with GNU General Public License v3.0 5 votes vote down vote up
RowElement = SortableElement((props) => {
    return props.children;
})
Example #25
Source File: imageGroup.js    From egoshop with Apache License 2.0 5 votes vote down vote up
SortableItem = SortableElement(({ value }) =>
    <li className={styles.sortableListLi}>{value}</li>
)
Example #26
Source File: PeopleList.jsx    From A2 with GNU General Public License v3.0 4 votes vote down vote up
PersonRow = SortableElement(
  ({
    person,
    hasPaid,
    nameError,
    paidError,
    showErrors,
    onSetPayer,
    onSetPayee,
    onNameChange,
    onRemove,
    onInputBlur,
    ...other
  }) => (
    // react-sortable-hoc needs to pass in some
    // props to the <li>, so we spread it here.
    /* eslint-disable react/jsx-props-no-spreading */
    <li {...other}>
      <div className={styles.personRow}>
        <DragHandle className={styles.dragHandle} />

        <ErrorBubbleAnchor className={styles.personNameWrapper}>
          <TextField
            required
            value={person.name}
            onChange={onNameChange}
            onBlur={onInputBlur}
            placeholder="Enter person’s name..."
            fullWidth
            className={styles.personNameTextField}
            InputProps={{
              inputProps: {
                className: styles.personNameInput
              },

              // We don't want their fancy rippled underline as
              // it is hard to customize.
              disableUnderline: true
            }}
          />
          <ErrorBubble
            className={styles.errorBubble}
            arrowTop
            show={showErrors}
            message={nameError}
          />
        </ErrorBubbleAnchor>

        <ToggleButtonGroup
          value={hasPaid ? "payee" : "payer"}
          size="small"
          exclusive
          className={styles.personPayeeToggleGroup}
        >
          <ToggleButton
            value="payer"
            onClick={onSetPayer}
            classes={{
              root: styles.personIsPayerButton,
              selected: styles.personIsPayerButtonSelected
            }}
          >
            Payer
          </ToggleButton>
          <ToggleButton
            value="payee"
            onClick={onSetPayee}
            classes={{
              root: styles.personIsPayeeButton,
              selected: styles.personIsPayeeButtonSelected
            }}
          >
            <ErrorBubbleAnchor className={styles.personPayeeWrapper}>
              Payee
              <ErrorBubble
                className={styles.errorBubble}
                center
                arrowTop
                show={showErrors}
                message={paidError}
              />
            </ErrorBubbleAnchor>
          </ToggleButton>
        </ToggleButtonGroup>

        <Button onClick={onRemove} className={styles.personRemoveButton}>
          <ClearIcon />
        </Button>
      </div>
    </li>
    /* eslint-enable react/jsx-props-no-spreading */
  )
)
Example #27
Source File: SamplesTable.jsx    From ui with MIT License 4 votes vote down vote up
SamplesTable = forwardRef((props, ref) => {
  const dispatch = useDispatch();
  const [tableData, setTableData] = useState([]);

  const experiments = useSelector((state) => state.experiments);
  const samples = useSelector((state) => state.samples);
  const areSamplesLoading = useSelector((state) => state.samples.meta.loading);

  const activeExperimentId = useSelector((state) => state.experiments.meta.activeExperimentId);
  const activeExperiment = useSelector((state) => state.experiments[activeExperimentId]);

  const [sampleNames, setSampleNames] = useState(new Set());
  const DragHandle = sortableHandle(() => <MenuOutlined style={{ cursor: 'grab', color: '#999' }} />);

  const initialTableColumns = [
    {
      fixed: 'left',
      index: 0,
      key: 'sort',
      dataIndex: 'sort',
      width: 30,
      render: () => <DragHandle />,
    },
    {
      className: `${integrationTestConstants.classes.SAMPLE_CELL}`,
      index: 1,
      key: 'sample',
      title: 'Sample',
      dataIndex: 'name',
      fixed: true,
      render: (text, record, indx) => <SampleNameCell cellInfo={{ text, record, indx }} />,
    },
    {
      index: 2,
      key: 'barcodes',
      title: 'barcodes.tsv',
      dataIndex: 'barcodes',
      render: (tableCellData) => <UploadCell columnId='barcodes' tableCellData={tableCellData} />,
    },
    {
      index: 3,
      key: 'genes',
      title: 'genes.tsv',
      dataIndex: 'genes',
      render: (tableCellData) => <UploadCell columnId='genes' tableCellData={tableCellData} />,
    },
    {
      index: 4,
      key: 'matrix',
      title: 'matrix.mtx',
      dataIndex: 'matrix',
      render: (tableCellData) => <UploadCell columnId='matrix' tableCellData={tableCellData} />,
    },
  ];

  const [tableColumns, setTableColumns] = useState(initialTableColumns);

  useEffect(() => {
    if (activeExperiment.sampleIds.length > 0) {
      // if there are samples - build the table columns
      setSampleNames(new Set(activeExperiment.sampleIds.map((id) => samples[id]?.name.trim())));
      const metadataColumns = activeExperiment.metadataKeys.map(
        (metadataKey) => createInitializedMetadataColumn(metadataKeyToName(metadataKey)),
      ) || [];
      setTableColumns([...initialTableColumns, ...metadataColumns]);
    } else {
      setTableColumns([]);
      setSampleNames(new Set());
    }
  }, [samples, activeExperiment]);

  useConditionalEffect(() => {
    dispatch(loadSamples(activeExperimentId));
  }, [activeExperiment?.sampleIds], { lazy: true });

  const deleteMetadataColumn = (name) => {
    dispatch(deleteMetadataTrack(name, activeExperimentId));
  };

  const createInitializedMetadataColumn = (name) => {
    const key = metadataNameToKey(name);

    return {
      key,
      title: () => (
        <MetadataColumnTitle
          name={name}
          sampleNames={sampleNames}
          setCells={setCells}
          deleteMetadataColumn={deleteMetadataColumn}
          activeExperimentId={activeExperimentId}
        />
      ),
      width: 200,
      dataIndex: key,
      render: (cellValue, record, rowIdx) => (
        <EditableFieldCell
          cellText={cellValue}
          dataIndex={key}
          rowIdx={rowIdx}
          onAfterSubmit={(newValue) => {
            dispatch(updateValueInMetadataTrack(activeExperimentId, record.uuid, key, newValue));
          }}
        />
      ),
    };
  };

  const onMetadataCreate = (name) => {
    dispatch(createMetadataTrack(name, activeExperimentId));
  };

  useImperativeHandle(ref, () => ({

    createMetadataColumn() {
      const key = temporaryMetadataKey(tableColumns);
      const metadataCreateColumn = {
        key,
        fixed: 'right',
        title: () => (
          <MetadataPopover
            existingMetadata={activeExperiment.metadataKeys}
            onCreate={(name) => {
              onMetadataCreate(name);
            }}
            onCancel={() => {
              deleteMetadataColumn(key);
            }}
            message='Provide new metadata track name'
            visible
          >
            <Space>
              New Metadata Track
            </Space>
          </MetadataPopover>
        ),
        width: 200,
      };
      setTableColumns([...tableColumns, metadataCreateColumn]);
    },
  }));

  const MASS_EDIT_ACTIONS = [
    'REPLACE_EMPTY',
    'REPLACE_ALL',
    'CLEAR_ALL',
  ];

  const setCells = (value, metadataKey, actionType) => {
    if (!MASS_EDIT_ACTIONS.includes(actionType)) return;

    const canUpdateCell = (sampleUuid, action) => {
      if (action !== 'REPLACE_EMPTY') return true;

      const isMetadataEmpty = (uuid) => (
        !samples[uuid].metadata[metadataKey]
        || samples[uuid].metadata[metadataKey] === METADATA_DEFAULT_VALUE
      );

      return isMetadataEmpty(sampleUuid);
    };

    activeExperiment.sampleIds.forEach(
      (sampleUuid) => {
        if (canUpdateCell(sampleUuid, actionType)) {
          dispatch(updateValueInMetadataTrack(activeExperimentId, sampleUuid, metadataKey, value));
        }
      },
    );
  };

  useEffect(() => {
    if (activeExperiment.sampleIds.length === 0) {
      setTableData([]);
      return;
    }

    const newData = activeExperiment.sampleIds.map((sampleUuid, idx) => {
      // upload problems sometimes lead to partial updates and incosistent states
      // in this situation it's possible that the sampleUuid does not exist
      // this a temporary fix so that the whole UI doesn't crash preventing the
      // user from removing the dataset or uploading another one.
      const sampleFiles = samples[sampleUuid]?.files || {};

      const barcodesFile = sampleFiles['barcodes.tsv.gz'] ?? { upload: { status: UploadStatus.FILE_NOT_FOUND } };
      const genesFile = sampleFiles['features.tsv.gz'] ?? { upload: { status: UploadStatus.FILE_NOT_FOUND } };
      const matrixFile = sampleFiles['matrix.mtx.gz'] ?? { upload: { status: UploadStatus.FILE_NOT_FOUND } };

      const barcodesData = { sampleUuid, file: barcodesFile };
      const genesData = { sampleUuid, file: genesFile };
      const matrixData = { sampleUuid, file: matrixFile };

      return {
        key: idx,
        name: samples[sampleUuid]?.name || 'UPLOAD ERROR: Please reupload sample',
        uuid: sampleUuid,
        barcodes: barcodesData,
        genes: genesData,
        matrix: matrixData,
        ...samples[sampleUuid]?.metadata,
      };
    });
    setTableData(newData);
  }, [experiments, samples, activeExperimentId]);

  const noDataComponent = (
    <ExampleExperimentsSpace
      introductionText='Start uploading your samples by clicking on Add samples.'
      imageStyle={{ height: 60 }}
    />
  );

  const onSortEnd = async ({ oldIndex, newIndex }) => {
    if (oldIndex !== newIndex) {
      const newData = arrayMoveImmutable(tableData, oldIndex, newIndex).filter((el) => !!el);
      const newSampleOrder = newData.map((sample) => sample.uuid);

      try {
        await dispatch(reorderSamples(activeExperimentId, oldIndex, newIndex, newSampleOrder));
      } catch (e) {
        // If the fetch fails, avoid doing setTableData(newData)
        return;
      }

      setTableData(newData);
    }
  };

  const SortableRow = sortableElement((otherProps) => <tr {...otherProps} className={`${otherProps.className} drag-visible`} />);
  const SortableTable = sortableContainer((otherProps) => <tbody {...otherProps} />);

  const DragContainer = (otherProps) => (
    <SortableTable
      useDragHandle
      disableAutoscroll
      helperClass='row-dragging'
      onSortEnd={onSortEnd}
      {...otherProps}
    />
  );

  const DraggableRow = (otherProps) => {
    const index = tableData.findIndex((x) => x.key === otherProps['data-row-key']);
    return <SortableRow index={index} {...otherProps} />;
  };

  const renderLoader = () => (
    <>
      <Row justify='center'>
        <ClipLoader
          size={50}
          color='#8f0b10'
        />
      </Row>

      <Row justify='center'>
        <Text>
          We&apos;re getting your samples ...
        </Text>
      </Row>
    </>
  );

  const renderSamplesTable = () => (
    <Row>
      <Col>
        <Table
          id='samples-table'
          size='small'
          scroll={{
            x: 'max-content',
          }}
          bordered
          columns={tableColumns}
          dataSource={tableData}
          sticky
          pagination={false}
          locale={{ emptyText: noDataComponent }}
          components={{
            body: {
              wrapper: DragContainer,
              row: DraggableRow,
            },
          }}
        />
      </Col>
    </Row>
  );

  return (
    <>
      {areSamplesLoading ? renderLoader() : renderSamplesTable()}
    </>
  );
})
Example #28
Source File: sidebar.js    From neutron with Mozilla Public License 2.0 4 votes vote down vote up
SortableItem = sortableElement(({ value }) => {
  const { workspace, themeColor, index } = value;
  const {
    accountInfo,
    active,
    disableAudio,
    disableNotifications,
    hibernated,
    id,
    name,
    pictureId,
    preferredIconType,
    transparentBackground,
    preferences,
  } = workspace;

  return (
    <WorkspaceSelector
      active={active}
      id={id}
      key={id}
      name={name}
      accountInfo={accountInfo}
      pictureId={pictureId}
      transparentBackground={transparentBackground}
      preferredIconType={preferredIconType}
      order={index}
      hibernated={hibernated}
      disableAudio={disableAudio}
      disableNotifications={disableNotifications}
      preferences={preferences}
      onClick={() => requestSetActiveWorkspace(id)}
      themeColor={themeColor}
      onContextMenu={(e) => {
        e.preventDefault();

        const template = [
          {
            label: `Reload ${getWorkspaceFriendlyName()}`,
            click: () => requestReloadWorkspace(id),
          },
          {
            label: hibernated ? `Wake Up ${getWorkspaceFriendlyName()}` : `Hibernate ${getWorkspaceFriendlyName()}`,
            click: () => {
              if (hibernated) {
                return requestWakeUpWorkspace(id);
              }
              return requestHibernateWorkspace(id);
            },
            visible: !active,
          },
          { type: 'separator' },
          {
            label: `Clear ${getWorkspaceFriendlyName()}'s Browsing Data`,
            click: () => requestClearWorkspaceBrowsingData(id),
            visible: !getStaticGlobal('shareWorkspaceBrowsingData'),
          },
          {
            type: 'separator',
            visible: !getStaticGlobal('shareWorkspaceBrowsingData'),
          },
          {
            label: `Edit ${getWorkspaceFriendlyName()}`,
            click: () => requestShowWorkspacePreferencesWindow(id),
          },
          {
            label: `Remove ${getWorkspaceFriendlyName()}`,
            click: () => requestRemoveWorkspace(id),
          },
          { type: 'separator' },
          {
            type: 'checkbox',
            checked: !disableNotifications,
            label: 'Notifications',
            click: () => {
              requestSetWorkspace(
                id,
                { disableNotifications: !disableNotifications },
              );
            },
          },
          {
            type: 'checkbox',
            checked: !disableAudio,
            label: 'Sound',
            click: () => {
              requestSetWorkspace(
                id,
                { disableAudio: !disableAudio },
              );
            },
          },
        ];

        const menu = Menu.buildFromTemplate(template);
        menu.popup({
          window: getCurrentWindow(),
        });
      }}
    />
  );
})