Web:Client:FilesSelector: add socket for create, update or delete file or folder inside tab

This commit is contained in:
Timofey Boyko 2023-08-17 15:42:08 +03:00
parent 10c18125eb
commit e5a4e57774
5 changed files with 289 additions and 9 deletions

View File

@ -41,6 +41,22 @@ export type useLoadersHelperProps = {
items: Item[] | null;
};
export type setItemsCallback = (value: Item[] | null) => Item[] | null;
export type setBreadCrumbsCallback = (
value: BreadCrumb[] | []
) => BreadCrumb[] | [];
export type setTotalCallback = (value: number) => number;
export type useSocketHelperProps = {
socketHelper: any;
socketSubscribersId: Set<string>;
setItems: (callback: setItemsCallback) => void;
setBreadCrumbs: (callback: setBreadCrumbsCallback) => void;
setTotal: (callback: setTotalCallback) => void;
disabledItems: string[] | number[];
filterParam?: string;
};
export type useRootHelperProps = {
setBreadCrumbs: (items: BreadCrumb[]) => void;
setIsBreadCrumbsLoading: (value: boolean) => void;
@ -153,4 +169,7 @@ export type FilesSelectorProps = {
setSelectedItems: () => void;
includeFolder?: boolean;
socketHelper: any;
socketSubscribersId: Set<string>;
};

View File

@ -171,7 +171,7 @@ const getIconUrl = (extension: string, isImage: boolean, isMedia: boolean) => {
return iconSize32.get(path);
};
const convertFoldersToItems = (
export const convertFoldersToItems = (
folders: any,
disabledItems: any[],
filterParam?: string
@ -215,9 +215,17 @@ const convertFoldersToItems = (
return items;
};
const convertFilesToItems = (files: any, filterParam?: string) => {
export const convertFilesToItems = (files: any, filterParam?: string) => {
const items = files.map((file: any) => {
const { id, title, security, parentId, rootFolderType, fileExst } = file;
const {
id,
title,
security,
parentId,
folderId,
rootFolderType,
fileExst,
} = file;
const isImage = file.viewAccessability.ImageView;
const isMedia = file.viewAccessability.MediaView;
@ -231,9 +239,8 @@ const convertFilesToItems = (files: any, filterParam?: string) => {
label: title.replace(fileExst, ""),
title,
icon,
security,
parentId,
parentId: parentId || folderId,
rootFolderType,
isFolder: false,
isDisabled: !filterParam,

View File

@ -0,0 +1,220 @@
import React from "react";
import { convertFilesToItems, convertFoldersToItems } from "./useFilesHelper";
import {
Item,
setItemsCallback,
useSocketHelperProps,
} from "../FilesSelector.types";
const useSocketHelper = ({
socketHelper,
socketSubscribersId,
setItems,
setBreadCrumbs,
setTotal,
disabledItems,
filterParam,
}: useSocketHelperProps) => {
const subscribedId = React.useRef<null | number>(null);
const subscribe = (id: number) => {
const roomParts = `DIR-${id}`;
if (socketSubscribersId.has(roomParts)) return (subscribedId.current = id);
if (subscribedId.current && !socketSubscribersId.has(roomParts)) {
unsubscribe(subscribedId.current, false);
}
socketHelper.emit({
command: "subscribe",
data: {
roomParts: `DIR-${id}`,
individual: true,
},
});
subscribedId.current = id;
};
const unsubscribe = (id: number, clear = true) => {
if (clear) {
subscribedId.current = null;
}
if (id && !socketSubscribersId.has(`DIR-${id}`)) {
socketHelper.emit({
command: "unsubscribe",
data: {
roomParts: `DIR-${id}`,
individual: true,
},
});
}
};
const addItem = React.useCallback((opt: any) => {
if (!opt?.data) return;
const data = JSON.parse(opt.data);
if (
data.folderId
? data.folderId !== subscribedId.current
: data.parentId !== subscribedId.current
)
return;
let item: null | Item = null;
if (opt?.type === "file") {
item = convertFilesToItems([data], filterParam)[0];
} else if (opt?.type === "folder") {
item = convertFoldersToItems([data], disabledItems, filterParam)[0];
}
const callback: setItemsCallback = (value: Item[] | null) => {
if (!item || !value) return value;
if (opt.type === "folder") {
setTotal((value) => value + 1);
return [item, ...value];
}
if (opt.type === "file") {
let idx = 0;
for (let i = 0; i < value.length - 1; i++) {
if (!value[i].isFolder) break;
idx = i + 1;
}
const newValue = [...value];
newValue.splice(idx, 0, item);
setTotal((value) => value + 1);
return newValue;
}
return value;
};
setItems(callback);
}, []);
const updateItem = React.useCallback((opt: any) => {
if (!opt?.data) return;
const data = JSON.parse(opt.data);
if (
data.folderId
? data.folderId !== subscribedId.current
: data.parentId !== subscribedId.current
)
return;
let item: null | Item = null;
if (opt?.type === "file") {
item = convertFilesToItems([data], filterParam)[0];
} else if (opt?.type === "folder") {
item = convertFoldersToItems([data], disabledItems, filterParam)[0];
}
const callback: setItemsCallback = (value: Item[] | null) => {
if (!item || !value) return value;
if (opt.type === "folder") {
const idx = value.findIndex((v) => v.id === item?.id && v.isFolder);
if (idx > -1) {
const newValue = [...value];
newValue.splice(idx, 1, item);
return newValue;
}
setBreadCrumbs((breadCrumbsValue) => {
if (breadCrumbsValue[breadCrumbsValue.length - 1].id === item?.id) {
breadCrumbsValue[breadCrumbsValue.length - 1].label = item.label;
}
return breadCrumbsValue;
});
}
if (opt.type === "file") {
const idx = value.findIndex((v) => v.id === item?.id && !v.isFolder);
if (idx > -1) {
const newValue = [...value];
newValue.splice(idx, 1, item);
return [...newValue];
}
}
return value;
};
setItems(callback);
}, []);
const deleteItem = React.useCallback((opt: any) => {
const callback: setItemsCallback = (value: Item[] | null) => {
if (!value) return value;
if (opt.type === "folder") {
const newValue = value.filter((v) => +v.id !== +opt?.id || !v.isFolder);
if (newValue.length !== value.length) {
setTotal((value) => value - 1);
}
return newValue;
}
if (opt.type === "file") {
const newValue = value.filter((v) => +v.id !== +opt?.id || v.isFolder);
if (newValue.length !== value.length) {
setTotal((value) => value - 1);
}
return newValue;
}
return value;
};
setItems(callback);
}, []);
React.useEffect(() => {
socketHelper.on("s:modify-folder", async (opt: any) => {
switch (opt?.cmd) {
case "create":
addItem(opt);
break;
case "update":
updateItem(opt);
break;
case "delete":
deleteItem(opt);
break;
}
});
}, [addItem, updateItem, deleteItem]);
return { subscribe, unsubscribe };
};
export default useSocketHelper;

View File

@ -29,6 +29,7 @@ import useRoomsHelper from "./helpers/useRoomsHelper";
import useLoadersHelper from "./helpers/useLoadersHelper";
import useFilesHelper from "./helpers/useFilesHelper";
import { getAcceptButtonLabel, getHeaderLabel, getIsDisabled } from "./utils";
import useSocketHelper from "./helpers/useSocketHelper";
const FilesSelector = ({
isPanelVisible = false,
@ -84,6 +85,9 @@ const FilesSelector = ({
setSelectedItems,
includeFolder,
socketHelper,
socketSubscribersId,
}: FilesSelectorProps) => {
const { t } = useTranslation(["Files", "Common", "Translations"]);
@ -114,6 +118,16 @@ const FilesSelector = ({
const [isRequestRunning, setIsRequestRunning] =
React.useState<boolean>(false);
const { subscribe, unsubscribe } = useSocketHelper({
socketHelper,
socketSubscribersId,
setItems,
setBreadCrumbs,
setTotal,
disabledItems,
filterParam,
});
const {
setIsBreadCrumbsLoading,
isNextPageLoading,
@ -194,6 +208,13 @@ const FilesSelector = ({
}
};
React.useEffect(() => {
if (!selectedItemId) return;
if (selectedItemId && isRoot) return unsubscribe(+selectedItemId);
subscribe(+selectedItemId);
}, [selectedItemId, isRoot]);
React.useEffect(() => {
if (!withoutBasicSelection) {
onSelectFolder && onSelectFolder(currentFolderId);
@ -514,7 +535,12 @@ export default inject(
}: any,
{ isCopy, isRestoreAll, isMove, isPanelVisible, id, passedFoldersTree }: any
) => {
const { id: selectedId, parentId, rootFolderType } = selectedFolderStore;
const {
id: selectedId,
parentId,
rootFolderType,
socketSubscribersId,
} = selectedFolderStore;
const { setConflictDialogData, checkFileConflicts, setSelectedItems } =
filesActionsStore;
@ -550,10 +576,15 @@ export default inject(
setIsFolderActions,
} = dialogsStore;
const { theme } = auth.settingsStore;
const { theme, socketHelper } = auth.settingsStore;
const { selection, bufferSelection, filesList, setMovingInProgress } =
filesStore;
const {
selection,
bufferSelection,
filesList,
setMovingInProgress,
} = filesStore;
const selections =
isMove || isCopy || isRestoreAll
@ -608,6 +639,8 @@ export default inject(
setIsFolderActions,
setSelectedItems,
includeFolder,
socketHelper,
socketSubscribersId,
};
}
)(observer(FilesSelector));

View File

@ -22,6 +22,7 @@ const compareFunction = (prevProps: ItemProps, nextProps: ItemProps) => {
return (
prevItem?.id === nextItem?.id &&
prevItem?.label === nextItem?.label &&
prevItem?.isSelected === nextItem?.isSelected
);
};