react-icons/fi#FiEdit JavaScript Examples

The following examples show how to use react-icons/fi#FiEdit. 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: PackPreview.js    From winstall with GNU General Public License v3.0 5 votes vote down vote up
export default function PackPreview({ pack, hideMeta, showDelete=false, auth, deleted}){
    const [appIcons, setIcons] = useState([]);

    useEffect(() => {
        const appIcons = pack.apps.filter(a => a.icon != "" ).map(a => ({ icon: a.icon, _id: a._id })); 

        setIcons([...appIcons].slice(0, 4));

    }, [])

    const deletePack = async () => {
        if(!auth) return;

        const { response } = await fetchWinstallAPI(`/packs/${pack._id}`, {
            method: "DELETE",
            headers: {
                'Authorization': `${auth.accessToken},${auth.refreshToken}`,
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({ creator: pack.creator })
        });

        if(response && response.msg){
            if(deleted) deleted(pack._id);
            localStorage.removeItem("ownPacks");
        }
    }

    const handleDelete = async (e) => {
        if ('confirm' in window && typeof window.confirm === 'function') {
            if (window.confirm("Are you sure you want to delete this pack?")) {
                deletePack();
            }
        } else {
            deletePack();
        }

    }
    
    return (
        <div className={styles.packCard}>
            <Link href="/packs/[id]" as={`/packs/${pack._id}`} prefetch={false}>
                <a>
                    <header className={`${styles.packIcons} ${appIcons.length <= 2? styles.singleIcon : ""}`} id={pack.accent}>
                        <ul style={{gridTemplateColumns: `repeat(${appIcons.length > 4 ? "4": appIcons.length},1fr)`}}>
                            {
                                appIcons.map((app, index) => <li key={index}><AppIcon icon={app.icon} id={app._id}/></li>)
                            }
                            { appIcons.length === 0 && (
                                <li><FiPackage/></li>
                            )}
                        </ul>
                    </header>
                </a>
            </Link>
            {!hideMeta && (
                <div className={styles.packMeta}>
                    <Link href="/packs/[id]" as={`/packs/${pack._id}`} prefetch={false}><a><h3>{pack.title}</h3></a></Link>
                    <p>{pack.desc}</p>
                    <p className={styles.includes}>Includes {pack.apps.slice(0, 3).map(a => a.name).join(", ")}, and more.</p>
                    <div className="box fBox">
                        <Link href="/packs/[id]" as={`/packs/${pack._id}`} prefetch={false}>
                            <button className="button accent"><FiPackage /> View Pack</button>
                        </Link>

                        { showDelete && (
                            <div className={styles.packEdit}>
                                <Link href={`/packs/edit?id=${pack._id}`} prefetch={false}><button title="Edit Pack" className={`button subtle ${styles.delete}`} ><FiEdit /></button></Link>
                                <button className={`button subtle ${styles.delete}`} title="Delete Pack" onClick={handleDelete}><FiTrash2 /></button>
                            </div>
                        )}
                    </div>
                </div>
            )}
        </div>
    )
}
Example #2
Source File: ContextMenu.js    From sailplane-web with GNU General Public License v3.0 5 votes vote down vote up
ContextMenu = () => {
  return (
    <>
      <Menu id={'menu-id'}>
        <Item
          className={'MenuItem'}
          onClick={(obj) => obj.props.handleDownload()}>
          <FiDownload size={16} style={styles.icon} />
          <span style={{...styles.menuItem}}>Download</span>
        </Item>

        <Item className={'MenuItem'} onClick={(obj) => obj.props.handleEdit()}>
          <FiEdit size={16} style={styles.icon} />
          <span style={{...styles.menuItem}}>Rename</span>
        </Item>

        <Item className={'MenuItem'} onClick={(obj) => obj.props.handleShare()}>
          <FiShare2 size={16} style={styles.icon} />
          <span style={{...styles.menuItem}}>Share</span>
        </Item>

        <Separator />

        <Item
          className={'MenuItem delete'}
          onClick={(obj) => obj.props.handleDelete()}>
          <FiTrash size={16} style={styles.icon} />
          <span style={{...styles.menuItem}}>Delete</span>
        </Item>
      </Menu>
      <Menu id={'menu-id-no-share'}>
        <Item className={'MenuItem'} onClick={(obj) => obj.props.handleDownload()}>
          <FiDownload size={16} style={styles.icon} />
          <span style={{...styles.menuItem}}>Download</span>
        </Item>

        <Item className={'MenuItem'} onClick={(obj) => obj.props.handleEdit()}>
          <FiEdit size={16} style={styles.icon} />
          <span style={{...styles.menuItem}}>Rename</span>
        </Item>

        <Separator />

        <Item className={'MenuItem delete'} onClick={(obj) => obj.props.handleDelete()}>
          <FiTrash size={16} style={styles.icon} />
          <span style={{...styles.menuItem}}>Delete</span>
        </Item>
      </Menu>
    </>
  );
}
Example #3
Source File: index.js    From dashboard-reactjs with MIT License 5 votes vote down vote up
export default function TablesPage() {

    useEffect(() => {
        document.title = 'Tables'
    }, []);

    return (
        <>
            <div className="col-12 title">
                <h1>Tables</h1>
            </div>
            <div className="col-12 px-0">
                <Card className="red">
                    <div className="card-title">
                        <h3>Tables</h3>
                    </div>
                    <div className="card-body">
                        <Table>
                            <thead>
                                <tr>
                                    <th className="col-1">#</th>
                                    <th className="col-8">Name</th>
                                    <th>Actions</th>
                                </tr>
                            </thead>
                            <tbody>
                                {array.map(item => (
                                    <tr>
                                        <td style={{ textAlign: 'center' }}>{ item.id }</td>
                                        <td style={{ textAlign: 'center' }}>{ item.name }</td>
                                        <td style={{ textAlign: 'center' }}>
                                            <button className="edit">
                                                <FiEdit />
                                            </button>
                                            <button className="info">
                                                <FiInfo />
                                            </button>
                                            <button className="eraser">
                                                <FiTrash />
                                            </button>
                                        </td>
                                    </tr>
                                ))}
                            </tbody>
                        </Table>
                    </div>
                </Card>
            </div>
        </>
    );
}
Example #4
Source File: [id].js    From winstall with GNU General Public License v3.0 4 votes vote down vote up
function PackDetail({ pack, creator, error }) {
  const router = useRouter();
  const { selectedApps, setSelectedApps } = useContext(SelectedContext);
  const [user, setUser] = useState();
  const [deleting, setDeleting] = useState(false);
  const [deleteLabel, setDeleteLabel] = useState("Delete Pack");

  useEffect(() => {
    getSession().then(async (session) => {
      if (!session) {
        return;
      }

      setUser(session.user);
    });
  }, []);

  const fallbackMessage = {
    title: "Sorry! We could not load this pack.",
    subtitle: error
      ? `Recieved error: ${error}`
      : "Unfortunately, this pack could not be loaded. Either it does not exist, or something else went wrong. Please try again later.",
  };

  if (!router.isFallback && !pack) {
    return <Error {...fallbackMessage} />;
  }

  const handleSelectAll = () => {
    const updatedList = [...selectedApps, ...pack.apps];

    let uniqueList = [
      ...new Map(updatedList.map((item) => [item["_id"], item])).values(),
    ];

    setSelectedApps(uniqueList);
  };

  const handleShare = () => {
    const link = `https://twitter.com/intent/tweet?text=${encodeURIComponent(
      `Checkout the "${pack.title}" pack by @${creator.screen_name}!`
    )}&url=${encodeURIComponent(
      `https://winstall.app/packs/${pack._id}`
    )}&via=winstallHQ`;

    window.open(link);
  };

  const deletePack = async () => {
    if (!user) return;

    setDeleting(true);
    setDeleteLabel("Deleting...");

    const { response } = await fetchWinstallAPI(`/packs/${pack._id}`, {
      method: "DELETE",
      headers: {
        Authorization: `${user.accessToken},${user.refreshToken}`,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({ creator: pack.creator }),
    });

    if (response && response.msg) {
      setDeleteLabel("Deleted!");
      localStorage.removeItem("ownPacks");
      router.push("/packs");
    }
  };

  const handleDelete = async (e) => {
    if (deleting) return;

    if ("confirm" in window && typeof window.confirm === "function") {
      if (window.confirm("Are you sure you want to delete this pack?")) {
        deletePack();
      }
    } else {
      deletePack();
    }
  };

  return (
    <PageWrapper>
      <div className={styles.content}>
        {router.isFallback ? (
          <AppSkeleton />
        ) : (
          <div>
            <MetaTags
              title={`${pack.title} - winstall`}
              desc={`Includes ${pack.apps[0].name}, ${pack.apps[1].name}, ${pack.apps[2].name}, and more!`}
            />

            <h1>{pack.title}</h1>

            <Link
              href="/users/[id]"
              as={`/users/${creator.id_str}`}
              prefetch={false}
            >
              <a
                className={styles.author}
                title="View other packs by this user"
              >
                <img
                  src={creator.profile_image_url_https}
                  alt="pack creator image"
                />
                @{creator.screen_name}
              </a>
            </Link>

            <p>{pack.desc}</p>
            <p className={styles.time}>
              <FiClock /> Last updated {timeAgo(pack.updatedAt)}{" "}
            </p>

            <div className={styles.packGet}>
              <a
                className="button lightText"
                href="#packScript"
                id={pack.accent}
              >
                <FiCodepen /> Get Pack
              </a>
              <a className="button" onClick={handleSelectAll}>
                <FiPackage /> Select Apps
              </a>
              <a className="button" onClick={handleShare}>
                <FiShare2 /> Share
              </a>
            </div>

            {user && user.id === pack.creator && (
              <div className={styles.packGet}>
                <Link href={`/packs/edit?id=${pack._id}`} prefetch={false}>
                  <a className="button subtle">
                    <FiEdit /> Edit Pack
                  </a>
                </Link>{" "}
                &nbsp;
                <a className="button subtle" onClick={handleDelete}>
                  <FiTrash /> {deleteLabel}
                </a>
              </div>
            )}

            <PackAppsList providedApps={pack.apps} reorderEnabled={false} />

            <ScriptCode apps={pack.apps} />
          </div>
        )}

        {/* <PackAppsList providedApps={packApps} reorderEnabled={false}/> */}
      </div>
    </PageWrapper>
  );
}
Example #5
Source File: FileItem.js    From sailplane-web with GNU General Public License v3.0 4 votes vote down vote up
export function FileItem({
  data,
  sharedFs,
  setCurrentDirectory,
  ipfs,
  isParent,
  snapshot,
  forceIcon,
  onIconClicked,
  readOnly,
}) {
  const {path, type} = data;
  const pathSplit = path.split('/');
  const name = pathSplit[pathSplit.length - 1];
  const mtime = sharedFs && sharedFs.current.fs.read(path)?.mtime;
  const [hoverRef, isHovered] = useHover();
  const [CID, setCID] = useState(null);
  const [fileInfo, setFileInfo] = useState(null);
  const [editMode, setEditMode] = useState(false);
  const [mobileActionsVisible, setMobileActionsVisible] = useState(false);
  const [fileBlob, setFileBlob] = useState(null);
  const [doubleClickRef] = useDoubleClick(() => setEditMode(true));
  const parentPath = pathSplit.slice(0, pathSplit.length - 1).join('/');
  const fileExtension = filenameExt(name);
  const isSmallScreen = useIsSmallScreen();
  const contextID = `menu-id`;
  const contextNoShareID = `menu-id-no-share`;
  const exists = sharedFs && sharedFs.current.fs.exists(path);
  const isTouchDevice = !hasMouse;
  const isUnsharable = sharedFs?.current.encrypted && type === 'dir';
  const hasWrite = sharedFs && doesUserHaveWriteInInstance(sharedFs.current);

  const styles = {
    paddingContainer: {
      paddingTop: 3,
      paddingBottom: 3,
    },
    outer: {
      borderRadius: 4,
      color: primary5,
      fontSize: 14,
      padding: 7,
      marginBottom: 8,
      fontFamily: 'Open Sans',
      userSelect: 'none',
    },
    container: {
      display: 'flex',
      flexDirection: 'row',
      flexWrap: isSmallScreen ? 'wrap' : 'nowrap',
      justifyContent: 'space-between',
      cursor: 'pointer',
    },
    flexItem: {
      width: '100%',
      display: 'flex',
      flexDirection: 'row',
      justifyContent: 'flex-start',
      alignItems: 'center',
      flexGrow: 2,
      marginBottom: isSmallScreen ? 10 : 0,
    },
    icon: {
      marginRight: 4,
      width: 30,
      flexShrink: 0,
    },
    tools: {
      display: isTouchDevice ? 'none' : 'flex',
      justifyContent: 'flex-end',
      width: '100%',
      opacity: (isHovered || fileBlob) && !isParent ? 1 : 0,
      pointerEvents: (isHovered || fileBlob) && !isParent ? null : 'none',
      fontSize: 14,
      marginLeft: 0,
    },
    filename: {
      textAlign: 'left',
      whiteSpace: 'nowrap',
      textOverflow: 'ellipsis',
      overflow: 'hidden',
    },
  };

  const dispatch = useDispatch();

  const InputComponent = useTextInput(
    editMode,
    (editNameValue) => rename(editNameValue),
    () => setEditMode(false),
    name,
    {
      placeholder: '',
    },
  );

  const iconComponent = forceIcon ? forceIcon : getIconForPath(type, name);

  const getCID = async () => {
    let tmpCID;

    if (data.cid) {
      tmpCID = data.cid;
    } else if (exists) {
      tmpCID = await sharedFs.current.read(path);
    }

    const tmpFileInfo = await getFileInfoFromCID(tmpCID, ipfs);

    setFileInfo(tmpFileInfo);
    setCID(tmpCID);
    return tmpCID;
  };

  useEffect(() => {
    if (exists && type !== 'dir') {
      getCID();
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [path]);

  const IconComponent = iconComponent;

  const rename = async (editNameValue) => {
    try {
      dispatch(setStatus({message: 'Renaming file'}));
      await sharedFs.current.move(path, parentPath, editNameValue);
      dispatch(setStatus({}));
    } catch (e) {
      console.log('Error moving!', e);
    }
  };

  async function getBlob() {
    let blob;

    if (!fileBlob) {
      dispatch(setStatus({message: 'Fetching download'}));
      const handleUpdate = (currentIndex, totalCount) => {
        dispatch(
          setStatus({
            message: `[${getPercent(currentIndex, totalCount)}%] Downloading`,
          }),
        );
      };
      blob = await getBlobFromPath(sharedFs.current, path, handleUpdate);
      dispatch(setStatus({}));
    } else {
      blob = fileBlob;
    }
    return blob;
  }

  const saveAsFile = (blob, name) => {
    if (type === 'dir') {
      name = `${name}.zip`;
    }

    saveAs(blob, name);
  };

  const handleShare = () => {
    setMobileActionsVisible(false);

    dispatch(
      setShareData({
        name,
        CID,
        path,
        pathType: type,
      }),
    );
  };

  const handleDownload = async () => {
    setMobileActionsVisible(false);

    const blob = await getBlob();
    saveAsFile(blob, name);
  };

  const handleEdit = async () => {
    setMobileActionsVisible(false);

    setEditMode(true);
  };

  const handleDelete = async () => {
    setMobileActionsVisible(false);

    dispatch(
      setStatus({
        message: `Deleting ${type === 'dir' ? 'folder' : 'file'}`,
      }),
    );
    await sharedFs.current.remove(path);
    dispatch(setStatus({}));
  };

  const fetchPreview = async () => {
    // Only fetch for audio on click now
    if (!fileBlob && isFileExtensionAudio(fileExtension)) {
      dispatch(setStatus({message: 'Fetching preview'}));
      const blob = await getBlob();
      dispatch(setStatus({}));
      setFileBlob(blob);
    } else {
      setFileBlob(null);
    }
  };

  const handleClick = async (event) => {
    event.stopPropagation();

    if (isTouchDevice && type !== 'dir') {
      setMobileActionsVisible(true);

      return;
    }

    if (onIconClicked) {
      onIconClicked();
      return;
    }

    if (editMode) {
      return;
    }

    if (type === 'dir') {
      setCurrentDirectory(path);
    } else {
      await fetchPreview();
    }
  };

  let mobileActionItems = [
    {
      title: 'Download',
      onClick: handleDownload,
      iconComponent: FiDownload,
    },
  ];

  if (hasWrite) {
    mobileActionItems = mobileActionItems.concat([
      {
        title: 'Rename',
        onClick: handleEdit,
        iconComponent: FiEdit,
      },
      {
        title: 'Delete',
        onClick: handleDelete,
        iconComponent: FiTrash,
        forceColor: lightErrorColor,
      },
    ]);
  }

  if (!isUnsharable) {
    mobileActionItems.unshift({
      title: 'Share',
      onClick: handleShare,
      iconComponent: FiShare2,
    });
  }

  if (type === 'dir') {
    mobileActionItems.unshift({
      title: 'Open folder',
      onClick: () => setCurrentDirectory(path),
      iconComponent: FaFolderOpen,
    });
  } else {
    if ((!fileBlob && isFileExtensionAudio(fileExtension)) || onIconClicked) {
      mobileActionItems.unshift({
        title: 'Open preview',
        onClick: () => {
          setMobileActionsVisible(false);

          if (onIconClicked) {
            onIconClicked();
          } else {
            fetchPreview();
          }
        },
        iconComponent: iconComponent,
      });
    }
  }

  const getContent = () => {
    if (!snapshot) {
      snapshot = {};
    }

    return (
      <div
        ref={hoverRef}
        style={styles.paddingContainer}
        className={`fileItem`}>
        <MobileActionsDialog
          isVisible={mobileActionsVisible}
          name={name}
          fileIcon={iconComponent}
          onClose={() => setMobileActionsVisible(false)}
          items={mobileActionItems}
        />
        <div
          onContextMenu={(event) => {
            event.preventDefault();

            contextMenu.show({
              event,
              id: isUnsharable ? contextNoShareID : contextID,
              props: {
                handleDelete,
                handleDownload,
                handleShare,
                handleEdit,
              },
            });
          }}
          style={{
            ...styles.outer,
            backgroundColor:
              (isHovered ||
                fileBlob ||
                snapshot.isDragging ||
                (snapshot.combineTargetFor && type === 'dir')) &&
              !isTouchDevice
                ? primary15
                : '#FFF',
          }}>
          <div style={styles.container} onClick={handleClick}>
            <div
              style={{
                ...styles.flexItem,
                maxWidth: isSmallScreen ? null : '25%',
              }}>
              <IconComponent color={primary45} size={16} style={styles.icon} />
              {editMode ? (
                <>{InputComponent}</>
              ) : isParent ? (
                '. . /'
              ) : (
                <span ref={doubleClickRef} style={styles.filename}>
                  {name}
                </span>
              )}
            </div>
            <div style={{...styles.flexItem, justifyContent: 'flex-end'}}>
              {type !== 'dir' && fileInfo ? humanFileSize(fileInfo.size) : null}
            </div>
            <div style={{...styles.flexItem, justifyContent: 'flex-end'}}>
              {type !== 'dir' && (mtime || fileInfo?.mtime)
                ? getFileTime(mtime?.secs || fileInfo.mtime.secs)
                : null}
            </div>
            <div style={styles.tools}>
              <div>
                <ToolItem
                  id={`Share-${type}`}
                  iconComponent={FiShare2}
                  changeColor={primary}
                  tooltip={
                    isUnsharable ? 'No encrypted folder sharing yet!' : 'Share'
                  }
                  onClick={handleShare}
                  disabled={isUnsharable}
                />

                <ToolItem
                  id={`Download-${type}`}
                  iconComponent={FiDownload}
                  changeColor={primary}
                  tooltip={'Download'}
                  onClick={handleDownload}
                />

                {!readOnly && hasWrite ? (
                  <>
                    <ToolItem
                      id={`Rename-${type}`}
                      iconComponent={FiEdit}
                      changeColor={primary}
                      tooltip={'Rename'}
                      onClick={handleEdit}
                    />
                    <ToolItem
                      id={`Delete-${type}`}
                      iconComponent={FiTrash}
                      tooltip={'Delete'}
                      onClick={handleDelete}
                    />
                  </>
                ) : null}
              </div>
            </div>
          </div>
          {fileBlob ? (
            <div style={styles.preview}>
              <FilePreview blob={fileBlob} filename={name} />
            </div>
          ) : null}
        </div>
      </div>
    );
  };

  return <>{getContent()}</>;
}
Example #6
Source File: Instance.js    From sailplane-web with GNU General Public License v3.0 4 votes vote down vote up
Instance = ({
  data,
  selected,
  onClick,
  onDelete,
  instanceIndex,
  onAccess,
  displayOnly,
}) => {
  const {address, isEncrypted, label} = data;
  const dispatch = useDispatch();
  const [hoverRef, isHovered] = useHover();
  const [mobileActionsVisible, setMobileActionsVisible] = useState(false);
  const [isLabelDialogVisible, setIsLabelDialogVisible] = useState(false);
  const isTouchDevice = !hasMouse;

  let backgroundColor = selected ? primary3 : '#FFF';

  if (isHovered && !selected) {
    backgroundColor = primary15;
  }

  const iconColor = selected ? '#FFF' : primary45;
  const styles = {
    paddingContainer: {
      paddingTop: 3,
      paddingBottom: 3,
    },
    outer: {
      backgroundColor: backgroundColor,
      color: iconColor,
      padding: 6,
      paddingTop: 6,
      fontFamily: 'Open Sans',
      cursor: 'pointer',
      borderRadius: 4,
    },
    container: {
      display: 'flex',
      justifyContent: 'space-between',
      alignItems: 'center',
    },
    address: {
      fontSize: 14,
      overflow: 'hidden',
      width: '40%',
      textOverflow: 'ellipsis',
      whiteSpace: 'nowrap',
    },
    tools: {
      display: displayOnly ? 'none' : 'flex',
      justifyContent: 'flex-end',
    },
    name: {
      fontSize: 16,
      height: 38,
      lineHeight: '19px',
      display: 'flex',
      alignItems: 'center',
    },
    icon: {
      marginRight: 4,
      flexShrink: 0,
    },
    importedTxt: {
      marginLeft: 6,
      fontSize: 13,
    },
    label: {
      fontWeight: 600,
    },
    nameHolder: {
      display: 'flex',
      flexDirection: 'column',
      alignItems: 'flex-start',
      justifyContent: 'center',
      lineHeight: '18px',
      position: 'relative',
      top: label ? -2 : null,
    },
  };

  const handleAddressCopy = async () => {
    await copyToClipboard(address);
    notify('Drive address copied to clipboard', dispatch);
  };

  const mobileActionItems = [
    {
      title: 'Open',
      onClick: () => {
        setMobileActionsVisible(false);
        onClick();
      },
      iconComponent: FiHardDrive,
    },
    {
      title: 'Set nickname',
      onClick: () => {
        setIsLabelDialogVisible(true);
        setMobileActionsVisible(false);
      },
      iconComponent: FiEdit,
    },
    {
      title: 'Manage users',
      onClick: () => {
        onAccess();
        setMobileActionsVisible(false);
      },
      iconComponent: FiUsers,
    },
    {
      title: 'Copy address',
      onClick: () => {
        handleAddressCopy();
        setMobileActionsVisible(false);
      },
      iconComponent: FiCopy,
    },
    {
      title: 'Delete',
      onClick: () => {
        onDelete();
        setMobileActionsVisible(false);
      },
      iconComponent: FiTrash,
      forceColor: lightErrorColor,
    },
  ];

  const thisDriveName = driveName(address);

  return (
    <div style={styles.paddingContainer} ref={hoverRef}>
      <div
        className={'drive'}
        style={styles.outer}
        onClick={(event) => {
          if (mobileActionsVisible) {
            return;
          }

          if (isTouchDevice) {
            setMobileActionsVisible(true);
          } else {
            event.stopPropagation();
            onClick();
          }
        }}>
        <MobileActionsDialog
          isVisible={mobileActionsVisible}
          name={thisDriveName}
          onClose={() => setMobileActionsVisible(false)}
          items={mobileActionItems}
        />
        <div style={styles.container}>
          <div style={styles.name}>
            <FiHardDrive
              className={'shareIcon'}
              color={iconColor}
              size={18}
              style={styles.icon}
            />
            <Pill
              title={isEncrypted ? 'private' : 'public'}
              inverted={selected}
            />
            <div style={styles.nameHolder}>
              {thisDriveName}
              {label ? <div style={styles.label}>[{label}]</div> : null}
            </div>
            {isHovered && !displayOnly && !isTouchDevice ? (
              <ToolItem
                className={'instanceLabel'}
                iconComponent={FiEdit}
                defaultColor={isHovered && selected ? '#FFF' : primary45}
                changeColor={primary}
                tooltip={'Set nickname'}
                onClick={() => setIsLabelDialogVisible(true)}
              />
            ) : null}
          </div>
          {!isTouchDevice ? (
            <div style={styles.tools}>
              <ToolItem
                className={'instanceAccess'}
                defaultColor={iconColor}
                iconComponent={FiUsers}
                size={15}
                changeColor={primary}
                onClick={() => onAccess()}
                tooltip={'Manage users'}
              />
              <ToolItem
                className={'instanceAddressCopy'}
                defaultColor={iconColor}
                iconComponent={FiCopy}
                size={15}
                changeColor={primary}
                tooltip={'Copy'}
                onClick={handleAddressCopy}
              />
              <ToolItem
                className={'instanceDelete'}
                defaultColor={iconColor}
                iconComponent={FiTrash}
                tooltip={'Delete'}
                size={15}
                changeColor={errorColor}
                onClick={() => onDelete()}
              />
            </div>
          ) : null}
        </div>
      </div>
      <LabelDriveDialog
        isVisible={isLabelDialogVisible}
        onClose={() => setIsLabelDialogVisible(false)}
        instance={data}
        instanceIndex={instanceIndex}
      />
    </div>
  );
}
Example #7
Source File: my-services.js    From plataforma-sabia with MIT License 4 votes vote down vote up
MyServices = ({
	initialServices,
	currentSort,
	currentPage,
	initialTotalPages,
	initialTotalItems,
	itemsPerPage,
	sortOptions,
}) => {
	const { t } = useTranslation(['helper', 'account']);
	const router = useRouter();
	const { openModal } = useModal();

	const {
		data: { services = [], totalPages, totalItems },
		isValidating: isValidatingServices,
		revalidate,
		mutate,
	} = useSWR(
		['getUserServices', router.query],
		() => getUserServices({ ...router.query, perPage: itemsPerPage }),
		{
			initialData: {
				services: initialServices,
				totalPages: initialTotalPages,
				totalItems: initialTotalItems,
			},
			revalidateOnFocus: false,
		},
	);

	const {
		data: keywordsOptions = [],
		isValidating: isValidatingKeywords,
		revalidate: revalidateKeywords,
	} = useSWR('getKeywords', () => getTerms({ taxonomy: 'KEYWORDS', embed: 'false' }), {
		revalidateOnFocus: false,
	});

	/**
	 * Pushes new page number to next/router
	 *
	 * @param {string} page Page number.
	 */
	const handlePagination = (page) => {
		const { pathname, query } = router;
		query.page = page;

		router.push({
			pathname,
			query,
		});
	};

	/**
	 * Pushes new sort options to next/router
	 *
	 * @param {string} orderBy Grid column to sort items.
	 * @param {('ASC'|'DESC')} order Sort order.
	 * @returns {Promise<boolean>} Next router push
	 */
	const handleSortBy = (orderBy, order = currentSort.order || orderEnum.ASC) => {
		const { pathname, query } = router;

		const shouldOrderAsc = order === orderEnum.DESC && currentSort.orderBy !== orderBy;
		query.order = shouldOrderAsc ? orderEnum.ASC : order;
		query.orderBy = orderBy;
		query.page = 1;

		return router.push({
			pathname,
			query,
		});
	};

	const handleActive = async (id) => {
		const updatedServices = services.map((service) => {
			if (service.id === id) {
				return { ...service, active: !service.active };
			}

			return service;
		});

		mutate({ services: updatedServices, totalPages, totalItems }, false);
		await updateServiceActiveStatus(id);
		revalidate();
	};

	return (
		<Container>
			<Protected>
				<UserProfile />
				<MainContentContainer>
					<TitleWrapper>
						<Title align="left" noPadding noMargin>
							{t('account:titles.myServices')}
						</Title>
						{(!!isValidatingServices || !!isValidatingKeywords) && (
							<Spinner noPadding />
						)}
					</TitleWrapper>

					{services.length ? (
						<MainContent>
							<InfoContainer>
								<Link href={internalPages.newService}>
									<AddButton>
										<span>{t('account:labels.addServices')}</span>
										<FiPlus />
									</AddButton>
								</Link>
								<Stats>
									{t('account:labels.registeredServices', {
										count: services.length,
									})}
								</Stats>
							</InfoContainer>
							<DataGrid
								data={services.map(
									({
										id,
										name,
										thumbnail,
										keywords,
										description,
										measure_unit,
										price,
										type,
										active,
									}) => ({
										id,
										Título: name,
										Tipo: getTypeLabel(type),
										Ativo: (
											<Actions>
												<SwitchField
													value={!!active}
													checked={!!active}
													name={`active-${id}`}
													onChange={() => handleActive(id)}
												/>
											</Actions>
										),
										Ações: (
											<Actions>
												<IconButton
													variant="info"
													aria-label="Edit Service"
													onClick={() =>
														openModal(
															'editService',
															{
																id,
																name,
																thumbnail,
																keywords: keywords.map(
																	(item) => item.id,
																),
																description,
																measure_unit,
																price: formatMoney(price),
																type,
																revalidateServices: revalidate,
																revalidateKeywords,
																// We need this dirty fix until SelectField has a pagination option
																// So the actual service keywords appears in edit select
																keywordsOptions: [
																	...keywordsOptions,
																	...(!!keywords.length &&
																		keywords.map((item) => ({
																			id: item.id,
																			term: item.term,
																		}))),
																],
															},
															{
																hideCloseModalIcon: true,
																overlayClick: false,
															},
														)
													}
												>
													<FiEdit />
												</IconButton>
											</Actions>
										),
									}),
								)}
								handlePagination={handlePagination}
								handleSortBy={handleSortBy}
								currentPage={currentPage}
								currentOrder={currentSort.order}
								totalPages={totalPages}
								totalItems={totalItems}
								itemsPerPage={itemsPerPage}
								sortOptions={sortOptions}
							/>
						</MainContent>
					) : (
						<EmptyScreen message={t('account:messages.noServicesToShow')} />
					)}
				</MainContentContainer>
			</Protected>
		</Container>
	);
}
Example #8
Source File: technologies.js    From plataforma-sabia with MIT License 4 votes vote down vote up
MyTechnologies = ({ initialTechnologies, user }) => {
	const { t } = useTranslation(['helper', 'account']);

	const { data: technologies = [], revalidate, mutate } = useSWR(
		['getUserTechnologies', user.id],
		(_, id) => getUserTechnologies(id),
		{
			initialData: initialTechnologies,
		},
	);

	const handleActive = async (id) => {
		const updatedTechnologies = technologies.map((technology) => {
			if (technology.id === id) {
				return { ...technology, active: !technology.active };
			}

			return technology;
		});

		mutate(updatedTechnologies, false);
		await updateTechnologyActiveStatus(id);
		revalidate();
	};

	const handleEditClick = useCallback(
		(id) => window.open(internalPages.editTechnology.replace(':id', id), '_ blank'),
		[],
	);

	return (
		<Container>
			<Protected>
				<UserProfile />
				<MainContentContainer>
					<Title align="left" noPadding noMargin>
						{t('account:titles.myTechnologies')}
					</Title>

					{technologies.length > 0 ? (
						<MainContent>
							<InfoContainer>
								<Link href={internalPages.newTechnology}>
									<AddButton>
										<span>{t('account:labels.addTechnologies')}</span>
										<FiPlus />
									</AddButton>
								</Link>
								<Stats>
									{t('account:labels.registeredTechnologies', {
										count: technologies.length,
									})}
								</Stats>
							</InfoContainer>
							<DataGrid
								data={technologies.map(
									({ id, title, status, installation_time, active }) => ({
										id,
										Título: title,
										Status: (
											<TechnologyStatus status={status}>
												{getTechnologyStatus(status)}
											</TechnologyStatus>
										),
										'Tempo de implantação': getPeriod(t, installation_time),
										Ativa: (
											<Actions>
												<SwitchField
													value={!!active}
													checked={!!active}
													name={`active-${id}`}
													onClick={() => handleActive(id)}
												/>
											</Actions>
										),
										Ações: (
											<Actions>
												<IconButton
													variant="info"
													aria-label="Edit Technology"
													onClick={() => handleEditClick(id)}
												>
													<FiEdit />
												</IconButton>
											</Actions>
										),
									}),
								)}
							/>
						</MainContent>
					) : (
						<EmptyScreen message={t('account:messages.noTechnologyToShow')} />
					)}
				</MainContentContainer>
			</Protected>
		</Container>
	);
}