export function FileListItem()

in frontend/apps/quantgrid/src/app/components/Dashboard/DashboardFileList/FileListItem.tsx [43:326]


export function FileListItem({ item }: Props) {
  const { setLoading } = useContext(AppContext);
  const { userBucket } = useContext(ApiContext);
  const [isHovered, setIsHovered] = useState(false);
  const [isSelected, setIsSelected] = useState(false);
  const {
    currentTab,
    folderPath,
    searchValue,
    selectedItems,
    setSelectedItems,
  } = useContext(DashboardContext);
  const {
    createProject: createProjectRequest,
    getDimensionalSchema: getDimensionalSchemaRequest,
  } = useApiRequests();
  const { getDimensionalTableFromFormula } = useManualCreateEntityDSL();
  const navigate = useNavigate();

  const isProject = useMemo(
    () => item.name.endsWith(dialProjectFileExtension),
    [item]
  );

  const isCSV = useMemo(() => item.name.endsWith(csvFileExtension), [item]);

  const isSimplifiedColumns =
    currentTab === 'recent' || (currentTab === 'sharedByMe' && !folderPath);

  const isSearchColumns = searchValue !== '';

  const isFolder = useMemo(() => item.nodeType === 'FOLDER', [item]);

  const isSharedWithMe = useMemo(
    () => item.bucket !== userBucket,
    [item.bucket, userBucket]
  );

  const itemLink = useMemo(() => {
    return isProject
      ? getProjectNavigateUrl({
          projectName: item.name.replaceAll(dialProjectFileExtension, ''),
          projectBucket: item.bucket,
          projectPath: item.parentPath,
        })
      : isFolder
      ? getDashboardNavigateUrl({
          folderPath: `${item.parentPath ? item.parentPath + '/' : ''}${
            item.name
          }`,
          folderBucket: item.bucket,
          tab: currentTab!,
        })
      : '';
  }, [
    currentTab,
    isFolder,
    isProject,
    item.bucket,
    item.name,
    item.parentPath,
  ]);

  const itemIcon = useMemo(() => {
    if (isFolder) {
      return <FolderIcon />;
    }

    if (isCSV) {
      return (
        <Icon
          className="text-textAccentSecondary"
          component={() => <CSVFileIcon />}
        ></Icon>
      );
    }

    if (isProject) {
      return <QGLogo />;
    }

    return <FileIcon />;
  }, [isFolder, isCSV, isProject]);

  const Tag = isFolder || isProject ? Link : 'div';

  const onSelectItem = useCallback(
    (e: CheckboxChangeEvent) => {
      if (isSelected) {
        setSelectedItems(selectedItems.filter((i) => i !== item));
      } else {
        setSelectedItems([...selectedItems, item]);
      }
    },
    [isSelected, item, selectedItems, setSelectedItems]
  );

  const handleItemClick = useCallback(async () => {
    // Ignore not csv file clicks
    if (!isCSV || !userBucket) return;

    setLoading(true);
    const formula = `INPUT("${encodeApiUrl(
      constructPath(['files', item.bucket, item.parentPath, item.name])
    )}")`;

    const dimensionalSchema = await getDimensionalSchemaRequest({
      formula,
      worksheets: {},
    });

    if (!dimensionalSchema) {
      setLoading(false);

      return;
    }

    const { dimTable } = getDimensionalTableFromFormula(
      'Table1',
      [],
      true,
      '',
      formula,
      dimensionalSchema.dimensionalSchemaResponse.schema,
      dimensionalSchema.dimensionalSchemaResponse.keys,
      1,
      1
    );

    const projectName = item.name.replaceAll(csvFileExtension, '');
    const projectPath = constructPath([
      projectFoldersRootPrefix,
      csvTempFolder,
      item.parentPath,
    ]);

    const res = await createProjectRequest({
      bucket: userBucket,
      path: projectPath,
      projectName,
      initialProjectData: {
        [defaultSheetName]: dimTable,
      },
      forceCreation: true,
    });

    if (!res) {
      setLoading(false);

      return;
    }

    setLoading(false);

    navigate(
      getProjectNavigateUrl({
        projectName,
        projectBucket: userBucket,
        projectPath,
        projectSheetName: defaultSheetName,
      })
    );
  }, [
    createProjectRequest,
    getDimensionalSchemaRequest,
    getDimensionalTableFromFormula,
    isCSV,
    item.bucket,
    item.name,
    item.parentPath,
    navigate,
    setLoading,
    userBucket,
  ]);

  useEffect(() => {
    setIsSelected(selectedItems.includes(item));
  }, [item, selectedItems]);

  return (
    <div className="relative flex flex-col group" data-file-name={item.name}>
      <FileListItemMenu
        className="flex flex-col"
        isFolder={isFolder}
        item={item}
        trigger={'contextMenu'}
      >
        <Tag
          className={cx('flex py-3 border-b border-b-strokeTertiary', {
            'cursor-pointer': isProject || isFolder || isCSV,
            'bg-bgAccentPrimaryAlpha': isHovered || isSelected,
          })}
          to={itemLink}
          onClick={handleItemClick}
          onMouseLeave={() => setIsHovered(false)}
          onMouseOver={() => setIsHovered(true)}
        >
          <div className="flex grow items-center overflow-x-hidden">
            <div className="flex items-center min-w-[60%] pl-4 pr-2 gap-4 overflow-hidden text-ellipsis">
              <div className="text-lg stroke-textSecondary flex items-center justify-center relative">
                {!isFolder && (isHovered || isSelected) ? (
                  <Checkbox
                    checked={isSelected}
                    className="w-[18px] h-[18px]"
                    rootClassName="dial-xl-checkbox"
                    onChange={onSelectItem}
                    onClick={(e) => e.stopPropagation()}
                  />
                ) : (
                  <>
                    <Icon
                      className={cx('w-[18px]', {
                        'stroke-textSecondary text-textSecondary': !isProject,
                        'stroke-transparent text-transparent': isProject,
                      })}
                      component={() => itemIcon}
                    ></Icon>
                    {item.isSharedByMe && (
                      <span className="p-[2px] absolute bottom-0 left-[-1px] flex items-center justify-center bg-bgLayer3 rounded-tr">
                        <Icon
                          className="w-[7px] text-textAccentSecondary"
                          component={() => <ArrowUpRightIcon />}
                        ></Icon>
                      </span>
                    )}
                  </>
                )}
              </div>

              <span
                className="text-textPrimary text-sm select-none overflow-hidden text-ellipsis text-nowrap"
                title={getDisplayName(item.name)}
              >
                {getDisplayName(item.name)}
              </span>
            </div>
            {(isSimplifiedColumns || isSearchColumns) && (
              <div className="min-w-[20%] pr-2 overflow-hidden text-ellipsis whitespace-nowrap">
                <span
                  className="text-textSecondary text-sm select-none"
                  title={
                    isSharedWithMe
                      ? 'Shared with me'
                      : `Home${item.parentPath ? '/' + item.parentPath : ''}`
                  }
                >
                  {isSharedWithMe
                    ? 'Shared with me'
                    : `Home${item.parentPath ? '/' + item.parentPath : ''}`}
                </span>
              </div>
            )}
            <div className="min-w-[20%] pr-2">
              <span className="text-textSecondary text-sm select-none">
                {item.nodeType === 'ITEM' && item.updatedAt
                  ? getFormattedFullDate(item.updatedAt)
                  : '-'}
              </span>
            </div>
            {!isSimplifiedColumns && !isSearchColumns && (
              <div className="min-w-[20%] pr-2">
                <span className="text-textSecondary text-sm select-none">
                  {item.contentLength ? formatBytes(item.contentLength) : '-'}
                </span>
              </div>
            )}
          </div>
          <div className="w-6"></div>
        </Tag>
      </FileListItemMenu>
      <FileListItemMenu
        className="absolute top-4 right-0 w-6 flex items-center justify-center pr-4 cursor-pointer mr-4 stroke-transparent group-hover:stroke-textSecondary group-hover:hover:stroke-textAccentPrimary"
        isFolder={isFolder}
        item={item}
        trigger={'click'}
      >
        <Icon
          component={() => <DotsIcon />}
          onClick={(e) => e.stopPropagation()}
        />
      </FileListItemMenu>
    </div>
  );
}