@edifice.io/react 2.5.15 → 2.5.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/AddAttachments/AddAttachments.d.ts +6 -3
- package/dist/components/AddAttachments/AddAttachments.js +17 -29
- package/dist/components/AddAttachments/hooks/useFileToAttachment.d.ts +3 -0
- package/dist/components/AddAttachments/hooks/useFileToAttachment.js +16 -0
- package/dist/components/AddAttachments/models/attachment.d.ts +1 -0
- package/dist/components/Tree/components/SortableTree.js +4 -3
- package/dist/components/Tree/components/Tree.js +4 -3
- package/dist/components/UserRightsList/SaveBookmark.d.ts +5 -0
- package/dist/components/UserRightsList/SaveBookmark.js +29 -0
- package/dist/components/UserRightsList/UserRightsBookmarkRow.d.ts +11 -0
- package/dist/components/UserRightsList/UserRightsBookmarkRow.js +30 -0
- package/dist/components/UserRightsList/UserRightsItem.d.ts +13 -0
- package/dist/components/UserRightsList/UserRightsItem.js +36 -0
- package/dist/components/UserRightsList/UserRightsList.d.ts +19 -0
- package/dist/components/UserRightsList/UserRightsList.js +94 -0
- package/dist/components/UserRightsList/helpers/rightsHelpers.d.ts +9 -0
- package/dist/components/UserRightsList/helpers/rightsHelpers.js +53 -0
- package/dist/components/UserRightsList/hooks/useBookmarkEntries.d.ts +19 -0
- package/dist/components/UserRightsList/hooks/useBookmarkEntries.js +58 -0
- package/dist/components/UserRightsList/hooks/useSharingItems.d.ts +20 -0
- package/dist/components/UserRightsList/hooks/useSharingItems.js +57 -0
- package/dist/components/UserRightsList/index.d.ts +2 -0
- package/dist/components/UserRightsList/types/types.d.ts +34 -0
- package/dist/components/UserRightsList/types/types.js +6 -0
- package/dist/components/UserSearch/UserSearch.d.ts +7 -0
- package/dist/components/UserSearch/UserSearch.js +82 -0
- package/dist/components/UserSearch/index.d.ts +3 -0
- package/dist/components/UserSearch/types/types.d.ts +24 -0
- package/dist/components/UserSearch/types/visible.d.ts +24 -0
- package/dist/components/UserSearch/types/visible.js +4 -0
- package/dist/components/index.d.ts +2 -0
- package/dist/hooks/useDirectory/useDirectory.d.ts +3 -2
- package/dist/hooks/useDropzone/useDropzone.js +4 -4
- package/dist/icons.js +364 -332
- package/dist/index.js +10 -0
- package/dist/modules/editor/components/EditorToolbar/EditorToolbar.js +1 -1
- package/dist/modules/icons/components/IconBulle.d.ts +7 -0
- package/dist/modules/icons/components/IconBulle.js +16 -0
- package/dist/modules/icons/components/IconBulleError.d.ts +7 -0
- package/dist/modules/icons/components/IconBulleError.js +13 -0
- package/dist/modules/icons/components/IconBulleSuccess.d.ts +7 -0
- package/dist/modules/icons/components/IconBulleSuccess.js +13 -0
- package/dist/modules/icons/components/IconLsuArt.d.ts +7 -0
- package/dist/modules/icons/components/IconLsuArt.js +13 -0
- package/dist/modules/icons/components/IconLsuCompetenceNumerique.d.ts +7 -0
- package/dist/modules/icons/components/IconLsuCompetenceNumerique.js +12 -0
- package/dist/modules/icons/components/IconLsuEmc.d.ts +7 -0
- package/dist/modules/icons/components/IconLsuEmc.js +13 -0
- package/dist/modules/icons/components/IconLsuFrancais.d.ts +7 -0
- package/dist/modules/icons/components/IconLsuFrancais.js +13 -0
- package/dist/modules/icons/components/IconLsuHistoireGeo.d.ts +7 -0
- package/dist/modules/icons/components/IconLsuHistoireGeo.js +12 -0
- package/dist/modules/icons/components/IconLsuLangue.d.ts +7 -0
- package/dist/modules/icons/components/IconLsuLangue.js +16 -0
- package/dist/modules/icons/components/IconLsuLangue2.d.ts +7 -0
- package/dist/modules/icons/components/IconLsuLangue2.js +13 -0
- package/dist/modules/icons/components/IconLsuMath.d.ts +7 -0
- package/dist/modules/icons/components/IconLsuMath.js +16 -0
- package/dist/modules/icons/components/IconLsuParcoursEducatif.d.ts +7 -0
- package/dist/modules/icons/components/IconLsuParcoursEducatif.js +12 -0
- package/dist/modules/icons/components/IconLsuSport.d.ts +7 -0
- package/dist/modules/icons/components/IconLsuSport.js +12 -0
- package/dist/modules/icons/components/IconLsuSvt.d.ts +7 -0
- package/dist/modules/icons/components/IconLsuSvt.js +12 -0
- package/dist/modules/icons/components/IconParcoursCitoyen.d.ts +7 -0
- package/dist/modules/icons/components/IconParcoursCitoyen.js +14 -0
- package/dist/modules/icons/components/IconParcoursSecours.d.ts +7 -0
- package/dist/modules/icons/components/IconParcoursSecours.js +14 -0
- package/dist/modules/icons/components/index.d.ts +16 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/sharing.d.ts +8 -0
- package/dist/utilities/index.d.ts +1 -0
- package/dist/utilities/rotate-transition-style/get-rotate-transition-style.d.ts +5 -0
- package/dist/utilities/rotate-transition-style/get-rotate-transition-style.js +12 -0
- package/dist/utilities/rotate-transition-style/index.d.ts +1 -0
- package/package.json +7 -7
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { Attachment } from './models/attachment';
|
|
2
|
+
export type SingleAttachmentType = Attachment;
|
|
3
|
+
export { useFileToAttachment } from './hooks/useFileToAttachment';
|
|
2
4
|
export interface AddAttachmentsProps {
|
|
3
5
|
attachments: Attachment[];
|
|
4
|
-
|
|
5
|
-
|
|
6
|
+
onChange?: (attachments: Attachment[]) => void;
|
|
7
|
+
onFilesSelected?: (files: File[]) => void;
|
|
8
|
+
onRemoveAttachment?: (attachmentId: string) => void;
|
|
6
9
|
editMode?: boolean;
|
|
7
10
|
isMutating?: boolean;
|
|
8
11
|
onCopyToWorkspace?: (attachments: Attachment[], folderId: string) => Promise<boolean>;
|
|
@@ -12,7 +15,7 @@ export interface AddAttachmentsProps {
|
|
|
12
15
|
downloadAllUrl?: string;
|
|
13
16
|
}
|
|
14
17
|
export declare const AddAttachments: {
|
|
15
|
-
({ attachments, onFilesSelected, onRemoveAttachment, editMode, isMutating, onCopyToWorkspace, getDownloadUrl, downloadAllUrl, }: AddAttachmentsProps): import("react/jsx-runtime").JSX.Element | null;
|
|
18
|
+
({ attachments, onChange, onFilesSelected, onRemoveAttachment, editMode, isMutating, onCopyToWorkspace, getDownloadUrl, downloadAllUrl, }: AddAttachmentsProps): import("react/jsx-runtime").JSX.Element | null;
|
|
16
19
|
displayName: string;
|
|
17
20
|
};
|
|
18
21
|
export default AddAttachments;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsxs, Fragment, jsx } from "react/jsx-runtime";
|
|
2
2
|
import clsx from "clsx";
|
|
3
|
-
import { useRef, useState
|
|
3
|
+
import { useRef, useState } from "react";
|
|
4
4
|
import { useTranslation } from "react-i18next";
|
|
5
5
|
import SvgIconDelete from "../../modules/icons/components/IconDelete.js";
|
|
6
6
|
import SvgIconDownload from "../../modules/icons/components/IconDownload.js";
|
|
@@ -8,22 +8,13 @@ import SvgIconFolderAdd from "../../modules/icons/components/IconFolderAdd.js";
|
|
|
8
8
|
import SvgIconPlus from "../../modules/icons/components/IconPlus.js";
|
|
9
9
|
import { AddAttachmentToWorkspaceModal } from "./components/AddAttachmentToWorkspaceModal.js";
|
|
10
10
|
import { SingleAttachment } from "./components/SingleAttachment.js";
|
|
11
|
+
import { useFileToAttachment } from "./hooks/useFileToAttachment.js";
|
|
11
12
|
import Flex from "../Flex/Flex.js";
|
|
12
13
|
import IconButton from "../Button/IconButton.js";
|
|
13
14
|
import Button from "../Button/Button.js";
|
|
14
|
-
function fileToAttachment(file) {
|
|
15
|
-
return {
|
|
16
|
-
id: `${file.name}-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`,
|
|
17
|
-
charset: "UTF-8",
|
|
18
|
-
contentTransferEncoding: "binary",
|
|
19
|
-
contentType: file.type || "application/octet-stream",
|
|
20
|
-
filename: file.name,
|
|
21
|
-
name: file.name,
|
|
22
|
-
size: file.size
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
15
|
const AddAttachments = ({
|
|
26
16
|
attachments,
|
|
17
|
+
onChange,
|
|
27
18
|
onFilesSelected,
|
|
28
19
|
onRemoveAttachment,
|
|
29
20
|
editMode = !1,
|
|
@@ -34,10 +25,8 @@ const AddAttachments = ({
|
|
|
34
25
|
}) => {
|
|
35
26
|
const {
|
|
36
27
|
t
|
|
37
|
-
} = useTranslation(), inputRef = useRef(null),
|
|
38
|
-
if (
|
|
39
|
-
attachments.length > prevAttachmentsLengthRef.current && setOptimisticAttachments([]), prevAttachmentsLengthRef.current = attachments.length;
|
|
40
|
-
}, [attachments.length]), !editMode && !displayedAttachments.length) return null;
|
|
28
|
+
} = useTranslation(), inputRef = useRef(null), fileToAttachment = useFileToAttachment(), [attachmentsToAddToWorkspace, setAttachmentsToAddToWorkspace] = useState(void 0);
|
|
29
|
+
if (!editMode && !attachments.length) return null;
|
|
41
30
|
const resetInputValue = () => {
|
|
42
31
|
inputRef.current && (inputRef.current.value = "");
|
|
43
32
|
}, handleAttachClick = () => {
|
|
@@ -46,36 +35,34 @@ const AddAttachments = ({
|
|
|
46
35
|
}, handleFileChange = (event) => {
|
|
47
36
|
const files = Array.from(event.target.files ?? []);
|
|
48
37
|
if (files.length > 0) {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
setOptimisticAttachments((prev) => [...prev, ...newOptimistic]);
|
|
38
|
+
const newAttachments = files.map(fileToAttachment);
|
|
39
|
+
onChange == null || onChange([...attachments, ...newAttachments]), onFilesSelected == null || onFilesSelected(files);
|
|
52
40
|
}
|
|
53
41
|
resetInputValue();
|
|
54
42
|
}, handleDetachAllClick = () => {
|
|
55
|
-
|
|
56
|
-
onRemoveAttachment(attachment.id);
|
|
57
|
-
}), resetInputValue();
|
|
43
|
+
onChange == null || onChange([]), attachments.forEach((a) => onRemoveAttachment == null ? void 0 : onRemoveAttachment(a.id)), resetInputValue();
|
|
58
44
|
}, handleDetachClick = (attachmentId) => {
|
|
59
|
-
|
|
45
|
+
const next = attachments.filter((a) => a.id !== attachmentId);
|
|
46
|
+
onChange == null || onChange(next), onRemoveAttachment == null || onRemoveAttachment(attachmentId), resetInputValue();
|
|
60
47
|
}, handleCopyToWorkspace = (attachments2) => {
|
|
61
48
|
setAttachmentsToAddToWorkspace(attachments2);
|
|
62
49
|
}, className = clsx("bg-gray-200 rounded px-12 py-8 message-attachments align-self-start gap-8 d-flex flex-column mw-100", {
|
|
63
50
|
"border add-attachments-edit mx-16": editMode
|
|
64
51
|
});
|
|
65
52
|
return /* @__PURE__ */ jsxs("div", { className, "data-drag-handle": !0, children: [
|
|
66
|
-
!!
|
|
53
|
+
!!attachments.length && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
67
54
|
/* @__PURE__ */ jsxs(Flex, { direction: "row", align: "center", justify: "between", className: "border-bottom", children: [
|
|
68
55
|
/* @__PURE__ */ jsx("span", { className: "caption fw-bold my-8", children: t("attachments") }),
|
|
69
|
-
|
|
70
|
-
onCopyToWorkspace && /* @__PURE__ */ jsx(IconButton, { title: t("conversation.copy.all.toworkspace"), color: "tertiary", type: "button", icon: /* @__PURE__ */ jsx(SvgIconFolderAdd, {}), onClick: () => handleCopyToWorkspace(
|
|
56
|
+
attachments.length > 1 && /* @__PURE__ */ jsxs("div", { children: [
|
|
57
|
+
onCopyToWorkspace && /* @__PURE__ */ jsx(IconButton, { title: t("conversation.copy.all.toworkspace"), color: "tertiary", type: "button", icon: /* @__PURE__ */ jsx(SvgIconFolderAdd, {}), onClick: () => handleCopyToWorkspace(attachments), variant: "ghost" }),
|
|
71
58
|
downloadAllUrl && /* @__PURE__ */ jsx("a", { href: downloadAllUrl, download: !0, children: /* @__PURE__ */ jsx(IconButton, { title: t("download.all.attachment"), color: "tertiary", type: "button", icon: /* @__PURE__ */ jsx(SvgIconDownload, {}), variant: "ghost" }) }),
|
|
72
59
|
editMode && /* @__PURE__ */ jsx(IconButton, { title: t("remove.all.attachment"), color: "danger", type: "button", icon: /* @__PURE__ */ jsx(SvgIconDelete, {}), variant: "ghost", onClick: handleDetachAllClick, disabled: isMutating })
|
|
73
60
|
] })
|
|
74
61
|
] }),
|
|
75
|
-
/* @__PURE__ */ jsx("ul", { className: "d-flex gap-8 flex-column list-unstyled m-0", children:
|
|
62
|
+
/* @__PURE__ */ jsx("ul", { className: "d-flex gap-8 flex-column list-unstyled m-0", children: attachments.map((attachment) => /* @__PURE__ */ jsx("li", { className: "mw-100", children: /* @__PURE__ */ jsx(SingleAttachment, { attachment, editMode, onDelete: handleDetachClick, onCopyToWorkspace: onCopyToWorkspace ? (attachment2) => handleCopyToWorkspace([attachment2]) : void 0, getDownloadUrl, disabled: isMutating }) }, `${attachment.id}-${attachment.name}`)) })
|
|
76
63
|
] }),
|
|
77
64
|
editMode && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
78
|
-
/* @__PURE__ */ jsx(Button, { color: "secondary", variant: "ghost", isLoading: isMutating, onClick: handleAttachClick, disabled: isMutating, className: "align-self-start", leftIcon: /* @__PURE__ */ jsx(SvgIconPlus, {}), children: t("add.attachment") }),
|
|
65
|
+
/* @__PURE__ */ jsx(Button, { color: "secondary", variant: "ghost", isLoading: isMutating, onClick: handleAttachClick, disabled: isMutating, className: "align-self-start", leftIcon: /* @__PURE__ */ jsx(SvgIconPlus, {}), "data-testid": "common-add-attachments-button-add-attachment", children: t("add.attachment") }),
|
|
79
66
|
/* @__PURE__ */ jsx("input", { ref: inputRef, multiple: !0, type: "file", name: "attachment-input", id: "attachment-input", onChange: handleFileChange, hidden: !0 })
|
|
80
67
|
] }),
|
|
81
68
|
onCopyToWorkspace && !!attachmentsToAddToWorkspace && /* @__PURE__ */ jsx(AddAttachmentToWorkspaceModal, { isOpen: !0, onModalClose: () => setAttachmentsToAddToWorkspace(void 0), attachments: attachmentsToAddToWorkspace, onCopyToWorkspace })
|
|
@@ -83,5 +70,6 @@ const AddAttachments = ({
|
|
|
83
70
|
};
|
|
84
71
|
export {
|
|
85
72
|
AddAttachments,
|
|
86
|
-
AddAttachments as default
|
|
73
|
+
AddAttachments as default,
|
|
74
|
+
useFileToAttachment
|
|
87
75
|
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { useCallback } from "react";
|
|
2
|
+
function useFileToAttachment() {
|
|
3
|
+
return useCallback((file) => ({
|
|
4
|
+
id: `${file.name}-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`,
|
|
5
|
+
charset: "UTF-8",
|
|
6
|
+
contentTransferEncoding: "binary",
|
|
7
|
+
contentType: file.type || "application/octet-stream",
|
|
8
|
+
filename: file.name,
|
|
9
|
+
name: file.name,
|
|
10
|
+
size: file.size,
|
|
11
|
+
file
|
|
12
|
+
}), []);
|
|
13
|
+
}
|
|
14
|
+
export {
|
|
15
|
+
useFileToAttachment
|
|
16
|
+
};
|
|
@@ -11,6 +11,7 @@ import SvgIconRafterRight from "../../../modules/icons/components/IconRafterRigh
|
|
|
11
11
|
import { useTree } from "../hooks/useTree.js";
|
|
12
12
|
import { useTreeSortable } from "../hooks/useTreeSortable.js";
|
|
13
13
|
import { flattenNodes } from "../utilities/tree-sortable.js";
|
|
14
|
+
import { getRotateTransitionStyle } from "../../../utilities/rotate-transition-style/get-rotate-transition-style.js";
|
|
14
15
|
import { mergeRefs } from "../../../utilities/refs/ref.js";
|
|
15
16
|
const SortableTree = ({
|
|
16
17
|
nodes,
|
|
@@ -113,9 +114,9 @@ const SortableTree = ({
|
|
|
113
114
|
...style,
|
|
114
115
|
marginLeft: spaceGestion()
|
|
115
116
|
}, ...listeners, children: /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsxs("div", { className: treeItemClasses.action, children: [
|
|
116
|
-
node.haveChilds && /* @__PURE__ */ jsx("div", { tabIndex: 0, role: "button", onClick: () => onToggleNode == null ? void 0 : onToggleNode(node.id), onKeyDown: handleItemToggleKeyDown, "aria-label": t("foldUnfold"), children: /* @__PURE__ */ jsx(SvgIconRafterRight, { width: 16, style: {
|
|
117
|
-
|
|
118
|
-
} }) }),
|
|
117
|
+
node.haveChilds && /* @__PURE__ */ jsx("div", { tabIndex: 0, role: "button", onClick: () => onToggleNode == null ? void 0 : onToggleNode(node.id), onKeyDown: handleItemToggleKeyDown, "aria-label": t("foldUnfold"), children: /* @__PURE__ */ jsx(SvgIconRafterRight, { width: 16, style: getRotateTransitionStyle(expanded, {
|
|
118
|
+
degrees: 90
|
|
119
|
+
}) }) }),
|
|
119
120
|
node.children && showIcon ? /* @__PURE__ */ jsx(SvgIconFolder, { title: "folder", width: 20, height: 20 }) : null,
|
|
120
121
|
/* @__PURE__ */ jsx("div", { tabIndex: 0, role: "button", className: treeItemClasses.button, onClick: () => onTreeItemClick(node.id), onKeyDown: handleItemKeyDown, children: renderNode ? renderNode({
|
|
121
122
|
node,
|
|
@@ -5,6 +5,7 @@ import { useTranslation } from "react-i18next";
|
|
|
5
5
|
import SvgIconFolder from "../../../modules/icons/components/IconFolder.js";
|
|
6
6
|
import SvgIconRafterRight from "../../../modules/icons/components/IconRafterRight.js";
|
|
7
7
|
import { useTree } from "../hooks/useTree.js";
|
|
8
|
+
import { getRotateTransitionStyle } from "../../../utilities/rotate-transition-style/get-rotate-transition-style.js";
|
|
8
9
|
const Tree = ({
|
|
9
10
|
nodes,
|
|
10
11
|
selectedNodeId: externalSelectedNodeId,
|
|
@@ -66,9 +67,9 @@ const Tree = ({
|
|
|
66
67
|
};
|
|
67
68
|
return /* @__PURE__ */ createElement("li", { ...restProps, ref, key: node.id, id: `treeitem-${node.id}`, role: "treeitem", "aria-selected": selected, "aria-expanded": expanded }, /* @__PURE__ */ jsxs("div", { children: [
|
|
68
69
|
/* @__PURE__ */ jsxs("div", { className: treeItemClasses.action, children: [
|
|
69
|
-
node.children && node.children.length > 0 ? /* @__PURE__ */ jsx("div", { className: treeItemClasses.arrow, tabIndex: 0, role: "button", onClick: () => onToggleNode == null ? void 0 : onToggleNode(node.id), onKeyDown: handleItemToggleKeyDown, "aria-label": t("foldUnfold"), children: /* @__PURE__ */ jsx(SvgIconRafterRight, { width: 16, style: {
|
|
70
|
-
|
|
71
|
-
} }) }) : /* @__PURE__ */ jsx("div", { className: "py-8 invisible" }),
|
|
70
|
+
node.children && node.children.length > 0 ? /* @__PURE__ */ jsx("div", { className: treeItemClasses.arrow, tabIndex: 0, role: "button", onClick: () => onToggleNode == null ? void 0 : onToggleNode(node.id), onKeyDown: handleItemToggleKeyDown, "aria-label": t("foldUnfold"), children: /* @__PURE__ */ jsx(SvgIconRafterRight, { width: 16, style: getRotateTransitionStyle(expanded, {
|
|
71
|
+
degrees: 90
|
|
72
|
+
}) }) }) : /* @__PURE__ */ jsx("div", { className: "py-8 invisible" }),
|
|
72
73
|
node.children && showIcon ? /* @__PURE__ */ jsx(SvgIconFolder, { title: "folder", width: 20, height: 20 }) : null,
|
|
73
74
|
/* @__PURE__ */ jsx("div", { tabIndex: 0, role: "button", className: treeItemClasses.button, onClick: () => onTreeItemClick(node.id), onKeyDown: handleItemKeyDown, children: renderNode ? renderNode({
|
|
74
75
|
node,
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from "react";
|
|
3
|
+
import { useTranslation } from "react-i18next";
|
|
4
|
+
import SvgIconSave from "../../modules/icons/components/IconSave.js";
|
|
5
|
+
import FormControl from "../Form/FormControl.js";
|
|
6
|
+
import Button from "../Button/Button.js";
|
|
7
|
+
const SaveBookmark = ({
|
|
8
|
+
onSave
|
|
9
|
+
}) => {
|
|
10
|
+
const [bookmarkName, setBookmarkName] = useState(""), [isSaving, setIsSaving] = useState(!1), {
|
|
11
|
+
t
|
|
12
|
+
} = useTranslation(), handleBookmarkNameChange = (e) => {
|
|
13
|
+
setBookmarkName(e.target.value);
|
|
14
|
+
}, handleSaveClick = async () => {
|
|
15
|
+
setIsSaving(!0);
|
|
16
|
+
try {
|
|
17
|
+
await onSave(bookmarkName), setBookmarkName("");
|
|
18
|
+
} finally {
|
|
19
|
+
setIsSaving(!1);
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
return /* @__PURE__ */ jsx("div", { className: "mt-16", children: /* @__PURE__ */ jsxs(FormControl, { id: "bookmarkName", className: "d-flex flex-wrap align-items-center gap-16", children: [
|
|
23
|
+
/* @__PURE__ */ jsx("div", { className: "flex-fill", children: /* @__PURE__ */ jsx(FormControl.Input, { "data-testid": "common-save-bookmark-name-input", value: bookmarkName, onChange: handleBookmarkNameChange, placeholder: t("explorer.modal.share.sharebookmark.placeholder"), size: "sm", type: "text" }) }),
|
|
24
|
+
/* @__PURE__ */ jsx(Button, { "data-testid": "common-save-bookmark-save-button", color: "primary", variant: "ghost", disabled: bookmarkName.length === 0 || isSaving, leftIcon: /* @__PURE__ */ jsx(SvgIconSave, {}), onClick: handleSaveClick, className: "text-nowrap", isLoading: isSaving, children: t("explorer.modal.share.sharebookmark.save") })
|
|
25
|
+
] }) });
|
|
26
|
+
};
|
|
27
|
+
export {
|
|
28
|
+
SaveBookmark
|
|
29
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { BookmarkState, ResourceRightName, ResourceRights } from './types/types';
|
|
2
|
+
interface UserRightsBookmarkRowProps {
|
|
3
|
+
bookmark: BookmarkState;
|
|
4
|
+
resourceRights: ResourceRights;
|
|
5
|
+
isReadOnly: boolean;
|
|
6
|
+
onToggleRight: (bookmarkId: string, rightName: ResourceRightName) => void;
|
|
7
|
+
onDelete: (bookmarkId: string) => void;
|
|
8
|
+
onToggleExpand: (bookmarkId: string) => void;
|
|
9
|
+
}
|
|
10
|
+
declare const UserRightsBookmarkRow: ({ bookmark, resourceRights, isReadOnly, onToggleRight, onDelete, onToggleExpand, }: UserRightsBookmarkRowProps) => import("react/jsx-runtime").JSX.Element;
|
|
11
|
+
export default UserRightsBookmarkRow;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useTranslation } from "react-i18next";
|
|
3
|
+
import SvgIconBookmark from "../../modules/icons/components/IconBookmark.js";
|
|
4
|
+
import SvgIconClose from "../../modules/icons/components/IconClose.js";
|
|
5
|
+
import SvgIconRafterDown from "../../modules/icons/components/IconRafterDown.js";
|
|
6
|
+
import Button from "../Button/Button.js";
|
|
7
|
+
import Checkbox from "../Checkbox/Checkbox.js";
|
|
8
|
+
import IconButton from "../Button/IconButton.js";
|
|
9
|
+
import { getRotateTransitionStyle } from "../../utilities/rotate-transition-style/get-rotate-transition-style.js";
|
|
10
|
+
const UserRightsBookmarkRow = ({
|
|
11
|
+
bookmark,
|
|
12
|
+
resourceRights,
|
|
13
|
+
isReadOnly,
|
|
14
|
+
onToggleRight,
|
|
15
|
+
onDelete,
|
|
16
|
+
onToggleExpand
|
|
17
|
+
}) => {
|
|
18
|
+
const {
|
|
19
|
+
t
|
|
20
|
+
} = useTranslation();
|
|
21
|
+
return /* @__PURE__ */ jsxs("tr", { "data-testid": "user-rights-list-bookmark-row", children: [
|
|
22
|
+
/* @__PURE__ */ jsx("td", { children: /* @__PURE__ */ jsx(SvgIconBookmark, {}) }),
|
|
23
|
+
/* @__PURE__ */ jsx("td", { children: /* @__PURE__ */ jsx(Button, { color: "tertiary", variant: "ghost", className: "fw-normal ps-0", "aria-expanded": bookmark.isExpanded, rightIcon: /* @__PURE__ */ jsx(SvgIconRafterDown, { title: bookmark.isExpanded ? t("hide") : t("show"), className: "w-16 min-w-0", style: getRotateTransitionStyle(bookmark.isExpanded) }), onClick: () => onToggleExpand(bookmark.id), children: bookmark.name }) }),
|
|
24
|
+
Object.entries(resourceRights).map(([rightName]) => /* @__PURE__ */ jsx("td", { children: /* @__PURE__ */ jsx(Checkbox, { checked: bookmark.permission.includes(rightName), onChange: () => onToggleRight(bookmark.id, rightName), disabled: isReadOnly, "aria-label": `${bookmark.name} - ${rightName}`, "data-testid": `user-rights-list-bookmark-${rightName}-checkbox` }) }, rightName)),
|
|
25
|
+
/* @__PURE__ */ jsx("td", { children: !isReadOnly && /* @__PURE__ */ jsx(IconButton, { "data-testid": "user-rights-list-bookmark-close-button", color: "tertiary", onClick: () => onDelete(bookmark.id), icon: /* @__PURE__ */ jsx(SvgIconClose, {}), title: `${t("close")} ${bookmark.name}`, variant: "ghost" }) })
|
|
26
|
+
] });
|
|
27
|
+
};
|
|
28
|
+
export {
|
|
29
|
+
UserRightsBookmarkRow as default
|
|
30
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { ResourceRightName, ResourceRights, SharingItem } from './types/types';
|
|
2
|
+
interface UserRightsItemProps {
|
|
3
|
+
item: SharingItem;
|
|
4
|
+
resourceRights: ResourceRights;
|
|
5
|
+
isReadOnly: boolean;
|
|
6
|
+
isDeletable?: boolean;
|
|
7
|
+
rowClassName?: string;
|
|
8
|
+
bookmarkName?: string;
|
|
9
|
+
onChange?: (item: SharingItem, rightName: ResourceRightName) => void;
|
|
10
|
+
onDeleteItem?: (item: SharingItem) => void;
|
|
11
|
+
}
|
|
12
|
+
declare const UserRightsItem: ({ item, resourceRights, isReadOnly, isDeletable, rowClassName, bookmarkName, onChange, onDeleteItem, }: UserRightsItemProps) => import("react/jsx-runtime").JSX.Element;
|
|
13
|
+
export default UserRightsItem;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useTranslation } from "react-i18next";
|
|
3
|
+
import SvgIconClose from "../../modules/icons/components/IconClose.js";
|
|
4
|
+
import useDirectory from "../../hooks/useDirectory/useDirectory.js";
|
|
5
|
+
import Avatar from "../Avatar/Avatar.js";
|
|
6
|
+
import Checkbox from "../Checkbox/Checkbox.js";
|
|
7
|
+
import IconButton from "../Button/IconButton.js";
|
|
8
|
+
const UserRightsItem = ({
|
|
9
|
+
item,
|
|
10
|
+
resourceRights,
|
|
11
|
+
isReadOnly,
|
|
12
|
+
isDeletable = !0,
|
|
13
|
+
rowClassName,
|
|
14
|
+
bookmarkName,
|
|
15
|
+
onChange,
|
|
16
|
+
onDeleteItem
|
|
17
|
+
}) => {
|
|
18
|
+
const {
|
|
19
|
+
getAvatarURL
|
|
20
|
+
} = useDirectory(), {
|
|
21
|
+
t
|
|
22
|
+
} = useTranslation(), handleChange = (rightName) => {
|
|
23
|
+
onChange == null || onChange(item, rightName);
|
|
24
|
+
}, handleDeleteItem = () => {
|
|
25
|
+
onDeleteItem == null || onDeleteItem(item);
|
|
26
|
+
};
|
|
27
|
+
return /* @__PURE__ */ jsxs("tr", { "data-testid": "user-rights-list-item-row", className: rowClassName, "aria-label": bookmarkName ? `${item.displayName} - ${bookmarkName}` : void 0, children: [
|
|
28
|
+
/* @__PURE__ */ jsx("td", { children: /* @__PURE__ */ jsx(Avatar, { src: getAvatarURL(item.recipientId, item.recipientType), size: "xs", alt: item.displayName, variant: "circle" }) }),
|
|
29
|
+
/* @__PURE__ */ jsx("td", { children: item.displayName }),
|
|
30
|
+
Object.entries(resourceRights).map(([rightName]) => /* @__PURE__ */ jsx("td", { "data-testid": `user-rights-list-item-${rightName}-checkbox`, children: /* @__PURE__ */ jsx(Checkbox, { checked: item.permission.includes(rightName), onChange: () => handleChange(rightName), disabled: isReadOnly, "aria-label": `${item.displayName} - ${rightName}` }) }, rightName)),
|
|
31
|
+
/* @__PURE__ */ jsx("td", { children: !isReadOnly && isDeletable && /* @__PURE__ */ jsx(IconButton, { "data-testid": "user-rights-list-close-button", color: "tertiary", onClick: () => handleDeleteItem(), icon: /* @__PURE__ */ jsx(SvgIconClose, {}), title: `${t("close")} ${item.displayName}`, variant: "ghost", type: "button" }) })
|
|
32
|
+
] });
|
|
33
|
+
};
|
|
34
|
+
export {
|
|
35
|
+
UserRightsItem as default
|
|
36
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { SharingItem } from '../../types';
|
|
2
|
+
import { BookmarkInput, ResourceRights } from './types/types';
|
|
3
|
+
interface UserRightsListProps {
|
|
4
|
+
resourceRights: ResourceRights;
|
|
5
|
+
isReadOnly: boolean;
|
|
6
|
+
isLoading: boolean;
|
|
7
|
+
ownerId: string;
|
|
8
|
+
isCreating: boolean;
|
|
9
|
+
initialSharings?: SharingItem[];
|
|
10
|
+
onChange: (value: SharingItem[]) => void;
|
|
11
|
+
onAddItems: (value: SharingItem[]) => void;
|
|
12
|
+
onDeleteItems: (value: SharingItem[]) => void;
|
|
13
|
+
onSaveBookmark?: (bookmarkName: string, items: SharingItem[]) => Promise<void>;
|
|
14
|
+
}
|
|
15
|
+
export interface UserRightsListRef {
|
|
16
|
+
addItem: (item: SharingItem | BookmarkInput) => void;
|
|
17
|
+
}
|
|
18
|
+
export declare const UserRightsList: import('react').ForwardRefExoticComponent<UserRightsListProps & import('react').RefAttributes<UserRightsListRef>>;
|
|
19
|
+
export {};
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef, useState, useRef, useMemo, useImperativeHandle, Fragment as Fragment$1 } from "react";
|
|
3
|
+
import { useTranslation } from "react-i18next";
|
|
4
|
+
import SvgIconBookmark from "../../modules/icons/components/IconBookmark.js";
|
|
5
|
+
import SvgIconRafterDown from "../../modules/icons/components/IconRafterDown.js";
|
|
6
|
+
import { createRightsHelpers } from "./helpers/rightsHelpers.js";
|
|
7
|
+
import { useBookmarkEntries } from "./hooks/useBookmarkEntries.js";
|
|
8
|
+
import { useSharingItems } from "./hooks/useSharingItems.js";
|
|
9
|
+
import { SaveBookmark } from "./SaveBookmark.js";
|
|
10
|
+
import { isBookmarkInput } from "./types/types.js";
|
|
11
|
+
import UserRightsBookmarkRow from "./UserRightsBookmarkRow.js";
|
|
12
|
+
import UserRightsItem from "./UserRightsItem.js";
|
|
13
|
+
import { useEdificeClient } from "../../providers/EdificeClientProvider/EdificeClientProvider.hook.js";
|
|
14
|
+
import LoadingScreen from "../LoadingScreen/LoadingScreen.js";
|
|
15
|
+
import VisuallyHidden from "../VisuallyHidden/VisuallyHidden.js";
|
|
16
|
+
import Button from "../Button/Button.js";
|
|
17
|
+
import { getRotateTransitionStyle } from "../../utilities/rotate-transition-style/get-rotate-transition-style.js";
|
|
18
|
+
const UserRightsList = /* @__PURE__ */ forwardRef(({
|
|
19
|
+
resourceRights,
|
|
20
|
+
isReadOnly = !0,
|
|
21
|
+
isLoading = !1,
|
|
22
|
+
ownerId,
|
|
23
|
+
isCreating = !1,
|
|
24
|
+
initialSharings = [],
|
|
25
|
+
onChange,
|
|
26
|
+
onAddItems,
|
|
27
|
+
onDeleteItems,
|
|
28
|
+
onSaveBookmark
|
|
29
|
+
}, ref) => {
|
|
30
|
+
const [showBookmarkInput, setBookmarkInput] = useState(!1), tableRef = useRef(null), {
|
|
31
|
+
t
|
|
32
|
+
} = useTranslation(), {
|
|
33
|
+
user
|
|
34
|
+
} = useEdificeClient(), {
|
|
35
|
+
applyRight,
|
|
36
|
+
toggleRight,
|
|
37
|
+
getOwnerItem
|
|
38
|
+
} = useMemo(() => createRightsHelpers(resourceRights), [resourceRights]), ownerItem = getOwnerItem(ownerId, user, isCreating), sharingItems = useSharingItems({
|
|
39
|
+
initialSharings,
|
|
40
|
+
toggleRight,
|
|
41
|
+
applyRight,
|
|
42
|
+
onChange,
|
|
43
|
+
onAddItems,
|
|
44
|
+
onDeleteItems
|
|
45
|
+
}), itemsByRecipientId = useMemo(() => new Map(sharingItems.items.map((item) => [item.recipientId, item])), [sharingItems.items]), existingRecipientIds = useMemo(() => new Set(itemsByRecipientId.keys()), [itemsByRecipientId]), bookmarks = useBookmarkEntries({
|
|
46
|
+
resourceRights,
|
|
47
|
+
existingRecipientIds,
|
|
48
|
+
toggleRight,
|
|
49
|
+
addItems: sharingItems.addItems,
|
|
50
|
+
deleteItemsByIds: sharingItems.deleteItemsByIds,
|
|
51
|
+
applyRightToIds: sharingItems.applyRightToIds
|
|
52
|
+
}), regularItems = useMemo(() => sharingItems.items.filter((item) => !bookmarks.bookmarkUserIds.has(item.recipientId)), [sharingItems.items, bookmarks.bookmarkUserIds]), focusTable = () => {
|
|
53
|
+
var _a;
|
|
54
|
+
(_a = tableRef.current) == null || _a.focus();
|
|
55
|
+
}, handleAddItem = (item) => {
|
|
56
|
+
isBookmarkInput(item) ? bookmarks.addBookmark(item) : sharingItems.addItem(item);
|
|
57
|
+
}, handleDeleteItem = (item) => {
|
|
58
|
+
sharingItems.deleteItem(item), focusTable();
|
|
59
|
+
}, handleDeleteBookmark = (bookmarkId) => {
|
|
60
|
+
bookmarks.deleteBookmark(bookmarkId), focusTable();
|
|
61
|
+
}, handleOnSaveBookmark = (bookmarkName) => onSaveBookmark ? onSaveBookmark(bookmarkName, sharingItems.items) : Promise.resolve(), toggleBookmarkInput = () => {
|
|
62
|
+
setBookmarkInput((prev) => !prev);
|
|
63
|
+
};
|
|
64
|
+
return useImperativeHandle(ref, () => ({
|
|
65
|
+
addItem: handleAddItem
|
|
66
|
+
})), /* @__PURE__ */ jsx("div", { className: "user-rights-list", children: isLoading ? /* @__PURE__ */ jsx(LoadingScreen, {}) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
67
|
+
/* @__PURE__ */ jsx("div", { className: "table-responsive", children: /* @__PURE__ */ jsxs("table", { ref: tableRef, tabIndex: -1, className: "table border align-middle", children: [
|
|
68
|
+
/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [
|
|
69
|
+
/* @__PURE__ */ jsx("th", { scope: "col", className: "w-32", children: /* @__PURE__ */ jsx(VisuallyHidden, { children: t("explorer.modal.share.avatar.shared.alt") }) }),
|
|
70
|
+
/* @__PURE__ */ jsx("th", { scope: "col", children: /* @__PURE__ */ jsx(VisuallyHidden, { children: t("explorer.modal.share.search.placeholder") }) }),
|
|
71
|
+
Object.entries(resourceRights).map(([rightName]) => /* @__PURE__ */ jsx("th", { children: rightName }, rightName)),
|
|
72
|
+
!isReadOnly && /* @__PURE__ */ jsx("th", { scope: "col", children: /* @__PURE__ */ jsx(VisuallyHidden, { children: t("close") }) })
|
|
73
|
+
] }) }),
|
|
74
|
+
/* @__PURE__ */ jsxs("tbody", { children: [
|
|
75
|
+
/* @__PURE__ */ jsx(UserRightsItem, { item: ownerItem, resourceRights, isReadOnly: !0 }, ownerItem == null ? void 0 : ownerItem.recipientId),
|
|
76
|
+
bookmarks.bookmarkEntries.map((bookmark) => /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
77
|
+
/* @__PURE__ */ jsx(UserRightsBookmarkRow, { bookmark, resourceRights, isReadOnly, onToggleRight: bookmarks.toggleBookmarkRight, onDelete: handleDeleteBookmark, onToggleExpand: bookmarks.toggleExpand }),
|
|
78
|
+
bookmark.isExpanded && bookmark.userIds.map((userId) => {
|
|
79
|
+
const item = itemsByRecipientId.get(userId);
|
|
80
|
+
return item ? /* @__PURE__ */ jsx(UserRightsItem, { item, resourceRights, isReadOnly, isDeletable: !1, rowClassName: "bg-light", bookmarkName: bookmark.name, onChange: sharingItems.changeRight }, item.recipientId) : null;
|
|
81
|
+
})
|
|
82
|
+
] }, bookmark.id)),
|
|
83
|
+
regularItems.map((item) => /* @__PURE__ */ jsx(UserRightsItem, { item, resourceRights, isReadOnly: isReadOnly || (ownerItem == null ? void 0 : ownerItem.recipientId) === item.recipientId, onChange: sharingItems.changeRight, onDeleteItem: handleDeleteItem }, item.recipientId))
|
|
84
|
+
] })
|
|
85
|
+
] }) }),
|
|
86
|
+
onSaveBookmark && /* @__PURE__ */ jsxs("div", { className: "mt-16", children: [
|
|
87
|
+
/* @__PURE__ */ jsx(Button, { "data-testid": "common-user-rights-list-share-bookmark-show-button", color: "tertiary", leftIcon: /* @__PURE__ */ jsx(SvgIconBookmark, {}), rightIcon: /* @__PURE__ */ jsx(SvgIconRafterDown, { title: t("show"), className: "w-16 min-w-0", style: getRotateTransitionStyle(showBookmarkInput) }), type: "button", variant: "ghost", className: "fw-normal", onClick: () => toggleBookmarkInput(), children: t("share.save.sharebookmark") }),
|
|
88
|
+
showBookmarkInput && /* @__PURE__ */ jsx(SaveBookmark, { onSave: handleOnSaveBookmark })
|
|
89
|
+
] })
|
|
90
|
+
] }) });
|
|
91
|
+
});
|
|
92
|
+
export {
|
|
93
|
+
UserRightsList
|
|
94
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { IUserInfo } from '@edifice.io/client';
|
|
2
|
+
import { SharingItem } from '../../../types';
|
|
3
|
+
import { ResourceRightName, ResourceRights } from '../types/types';
|
|
4
|
+
export declare const createRightsHelpers: (resourceRights: ResourceRights) => {
|
|
5
|
+
applyRight: (item: SharingItem, rightName: ResourceRightName, add: boolean) => SharingItem;
|
|
6
|
+
toggleRight: (item: SharingItem, rightName: ResourceRightName) => SharingItem;
|
|
7
|
+
createOwnerItem: (user: IUserInfo) => SharingItem;
|
|
8
|
+
getOwnerItem: (ownerId: string, user: IUserInfo | undefined, isCreating: boolean) => SharingItem;
|
|
9
|
+
};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
const createRightsHelpers = (resourceRights) => {
|
|
2
|
+
const getOwnerItem = (ownerId, user, isCreating) => {
|
|
3
|
+
if (!ownerId && user && isCreating || user && ownerId === user.userId)
|
|
4
|
+
return createOwnerItem(user);
|
|
5
|
+
if (!ownerId)
|
|
6
|
+
throw new Error("Owner ID or user is required");
|
|
7
|
+
return {
|
|
8
|
+
recipientId: ownerId,
|
|
9
|
+
recipientType: "user",
|
|
10
|
+
displayName: "owner",
|
|
11
|
+
permission: Object.keys(resourceRights)
|
|
12
|
+
};
|
|
13
|
+
}, createOwnerItem = (user) => ({
|
|
14
|
+
recipientId: user.userId ?? "",
|
|
15
|
+
recipientType: "user",
|
|
16
|
+
displayName: user.username,
|
|
17
|
+
permission: Object.keys(resourceRights)
|
|
18
|
+
}), applyRight = (item, rightName, add) => {
|
|
19
|
+
const {
|
|
20
|
+
requires,
|
|
21
|
+
excludes
|
|
22
|
+
} = resourceRights[rightName];
|
|
23
|
+
let newPermission;
|
|
24
|
+
if (add)
|
|
25
|
+
newPermission = [.../* @__PURE__ */ new Set([...item.permission.filter((perm) => !excludes.includes(perm)), ...requires, rightName])];
|
|
26
|
+
else {
|
|
27
|
+
const toRemove = /* @__PURE__ */ new Set([rightName]);
|
|
28
|
+
let changed = !0;
|
|
29
|
+
for (; changed; ) {
|
|
30
|
+
changed = !1;
|
|
31
|
+
for (const [name, definition] of Object.entries(resourceRights))
|
|
32
|
+
!toRemove.has(name) && definition.requires.some((required) => toRemove.has(required)) && (toRemove.add(name), changed = !0);
|
|
33
|
+
}
|
|
34
|
+
newPermission = item.permission.filter((perm) => !toRemove.has(perm));
|
|
35
|
+
}
|
|
36
|
+
return {
|
|
37
|
+
...item,
|
|
38
|
+
permission: newPermission
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
return {
|
|
42
|
+
applyRight,
|
|
43
|
+
toggleRight: (item, rightName) => {
|
|
44
|
+
const hasRight = item.permission.includes(rightName);
|
|
45
|
+
return applyRight(item, rightName, !hasRight);
|
|
46
|
+
},
|
|
47
|
+
createOwnerItem,
|
|
48
|
+
getOwnerItem
|
|
49
|
+
};
|
|
50
|
+
};
|
|
51
|
+
export {
|
|
52
|
+
createRightsHelpers
|
|
53
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { SharingItem } from '../../../types';
|
|
2
|
+
import { BookmarkInput, BookmarkState, ResourceRightName, ResourceRights } from '../types/types';
|
|
3
|
+
interface UseBookmarkEntriesParams {
|
|
4
|
+
resourceRights: ResourceRights;
|
|
5
|
+
existingRecipientIds: Set<string>;
|
|
6
|
+
toggleRight: (item: SharingItem, rightName: ResourceRightName) => SharingItem;
|
|
7
|
+
addItems: (items: SharingItem[]) => void;
|
|
8
|
+
deleteItemsByIds: (ids: Set<string>) => void;
|
|
9
|
+
applyRightToIds: (ids: Set<string>, rightName: ResourceRightName, shouldAdd: boolean) => void;
|
|
10
|
+
}
|
|
11
|
+
export declare const useBookmarkEntries: ({ resourceRights, existingRecipientIds, toggleRight, addItems, deleteItemsByIds, applyRightToIds, }: UseBookmarkEntriesParams) => {
|
|
12
|
+
bookmarkEntries: BookmarkState[];
|
|
13
|
+
bookmarkUserIds: Set<string>;
|
|
14
|
+
addBookmark: (bookmark: BookmarkInput) => void;
|
|
15
|
+
deleteBookmark: (bookmarkId: string) => void;
|
|
16
|
+
toggleBookmarkRight: (bookmarkId: string, rightName: ResourceRightName) => void;
|
|
17
|
+
toggleExpand: (bookmarkId: string) => void;
|
|
18
|
+
};
|
|
19
|
+
export {};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { useState, useMemo } from "react";
|
|
2
|
+
const useBookmarkEntries = ({
|
|
3
|
+
resourceRights,
|
|
4
|
+
existingRecipientIds,
|
|
5
|
+
toggleRight,
|
|
6
|
+
addItems,
|
|
7
|
+
deleteItemsByIds,
|
|
8
|
+
applyRightToIds
|
|
9
|
+
}) => {
|
|
10
|
+
const [bookmarkEntries, setBookmarkEntries] = useState([]), bookmarkUserIds = useMemo(() => new Set(bookmarkEntries.flatMap((entry) => entry.userIds)), [bookmarkEntries]), getDefaultPermissions = () => Object.entries(resourceRights).filter(([, definition]) => definition.default).map(([name]) => name);
|
|
11
|
+
return {
|
|
12
|
+
bookmarkEntries,
|
|
13
|
+
bookmarkUserIds,
|
|
14
|
+
addBookmark: (bookmark) => {
|
|
15
|
+
if (bookmarkEntries.some((entry) => entry.id === bookmark.id)) return;
|
|
16
|
+
const defaultPermissions = getDefaultPermissions(), newBookmarkUsers = bookmark.users.filter((bookmarkUser) => !existingRecipientIds.has(bookmarkUser.id)), newUsers = newBookmarkUsers.map((bookmarkUser) => ({
|
|
17
|
+
recipientId: bookmarkUser.id,
|
|
18
|
+
recipientType: "user",
|
|
19
|
+
displayName: bookmarkUser.displayName,
|
|
20
|
+
permission: [...defaultPermissions]
|
|
21
|
+
})), bookmarkState = {
|
|
22
|
+
id: bookmark.id,
|
|
23
|
+
name: bookmark.name,
|
|
24
|
+
permission: [...defaultPermissions],
|
|
25
|
+
userIds: newBookmarkUsers.map((bookmarkUser) => bookmarkUser.id),
|
|
26
|
+
isExpanded: !1
|
|
27
|
+
};
|
|
28
|
+
setBookmarkEntries((prev) => [...prev, bookmarkState]), addItems(newUsers);
|
|
29
|
+
},
|
|
30
|
+
deleteBookmark: (bookmarkId) => {
|
|
31
|
+
const bookmark = bookmarkEntries.find((entry) => entry.id === bookmarkId);
|
|
32
|
+
bookmark && (setBookmarkEntries((prev) => prev.filter((entry) => entry.id !== bookmarkId)), deleteItemsByIds(new Set(bookmark.userIds)));
|
|
33
|
+
},
|
|
34
|
+
toggleBookmarkRight: (bookmarkId, rightName) => {
|
|
35
|
+
const bookmark = bookmarkEntries.find((entry) => entry.id === bookmarkId);
|
|
36
|
+
if (!bookmark) return;
|
|
37
|
+
const shouldAdd = !bookmark.permission.includes(rightName), bookmarkAsSharingItem = {
|
|
38
|
+
recipientId: bookmark.id,
|
|
39
|
+
recipientType: "bookmark",
|
|
40
|
+
displayName: bookmark.name,
|
|
41
|
+
permission: bookmark.permission
|
|
42
|
+
}, toggledBookmark = toggleRight(bookmarkAsSharingItem, rightName);
|
|
43
|
+
setBookmarkEntries((prev) => prev.map((entry) => entry.id === bookmarkId ? {
|
|
44
|
+
...entry,
|
|
45
|
+
permission: toggledBookmark.permission
|
|
46
|
+
} : entry)), applyRightToIds(new Set(bookmark.userIds), rightName, shouldAdd);
|
|
47
|
+
},
|
|
48
|
+
toggleExpand: (bookmarkId) => {
|
|
49
|
+
setBookmarkEntries((prev) => prev.map((entry) => entry.id === bookmarkId ? {
|
|
50
|
+
...entry,
|
|
51
|
+
isExpanded: !entry.isExpanded
|
|
52
|
+
} : entry));
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
};
|
|
56
|
+
export {
|
|
57
|
+
useBookmarkEntries
|
|
58
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { SharingItem } from '../../../types';
|
|
2
|
+
import { ResourceRightName } from '../types/types';
|
|
3
|
+
interface UseSharingItemsParams {
|
|
4
|
+
initialSharings: SharingItem[];
|
|
5
|
+
toggleRight: (item: SharingItem, rightName: ResourceRightName) => SharingItem;
|
|
6
|
+
applyRight: (item: SharingItem, rightName: ResourceRightName, add: boolean) => SharingItem;
|
|
7
|
+
onChange: (value: SharingItem[]) => void;
|
|
8
|
+
onAddItems: (value: SharingItem[]) => void;
|
|
9
|
+
onDeleteItems: (value: SharingItem[]) => void;
|
|
10
|
+
}
|
|
11
|
+
export declare const useSharingItems: ({ initialSharings, toggleRight, applyRight, onChange, onAddItems, onDeleteItems, }: UseSharingItemsParams) => {
|
|
12
|
+
items: SharingItem[];
|
|
13
|
+
addItem: (item: SharingItem) => void;
|
|
14
|
+
addItems: (newItems: SharingItem[]) => void;
|
|
15
|
+
deleteItem: (item: SharingItem) => void;
|
|
16
|
+
deleteItemsByIds: (ids: Set<string>) => void;
|
|
17
|
+
changeRight: (item: SharingItem, rightName: ResourceRightName) => void;
|
|
18
|
+
applyRightToIds: (ids: Set<string>, rightName: ResourceRightName, shouldAdd: boolean) => void;
|
|
19
|
+
};
|
|
20
|
+
export {};
|