@ynput/ayon-frontend-shared 0.2.0 → 0.2.1
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/shared/src/containers/Actions/Actions.cjs.js +5 -0
- package/dist/shared/src/containers/Actions/Actions.cjs.js.map +1 -1
- package/dist/shared/src/containers/Actions/Actions.es.js +5 -0
- package/dist/shared/src/containers/Actions/Actions.es.js.map +1 -1
- package/dist/shared/src/containers/ProjectTreeTable/ProjectTreeTable.cjs.js +5 -1
- package/dist/shared/src/containers/ProjectTreeTable/ProjectTreeTable.cjs.js.map +1 -1
- package/dist/shared/src/containers/ProjectTreeTable/ProjectTreeTable.es.js +5 -1
- package/dist/shared/src/containers/ProjectTreeTable/ProjectTreeTable.es.js.map +1 -1
- package/dist/shared/src/context/DetailsPanelContext.cjs.js +4 -0
- package/dist/shared/src/context/DetailsPanelContext.cjs.js.map +1 -1
- package/dist/shared/src/context/DetailsPanelContext.es.js +4 -0
- package/dist/shared/src/context/DetailsPanelContext.es.js.map +1 -1
- package/dist/shared/src/hooks/useEntityUpdate.cjs.js +8 -0
- package/dist/shared/src/hooks/useEntityUpdate.cjs.js.map +1 -1
- package/dist/shared/src/hooks/useEntityUpdate.es.js +8 -0
- package/dist/shared/src/hooks/useEntityUpdate.es.js.map +1 -1
- package/dist/types/context/DetailsPanelContext.d.ts +4 -0
- package/package.json +1 -1
|
@@ -71,6 +71,11 @@ require("../../context/RemoteModulesContext.cjs.js");
|
|
|
71
71
|
require("../../../../_virtual/runtime.cjs.js");
|
|
72
72
|
require("../../../../_virtual/semver.cjs.js");
|
|
73
73
|
require("../../../../_virtual/lodash.cjs.js");
|
|
74
|
+
require("../../context/DetailsPanelContext.cjs.js");
|
|
75
|
+
require("../../context/ThumbnailUploaderContext.cjs.js");
|
|
76
|
+
require("../../context/pip/PiPProvider.cjs.js");
|
|
77
|
+
require("react-dom");
|
|
78
|
+
require("../../context/pip/PiPWrapper.cjs.js");
|
|
74
79
|
const useActionTriggers = require("../../hooks/useActionTriggers.cjs.js");
|
|
75
80
|
const ActionConfigDialog = require("./ActionConfigDialog.cjs.js");
|
|
76
81
|
const InteractiveActionDialog = require("./InteractiveActionDialog.cjs.js");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Actions.cjs.js","sources":["../../../../../src/containers/Actions/Actions.tsx"],"sourcesContent":["import * as Styled from './Actions.styled'\nimport { MouseEvent, useState } from 'react'\nimport clsx from 'clsx'\nimport { toast } from 'react-toastify'\nimport { useMemo, useEffect } from 'react'\nimport { ActionContext, useExecuteActionMutation, useGetActionsFromContextQuery } from '@shared/api'\nimport { ActionsDropdown } from './ActionsDropdown'\nimport ActionIcon from './ActionIcon'\nimport { useActionTriggers } from '@shared/hooks'\nimport { ActionConfigDialog } from './ActionConfigDialog'\nimport { InteractiveActionDialog, InteractiveForm } from './InteractiveActionDialog'\n\nconst placeholder = {\n identifier: 'placeholder',\n label: 'Featured action slot',\n isPlaceholder: true,\n icon: { type: 'material-symbols', name: 'sync' },\n}\n\ntype ActionsProps = {\n entities: any[]\n entityType: ActionContext['entityType']\n entitySubTypes?: string[]\n isLoadingEntity: boolean\n}\n\nexport const Actions = ({\n entities,\n entityType,\n entitySubTypes,\n isLoadingEntity,\n}: ActionsProps) => {\n // special triggers the actions can make to perform stuff on the client\n const { handleActionPayload } = useActionTriggers()\n const [actionBeingConfigured, setActionBeingConfigured] = useState<any>(null)\n const [interactiveForm, setInteractiveForm] = useState<any>(null)\n\n const context: ActionContext | null = useMemo(() => {\n if (!entities.length) return null\n if (!entities[0].projectName) return null\n\n // get a list of unique entity subtypes from loaded data\n const entitySubtypesLoaded = entities\n .map((entity) => entity.entitySubType)\n .filter((value, index, self) => self.indexOf(value) === index && value)\n\n // try and use the passed in entitySubTypes, if not use the loaded ones\n const entitySubTypesToUse = entitySubTypes || entitySubtypesLoaded || []\n\n // all types except version should have subtypes\n if (!entitySubTypesToUse?.length && entityType !== 'version') return null\n\n return {\n projectName: entities[0].projectName,\n entityType: entityType,\n entityIds: entities.map((entity) => entity.id),\n entitySubtypes: entitySubTypesToUse,\n }\n }, [entities, entityType])\n\n useEffect(() => {\n setInteractiveForm(null)\n }, [context])\n\n const { data, isFetching: isFetchingActions } = useGetActionsFromContextQuery(\n { mode: 'simple', actionContext: context as ActionContext },\n { skip: !context },\n )\n const actions = data?.actions || []\n\n const categoryOrder = ['application', 'admin', 'workflow']\n // group actions by category\n // sort by hardcoded category, this will changing the future\n const groupedActions = useMemo(() => {\n // Step 1: Group actions by category\n const grouped = actions.reduce((acc: { [key: string]: any[] }, action) => {\n const category = action.category || 'uncategorized'\n if (!acc[category]) {\n acc[category] = []\n }\n acc[category].push(action)\n return acc\n }, {})\n\n // Step 5: Return the ordered groups\n return grouped\n }, [actions])\n\n // get categories that don't have a specific order (not in categoryOrder)\n // then sort them alphabetically\n const unorderedCategories = useMemo(\n () => [\n ...new Set(\n Object.keys(groupedActions)\n .filter((category) => !categoryOrder.includes(category))\n .sort((a, b) => a.localeCompare(b)),\n ),\n ],\n [groupedActions],\n )\n\n const categories = [...categoryOrder, ...unorderedCategories]\n\n // create the options for the dropdown, each category is separated by a divider and a title\n // for the divider we will use a custom dropdown item template\n const dropdownOptions = useMemo(() => {\n const options = []\n\n categories.forEach((category) => {\n if (!groupedActions[category] || !groupedActions[category].length) return\n\n options.push({\n label: category,\n header: true,\n value: category,\n disabled: true,\n })\n\n const groupOptions = groupedActions[category].map((action) => ({\n value: action.identifier,\n label: action.label,\n icon: action.icon,\n hasConfig: !!action.configFields,\n }))\n\n options.push(...groupOptions)\n })\n\n // if no actions, add placeholder\n if (!options.length) {\n options.push({\n label: 'No actions available',\n value: 'no-actions',\n disabled: true,\n header: true,\n })\n }\n\n return options\n }, [groupedActions, unorderedCategories, categoryOrder])\n\n const featuredNumber = 2\n\n const featuredActions = useMemo(() => {\n // Filter and sort to get initial featured actions\n let tempFeaturedActions = actions\n .filter((action) => action.featured)\n .sort((a, b) => (a.order || 0) - (b.order || 0))\n .slice(0, featuredNumber)\n\n // Check if we need to add more actions to reach featuredNumber\n if (tempFeaturedActions.length < featuredNumber) {\n categories.forEach((category) => {\n if (tempFeaturedActions.length >= featuredNumber) return\n const actions = groupedActions[category]\n if (!actions || !actions.length) return\n\n for (let i = tempFeaturedActions.length; i < featuredNumber; i++) {\n const action = actions[i]\n if (!action) break\n if (!action.icon) continue\n tempFeaturedActions.push(action)\n }\n })\n }\n\n return tempFeaturedActions\n }, [actions, groupedActions, placeholder])\n\n const [executeAction, { isLoading: isLoadingExecution, originalArgs }] =\n useExecuteActionMutation()\n const executingAction = isLoadingExecution && originalArgs?.identifier\n\n const handleExecuteAction = async (\n identifier: string,\n e?: MouseEvent<HTMLElement> | null,\n formData?: InteractiveForm,\n ) => {\n e?.preventDefault()\n const action = actions.find((option) => option.identifier === identifier)\n\n if (!action) {\n toast.error('Action not found')\n console.warn('Action not found', identifier)\n return\n }\n\n const params = {\n addonName: action.addonName as string,\n addonVersion: action.addonVersion as string,\n variant: action.variant,\n identifier: action.identifier,\n }\n\n const actionContext = { ...context }\n if (formData) {\n actionContext.formData = formData\n }\n\n let response = null\n\n try {\n response = await executeAction({ actionContext, ...params }).unwrap()\n } catch (error: any) {\n console.error('Error executing action', error)\n toast.error(error?.data?.detail || 'Error executing action')\n return\n }\n\n try {\n // Toast the message if it is available\n if (response?.message) {\n if (response?.success) {\n toast.success(response.message, { autoClose: 2000 })\n } else {\n toast.error(response.message, { autoClose: 2000 })\n }\n }\n\n // Even if response?.success is false, we still want to handle the payload\n // as it may contain useful information - complex error messages in form,\n // redirect to another page etc. If the action just needs to abort,\n // it raises exception instead of returning a response with success: false\n\n // Use the new hook to handle payload\n if (response?.payload) {\n if (response.type === 'form') {\n // action requests additional information from the user.\n // we show a dialog with the form and when the user submits it we call the action again\n\n // It probably does not make sense to move to the useActionTriggers hook\n // as it need contexts and the dialog\n const intf = {\n identifier,\n // @ts-expect-error\n title: response.payload['title'],\n // @ts-expect-error\n fields: response.payload['fields'],\n // @ts-expect-error\n submitLabel: response.payload['submit_label'],\n // @ts-expect-error\n cancelLabel: response.payload['cancel_label'],\n // @ts-expect-error\n submitIcon: response.payload['submit_icon'],\n // @ts-expect-error\n cancelIcon: response.payload['cancel_icon'],\n }\n setInteractiveForm(intf)\n } else {\n handleActionPayload(response.type as string, response.payload)\n }\n }\n } catch (error) {\n // got response, but failed to process it\n console.warn('Error during action response processing', error)\n toast.error('Error occured during action processing')\n }\n }\n\n const handleConfigureAction = (identifier: string) => {\n const action = actions.find((data) => data.identifier === identifier)\n if (!action) return\n setActionBeingConfigured(action)\n }\n\n const handleSubmitInteractiveForm = async (identifier: string, formData: InteractiveForm) => {\n handleExecuteAction(identifier, null, formData)\n }\n\n const loadingActions = [placeholder, placeholder, placeholder]\n\n const isLoading = isFetchingActions || isLoadingEntity\n const featuredActionsToDisplay = isLoading ? loadingActions : featuredActions\n\n return (\n <Styled.Actions className=\"actions\">\n {featuredActionsToDisplay.map((action, i) => (\n <Styled.FeaturedAction\n key={action.identifier + '-' + i}\n className={clsx('action', {\n loading: isLoading,\n // @ts-expect-error\n isPlaceholder: action.isPlaceholder,\n })}\n data-tooltip={action.label}\n // @ts-expect-error\n disabled={action.isPlaceholder}\n onClick={(e) => handleExecuteAction(action.identifier, e)}\n >\n {/* @ts-ignore */}\n <ActionIcon icon={action.icon} isExecuting={executingAction === action.identifier} />\n </Styled.FeaturedAction>\n ))}\n <ActionsDropdown\n options={dropdownOptions}\n isLoading={isLoading}\n onAction={handleExecuteAction}\n onConfig={handleConfigureAction}\n />\n <ActionConfigDialog\n action={actionBeingConfigured}\n // @ts-expect-error\n context={context}\n onClose={() => setActionBeingConfigured(null)}\n />\n <InteractiveActionDialog\n interactiveForm={interactiveForm}\n onClose={() => setInteractiveForm(null)}\n // @ts-expect-error\n onSubmit={handleSubmitInteractiveForm}\n />\n </Styled.Actions>\n )\n}\n"],"names":["useActionTriggers","useState","useMemo","useEffect","useGetActionsFromContextQuery","actions","useExecuteActionMutation","toast","data","jsxs","Styled.Actions","jsx","Styled.FeaturedAction","ActionsDropdown","ActionConfigDialog","InteractiveActionDialog"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Actions.cjs.js","sources":["../../../../../src/containers/Actions/Actions.tsx"],"sourcesContent":["import * as Styled from './Actions.styled'\nimport { MouseEvent, useState } from 'react'\nimport clsx from 'clsx'\nimport { toast } from 'react-toastify'\nimport { useMemo, useEffect } from 'react'\nimport { ActionContext, useExecuteActionMutation, useGetActionsFromContextQuery } from '@shared/api'\nimport { ActionsDropdown } from './ActionsDropdown'\nimport ActionIcon from './ActionIcon'\nimport { useActionTriggers } from '@shared/hooks'\nimport { ActionConfigDialog } from './ActionConfigDialog'\nimport { InteractiveActionDialog, InteractiveForm } from './InteractiveActionDialog'\n\nconst placeholder = {\n identifier: 'placeholder',\n label: 'Featured action slot',\n isPlaceholder: true,\n icon: { type: 'material-symbols', name: 'sync' },\n}\n\ntype ActionsProps = {\n entities: any[]\n entityType: ActionContext['entityType']\n entitySubTypes?: string[]\n isLoadingEntity: boolean\n}\n\nexport const Actions = ({\n entities,\n entityType,\n entitySubTypes,\n isLoadingEntity,\n}: ActionsProps) => {\n // special triggers the actions can make to perform stuff on the client\n const { handleActionPayload } = useActionTriggers()\n const [actionBeingConfigured, setActionBeingConfigured] = useState<any>(null)\n const [interactiveForm, setInteractiveForm] = useState<any>(null)\n\n const context: ActionContext | null = useMemo(() => {\n if (!entities.length) return null\n if (!entities[0].projectName) return null\n\n // get a list of unique entity subtypes from loaded data\n const entitySubtypesLoaded = entities\n .map((entity) => entity.entitySubType)\n .filter((value, index, self) => self.indexOf(value) === index && value)\n\n // try and use the passed in entitySubTypes, if not use the loaded ones\n const entitySubTypesToUse = entitySubTypes || entitySubtypesLoaded || []\n\n // all types except version should have subtypes\n if (!entitySubTypesToUse?.length && entityType !== 'version') return null\n\n return {\n projectName: entities[0].projectName,\n entityType: entityType,\n entityIds: entities.map((entity) => entity.id),\n entitySubtypes: entitySubTypesToUse,\n }\n }, [entities, entityType])\n\n useEffect(() => {\n setInteractiveForm(null)\n }, [context])\n\n const { data, isFetching: isFetchingActions } = useGetActionsFromContextQuery(\n { mode: 'simple', actionContext: context as ActionContext },\n { skip: !context },\n )\n const actions = data?.actions || []\n\n const categoryOrder = ['application', 'admin', 'workflow']\n // group actions by category\n // sort by hardcoded category, this will changing the future\n const groupedActions = useMemo(() => {\n // Step 1: Group actions by category\n const grouped = actions.reduce((acc: { [key: string]: any[] }, action) => {\n const category = action.category || 'uncategorized'\n if (!acc[category]) {\n acc[category] = []\n }\n acc[category].push(action)\n return acc\n }, {})\n\n // Step 5: Return the ordered groups\n return grouped\n }, [actions])\n\n // get categories that don't have a specific order (not in categoryOrder)\n // then sort them alphabetically\n const unorderedCategories = useMemo(\n () => [\n ...new Set(\n Object.keys(groupedActions)\n .filter((category) => !categoryOrder.includes(category))\n .sort((a, b) => a.localeCompare(b)),\n ),\n ],\n [groupedActions],\n )\n\n const categories = [...categoryOrder, ...unorderedCategories]\n\n // create the options for the dropdown, each category is separated by a divider and a title\n // for the divider we will use a custom dropdown item template\n const dropdownOptions = useMemo(() => {\n const options = []\n\n categories.forEach((category) => {\n if (!groupedActions[category] || !groupedActions[category].length) return\n\n options.push({\n label: category,\n header: true,\n value: category,\n disabled: true,\n })\n\n const groupOptions = groupedActions[category].map((action) => ({\n value: action.identifier,\n label: action.label,\n icon: action.icon,\n hasConfig: !!action.configFields,\n }))\n\n options.push(...groupOptions)\n })\n\n // if no actions, add placeholder\n if (!options.length) {\n options.push({\n label: 'No actions available',\n value: 'no-actions',\n disabled: true,\n header: true,\n })\n }\n\n return options\n }, [groupedActions, unorderedCategories, categoryOrder])\n\n const featuredNumber = 2\n\n const featuredActions = useMemo(() => {\n // Filter and sort to get initial featured actions\n let tempFeaturedActions = actions\n .filter((action) => action.featured)\n .sort((a, b) => (a.order || 0) - (b.order || 0))\n .slice(0, featuredNumber)\n\n // Check if we need to add more actions to reach featuredNumber\n if (tempFeaturedActions.length < featuredNumber) {\n categories.forEach((category) => {\n if (tempFeaturedActions.length >= featuredNumber) return\n const actions = groupedActions[category]\n if (!actions || !actions.length) return\n\n for (let i = tempFeaturedActions.length; i < featuredNumber; i++) {\n const action = actions[i]\n if (!action) break\n if (!action.icon) continue\n tempFeaturedActions.push(action)\n }\n })\n }\n\n return tempFeaturedActions\n }, [actions, groupedActions, placeholder])\n\n const [executeAction, { isLoading: isLoadingExecution, originalArgs }] =\n useExecuteActionMutation()\n const executingAction = isLoadingExecution && originalArgs?.identifier\n\n const handleExecuteAction = async (\n identifier: string,\n e?: MouseEvent<HTMLElement> | null,\n formData?: InteractiveForm,\n ) => {\n e?.preventDefault()\n const action = actions.find((option) => option.identifier === identifier)\n\n if (!action) {\n toast.error('Action not found')\n console.warn('Action not found', identifier)\n return\n }\n\n const params = {\n addonName: action.addonName as string,\n addonVersion: action.addonVersion as string,\n variant: action.variant,\n identifier: action.identifier,\n }\n\n const actionContext = { ...context }\n if (formData) {\n actionContext.formData = formData\n }\n\n let response = null\n\n try {\n response = await executeAction({ actionContext, ...params }).unwrap()\n } catch (error: any) {\n console.error('Error executing action', error)\n toast.error(error?.data?.detail || 'Error executing action')\n return\n }\n\n try {\n // Toast the message if it is available\n if (response?.message) {\n if (response?.success) {\n toast.success(response.message, { autoClose: 2000 })\n } else {\n toast.error(response.message, { autoClose: 2000 })\n }\n }\n\n // Even if response?.success is false, we still want to handle the payload\n // as it may contain useful information - complex error messages in form,\n // redirect to another page etc. If the action just needs to abort,\n // it raises exception instead of returning a response with success: false\n\n // Use the new hook to handle payload\n if (response?.payload) {\n if (response.type === 'form') {\n // action requests additional information from the user.\n // we show a dialog with the form and when the user submits it we call the action again\n\n // It probably does not make sense to move to the useActionTriggers hook\n // as it need contexts and the dialog\n const intf = {\n identifier,\n // @ts-expect-error\n title: response.payload['title'],\n // @ts-expect-error\n fields: response.payload['fields'],\n // @ts-expect-error\n submitLabel: response.payload['submit_label'],\n // @ts-expect-error\n cancelLabel: response.payload['cancel_label'],\n // @ts-expect-error\n submitIcon: response.payload['submit_icon'],\n // @ts-expect-error\n cancelIcon: response.payload['cancel_icon'],\n }\n setInteractiveForm(intf)\n } else {\n handleActionPayload(response.type as string, response.payload)\n }\n }\n } catch (error) {\n // got response, but failed to process it\n console.warn('Error during action response processing', error)\n toast.error('Error occured during action processing')\n }\n }\n\n const handleConfigureAction = (identifier: string) => {\n const action = actions.find((data) => data.identifier === identifier)\n if (!action) return\n setActionBeingConfigured(action)\n }\n\n const handleSubmitInteractiveForm = async (identifier: string, formData: InteractiveForm) => {\n handleExecuteAction(identifier, null, formData)\n }\n\n const loadingActions = [placeholder, placeholder, placeholder]\n\n const isLoading = isFetchingActions || isLoadingEntity\n const featuredActionsToDisplay = isLoading ? loadingActions : featuredActions\n\n return (\n <Styled.Actions className=\"actions\">\n {featuredActionsToDisplay.map((action, i) => (\n <Styled.FeaturedAction\n key={action.identifier + '-' + i}\n className={clsx('action', {\n loading: isLoading,\n // @ts-expect-error\n isPlaceholder: action.isPlaceholder,\n })}\n data-tooltip={action.label}\n // @ts-expect-error\n disabled={action.isPlaceholder}\n onClick={(e) => handleExecuteAction(action.identifier, e)}\n >\n {/* @ts-ignore */}\n <ActionIcon icon={action.icon} isExecuting={executingAction === action.identifier} />\n </Styled.FeaturedAction>\n ))}\n <ActionsDropdown\n options={dropdownOptions}\n isLoading={isLoading}\n onAction={handleExecuteAction}\n onConfig={handleConfigureAction}\n />\n <ActionConfigDialog\n action={actionBeingConfigured}\n // @ts-expect-error\n context={context}\n onClose={() => setActionBeingConfigured(null)}\n />\n <InteractiveActionDialog\n interactiveForm={interactiveForm}\n onClose={() => setInteractiveForm(null)}\n // @ts-expect-error\n onSubmit={handleSubmitInteractiveForm}\n />\n </Styled.Actions>\n )\n}\n"],"names":["useActionTriggers","useState","useMemo","useEffect","useGetActionsFromContextQuery","actions","useExecuteActionMutation","toast","data","jsxs","Styled.Actions","jsx","Styled.FeaturedAction","ActionsDropdown","ActionConfigDialog","InteractiveActionDialog"],"mappings":"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"}
|
|
@@ -69,6 +69,11 @@ import "../../context/RemoteModulesContext.es.js";
|
|
|
69
69
|
import "../../../../_virtual/runtime.es.js";
|
|
70
70
|
import "../../../../_virtual/semver.es.js";
|
|
71
71
|
import "../../../../_virtual/lodash.es.js";
|
|
72
|
+
import "../../context/DetailsPanelContext.es.js";
|
|
73
|
+
import "../../context/ThumbnailUploaderContext.es.js";
|
|
74
|
+
import "../../context/pip/PiPProvider.es.js";
|
|
75
|
+
import "react-dom";
|
|
76
|
+
import "../../context/pip/PiPWrapper.es.js";
|
|
72
77
|
import { useActionTriggers } from "../../hooks/useActionTriggers.es.js";
|
|
73
78
|
import { ActionConfigDialog } from "./ActionConfigDialog.es.js";
|
|
74
79
|
import { InteractiveActionDialog } from "./InteractiveActionDialog.es.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Actions.es.js","sources":["../../../../../src/containers/Actions/Actions.tsx"],"sourcesContent":["import * as Styled from './Actions.styled'\nimport { MouseEvent, useState } from 'react'\nimport clsx from 'clsx'\nimport { toast } from 'react-toastify'\nimport { useMemo, useEffect } from 'react'\nimport { ActionContext, useExecuteActionMutation, useGetActionsFromContextQuery } from '@shared/api'\nimport { ActionsDropdown } from './ActionsDropdown'\nimport ActionIcon from './ActionIcon'\nimport { useActionTriggers } from '@shared/hooks'\nimport { ActionConfigDialog } from './ActionConfigDialog'\nimport { InteractiveActionDialog, InteractiveForm } from './InteractiveActionDialog'\n\nconst placeholder = {\n identifier: 'placeholder',\n label: 'Featured action slot',\n isPlaceholder: true,\n icon: { type: 'material-symbols', name: 'sync' },\n}\n\ntype ActionsProps = {\n entities: any[]\n entityType: ActionContext['entityType']\n entitySubTypes?: string[]\n isLoadingEntity: boolean\n}\n\nexport const Actions = ({\n entities,\n entityType,\n entitySubTypes,\n isLoadingEntity,\n}: ActionsProps) => {\n // special triggers the actions can make to perform stuff on the client\n const { handleActionPayload } = useActionTriggers()\n const [actionBeingConfigured, setActionBeingConfigured] = useState<any>(null)\n const [interactiveForm, setInteractiveForm] = useState<any>(null)\n\n const context: ActionContext | null = useMemo(() => {\n if (!entities.length) return null\n if (!entities[0].projectName) return null\n\n // get a list of unique entity subtypes from loaded data\n const entitySubtypesLoaded = entities\n .map((entity) => entity.entitySubType)\n .filter((value, index, self) => self.indexOf(value) === index && value)\n\n // try and use the passed in entitySubTypes, if not use the loaded ones\n const entitySubTypesToUse = entitySubTypes || entitySubtypesLoaded || []\n\n // all types except version should have subtypes\n if (!entitySubTypesToUse?.length && entityType !== 'version') return null\n\n return {\n projectName: entities[0].projectName,\n entityType: entityType,\n entityIds: entities.map((entity) => entity.id),\n entitySubtypes: entitySubTypesToUse,\n }\n }, [entities, entityType])\n\n useEffect(() => {\n setInteractiveForm(null)\n }, [context])\n\n const { data, isFetching: isFetchingActions } = useGetActionsFromContextQuery(\n { mode: 'simple', actionContext: context as ActionContext },\n { skip: !context },\n )\n const actions = data?.actions || []\n\n const categoryOrder = ['application', 'admin', 'workflow']\n // group actions by category\n // sort by hardcoded category, this will changing the future\n const groupedActions = useMemo(() => {\n // Step 1: Group actions by category\n const grouped = actions.reduce((acc: { [key: string]: any[] }, action) => {\n const category = action.category || 'uncategorized'\n if (!acc[category]) {\n acc[category] = []\n }\n acc[category].push(action)\n return acc\n }, {})\n\n // Step 5: Return the ordered groups\n return grouped\n }, [actions])\n\n // get categories that don't have a specific order (not in categoryOrder)\n // then sort them alphabetically\n const unorderedCategories = useMemo(\n () => [\n ...new Set(\n Object.keys(groupedActions)\n .filter((category) => !categoryOrder.includes(category))\n .sort((a, b) => a.localeCompare(b)),\n ),\n ],\n [groupedActions],\n )\n\n const categories = [...categoryOrder, ...unorderedCategories]\n\n // create the options for the dropdown, each category is separated by a divider and a title\n // for the divider we will use a custom dropdown item template\n const dropdownOptions = useMemo(() => {\n const options = []\n\n categories.forEach((category) => {\n if (!groupedActions[category] || !groupedActions[category].length) return\n\n options.push({\n label: category,\n header: true,\n value: category,\n disabled: true,\n })\n\n const groupOptions = groupedActions[category].map((action) => ({\n value: action.identifier,\n label: action.label,\n icon: action.icon,\n hasConfig: !!action.configFields,\n }))\n\n options.push(...groupOptions)\n })\n\n // if no actions, add placeholder\n if (!options.length) {\n options.push({\n label: 'No actions available',\n value: 'no-actions',\n disabled: true,\n header: true,\n })\n }\n\n return options\n }, [groupedActions, unorderedCategories, categoryOrder])\n\n const featuredNumber = 2\n\n const featuredActions = useMemo(() => {\n // Filter and sort to get initial featured actions\n let tempFeaturedActions = actions\n .filter((action) => action.featured)\n .sort((a, b) => (a.order || 0) - (b.order || 0))\n .slice(0, featuredNumber)\n\n // Check if we need to add more actions to reach featuredNumber\n if (tempFeaturedActions.length < featuredNumber) {\n categories.forEach((category) => {\n if (tempFeaturedActions.length >= featuredNumber) return\n const actions = groupedActions[category]\n if (!actions || !actions.length) return\n\n for (let i = tempFeaturedActions.length; i < featuredNumber; i++) {\n const action = actions[i]\n if (!action) break\n if (!action.icon) continue\n tempFeaturedActions.push(action)\n }\n })\n }\n\n return tempFeaturedActions\n }, [actions, groupedActions, placeholder])\n\n const [executeAction, { isLoading: isLoadingExecution, originalArgs }] =\n useExecuteActionMutation()\n const executingAction = isLoadingExecution && originalArgs?.identifier\n\n const handleExecuteAction = async (\n identifier: string,\n e?: MouseEvent<HTMLElement> | null,\n formData?: InteractiveForm,\n ) => {\n e?.preventDefault()\n const action = actions.find((option) => option.identifier === identifier)\n\n if (!action) {\n toast.error('Action not found')\n console.warn('Action not found', identifier)\n return\n }\n\n const params = {\n addonName: action.addonName as string,\n addonVersion: action.addonVersion as string,\n variant: action.variant,\n identifier: action.identifier,\n }\n\n const actionContext = { ...context }\n if (formData) {\n actionContext.formData = formData\n }\n\n let response = null\n\n try {\n response = await executeAction({ actionContext, ...params }).unwrap()\n } catch (error: any) {\n console.error('Error executing action', error)\n toast.error(error?.data?.detail || 'Error executing action')\n return\n }\n\n try {\n // Toast the message if it is available\n if (response?.message) {\n if (response?.success) {\n toast.success(response.message, { autoClose: 2000 })\n } else {\n toast.error(response.message, { autoClose: 2000 })\n }\n }\n\n // Even if response?.success is false, we still want to handle the payload\n // as it may contain useful information - complex error messages in form,\n // redirect to another page etc. If the action just needs to abort,\n // it raises exception instead of returning a response with success: false\n\n // Use the new hook to handle payload\n if (response?.payload) {\n if (response.type === 'form') {\n // action requests additional information from the user.\n // we show a dialog with the form and when the user submits it we call the action again\n\n // It probably does not make sense to move to the useActionTriggers hook\n // as it need contexts and the dialog\n const intf = {\n identifier,\n // @ts-expect-error\n title: response.payload['title'],\n // @ts-expect-error\n fields: response.payload['fields'],\n // @ts-expect-error\n submitLabel: response.payload['submit_label'],\n // @ts-expect-error\n cancelLabel: response.payload['cancel_label'],\n // @ts-expect-error\n submitIcon: response.payload['submit_icon'],\n // @ts-expect-error\n cancelIcon: response.payload['cancel_icon'],\n }\n setInteractiveForm(intf)\n } else {\n handleActionPayload(response.type as string, response.payload)\n }\n }\n } catch (error) {\n // got response, but failed to process it\n console.warn('Error during action response processing', error)\n toast.error('Error occured during action processing')\n }\n }\n\n const handleConfigureAction = (identifier: string) => {\n const action = actions.find((data) => data.identifier === identifier)\n if (!action) return\n setActionBeingConfigured(action)\n }\n\n const handleSubmitInteractiveForm = async (identifier: string, formData: InteractiveForm) => {\n handleExecuteAction(identifier, null, formData)\n }\n\n const loadingActions = [placeholder, placeholder, placeholder]\n\n const isLoading = isFetchingActions || isLoadingEntity\n const featuredActionsToDisplay = isLoading ? loadingActions : featuredActions\n\n return (\n <Styled.Actions className=\"actions\">\n {featuredActionsToDisplay.map((action, i) => (\n <Styled.FeaturedAction\n key={action.identifier + '-' + i}\n className={clsx('action', {\n loading: isLoading,\n // @ts-expect-error\n isPlaceholder: action.isPlaceholder,\n })}\n data-tooltip={action.label}\n // @ts-expect-error\n disabled={action.isPlaceholder}\n onClick={(e) => handleExecuteAction(action.identifier, e)}\n >\n {/* @ts-ignore */}\n <ActionIcon icon={action.icon} isExecuting={executingAction === action.identifier} />\n </Styled.FeaturedAction>\n ))}\n <ActionsDropdown\n options={dropdownOptions}\n isLoading={isLoading}\n onAction={handleExecuteAction}\n onConfig={handleConfigureAction}\n />\n <ActionConfigDialog\n action={actionBeingConfigured}\n // @ts-expect-error\n context={context}\n onClose={() => setActionBeingConfigured(null)}\n />\n <InteractiveActionDialog\n interactiveForm={interactiveForm}\n onClose={() => setInteractiveForm(null)}\n // @ts-expect-error\n onSubmit={handleSubmitInteractiveForm}\n />\n </Styled.Actions>\n )\n}\n"],"names":["actions","data","jsxs","Styled.Actions","jsx","Styled.FeaturedAction"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Actions.es.js","sources":["../../../../../src/containers/Actions/Actions.tsx"],"sourcesContent":["import * as Styled from './Actions.styled'\nimport { MouseEvent, useState } from 'react'\nimport clsx from 'clsx'\nimport { toast } from 'react-toastify'\nimport { useMemo, useEffect } from 'react'\nimport { ActionContext, useExecuteActionMutation, useGetActionsFromContextQuery } from '@shared/api'\nimport { ActionsDropdown } from './ActionsDropdown'\nimport ActionIcon from './ActionIcon'\nimport { useActionTriggers } from '@shared/hooks'\nimport { ActionConfigDialog } from './ActionConfigDialog'\nimport { InteractiveActionDialog, InteractiveForm } from './InteractiveActionDialog'\n\nconst placeholder = {\n identifier: 'placeholder',\n label: 'Featured action slot',\n isPlaceholder: true,\n icon: { type: 'material-symbols', name: 'sync' },\n}\n\ntype ActionsProps = {\n entities: any[]\n entityType: ActionContext['entityType']\n entitySubTypes?: string[]\n isLoadingEntity: boolean\n}\n\nexport const Actions = ({\n entities,\n entityType,\n entitySubTypes,\n isLoadingEntity,\n}: ActionsProps) => {\n // special triggers the actions can make to perform stuff on the client\n const { handleActionPayload } = useActionTriggers()\n const [actionBeingConfigured, setActionBeingConfigured] = useState<any>(null)\n const [interactiveForm, setInteractiveForm] = useState<any>(null)\n\n const context: ActionContext | null = useMemo(() => {\n if (!entities.length) return null\n if (!entities[0].projectName) return null\n\n // get a list of unique entity subtypes from loaded data\n const entitySubtypesLoaded = entities\n .map((entity) => entity.entitySubType)\n .filter((value, index, self) => self.indexOf(value) === index && value)\n\n // try and use the passed in entitySubTypes, if not use the loaded ones\n const entitySubTypesToUse = entitySubTypes || entitySubtypesLoaded || []\n\n // all types except version should have subtypes\n if (!entitySubTypesToUse?.length && entityType !== 'version') return null\n\n return {\n projectName: entities[0].projectName,\n entityType: entityType,\n entityIds: entities.map((entity) => entity.id),\n entitySubtypes: entitySubTypesToUse,\n }\n }, [entities, entityType])\n\n useEffect(() => {\n setInteractiveForm(null)\n }, [context])\n\n const { data, isFetching: isFetchingActions } = useGetActionsFromContextQuery(\n { mode: 'simple', actionContext: context as ActionContext },\n { skip: !context },\n )\n const actions = data?.actions || []\n\n const categoryOrder = ['application', 'admin', 'workflow']\n // group actions by category\n // sort by hardcoded category, this will changing the future\n const groupedActions = useMemo(() => {\n // Step 1: Group actions by category\n const grouped = actions.reduce((acc: { [key: string]: any[] }, action) => {\n const category = action.category || 'uncategorized'\n if (!acc[category]) {\n acc[category] = []\n }\n acc[category].push(action)\n return acc\n }, {})\n\n // Step 5: Return the ordered groups\n return grouped\n }, [actions])\n\n // get categories that don't have a specific order (not in categoryOrder)\n // then sort them alphabetically\n const unorderedCategories = useMemo(\n () => [\n ...new Set(\n Object.keys(groupedActions)\n .filter((category) => !categoryOrder.includes(category))\n .sort((a, b) => a.localeCompare(b)),\n ),\n ],\n [groupedActions],\n )\n\n const categories = [...categoryOrder, ...unorderedCategories]\n\n // create the options for the dropdown, each category is separated by a divider and a title\n // for the divider we will use a custom dropdown item template\n const dropdownOptions = useMemo(() => {\n const options = []\n\n categories.forEach((category) => {\n if (!groupedActions[category] || !groupedActions[category].length) return\n\n options.push({\n label: category,\n header: true,\n value: category,\n disabled: true,\n })\n\n const groupOptions = groupedActions[category].map((action) => ({\n value: action.identifier,\n label: action.label,\n icon: action.icon,\n hasConfig: !!action.configFields,\n }))\n\n options.push(...groupOptions)\n })\n\n // if no actions, add placeholder\n if (!options.length) {\n options.push({\n label: 'No actions available',\n value: 'no-actions',\n disabled: true,\n header: true,\n })\n }\n\n return options\n }, [groupedActions, unorderedCategories, categoryOrder])\n\n const featuredNumber = 2\n\n const featuredActions = useMemo(() => {\n // Filter and sort to get initial featured actions\n let tempFeaturedActions = actions\n .filter((action) => action.featured)\n .sort((a, b) => (a.order || 0) - (b.order || 0))\n .slice(0, featuredNumber)\n\n // Check if we need to add more actions to reach featuredNumber\n if (tempFeaturedActions.length < featuredNumber) {\n categories.forEach((category) => {\n if (tempFeaturedActions.length >= featuredNumber) return\n const actions = groupedActions[category]\n if (!actions || !actions.length) return\n\n for (let i = tempFeaturedActions.length; i < featuredNumber; i++) {\n const action = actions[i]\n if (!action) break\n if (!action.icon) continue\n tempFeaturedActions.push(action)\n }\n })\n }\n\n return tempFeaturedActions\n }, [actions, groupedActions, placeholder])\n\n const [executeAction, { isLoading: isLoadingExecution, originalArgs }] =\n useExecuteActionMutation()\n const executingAction = isLoadingExecution && originalArgs?.identifier\n\n const handleExecuteAction = async (\n identifier: string,\n e?: MouseEvent<HTMLElement> | null,\n formData?: InteractiveForm,\n ) => {\n e?.preventDefault()\n const action = actions.find((option) => option.identifier === identifier)\n\n if (!action) {\n toast.error('Action not found')\n console.warn('Action not found', identifier)\n return\n }\n\n const params = {\n addonName: action.addonName as string,\n addonVersion: action.addonVersion as string,\n variant: action.variant,\n identifier: action.identifier,\n }\n\n const actionContext = { ...context }\n if (formData) {\n actionContext.formData = formData\n }\n\n let response = null\n\n try {\n response = await executeAction({ actionContext, ...params }).unwrap()\n } catch (error: any) {\n console.error('Error executing action', error)\n toast.error(error?.data?.detail || 'Error executing action')\n return\n }\n\n try {\n // Toast the message if it is available\n if (response?.message) {\n if (response?.success) {\n toast.success(response.message, { autoClose: 2000 })\n } else {\n toast.error(response.message, { autoClose: 2000 })\n }\n }\n\n // Even if response?.success is false, we still want to handle the payload\n // as it may contain useful information - complex error messages in form,\n // redirect to another page etc. If the action just needs to abort,\n // it raises exception instead of returning a response with success: false\n\n // Use the new hook to handle payload\n if (response?.payload) {\n if (response.type === 'form') {\n // action requests additional information from the user.\n // we show a dialog with the form and when the user submits it we call the action again\n\n // It probably does not make sense to move to the useActionTriggers hook\n // as it need contexts and the dialog\n const intf = {\n identifier,\n // @ts-expect-error\n title: response.payload['title'],\n // @ts-expect-error\n fields: response.payload['fields'],\n // @ts-expect-error\n submitLabel: response.payload['submit_label'],\n // @ts-expect-error\n cancelLabel: response.payload['cancel_label'],\n // @ts-expect-error\n submitIcon: response.payload['submit_icon'],\n // @ts-expect-error\n cancelIcon: response.payload['cancel_icon'],\n }\n setInteractiveForm(intf)\n } else {\n handleActionPayload(response.type as string, response.payload)\n }\n }\n } catch (error) {\n // got response, but failed to process it\n console.warn('Error during action response processing', error)\n toast.error('Error occured during action processing')\n }\n }\n\n const handleConfigureAction = (identifier: string) => {\n const action = actions.find((data) => data.identifier === identifier)\n if (!action) return\n setActionBeingConfigured(action)\n }\n\n const handleSubmitInteractiveForm = async (identifier: string, formData: InteractiveForm) => {\n handleExecuteAction(identifier, null, formData)\n }\n\n const loadingActions = [placeholder, placeholder, placeholder]\n\n const isLoading = isFetchingActions || isLoadingEntity\n const featuredActionsToDisplay = isLoading ? loadingActions : featuredActions\n\n return (\n <Styled.Actions className=\"actions\">\n {featuredActionsToDisplay.map((action, i) => (\n <Styled.FeaturedAction\n key={action.identifier + '-' + i}\n className={clsx('action', {\n loading: isLoading,\n // @ts-expect-error\n isPlaceholder: action.isPlaceholder,\n })}\n data-tooltip={action.label}\n // @ts-expect-error\n disabled={action.isPlaceholder}\n onClick={(e) => handleExecuteAction(action.identifier, e)}\n >\n {/* @ts-ignore */}\n <ActionIcon icon={action.icon} isExecuting={executingAction === action.identifier} />\n </Styled.FeaturedAction>\n ))}\n <ActionsDropdown\n options={dropdownOptions}\n isLoading={isLoading}\n onAction={handleExecuteAction}\n onConfig={handleConfigureAction}\n />\n <ActionConfigDialog\n action={actionBeingConfigured}\n // @ts-expect-error\n context={context}\n onClose={() => setActionBeingConfigured(null)}\n />\n <InteractiveActionDialog\n interactiveForm={interactiveForm}\n onClose={() => setInteractiveForm(null)}\n // @ts-expect-error\n onSubmit={handleSubmitInteractiveForm}\n />\n </Styled.Actions>\n )\n}\n"],"names":["actions","data","jsxs","Styled.Actions","jsx","Styled.FeaturedAction"],"mappings":"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"}
|
|
@@ -83,6 +83,11 @@ require("../../api/queries/users/updateUsers.cjs.js");
|
|
|
83
83
|
require("../../api/queries/watchers/getWatchers.cjs.js");
|
|
84
84
|
require("../../../../_virtual/lodash.cjs.js");
|
|
85
85
|
require("react-toastify");
|
|
86
|
+
require("../../context/DetailsPanelContext.cjs.js");
|
|
87
|
+
require("../../context/ThumbnailUploaderContext.cjs.js");
|
|
88
|
+
require("../../context/pip/PiPProvider.cjs.js");
|
|
89
|
+
const ReactDOM = require("react-dom");
|
|
90
|
+
require("../../context/pip/PiPWrapper.cjs.js");
|
|
86
91
|
require("react-router-dom");
|
|
87
92
|
require("custom-protocol-check");
|
|
88
93
|
const useCellContextMenu = require("./hooks/useCellContextMenu.cjs.js");
|
|
@@ -90,7 +95,6 @@ const useColumnVirtualization = require("./hooks/useColumnVirtualization.cjs.js"
|
|
|
90
95
|
const useKeyboardNavigation = require("./hooks/useKeyboardNavigation.cjs.js");
|
|
91
96
|
const cellUtils = require("./utils/cellUtils.cjs.js");
|
|
92
97
|
const loadingUtils = require("./utils/loadingUtils.cjs.js");
|
|
93
|
-
const ReactDOM = require("react-dom");
|
|
94
98
|
const ayonReactComponents = require("@ynput/ayon-react-components");
|
|
95
99
|
const ProjectTableContext = require("./context/ProjectTableContext.cjs.js");
|
|
96
100
|
const getCommonPinningStyles = (column) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProjectTreeTable.cjs.js","sources":["../../../../../src/containers/ProjectTreeTable/ProjectTreeTable.tsx"],"sourcesContent":["import { useMemo, useRef, useEffect, memo, CSSProperties } from 'react'\nimport { useVirtualizer, VirtualItem, Virtualizer } from '@tanstack/react-virtual'\n// TanStack Table imports\nimport {\n useReactTable,\n getCoreRowModel,\n getFilteredRowModel,\n getExpandedRowModel,\n filterFns,\n flexRender,\n Row,\n OnChangeFn,\n getSortedRowModel,\n Cell,\n Column,\n functionalUpdate,\n ColumnSizingState,\n Table,\n Header,\n HeaderGroup,\n} from '@tanstack/react-table'\n\n// Utility imports\nimport clsx from 'clsx'\n\n// Type imports\nimport type { FolderNodeMap, TableRow, TaskNodeMap } from './types/table'\n\n// Component imports\nimport ProjectTreeTableColumns from './ProjectTreeTableColumns'\nimport * as Styled from './ProjectTreeTable.styled'\nimport HeaderActionButton from './components/HeaderActionButton'\nimport EmptyPlaceholder from '../../components/EmptyPlaceholder'\n\n// Context imports\nimport { useCellEditing } from './context/CellEditingContext'\nimport { ROW_SELECTION_COLUMN_ID, useSelectionCellsContext } from './context/SelectionCellsContext'\nimport { ClipboardProvider } from './context/ClipboardContext'\nimport { useSelectedRowsContext } from './context/SelectedRowsContext'\nimport { useColumnSettings } from './context/ColumnSettingsContext'\n\n// Hook imports\nimport useCustomColumnWidthVars from './hooks/useCustomColumnWidthVars'\nimport usePrefetchFolderTasks from './hooks/usePrefetchFolderTasks'\nimport { useLocalStorage } from '../../hooks'\nimport useCellContextMenu from './hooks/useCellContextMenu'\nimport useColumnVirtualization from './hooks/useColumnVirtualization'\nimport useKeyboardNavigation from './hooks/useKeyboardNavigation'\n\n// Utility function imports\nimport { getCellId } from './utils/cellUtils'\nimport { generateLoadingRows, generateDummyAttributes } from './utils/loadingUtils'\nimport { createPortal } from 'react-dom'\nimport { Icon } from '@ynput/ayon-react-components'\nimport { AttributeEnumItem, AttributeWithPermissions, BuiltInFieldOptions } from './types'\nimport { useProjectTableContext } from './context/ProjectTableContext'\n\n//These are the important styles to make sticky column pinning work!\n//Apply styles like this using your CSS strategy of choice with this kind of logic to head cells, data cells, footer cells, etc.\n//View the index.css file for more needed styles such as border-collapse: separate\nconst getCommonPinningStyles = (column: Column<TableRow, unknown>): CSSProperties => {\n const isPinned = column.getIsPinned()\n\n return {\n left: isPinned === 'left' ? `${column.getStart('left')}px` : undefined,\n right: isPinned === 'right' ? `${column.getAfter('right')}px` : undefined,\n position: isPinned ? 'sticky' : 'relative',\n width: column.getSize(),\n zIndex: isPinned ? 100 : 0,\n }\n}\n\ninterface Props extends React.HTMLAttributes<HTMLDivElement> {\n scope: string\n options: BuiltInFieldOptions\n attribs: AttributeWithPermissions[]\n sliceId: string\n // metadata\n fetchMoreOnBottomReached: (element: HTMLDivElement | null) => void\n onOpenNew?: (type: 'folder' | 'task') => void\n // pass through props\n pt?: {\n container?: React.HTMLAttributes<HTMLDivElement>\n head?: Partial<TableHeadProps>\n }\n}\n\n// Component to wrap with all providers\nconst FlexTableWithProviders = (props: Props) => {\n return (\n <ClipboardProvider options={props.options}>\n <FlexTable {...props} />\n </ClipboardProvider>\n )\n}\n\nconst FlexTable = ({\n scope,\n attribs,\n options,\n sliceId,\n fetchMoreOnBottomReached,\n onOpenNew,\n pt,\n ...props\n}: Props) => {\n const {\n columnVisibility,\n columnVisibilityUpdater,\n columnPinning,\n columnPinningUpdater,\n columnOrder,\n columnOrderUpdater,\n } = useColumnSettings()\n\n const {\n tableData,\n isLoading,\n isInitialized,\n expanded,\n updateExpanded,\n toggleExpandAll,\n toggleExpanded,\n sorting,\n updateSorting,\n showHierarchy,\n } = useProjectTableContext()\n\n //The virtualizer needs to know the scrollable container element\n const tableContainerRef = useRef<HTMLDivElement>(null)\n\n // Selection context\n const { registerGrid } = useSelectionCellsContext()\n\n // COLUMN SIZING\n const [columnSizing, setColumnSizing] = useLocalStorage<ColumnSizingState>(\n `column-widths-${scope}`,\n {},\n )\n\n const updateColumnSizing: OnChangeFn<ColumnSizingState> = (columnSizingUpdater) => {\n setColumnSizing(functionalUpdate(columnSizingUpdater, columnSizing))\n }\n\n //a check on mount and after a fetch to see if the table is already scrolled to the bottom and immediately needs to fetch more data\n useEffect(() => {\n fetchMoreOnBottomReached(tableContainerRef.current)\n }, [fetchMoreOnBottomReached])\n\n // generate loading attrib and rows\n const { loadingAttrib, loadingRows } = useMemo(() => {\n // count the number of children in tbody\n const tableRowsCount = tableContainerRef.current?.querySelectorAll('tbody tr').length || 0\n const loadingAttrib = generateDummyAttributes()\n const loadingRows = generateLoadingRows(\n attribs,\n showHierarchy && tableData.length > 0 ? Math.min(tableRowsCount, 50) : 50,\n )\n return { loadingAttrib, loadingRows }\n }, [attribs, tableData, showHierarchy, tableContainerRef.current])\n\n const showLoadingRows = !isInitialized || isLoading\n\n const columns = ProjectTreeTableColumns({\n tableData: showLoadingRows ? loadingRows : tableData,\n columnSizing,\n attribs: isInitialized ? attribs : loadingAttrib,\n isLoading: !isInitialized,\n showHierarchy,\n sliceId,\n options,\n toggleExpandAll: (id: string) => toggleExpandAll([id]),\n toggleExpanded: (id: string) => toggleExpanded(id),\n })\n\n const table = useReactTable({\n data: showLoadingRows ? loadingRows : tableData,\n columns,\n enableRowSelection: true, //enable row selection for all rows\n getRowId: (row) => row.id,\n enableSubRowSelection: false, //disable sub row selection\n getSubRows: (row) => row.subRows,\n getRowCanExpand: () => true,\n getCoreRowModel: getCoreRowModel(),\n getFilteredRowModel: getFilteredRowModel(),\n getExpandedRowModel: getExpandedRowModel(),\n filterFromLeafRows: true,\n // EXPANDABLE\n onExpandedChange: updateExpanded,\n // SORTING\n getSortedRowModel: getSortedRowModel(),\n onSortingChange: updateSorting,\n columnResizeMode: 'onChange',\n onColumnPinningChange: columnPinningUpdater,\n onColumnSizingChange: updateColumnSizing,\n onColumnVisibilityChange: columnVisibilityUpdater,\n onColumnOrderChange: columnOrderUpdater,\n // @ts-ignore\n filterFns,\n state: {\n expanded,\n sorting,\n columnPinning: {\n left: [ROW_SELECTION_COLUMN_ID, ...(columnPinning.left || [])],\n right: columnPinning.right,\n },\n columnSizing,\n columnVisibility,\n columnOrder,\n },\n enableSorting: true,\n })\n\n const { rows } = table.getRowModel()\n\n // Register grid structure with selection context when rows or columns change\n useEffect(() => {\n const rowIds = rows.map((row) => row.id)\n const colIds = table.getAllLeafColumns().map((col) => col.id)\n const colIdsSortedByPinning = [...colIds].sort((a, b) => {\n if (ROW_SELECTION_COLUMN_ID === b) return 1\n const colA = columnPinning.left?.includes(a) ? 0 : 1\n const colB = columnPinning.left?.includes(b) ? 0 : 1\n return colA - colB\n })\n\n registerGrid(rowIds, colIdsSortedByPinning)\n }, [rows, table.getAllLeafColumns(), columnPinning, ROW_SELECTION_COLUMN_ID, registerGrid])\n\n const visibleColumns = table.getVisibleLeafColumns()\n\n // Use the column virtualization hook\n const { columnVirtualizer, virtualPaddingLeft, virtualPaddingRight } = useColumnVirtualization({\n visibleColumns,\n tableContainerRef,\n columnPinning,\n })\n\n const columnSizeVars = useCustomColumnWidthVars(table, columnSizing)\n const readOnlyColumns = useMemo(\n () => attribs.filter((attrib) => attrib.readOnly).map((attrib) => 'attrib_' + attrib.name),\n [attribs],\n )\n\n return (\n <Styled.TableWrapper {...props}>\n <Styled.TableContainer\n ref={tableContainerRef}\n style={{ height: '100%', padding: 0 }}\n onScroll={(e) => fetchMoreOnBottomReached(e.currentTarget)}\n {...pt?.container}\n className={clsx('table-container', pt?.container?.className)}\n >\n <table\n style={{\n display: 'grid',\n borderCollapse: 'collapse',\n userSelect: 'none',\n ...columnSizeVars,\n width: table.getTotalSize(),\n }}\n >\n <TableHead\n columnVirtualizer={columnVirtualizer}\n table={table}\n virtualPaddingLeft={virtualPaddingLeft}\n virtualPaddingRight={virtualPaddingRight}\n isLoading={isLoading}\n readOnlyColumns={readOnlyColumns}\n {...pt?.head}\n />\n <TableBody\n columnVirtualizer={columnVirtualizer}\n table={table}\n tableContainerRef={tableContainerRef}\n virtualPaddingLeft={virtualPaddingLeft}\n virtualPaddingRight={virtualPaddingRight}\n showHierarchy={showHierarchy}\n attribs={attribs}\n onOpenNew={onOpenNew}\n />\n </table>\n </Styled.TableContainer>\n </Styled.TableWrapper>\n )\n}\n\ninterface TableHeadProps extends React.HTMLAttributes<HTMLTableSectionElement> {\n columnVirtualizer: Virtualizer<HTMLDivElement, HTMLTableCellElement>\n table: Table<TableRow>\n virtualPaddingLeft: number | undefined\n virtualPaddingRight: number | undefined\n isLoading: boolean\n readOnlyColumns?: string[]\n}\n\nconst TableHead = ({\n columnVirtualizer,\n table,\n virtualPaddingLeft,\n virtualPaddingRight,\n isLoading,\n readOnlyColumns,\n ...props\n}: TableHeadProps) => {\n return (\n <Styled.TableHeader {...props}>\n {table.getHeaderGroups().map((headerGroup) => (\n <TableHeadRow\n key={headerGroup.id}\n columnVirtualizer={columnVirtualizer}\n headerGroup={headerGroup}\n virtualPaddingLeft={virtualPaddingLeft}\n virtualPaddingRight={virtualPaddingRight}\n isLoading={isLoading}\n readOnlyColumns={readOnlyColumns}\n />\n ))}\n </Styled.TableHeader>\n )\n}\n\ninterface TableHeadRowProps {\n columnVirtualizer: Virtualizer<HTMLDivElement, HTMLTableCellElement>\n headerGroup: HeaderGroup<TableRow>\n virtualPaddingLeft: number | undefined\n virtualPaddingRight: number | undefined\n isLoading: boolean\n readOnlyColumns?: string[]\n}\n\nconst TableHeadRow = ({\n columnVirtualizer,\n headerGroup,\n virtualPaddingLeft,\n virtualPaddingRight,\n isLoading,\n readOnlyColumns,\n}: TableHeadRowProps) => {\n const virtualColumns = columnVirtualizer.getVirtualItems()\n return (\n <Styled.ColumnHeader key={headerGroup.id} style={{ display: 'flex' }}>\n {virtualPaddingLeft ? (\n //fake empty column to the left for virtualization scroll padding\n <th style={{ display: 'flex', width: virtualPaddingLeft }} />\n ) : null}\n {virtualColumns.map((virtualColumn) => {\n const header = headerGroup.headers[virtualColumn.index]\n return (\n <TableHeadCell\n key={header.id}\n header={header}\n isLoading={isLoading}\n isReadOnly={readOnlyColumns?.includes(header.id)}\n />\n )\n })}\n {virtualPaddingRight ? (\n //fake empty column to the right for virtualization scroll padding\n <th style={{ display: 'flex', width: virtualPaddingRight }} />\n ) : null}\n </Styled.ColumnHeader>\n )\n}\n\ninterface TableHeadCellProps {\n header: Header<TableRow, unknown>\n isLoading: boolean\n isReadOnly?: boolean\n}\n\nconst TableHeadCell = ({ header, isLoading, isReadOnly }: TableHeadCellProps) => {\n const { column } = header\n const isRowSelectionColumn = column.id === ROW_SELECTION_COLUMN_ID\n\n return (\n <Styled.HeaderCell\n className={clsx(header.id, 'shimmer-dark', {\n loading: isLoading,\n large: column.id === 'folderType',\n 'last-pinned-left': column.getIsPinned() === 'left' && column.getIsLastColumn('left'),\n })}\n key={header.id}\n style={{\n ...getCommonPinningStyles(column),\n width: `calc(var(--header-${header?.id}-size) * 1px)`,\n }}\n >\n {header.isPlaceholder ? null : (\n <Styled.TableCellContent\n className={clsx('bold', {\n large: column.id === 'folderType',\n })}\n >\n {flexRender(column.columnDef.header, header.getContext())}\n {isReadOnly && (\n <Icon icon=\"lock\" data-tooltip={'You only have permission to read this column.'} />\n )}\n\n <Styled.HeaderButtons className=\"actions\">\n {/* COLUMN HIDING */}\n <HeaderActionButton\n icon=\"visibility_off\"\n selected={!column.getIsVisible()}\n onClick={column.getToggleVisibilityHandler()}\n />\n {/* COLUMN SORTING */}\n <HeaderActionButton\n icon=\"push_pin\"\n selected={header.column.getIsPinned() === 'left'}\n onClick={() => {\n if (header.column.getIsPinned() === 'left') {\n header.column.pin(false)\n } else {\n header.column.pin('left')\n }\n }}\n />\n {/* COLUMN PINNING */}\n <HeaderActionButton\n icon={'sort'}\n style={{\n transform: (column.getIsSorted() as string) === 'asc' ? 'scaleY(-1)' : undefined,\n }}\n onClick={column.getToggleSortingHandler()}\n selected={!!column.getIsSorted()}\n />\n </Styled.HeaderButtons>\n {!isRowSelectionColumn && (\n <Styled.ResizedHandler\n {...{\n onDoubleClick: () => column.resetSize(),\n onMouseDown: header.getResizeHandler(),\n onTouchStart: header.getResizeHandler(),\n className: clsx('resize-handle', {\n resizing: column.getIsResizing(),\n }),\n }}\n />\n )}\n </Styled.TableCellContent>\n )}\n </Styled.HeaderCell>\n )\n}\n\ninterface TableBodyProps {\n columnVirtualizer: Virtualizer<HTMLDivElement, HTMLTableCellElement>\n table: Table<TableRow>\n tableContainerRef: React.RefObject<HTMLDivElement>\n showHierarchy: boolean\n virtualPaddingLeft: number | undefined\n virtualPaddingRight: number | undefined\n attribs: AttributeWithPermissions[]\n onOpenNew?: (type: 'folder' | 'task') => void\n}\n\nconst TableBody = ({\n columnVirtualizer,\n table,\n tableContainerRef,\n showHierarchy,\n virtualPaddingLeft,\n virtualPaddingRight,\n attribs,\n onOpenNew,\n}: TableBodyProps) => {\n const { handleTableBodyContextMenu } = useCellContextMenu({ attribs, onOpenNew })\n\n const { handlePreFetchTasks } = usePrefetchFolderTasks()\n\n const { rows } = table.getRowModel()\n\n const rowVirtualizer = useVirtualizer<HTMLDivElement, HTMLTableRowElement>({\n count: rows.length,\n estimateSize: () => (showHierarchy ? 36 : 40), //estimate row height for accurate scrollbar dragging\n getScrollElement: () => tableContainerRef.current,\n //measure dynamic row height, except in firefox because it measures table border height incorrectly\n measureElement:\n typeof window !== 'undefined' && navigator.userAgent.indexOf('Firefox') === -1\n ? (element) => element?.getBoundingClientRect().height\n : undefined,\n overscan: 5,\n })\n\n const virtualRows = rowVirtualizer.getVirtualItems()\n\n useKeyboardNavigation()\n\n return virtualRows.length ? (\n <tbody\n style={{\n height: `${rowVirtualizer.getTotalSize()}px`,\n position: 'relative',\n display: 'grid',\n }}\n onContextMenu={handleTableBodyContextMenu}\n onMouseOver={(e) => {\n handlePreFetchTasks(e)\n }}\n >\n {virtualRows.map((virtualRow) => {\n const row = rows[virtualRow.index] as Row<TableRow>\n return (\n <TableBodyRow\n key={row.id}\n columnVirtualizer={columnVirtualizer}\n row={row}\n rowVirtualizer={rowVirtualizer}\n virtualPaddingLeft={virtualPaddingLeft}\n virtualPaddingRight={virtualPaddingRight}\n virtualRow={virtualRow}\n showHierarchy={showHierarchy}\n />\n )\n })}\n </tbody>\n ) : (\n tableContainerRef.current &&\n createPortal(\n <EmptyPlaceholder message=\"No folders or tasks found\" />,\n tableContainerRef.current,\n )\n )\n}\n\ninterface TableBodyRowProps {\n columnVirtualizer: Virtualizer<HTMLDivElement, HTMLTableCellElement>\n row: Row<TableRow>\n rowVirtualizer: Virtualizer<HTMLDivElement, HTMLTableRowElement>\n virtualPaddingLeft: number | undefined\n virtualPaddingRight: number | undefined\n virtualRow: VirtualItem\n showHierarchy: boolean\n}\n\nconst TableBodyRow = ({\n columnVirtualizer,\n row,\n rowVirtualizer,\n virtualPaddingLeft,\n virtualPaddingRight,\n virtualRow,\n showHierarchy,\n}: TableBodyRowProps) => {\n // We should do this so that we don't re-render every time anything in projectTableContext changes\n const visibleCells = row.getVisibleCells()\n const virtualColumns = columnVirtualizer.getVirtualItems()\n\n return (\n <Styled.TR\n data-index={virtualRow.index} //needed for dynamic row height measurement\n ref={(node) => rowVirtualizer.measureElement(node)} //measure dynamic row height\n key={row.id}\n style={{\n transform: `translateY(${virtualRow.start}px)`, //this should always be a `style` as it changes on scroll\n }}\n >\n {virtualPaddingLeft ? (\n //fake empty column to the left for virtualization scroll padding\n <td style={{ display: 'flex', width: virtualPaddingLeft }} />\n ) : null}\n {virtualColumns.map((vc) => {\n const cell = visibleCells[vc.index]\n const cellId = getCellId(row.id, cell.column.id)\n return (\n <TableCellMemo\n cell={cell}\n cellId={cellId}\n rowId={row.id}\n key={cell.id}\n showHierarchy={showHierarchy}\n />\n )\n })}\n\n {virtualPaddingRight ? (\n //fake empty column to the right for virtualization scroll padding\n <td style={{ display: 'flex', width: virtualPaddingRight }} />\n ) : null}\n </Styled.TR>\n )\n}\n\ninterface TableCellProps {\n cell: Cell<TableRow, unknown>\n cellId: string\n rowId: string\n className?: string\n showHierarchy: boolean\n}\n\nconst TableCell = ({ cell, rowId, cellId, className, showHierarchy, ...props }: TableCellProps) => {\n const {\n isCellSelected,\n isCellFocused,\n startSelection,\n extendSelection,\n endSelection,\n selectCell,\n getCellBorderClasses,\n } = useSelectionCellsContext()\n\n const { isRowSelected } = useSelectedRowsContext()\n\n const { isEditing } = useCellEditing()\n\n const borderClasses = getCellBorderClasses(cellId)\n\n const isPinned = cell.column.getIsPinned()\n const isLastLeftPinnedColumn = isPinned === 'left' && cell.column.getIsLastColumn('left')\n const isRowSelectionColumn = cell.column.id === ROW_SELECTION_COLUMN_ID\n\n return (\n <Styled.TableCell\n {...props}\n tabIndex={0}\n key={cell.id}\n $isLastPinned={isLastLeftPinnedColumn} // is this column the last pinned column? Custom styling for borders.\n className={clsx(\n cell.column.id,\n cell.column.id === 'folderType' ? 'large' : '',\n {\n selected: isCellSelected(cellId),\n focused: isCellFocused(cellId),\n editing: isEditing(cellId),\n 'last-pinned-left': isLastLeftPinnedColumn,\n 'selected-row': isRowSelected(rowId),\n task: cell.row.original.entityType === 'task',\n },\n className,\n ...borderClasses,\n )}\n style={{\n ...getCommonPinningStyles(cell.column),\n width: `calc(var(--col-${cell.column.id}-size) * 1px)`,\n height: showHierarchy ? 36 : 40,\n }}\n onMouseDown={(e) => {\n // Only process left clicks (button 0), ignore right clicks\n if (e.button !== 0) return\n\n // check we are not clicking on expander\n if ((e.target as HTMLElement).closest('.expander')) return\n const additive = e.metaKey || e.ctrlKey || isRowSelectionColumn\n if (e.shiftKey) {\n // Shift+click extends selection from anchor cell\n selectCell(cellId, additive, true) // true for range selection\n } else {\n // Normal click starts a new selection\n startSelection(cellId, additive)\n }\n }}\n onMouseOver={(e) => {\n if (e.buttons === 1) {\n // Left button is pressed during mouse move - drag selection\n extendSelection(cellId, isRowSelectionColumn)\n }\n }}\n onMouseUp={() => {\n endSelection(cellId)\n }}\n onDoubleClick={(e) => {\n if (cell.column.id === 'name') {\n // select the row by selecting the row-selection cell\n const rowSelectionCellId = getCellId(cell.row.id, ROW_SELECTION_COLUMN_ID)\n if (!isCellSelected(rowSelectionCellId)) {\n const additive = e.metaKey || e.ctrlKey\n selectCell(rowSelectionCellId, additive, false)\n }\n }\n }}\n onContextMenu={(e) => {\n e.preventDefault()\n // if the cell is not selected, select it and deselect all others\n if (!isCellSelected(cellId)) {\n selectCell(cellId, false, false)\n }\n }}\n >\n {flexRender(cell.column.columnDef.cell, cell.getContext())}\n </Styled.TableCell>\n )\n}\n\nconst TableCellMemo = memo(TableCell)\n\nexport { FlexTableWithProviders as ProjectTreeTable }\n"],"names":["jsx","ClipboardProvider","useColumnSettings","useProjectTableContext","useRef","useSelectionCellsContext","useLocalStorage","functionalUpdate","useEffect","useMemo","_a","loadingAttrib","generateDummyAttributes","loadingRows","generateLoadingRows","useReactTable","getCoreRowModel","getFilteredRowModel","getExpandedRowModel","getSortedRowModel","filterFns","ROW_SELECTION_COLUMN_ID","Styled.TableWrapper","Styled.TableContainer","jsxs","Styled.TableHeader","Styled.ColumnHeader","Styled.HeaderCell","Styled.TableCellContent","flexRender","Icon","Styled.HeaderButtons","Styled.ResizedHandler","usePrefetchFolderTasks","useVirtualizer","createPortal","EmptyPlaceholder","Styled.TR","getCellId","useSelectedRowsContext","useCellEditing","createElement","Styled.TableCell","memo"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4DA,MAAM,yBAAyB,CAAC,WAAqD;AAC7E,QAAA,WAAW,OAAO,YAAY;AAE7B,SAAA;AAAA,IACL,MAAM,aAAa,SAAS,GAAG,OAAO,SAAS,MAAM,CAAC,OAAO;AAAA,IAC7D,OAAO,aAAa,UAAU,GAAG,OAAO,SAAS,OAAO,CAAC,OAAO;AAAA,IAChE,UAAU,WAAW,WAAW;AAAA,IAChC,OAAO,OAAO,QAAQ;AAAA,IACtB,QAAQ,WAAW,MAAM;AAAA,EAC3B;AACF;AAkBM,MAAA,yBAAyB,CAAC,UAAiB;AAE7C,SAAAA,2BAAA,kBAAA,IAACC,sCAAkB,SAAS,MAAM,SAChC,UAACD,2BAAAA,kBAAAA,IAAA,WAAA,EAAW,GAAG,MAAA,CAAO,EACxB,CAAA;AAEJ;AAEA,MAAM,YAAY,CAAC;AAAA,EACjB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,MAAa;;AACL,QAAA;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,MACEE,wCAAkB;AAEhB,QAAA;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,MACEC,2CAAuB;AAGrB,QAAA,oBAAoBC,aAAuB,IAAI;AAG/C,QAAA,EAAE,aAAa,IAAIC,+CAAyB;AAG5C,QAAA,CAAC,cAAc,eAAe,IAAIC,gBAAA;AAAA,IACtC,iBAAiB,KAAK;AAAA,IACtB,CAAA;AAAA,EACF;AAEM,QAAA,qBAAoD,CAAC,wBAAwB;AACjE,oBAAAC,WAAA,iBAAiB,qBAAqB,YAAY,CAAC;AAAA,EACrE;AAGAC,QAAAA,UAAU,MAAM;AACd,6BAAyB,kBAAkB,OAAO;AAAA,EAAA,GACjD,CAAC,wBAAwB,CAAC;AAG7B,QAAM,EAAE,eAAe,YAAY,IAAIC,cAAQ,MAAM;;AAEnD,UAAM,mBAAiBC,MAAA,kBAAkB,YAAlB,gBAAAA,IAA2B,iBAAiB,YAAY,WAAU;AACzF,UAAMC,iBAAgBC,aAAAA,wBAAwB;AAC9C,UAAMC,eAAcC,aAAA;AAAA,MAClB;AAAA,MACA,iBAAiB,UAAU,SAAS,IAAI,KAAK,IAAI,gBAAgB,EAAE,IAAI;AAAA,IACzE;AACA,WAAO,EAAE,eAAAH,gBAAe,aAAAE,aAAY;AAAA,EAAA,GACnC,CAAC,SAAS,WAAW,eAAe,kBAAkB,OAAO,CAAC;AAE3D,QAAA,kBAAkB,CAAC,iBAAiB;AAE1C,QAAM,UAAU,wBAAwB;AAAA,IACtC,WAAW,kBAAkB,cAAc;AAAA,IAC3C;AAAA,IACA,SAAS,gBAAgB,UAAU;AAAA,IACnC,WAAW,CAAC;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA,iBAAiB,CAAC,OAAe,gBAAgB,CAAC,EAAE,CAAC;AAAA,IACrD,gBAAgB,CAAC,OAAe,eAAe,EAAE;AAAA,EAAA,CAClD;AAED,QAAM,QAAQE,WAAAA,cAAc;AAAA,IAC1B,MAAM,kBAAkB,cAAc;AAAA,IACtC;AAAA,IACA,oBAAoB;AAAA;AAAA,IACpB,UAAU,CAAC,QAAQ,IAAI;AAAA,IACvB,uBAAuB;AAAA;AAAA,IACvB,YAAY,CAAC,QAAQ,IAAI;AAAA,IACzB,iBAAiB,MAAM;AAAA,IACvB,iBAAiBC,WAAAA,gBAAgB;AAAA,IACjC,qBAAqBC,WAAAA,oBAAoB;AAAA,IACzC,qBAAqBC,WAAAA,oBAAoB;AAAA,IACzC,oBAAoB;AAAA;AAAA,IAEpB,kBAAkB;AAAA;AAAA,IAElB,mBAAmBC,WAAAA,kBAAkB;AAAA,IACrC,iBAAiB;AAAA,IACjB,kBAAkB;AAAA,IAClB,uBAAuB;AAAA,IACvB,sBAAsB;AAAA,IACtB,0BAA0B;AAAA,IAC1B,qBAAqB;AAAA;AAAA,IAAA,WAErBC,WAAA;AAAA,IACA,OAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,eAAe;AAAA,QACb,MAAM,CAACC,sBAAA,yBAAyB,GAAI,cAAc,QAAQ,CAAA,CAAG;AAAA,QAC7D,OAAO,cAAc;AAAA,MACvB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,eAAe;AAAA,EAAA,CAChB;AAED,QAAM,EAAE,KAAA,IAAS,MAAM,YAAY;AAGnCb,QAAAA,UAAU,MAAM;AACd,UAAM,SAAS,KAAK,IAAI,CAAC,QAAQ,IAAI,EAAE;AACjC,UAAA,SAAS,MAAM,kBAAkB,EAAE,IAAI,CAAC,QAAQ,IAAI,EAAE;AACtD,UAAA,wBAAwB,CAAC,GAAG,MAAM,EAAE,KAAK,CAAC,GAAG,MAAM;;AACnD,UAAAa,sBAAA,4BAA4B,EAAU,QAAA;AAC1C,YAAM,SAAOX,MAAA,cAAc,SAAd,gBAAAA,IAAoB,SAAS,MAAK,IAAI;AACnD,YAAM,SAAO,mBAAc,SAAd,mBAAoB,SAAS,MAAK,IAAI;AACnD,aAAO,OAAO;AAAA,IAAA,CACf;AAED,iBAAa,QAAQ,qBAAqB;AAAA,EAAA,GACzC,CAAC,MAAM,MAAM,kBAAqB,GAAA,eAAeW,sBAAAA,yBAAyB,YAAY,CAAC;AAEpF,QAAA,iBAAiB,MAAM,sBAAsB;AAGnD,QAAM,EAAE,mBAAmB,oBAAoB,oBAAA,IAAwB,wBAAwB;AAAA,IAC7F;AAAA,IACA;AAAA,IACA;AAAA,EAAA,CACD;AAEK,QAAA,iBAAiB,yBAAyB,OAAO,YAAY;AACnE,QAAM,kBAAkBZ,MAAA;AAAA,IACtB,MAAM,QAAQ,OAAO,CAAC,WAAW,OAAO,QAAQ,EAAE,IAAI,CAAC,WAAW,YAAY,OAAO,IAAI;AAAA,IACzF,CAAC,OAAO;AAAA,EACV;AAEA,SACGT,2BAAA,kBAAA,IAAAsB,wBAAA,cAAA,EAAqB,GAAG,OACvB,UAAAtB,2BAAA,kBAAA;AAAA,IAACuB,wBAAO;AAAA,IAAP;AAAA,MACC,KAAK;AAAA,MACL,OAAO,EAAE,QAAQ,QAAQ,SAAS,EAAE;AAAA,MACpC,UAAU,CAAC,MAAM,yBAAyB,EAAE,aAAa;AAAA,MACxD,GAAG,yBAAI;AAAA,MACR,WAAW,KAAK,oBAAmB,8BAAI,cAAJ,mBAAe,SAAS;AAAA,MAE3D,UAAAC,2BAAA,kBAAA;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,OAAO;AAAA,YACL,SAAS;AAAA,YACT,gBAAgB;AAAA,YAChB,YAAY;AAAA,YACZ,GAAG;AAAA,YACH,OAAO,MAAM,aAAa;AAAA,UAC5B;AAAA,UAEA,UAAA;AAAA,YAAAxB,2BAAA,kBAAA;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC;AAAA,gBACA;AAAA,gBACA;AAAA,gBACA;AAAA,gBACA;AAAA,gBACA;AAAA,gBACC,GAAG,yBAAI;AAAA,cAAA;AAAA,YACV;AAAA,YACAA,2BAAA,kBAAA;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC;AAAA,gBACA;AAAA,gBACA;AAAA,gBACA;AAAA,gBACA;AAAA,gBACA;AAAA,gBACA;AAAA,gBACA;AAAA,cAAA;AAAA,YAAA;AAAA,UACF;AAAA,QAAA;AAAA,MAAA;AAAA,IACF;AAAA,EAAA,GAEJ;AAEJ;AAWA,MAAM,YAAY,CAAC;AAAA,EACjB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,MAAsB;AAElB,SAAAA,iDAACyB,wBAAAA,aAAA,EAAoB,GAAG,OACrB,UAAA,MAAM,gBAAgB,EAAE,IAAI,CAAC,gBAC5BzB,2BAAA,kBAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MAEC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAAA,IANK,YAAY;AAAA,EAQpB,CAAA,GACH;AAEJ;AAWA,MAAM,eAAe,CAAC;AAAA,EACpB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAyB;AACjB,QAAA,iBAAiB,kBAAkB,gBAAgB;AAEvD,SAAAwB,2BAAAA,kBAAAA,KAACE,wBAAAA,cAAA,EAAyC,OAAO,EAAE,SAAS,OACzD,GAAA,UAAA;AAAA,IAAA;AAAA;AAAA,MAEC1B,iDAAC,QAAG,OAAO,EAAE,SAAS,QAAQ,OAAO,qBAAsB,CAAA;AAAA,QACzD;AAAA,IACH,eAAe,IAAI,CAAC,kBAAkB;AACrC,YAAM,SAAS,YAAY,QAAQ,cAAc,KAAK;AAEpD,aAAAA,2BAAA,kBAAA;AAAA,QAAC;AAAA,QAAA;AAAA,UAEC;AAAA,UACA;AAAA,UACA,YAAY,mDAAiB,SAAS,OAAO;AAAA,QAAE;AAAA,QAH1C,OAAO;AAAA,MAId;AAAA,IAAA,CAEH;AAAA,IACA;AAAA;AAAA,MAECA,iDAAC,QAAG,OAAO,EAAE,SAAS,QAAQ,OAAO,sBAAuB,CAAA;AAAA,QAC1D;AAAA,EAAA,EAAA,GAnBoB,YAAY,EAoBtC;AAEJ;AAQA,MAAM,gBAAgB,CAAC,EAAE,QAAQ,WAAW,iBAAqC;AACzE,QAAA,EAAE,WAAW;AACb,QAAA,uBAAuB,OAAO,OAAOqB,sBAAA;AAGzC,SAAArB,2BAAA,kBAAA;AAAA,IAAC2B,wBAAO;AAAA,IAAP;AAAA,MACC,WAAW,KAAK,OAAO,IAAI,gBAAgB;AAAA,QACzC,SAAS;AAAA,QACT,OAAO,OAAO,OAAO;AAAA,QACrB,oBAAoB,OAAO,YAAA,MAAkB,UAAU,OAAO,gBAAgB,MAAM;AAAA,MAAA,CACrF;AAAA,MAED,OAAO;AAAA,QACL,GAAG,uBAAuB,MAAM;AAAA,QAChC,OAAO,qBAAqB,iCAAQ,EAAE;AAAA,MACxC;AAAA,MAEC,UAAA,OAAO,gBAAgB,OACtBH,2BAAA,kBAAA;AAAA,QAACI,wBAAO;AAAA,QAAP;AAAA,UACC,WAAW,KAAK,QAAQ;AAAA,YACtB,OAAO,OAAO,OAAO;AAAA,UAAA,CACtB;AAAA,UAEA,UAAA;AAAA,YAAAC,WAAA,WAAW,OAAO,UAAU,QAAQ,OAAO,YAAY;AAAA,YACvD,cACE7B,2BAAA,kBAAA,IAAA8B,0BAAA,EAAK,MAAK,QAAO,gBAAc,iDAAiD;AAAA,YAGlFN,2BAAAA,kBAAAA,KAAAO,wBAAAA,eAAA,EAAqB,WAAU,WAE9B,UAAA;AAAA,cAAA/B,2BAAA,kBAAA;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,MAAK;AAAA,kBACL,UAAU,CAAC,OAAO,aAAa;AAAA,kBAC/B,SAAS,OAAO,2BAA2B;AAAA,gBAAA;AAAA,cAC7C;AAAA,cAEAA,2BAAA,kBAAA;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,MAAK;AAAA,kBACL,UAAU,OAAO,OAAO,YAAkB,MAAA;AAAA,kBAC1C,SAAS,MAAM;AACb,wBAAI,OAAO,OAAO,YAAY,MAAM,QAAQ;AACnC,6BAAA,OAAO,IAAI,KAAK;AAAA,oBAAA,OAClB;AACE,6BAAA,OAAO,IAAI,MAAM;AAAA,oBAAA;AAAA,kBAC1B;AAAA,gBACF;AAAA,cACF;AAAA,cAEAA,2BAAA,kBAAA;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,MAAM;AAAA,kBACN,OAAO;AAAA,oBACL,WAAY,OAAO,kBAA6B,QAAQ,eAAe;AAAA,kBACzE;AAAA,kBACA,SAAS,OAAO,wBAAwB;AAAA,kBACxC,UAAU,CAAC,CAAC,OAAO,YAAY;AAAA,gBAAA;AAAA,cAAA;AAAA,YACjC,GACF;AAAA,YACC,CAAC,wBACAA,2BAAA,kBAAA;AAAA,cAACgC,wBAAO;AAAA,cAAP;AAAA,gBACE,GAAG;AAAA,kBACF,eAAe,MAAM,OAAO,UAAU;AAAA,kBACtC,aAAa,OAAO,iBAAiB;AAAA,kBACrC,cAAc,OAAO,iBAAiB;AAAA,kBACtC,WAAW,KAAK,iBAAiB;AAAA,oBAC/B,UAAU,OAAO,cAAc;AAAA,kBAChC,CAAA;AAAA,gBAAA;AAAA,cACH;AAAA,YAAA;AAAA,UACF;AAAA,QAAA;AAAA,MAAA;AAAA,IAEJ;AAAA,IA1DG,OAAO;AAAA,EA4Dd;AAEJ;AAaA,MAAM,YAAY,CAAC;AAAA,EACjB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAsB;AACpB,QAAM,EAAE,2BAA2B,IAAI,mBAAmB,EAAE,SAAS,WAAW;AAE1E,QAAA,EAAE,oBAAoB,IAAIC,8CAAuB;AAEvD,QAAM,EAAE,KAAA,IAAS,MAAM,YAAY;AAEnC,QAAM,iBAAiBC,aAAAA,eAAoD;AAAA,IACzE,OAAO,KAAK;AAAA,IACZ,cAAc,MAAO,gBAAgB,KAAK;AAAA;AAAA,IAC1C,kBAAkB,MAAM,kBAAkB;AAAA;AAAA,IAE1C,gBACE,OAAO,WAAW,eAAe,UAAU,UAAU,QAAQ,SAAS,MAAM,KACxE,CAAC,YAAY,mCAAS,wBAAwB,SAC9C;AAAA,IACN,UAAU;AAAA,EAAA,CACX;AAEK,QAAA,cAAc,eAAe,gBAAgB;AAE7B,wBAAA;AAEtB,SAAO,YAAY,SACjBlC,2BAAA,kBAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,OAAO;AAAA,QACL,QAAQ,GAAG,eAAe,aAAA,CAAc;AAAA,QACxC,UAAU;AAAA,QACV,SAAS;AAAA,MACX;AAAA,MACA,eAAe;AAAA,MACf,aAAa,CAAC,MAAM;AAClB,4BAAoB,CAAC;AAAA,MACvB;AAAA,MAEC,UAAA,YAAY,IAAI,CAAC,eAAe;AACzB,cAAA,MAAM,KAAK,WAAW,KAAK;AAE/B,eAAAA,2BAAA,kBAAA;AAAA,UAAC;AAAA,UAAA;AAAA,YAEC;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,UAAA;AAAA,UAPK,IAAI;AAAA,QAQX;AAAA,MAEH,CAAA;AAAA,IAAA;AAAA,EAAA,IAGH,kBAAkB,WAChBmC,SAAA;AAAA,IACEnC,2BAAAA,kBAAAA,IAACoC,iBAAiB,kBAAA,EAAA,SAAQ,4BAA4B,CAAA;AAAA,IACtD,kBAAkB;AAAA,EACpB;AAEN;AAYA,MAAM,eAAe,CAAC;AAAA,EACpB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAyB;AAEjB,QAAA,eAAe,IAAI,gBAAgB;AACnC,QAAA,iBAAiB,kBAAkB,gBAAgB;AAGvD,SAAAZ,2BAAA,kBAAA;AAAA,IAACa,wBAAO;AAAA,IAAP;AAAA,MACC,cAAY,WAAW;AAAA,MACvB,KAAK,CAAC,SAAS,eAAe,eAAe,IAAI;AAAA,MAEjD,OAAO;AAAA,QACL,WAAW,cAAc,WAAW,KAAK;AAAA;AAAA,MAC3C;AAAA,MAEC,UAAA;AAAA,QAAA;AAAA;AAAA,UAECrC,iDAAC,QAAG,OAAO,EAAE,SAAS,QAAQ,OAAO,qBAAsB,CAAA;AAAA,YACzD;AAAA,QACH,eAAe,IAAI,CAAC,OAAO;AACpB,gBAAA,OAAO,aAAa,GAAG,KAAK;AAClC,gBAAM,SAASsC,UAAAA,UAAU,IAAI,IAAI,KAAK,OAAO,EAAE;AAE7C,iBAAAtC,2BAAA,kBAAA;AAAA,YAAC;AAAA,YAAA;AAAA,cACC;AAAA,cACA;AAAA,cACA,OAAO,IAAI;AAAA,cAEX;AAAA,YAAA;AAAA,YADK,KAAK;AAAA,UAEZ;AAAA,QAAA,CAEH;AAAA,QAEA;AAAA;AAAA,UAECA,iDAAC,QAAG,OAAO,EAAE,SAAS,QAAQ,OAAO,sBAAuB,CAAA;AAAA,YAC1D;AAAA,MAAA;AAAA,IAAA;AAAA,IA1BC,IAAI;AAAA,EA2BX;AAEJ;AAUA,MAAM,YAAY,CAAC,EAAE,MAAM,OAAO,QAAQ,WAAW,eAAe,GAAG,YAA4B;AAC3F,QAAA;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,MACEK,+CAAyB;AAEvB,QAAA,EAAE,cAAc,IAAIkC,2CAAuB;AAE3C,QAAA,EAAE,UAAU,IAAIC,kCAAe;AAE/B,QAAA,gBAAgB,qBAAqB,MAAM;AAE3C,QAAA,WAAW,KAAK,OAAO,YAAY;AACzC,QAAM,yBAAyB,aAAa,UAAU,KAAK,OAAO,gBAAgB,MAAM;AAClF,QAAA,uBAAuB,KAAK,OAAO,OAAOnB,sBAAA;AAG9C,SAAAoB,sBAAA;AAAA,IAACC,wBAAO;AAAA,IAAP;AAAA,MACE,GAAG;AAAA,MACJ,UAAU;AAAA,MACV,KAAK,KAAK;AAAA,MACV,eAAe;AAAA,MACf,WAAW;AAAA,QACT,KAAK,OAAO;AAAA,QACZ,KAAK,OAAO,OAAO,eAAe,UAAU;AAAA,QAC5C;AAAA,UACE,UAAU,eAAe,MAAM;AAAA,UAC/B,SAAS,cAAc,MAAM;AAAA,UAC7B,SAAS,UAAU,MAAM;AAAA,UACzB,oBAAoB;AAAA,UACpB,gBAAgB,cAAc,KAAK;AAAA,UACnC,MAAM,KAAK,IAAI,SAAS,eAAe;AAAA,QACzC;AAAA,QACA;AAAA,QACA,GAAG;AAAA,MACL;AAAA,MACA,OAAO;AAAA,QACL,GAAG,uBAAuB,KAAK,MAAM;AAAA,QACrC,OAAO,kBAAkB,KAAK,OAAO,EAAE;AAAA,QACvC,QAAQ,gBAAgB,KAAK;AAAA,MAC/B;AAAA,MACA,aAAa,CAAC,MAAM;AAEd,YAAA,EAAE,WAAW,EAAG;AAGpB,YAAK,EAAE,OAAuB,QAAQ,WAAW,EAAG;AACpD,cAAM,WAAW,EAAE,WAAW,EAAE,WAAW;AAC3C,YAAI,EAAE,UAAU;AAEH,qBAAA,QAAQ,UAAU,IAAI;AAAA,QAAA,OAC5B;AAEL,yBAAe,QAAQ,QAAQ;AAAA,QAAA;AAAA,MAEnC;AAAA,MACA,aAAa,CAAC,MAAM;AACd,YAAA,EAAE,YAAY,GAAG;AAEnB,0BAAgB,QAAQ,oBAAoB;AAAA,QAAA;AAAA,MAEhD;AAAA,MACA,WAAW,MAAM;AACf,qBAAa,MAAM;AAAA,MACrB;AAAA,MACA,eAAe,CAAC,MAAM;AAChB,YAAA,KAAK,OAAO,OAAO,QAAQ;AAE7B,gBAAM,qBAAqBJ,UAAAA,UAAU,KAAK,IAAI,IAAIjB,sBAAAA,uBAAuB;AACrE,cAAA,CAAC,eAAe,kBAAkB,GAAG;AACjC,kBAAA,WAAW,EAAE,WAAW,EAAE;AACrB,uBAAA,oBAAoB,UAAU,KAAK;AAAA,UAAA;AAAA,QAChD;AAAA,MAEJ;AAAA,MACA,eAAe,CAAC,MAAM;AACpB,UAAE,eAAe;AAEb,YAAA,CAAC,eAAe,MAAM,GAAG;AAChB,qBAAA,QAAQ,OAAO,KAAK;AAAA,QAAA;AAAA,MACjC;AAAA,IACF;AAAA,IAECQ,sBAAW,KAAK,OAAO,UAAU,MAAM,KAAK,WAAY,CAAA;AAAA,EAC3D;AAEJ;AAEA,MAAM,gBAAgBc,WAAK,SAAS;;"}
|
|
1
|
+
{"version":3,"file":"ProjectTreeTable.cjs.js","sources":["../../../../../src/containers/ProjectTreeTable/ProjectTreeTable.tsx"],"sourcesContent":["import { useMemo, useRef, useEffect, memo, CSSProperties } from 'react'\nimport { useVirtualizer, VirtualItem, Virtualizer } from '@tanstack/react-virtual'\n// TanStack Table imports\nimport {\n useReactTable,\n getCoreRowModel,\n getFilteredRowModel,\n getExpandedRowModel,\n filterFns,\n flexRender,\n Row,\n OnChangeFn,\n getSortedRowModel,\n Cell,\n Column,\n functionalUpdate,\n ColumnSizingState,\n Table,\n Header,\n HeaderGroup,\n} from '@tanstack/react-table'\n\n// Utility imports\nimport clsx from 'clsx'\n\n// Type imports\nimport type { FolderNodeMap, TableRow, TaskNodeMap } from './types/table'\n\n// Component imports\nimport ProjectTreeTableColumns from './ProjectTreeTableColumns'\nimport * as Styled from './ProjectTreeTable.styled'\nimport HeaderActionButton from './components/HeaderActionButton'\nimport EmptyPlaceholder from '../../components/EmptyPlaceholder'\n\n// Context imports\nimport { useCellEditing } from './context/CellEditingContext'\nimport { ROW_SELECTION_COLUMN_ID, useSelectionCellsContext } from './context/SelectionCellsContext'\nimport { ClipboardProvider } from './context/ClipboardContext'\nimport { useSelectedRowsContext } from './context/SelectedRowsContext'\nimport { useColumnSettings } from './context/ColumnSettingsContext'\n\n// Hook imports\nimport useCustomColumnWidthVars from './hooks/useCustomColumnWidthVars'\nimport usePrefetchFolderTasks from './hooks/usePrefetchFolderTasks'\nimport { useLocalStorage } from '../../hooks'\nimport useCellContextMenu from './hooks/useCellContextMenu'\nimport useColumnVirtualization from './hooks/useColumnVirtualization'\nimport useKeyboardNavigation from './hooks/useKeyboardNavigation'\n\n// Utility function imports\nimport { getCellId } from './utils/cellUtils'\nimport { generateLoadingRows, generateDummyAttributes } from './utils/loadingUtils'\nimport { createPortal } from 'react-dom'\nimport { Icon } from '@ynput/ayon-react-components'\nimport { AttributeEnumItem, AttributeWithPermissions, BuiltInFieldOptions } from './types'\nimport { useProjectTableContext } from './context/ProjectTableContext'\n\n//These are the important styles to make sticky column pinning work!\n//Apply styles like this using your CSS strategy of choice with this kind of logic to head cells, data cells, footer cells, etc.\n//View the index.css file for more needed styles such as border-collapse: separate\nconst getCommonPinningStyles = (column: Column<TableRow, unknown>): CSSProperties => {\n const isPinned = column.getIsPinned()\n\n return {\n left: isPinned === 'left' ? `${column.getStart('left')}px` : undefined,\n right: isPinned === 'right' ? `${column.getAfter('right')}px` : undefined,\n position: isPinned ? 'sticky' : 'relative',\n width: column.getSize(),\n zIndex: isPinned ? 100 : 0,\n }\n}\n\ninterface Props extends React.HTMLAttributes<HTMLDivElement> {\n scope: string\n options: BuiltInFieldOptions\n attribs: AttributeWithPermissions[]\n sliceId: string\n // metadata\n fetchMoreOnBottomReached: (element: HTMLDivElement | null) => void\n onOpenNew?: (type: 'folder' | 'task') => void\n // pass through props\n pt?: {\n container?: React.HTMLAttributes<HTMLDivElement>\n head?: Partial<TableHeadProps>\n }\n}\n\n// Component to wrap with all providers\nconst FlexTableWithProviders = (props: Props) => {\n return (\n <ClipboardProvider options={props.options}>\n <FlexTable {...props} />\n </ClipboardProvider>\n )\n}\n\nconst FlexTable = ({\n scope,\n attribs,\n options,\n sliceId,\n fetchMoreOnBottomReached,\n onOpenNew,\n pt,\n ...props\n}: Props) => {\n const {\n columnVisibility,\n columnVisibilityUpdater,\n columnPinning,\n columnPinningUpdater,\n columnOrder,\n columnOrderUpdater,\n } = useColumnSettings()\n\n const {\n tableData,\n isLoading,\n isInitialized,\n expanded,\n updateExpanded,\n toggleExpandAll,\n toggleExpanded,\n sorting,\n updateSorting,\n showHierarchy,\n } = useProjectTableContext()\n\n //The virtualizer needs to know the scrollable container element\n const tableContainerRef = useRef<HTMLDivElement>(null)\n\n // Selection context\n const { registerGrid } = useSelectionCellsContext()\n\n // COLUMN SIZING\n const [columnSizing, setColumnSizing] = useLocalStorage<ColumnSizingState>(\n `column-widths-${scope}`,\n {},\n )\n\n const updateColumnSizing: OnChangeFn<ColumnSizingState> = (columnSizingUpdater) => {\n setColumnSizing(functionalUpdate(columnSizingUpdater, columnSizing))\n }\n\n //a check on mount and after a fetch to see if the table is already scrolled to the bottom and immediately needs to fetch more data\n useEffect(() => {\n fetchMoreOnBottomReached(tableContainerRef.current)\n }, [fetchMoreOnBottomReached])\n\n // generate loading attrib and rows\n const { loadingAttrib, loadingRows } = useMemo(() => {\n // count the number of children in tbody\n const tableRowsCount = tableContainerRef.current?.querySelectorAll('tbody tr').length || 0\n const loadingAttrib = generateDummyAttributes()\n const loadingRows = generateLoadingRows(\n attribs,\n showHierarchy && tableData.length > 0 ? Math.min(tableRowsCount, 50) : 50,\n )\n return { loadingAttrib, loadingRows }\n }, [attribs, tableData, showHierarchy, tableContainerRef.current])\n\n const showLoadingRows = !isInitialized || isLoading\n\n const columns = ProjectTreeTableColumns({\n tableData: showLoadingRows ? loadingRows : tableData,\n columnSizing,\n attribs: isInitialized ? attribs : loadingAttrib,\n isLoading: !isInitialized,\n showHierarchy,\n sliceId,\n options,\n toggleExpandAll: (id: string) => toggleExpandAll([id]),\n toggleExpanded: (id: string) => toggleExpanded(id),\n })\n\n const table = useReactTable({\n data: showLoadingRows ? loadingRows : tableData,\n columns,\n enableRowSelection: true, //enable row selection for all rows\n getRowId: (row) => row.id,\n enableSubRowSelection: false, //disable sub row selection\n getSubRows: (row) => row.subRows,\n getRowCanExpand: () => true,\n getCoreRowModel: getCoreRowModel(),\n getFilteredRowModel: getFilteredRowModel(),\n getExpandedRowModel: getExpandedRowModel(),\n filterFromLeafRows: true,\n // EXPANDABLE\n onExpandedChange: updateExpanded,\n // SORTING\n getSortedRowModel: getSortedRowModel(),\n onSortingChange: updateSorting,\n columnResizeMode: 'onChange',\n onColumnPinningChange: columnPinningUpdater,\n onColumnSizingChange: updateColumnSizing,\n onColumnVisibilityChange: columnVisibilityUpdater,\n onColumnOrderChange: columnOrderUpdater,\n // @ts-ignore\n filterFns,\n state: {\n expanded,\n sorting,\n columnPinning: {\n left: [ROW_SELECTION_COLUMN_ID, ...(columnPinning.left || [])],\n right: columnPinning.right,\n },\n columnSizing,\n columnVisibility,\n columnOrder,\n },\n enableSorting: true,\n })\n\n const { rows } = table.getRowModel()\n\n // Register grid structure with selection context when rows or columns change\n useEffect(() => {\n const rowIds = rows.map((row) => row.id)\n const colIds = table.getAllLeafColumns().map((col) => col.id)\n const colIdsSortedByPinning = [...colIds].sort((a, b) => {\n if (ROW_SELECTION_COLUMN_ID === b) return 1\n const colA = columnPinning.left?.includes(a) ? 0 : 1\n const colB = columnPinning.left?.includes(b) ? 0 : 1\n return colA - colB\n })\n\n registerGrid(rowIds, colIdsSortedByPinning)\n }, [rows, table.getAllLeafColumns(), columnPinning, ROW_SELECTION_COLUMN_ID, registerGrid])\n\n const visibleColumns = table.getVisibleLeafColumns()\n\n // Use the column virtualization hook\n const { columnVirtualizer, virtualPaddingLeft, virtualPaddingRight } = useColumnVirtualization({\n visibleColumns,\n tableContainerRef,\n columnPinning,\n })\n\n const columnSizeVars = useCustomColumnWidthVars(table, columnSizing)\n const readOnlyColumns = useMemo(\n () => attribs.filter((attrib) => attrib.readOnly).map((attrib) => 'attrib_' + attrib.name),\n [attribs],\n )\n\n return (\n <Styled.TableWrapper {...props}>\n <Styled.TableContainer\n ref={tableContainerRef}\n style={{ height: '100%', padding: 0 }}\n onScroll={(e) => fetchMoreOnBottomReached(e.currentTarget)}\n {...pt?.container}\n className={clsx('table-container', pt?.container?.className)}\n >\n <table\n style={{\n display: 'grid',\n borderCollapse: 'collapse',\n userSelect: 'none',\n ...columnSizeVars,\n width: table.getTotalSize(),\n }}\n >\n <TableHead\n columnVirtualizer={columnVirtualizer}\n table={table}\n virtualPaddingLeft={virtualPaddingLeft}\n virtualPaddingRight={virtualPaddingRight}\n isLoading={isLoading}\n readOnlyColumns={readOnlyColumns}\n {...pt?.head}\n />\n <TableBody\n columnVirtualizer={columnVirtualizer}\n table={table}\n tableContainerRef={tableContainerRef}\n virtualPaddingLeft={virtualPaddingLeft}\n virtualPaddingRight={virtualPaddingRight}\n showHierarchy={showHierarchy}\n attribs={attribs}\n onOpenNew={onOpenNew}\n />\n </table>\n </Styled.TableContainer>\n </Styled.TableWrapper>\n )\n}\n\ninterface TableHeadProps extends React.HTMLAttributes<HTMLTableSectionElement> {\n columnVirtualizer: Virtualizer<HTMLDivElement, HTMLTableCellElement>\n table: Table<TableRow>\n virtualPaddingLeft: number | undefined\n virtualPaddingRight: number | undefined\n isLoading: boolean\n readOnlyColumns?: string[]\n}\n\nconst TableHead = ({\n columnVirtualizer,\n table,\n virtualPaddingLeft,\n virtualPaddingRight,\n isLoading,\n readOnlyColumns,\n ...props\n}: TableHeadProps) => {\n return (\n <Styled.TableHeader {...props}>\n {table.getHeaderGroups().map((headerGroup) => (\n <TableHeadRow\n key={headerGroup.id}\n columnVirtualizer={columnVirtualizer}\n headerGroup={headerGroup}\n virtualPaddingLeft={virtualPaddingLeft}\n virtualPaddingRight={virtualPaddingRight}\n isLoading={isLoading}\n readOnlyColumns={readOnlyColumns}\n />\n ))}\n </Styled.TableHeader>\n )\n}\n\ninterface TableHeadRowProps {\n columnVirtualizer: Virtualizer<HTMLDivElement, HTMLTableCellElement>\n headerGroup: HeaderGroup<TableRow>\n virtualPaddingLeft: number | undefined\n virtualPaddingRight: number | undefined\n isLoading: boolean\n readOnlyColumns?: string[]\n}\n\nconst TableHeadRow = ({\n columnVirtualizer,\n headerGroup,\n virtualPaddingLeft,\n virtualPaddingRight,\n isLoading,\n readOnlyColumns,\n}: TableHeadRowProps) => {\n const virtualColumns = columnVirtualizer.getVirtualItems()\n return (\n <Styled.ColumnHeader key={headerGroup.id} style={{ display: 'flex' }}>\n {virtualPaddingLeft ? (\n //fake empty column to the left for virtualization scroll padding\n <th style={{ display: 'flex', width: virtualPaddingLeft }} />\n ) : null}\n {virtualColumns.map((virtualColumn) => {\n const header = headerGroup.headers[virtualColumn.index]\n return (\n <TableHeadCell\n key={header.id}\n header={header}\n isLoading={isLoading}\n isReadOnly={readOnlyColumns?.includes(header.id)}\n />\n )\n })}\n {virtualPaddingRight ? (\n //fake empty column to the right for virtualization scroll padding\n <th style={{ display: 'flex', width: virtualPaddingRight }} />\n ) : null}\n </Styled.ColumnHeader>\n )\n}\n\ninterface TableHeadCellProps {\n header: Header<TableRow, unknown>\n isLoading: boolean\n isReadOnly?: boolean\n}\n\nconst TableHeadCell = ({ header, isLoading, isReadOnly }: TableHeadCellProps) => {\n const { column } = header\n const isRowSelectionColumn = column.id === ROW_SELECTION_COLUMN_ID\n\n return (\n <Styled.HeaderCell\n className={clsx(header.id, 'shimmer-dark', {\n loading: isLoading,\n large: column.id === 'folderType',\n 'last-pinned-left': column.getIsPinned() === 'left' && column.getIsLastColumn('left'),\n })}\n key={header.id}\n style={{\n ...getCommonPinningStyles(column),\n width: `calc(var(--header-${header?.id}-size) * 1px)`,\n }}\n >\n {header.isPlaceholder ? null : (\n <Styled.TableCellContent\n className={clsx('bold', {\n large: column.id === 'folderType',\n })}\n >\n {flexRender(column.columnDef.header, header.getContext())}\n {isReadOnly && (\n <Icon icon=\"lock\" data-tooltip={'You only have permission to read this column.'} />\n )}\n\n <Styled.HeaderButtons className=\"actions\">\n {/* COLUMN HIDING */}\n <HeaderActionButton\n icon=\"visibility_off\"\n selected={!column.getIsVisible()}\n onClick={column.getToggleVisibilityHandler()}\n />\n {/* COLUMN SORTING */}\n <HeaderActionButton\n icon=\"push_pin\"\n selected={header.column.getIsPinned() === 'left'}\n onClick={() => {\n if (header.column.getIsPinned() === 'left') {\n header.column.pin(false)\n } else {\n header.column.pin('left')\n }\n }}\n />\n {/* COLUMN PINNING */}\n <HeaderActionButton\n icon={'sort'}\n style={{\n transform: (column.getIsSorted() as string) === 'asc' ? 'scaleY(-1)' : undefined,\n }}\n onClick={column.getToggleSortingHandler()}\n selected={!!column.getIsSorted()}\n />\n </Styled.HeaderButtons>\n {!isRowSelectionColumn && (\n <Styled.ResizedHandler\n {...{\n onDoubleClick: () => column.resetSize(),\n onMouseDown: header.getResizeHandler(),\n onTouchStart: header.getResizeHandler(),\n className: clsx('resize-handle', {\n resizing: column.getIsResizing(),\n }),\n }}\n />\n )}\n </Styled.TableCellContent>\n )}\n </Styled.HeaderCell>\n )\n}\n\ninterface TableBodyProps {\n columnVirtualizer: Virtualizer<HTMLDivElement, HTMLTableCellElement>\n table: Table<TableRow>\n tableContainerRef: React.RefObject<HTMLDivElement>\n showHierarchy: boolean\n virtualPaddingLeft: number | undefined\n virtualPaddingRight: number | undefined\n attribs: AttributeWithPermissions[]\n onOpenNew?: (type: 'folder' | 'task') => void\n}\n\nconst TableBody = ({\n columnVirtualizer,\n table,\n tableContainerRef,\n showHierarchy,\n virtualPaddingLeft,\n virtualPaddingRight,\n attribs,\n onOpenNew,\n}: TableBodyProps) => {\n const { handleTableBodyContextMenu } = useCellContextMenu({ attribs, onOpenNew })\n\n const { handlePreFetchTasks } = usePrefetchFolderTasks()\n\n const { rows } = table.getRowModel()\n\n const rowVirtualizer = useVirtualizer<HTMLDivElement, HTMLTableRowElement>({\n count: rows.length,\n estimateSize: () => (showHierarchy ? 36 : 40), //estimate row height for accurate scrollbar dragging\n getScrollElement: () => tableContainerRef.current,\n //measure dynamic row height, except in firefox because it measures table border height incorrectly\n measureElement:\n typeof window !== 'undefined' && navigator.userAgent.indexOf('Firefox') === -1\n ? (element) => element?.getBoundingClientRect().height\n : undefined,\n overscan: 5,\n })\n\n const virtualRows = rowVirtualizer.getVirtualItems()\n\n useKeyboardNavigation()\n\n return virtualRows.length ? (\n <tbody\n style={{\n height: `${rowVirtualizer.getTotalSize()}px`,\n position: 'relative',\n display: 'grid',\n }}\n onContextMenu={handleTableBodyContextMenu}\n onMouseOver={(e) => {\n handlePreFetchTasks(e)\n }}\n >\n {virtualRows.map((virtualRow) => {\n const row = rows[virtualRow.index] as Row<TableRow>\n return (\n <TableBodyRow\n key={row.id}\n columnVirtualizer={columnVirtualizer}\n row={row}\n rowVirtualizer={rowVirtualizer}\n virtualPaddingLeft={virtualPaddingLeft}\n virtualPaddingRight={virtualPaddingRight}\n virtualRow={virtualRow}\n showHierarchy={showHierarchy}\n />\n )\n })}\n </tbody>\n ) : (\n tableContainerRef.current &&\n createPortal(\n <EmptyPlaceholder message=\"No folders or tasks found\" />,\n tableContainerRef.current,\n )\n )\n}\n\ninterface TableBodyRowProps {\n columnVirtualizer: Virtualizer<HTMLDivElement, HTMLTableCellElement>\n row: Row<TableRow>\n rowVirtualizer: Virtualizer<HTMLDivElement, HTMLTableRowElement>\n virtualPaddingLeft: number | undefined\n virtualPaddingRight: number | undefined\n virtualRow: VirtualItem\n showHierarchy: boolean\n}\n\nconst TableBodyRow = ({\n columnVirtualizer,\n row,\n rowVirtualizer,\n virtualPaddingLeft,\n virtualPaddingRight,\n virtualRow,\n showHierarchy,\n}: TableBodyRowProps) => {\n // We should do this so that we don't re-render every time anything in projectTableContext changes\n const visibleCells = row.getVisibleCells()\n const virtualColumns = columnVirtualizer.getVirtualItems()\n\n return (\n <Styled.TR\n data-index={virtualRow.index} //needed for dynamic row height measurement\n ref={(node) => rowVirtualizer.measureElement(node)} //measure dynamic row height\n key={row.id}\n style={{\n transform: `translateY(${virtualRow.start}px)`, //this should always be a `style` as it changes on scroll\n }}\n >\n {virtualPaddingLeft ? (\n //fake empty column to the left for virtualization scroll padding\n <td style={{ display: 'flex', width: virtualPaddingLeft }} />\n ) : null}\n {virtualColumns.map((vc) => {\n const cell = visibleCells[vc.index]\n const cellId = getCellId(row.id, cell.column.id)\n return (\n <TableCellMemo\n cell={cell}\n cellId={cellId}\n rowId={row.id}\n key={cell.id}\n showHierarchy={showHierarchy}\n />\n )\n })}\n\n {virtualPaddingRight ? (\n //fake empty column to the right for virtualization scroll padding\n <td style={{ display: 'flex', width: virtualPaddingRight }} />\n ) : null}\n </Styled.TR>\n )\n}\n\ninterface TableCellProps {\n cell: Cell<TableRow, unknown>\n cellId: string\n rowId: string\n className?: string\n showHierarchy: boolean\n}\n\nconst TableCell = ({ cell, rowId, cellId, className, showHierarchy, ...props }: TableCellProps) => {\n const {\n isCellSelected,\n isCellFocused,\n startSelection,\n extendSelection,\n endSelection,\n selectCell,\n getCellBorderClasses,\n } = useSelectionCellsContext()\n\n const { isRowSelected } = useSelectedRowsContext()\n\n const { isEditing } = useCellEditing()\n\n const borderClasses = getCellBorderClasses(cellId)\n\n const isPinned = cell.column.getIsPinned()\n const isLastLeftPinnedColumn = isPinned === 'left' && cell.column.getIsLastColumn('left')\n const isRowSelectionColumn = cell.column.id === ROW_SELECTION_COLUMN_ID\n\n return (\n <Styled.TableCell\n {...props}\n tabIndex={0}\n key={cell.id}\n $isLastPinned={isLastLeftPinnedColumn} // is this column the last pinned column? Custom styling for borders.\n className={clsx(\n cell.column.id,\n cell.column.id === 'folderType' ? 'large' : '',\n {\n selected: isCellSelected(cellId),\n focused: isCellFocused(cellId),\n editing: isEditing(cellId),\n 'last-pinned-left': isLastLeftPinnedColumn,\n 'selected-row': isRowSelected(rowId),\n task: cell.row.original.entityType === 'task',\n },\n className,\n ...borderClasses,\n )}\n style={{\n ...getCommonPinningStyles(cell.column),\n width: `calc(var(--col-${cell.column.id}-size) * 1px)`,\n height: showHierarchy ? 36 : 40,\n }}\n onMouseDown={(e) => {\n // Only process left clicks (button 0), ignore right clicks\n if (e.button !== 0) return\n\n // check we are not clicking on expander\n if ((e.target as HTMLElement).closest('.expander')) return\n const additive = e.metaKey || e.ctrlKey || isRowSelectionColumn\n if (e.shiftKey) {\n // Shift+click extends selection from anchor cell\n selectCell(cellId, additive, true) // true for range selection\n } else {\n // Normal click starts a new selection\n startSelection(cellId, additive)\n }\n }}\n onMouseOver={(e) => {\n if (e.buttons === 1) {\n // Left button is pressed during mouse move - drag selection\n extendSelection(cellId, isRowSelectionColumn)\n }\n }}\n onMouseUp={() => {\n endSelection(cellId)\n }}\n onDoubleClick={(e) => {\n if (cell.column.id === 'name') {\n // select the row by selecting the row-selection cell\n const rowSelectionCellId = getCellId(cell.row.id, ROW_SELECTION_COLUMN_ID)\n if (!isCellSelected(rowSelectionCellId)) {\n const additive = e.metaKey || e.ctrlKey\n selectCell(rowSelectionCellId, additive, false)\n }\n }\n }}\n onContextMenu={(e) => {\n e.preventDefault()\n // if the cell is not selected, select it and deselect all others\n if (!isCellSelected(cellId)) {\n selectCell(cellId, false, false)\n }\n }}\n >\n {flexRender(cell.column.columnDef.cell, cell.getContext())}\n </Styled.TableCell>\n )\n}\n\nconst TableCellMemo = memo(TableCell)\n\nexport { FlexTableWithProviders as ProjectTreeTable }\n"],"names":["jsx","ClipboardProvider","useColumnSettings","useProjectTableContext","useRef","useSelectionCellsContext","useLocalStorage","functionalUpdate","useEffect","useMemo","_a","loadingAttrib","generateDummyAttributes","loadingRows","generateLoadingRows","useReactTable","getCoreRowModel","getFilteredRowModel","getExpandedRowModel","getSortedRowModel","filterFns","ROW_SELECTION_COLUMN_ID","Styled.TableWrapper","Styled.TableContainer","jsxs","Styled.TableHeader","Styled.ColumnHeader","Styled.HeaderCell","Styled.TableCellContent","flexRender","Icon","Styled.HeaderButtons","Styled.ResizedHandler","usePrefetchFolderTasks","useVirtualizer","createPortal","EmptyPlaceholder","Styled.TR","getCellId","useSelectedRowsContext","useCellEditing","createElement","Styled.TableCell","memo"],"mappings":"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"}
|
|
@@ -81,6 +81,11 @@ import "../../api/queries/users/updateUsers.es.js";
|
|
|
81
81
|
import "../../api/queries/watchers/getWatchers.es.js";
|
|
82
82
|
import "../../../../_virtual/lodash.es.js";
|
|
83
83
|
import "react-toastify";
|
|
84
|
+
import "../../context/DetailsPanelContext.es.js";
|
|
85
|
+
import "../../context/ThumbnailUploaderContext.es.js";
|
|
86
|
+
import "../../context/pip/PiPProvider.es.js";
|
|
87
|
+
import { createPortal } from "react-dom";
|
|
88
|
+
import "../../context/pip/PiPWrapper.es.js";
|
|
84
89
|
import "react-router-dom";
|
|
85
90
|
import "custom-protocol-check";
|
|
86
91
|
import useCellContextMenu from "./hooks/useCellContextMenu.es.js";
|
|
@@ -88,7 +93,6 @@ import useColumnVirtualization from "./hooks/useColumnVirtualization.es.js";
|
|
|
88
93
|
import useKeyboardNavigation from "./hooks/useKeyboardNavigation.es.js";
|
|
89
94
|
import { getCellId } from "./utils/cellUtils.es.js";
|
|
90
95
|
import { generateDummyAttributes, generateLoadingRows } from "./utils/loadingUtils.es.js";
|
|
91
|
-
import { createPortal } from "react-dom";
|
|
92
96
|
import { Icon } from "@ynput/ayon-react-components";
|
|
93
97
|
import { useProjectTableContext } from "./context/ProjectTableContext.es.js";
|
|
94
98
|
const getCommonPinningStyles = (column) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProjectTreeTable.es.js","sources":["../../../../../src/containers/ProjectTreeTable/ProjectTreeTable.tsx"],"sourcesContent":["import { useMemo, useRef, useEffect, memo, CSSProperties } from 'react'\nimport { useVirtualizer, VirtualItem, Virtualizer } from '@tanstack/react-virtual'\n// TanStack Table imports\nimport {\n useReactTable,\n getCoreRowModel,\n getFilteredRowModel,\n getExpandedRowModel,\n filterFns,\n flexRender,\n Row,\n OnChangeFn,\n getSortedRowModel,\n Cell,\n Column,\n functionalUpdate,\n ColumnSizingState,\n Table,\n Header,\n HeaderGroup,\n} from '@tanstack/react-table'\n\n// Utility imports\nimport clsx from 'clsx'\n\n// Type imports\nimport type { FolderNodeMap, TableRow, TaskNodeMap } from './types/table'\n\n// Component imports\nimport ProjectTreeTableColumns from './ProjectTreeTableColumns'\nimport * as Styled from './ProjectTreeTable.styled'\nimport HeaderActionButton from './components/HeaderActionButton'\nimport EmptyPlaceholder from '../../components/EmptyPlaceholder'\n\n// Context imports\nimport { useCellEditing } from './context/CellEditingContext'\nimport { ROW_SELECTION_COLUMN_ID, useSelectionCellsContext } from './context/SelectionCellsContext'\nimport { ClipboardProvider } from './context/ClipboardContext'\nimport { useSelectedRowsContext } from './context/SelectedRowsContext'\nimport { useColumnSettings } from './context/ColumnSettingsContext'\n\n// Hook imports\nimport useCustomColumnWidthVars from './hooks/useCustomColumnWidthVars'\nimport usePrefetchFolderTasks from './hooks/usePrefetchFolderTasks'\nimport { useLocalStorage } from '../../hooks'\nimport useCellContextMenu from './hooks/useCellContextMenu'\nimport useColumnVirtualization from './hooks/useColumnVirtualization'\nimport useKeyboardNavigation from './hooks/useKeyboardNavigation'\n\n// Utility function imports\nimport { getCellId } from './utils/cellUtils'\nimport { generateLoadingRows, generateDummyAttributes } from './utils/loadingUtils'\nimport { createPortal } from 'react-dom'\nimport { Icon } from '@ynput/ayon-react-components'\nimport { AttributeEnumItem, AttributeWithPermissions, BuiltInFieldOptions } from './types'\nimport { useProjectTableContext } from './context/ProjectTableContext'\n\n//These are the important styles to make sticky column pinning work!\n//Apply styles like this using your CSS strategy of choice with this kind of logic to head cells, data cells, footer cells, etc.\n//View the index.css file for more needed styles such as border-collapse: separate\nconst getCommonPinningStyles = (column: Column<TableRow, unknown>): CSSProperties => {\n const isPinned = column.getIsPinned()\n\n return {\n left: isPinned === 'left' ? `${column.getStart('left')}px` : undefined,\n right: isPinned === 'right' ? `${column.getAfter('right')}px` : undefined,\n position: isPinned ? 'sticky' : 'relative',\n width: column.getSize(),\n zIndex: isPinned ? 100 : 0,\n }\n}\n\ninterface Props extends React.HTMLAttributes<HTMLDivElement> {\n scope: string\n options: BuiltInFieldOptions\n attribs: AttributeWithPermissions[]\n sliceId: string\n // metadata\n fetchMoreOnBottomReached: (element: HTMLDivElement | null) => void\n onOpenNew?: (type: 'folder' | 'task') => void\n // pass through props\n pt?: {\n container?: React.HTMLAttributes<HTMLDivElement>\n head?: Partial<TableHeadProps>\n }\n}\n\n// Component to wrap with all providers\nconst FlexTableWithProviders = (props: Props) => {\n return (\n <ClipboardProvider options={props.options}>\n <FlexTable {...props} />\n </ClipboardProvider>\n )\n}\n\nconst FlexTable = ({\n scope,\n attribs,\n options,\n sliceId,\n fetchMoreOnBottomReached,\n onOpenNew,\n pt,\n ...props\n}: Props) => {\n const {\n columnVisibility,\n columnVisibilityUpdater,\n columnPinning,\n columnPinningUpdater,\n columnOrder,\n columnOrderUpdater,\n } = useColumnSettings()\n\n const {\n tableData,\n isLoading,\n isInitialized,\n expanded,\n updateExpanded,\n toggleExpandAll,\n toggleExpanded,\n sorting,\n updateSorting,\n showHierarchy,\n } = useProjectTableContext()\n\n //The virtualizer needs to know the scrollable container element\n const tableContainerRef = useRef<HTMLDivElement>(null)\n\n // Selection context\n const { registerGrid } = useSelectionCellsContext()\n\n // COLUMN SIZING\n const [columnSizing, setColumnSizing] = useLocalStorage<ColumnSizingState>(\n `column-widths-${scope}`,\n {},\n )\n\n const updateColumnSizing: OnChangeFn<ColumnSizingState> = (columnSizingUpdater) => {\n setColumnSizing(functionalUpdate(columnSizingUpdater, columnSizing))\n }\n\n //a check on mount and after a fetch to see if the table is already scrolled to the bottom and immediately needs to fetch more data\n useEffect(() => {\n fetchMoreOnBottomReached(tableContainerRef.current)\n }, [fetchMoreOnBottomReached])\n\n // generate loading attrib and rows\n const { loadingAttrib, loadingRows } = useMemo(() => {\n // count the number of children in tbody\n const tableRowsCount = tableContainerRef.current?.querySelectorAll('tbody tr').length || 0\n const loadingAttrib = generateDummyAttributes()\n const loadingRows = generateLoadingRows(\n attribs,\n showHierarchy && tableData.length > 0 ? Math.min(tableRowsCount, 50) : 50,\n )\n return { loadingAttrib, loadingRows }\n }, [attribs, tableData, showHierarchy, tableContainerRef.current])\n\n const showLoadingRows = !isInitialized || isLoading\n\n const columns = ProjectTreeTableColumns({\n tableData: showLoadingRows ? loadingRows : tableData,\n columnSizing,\n attribs: isInitialized ? attribs : loadingAttrib,\n isLoading: !isInitialized,\n showHierarchy,\n sliceId,\n options,\n toggleExpandAll: (id: string) => toggleExpandAll([id]),\n toggleExpanded: (id: string) => toggleExpanded(id),\n })\n\n const table = useReactTable({\n data: showLoadingRows ? loadingRows : tableData,\n columns,\n enableRowSelection: true, //enable row selection for all rows\n getRowId: (row) => row.id,\n enableSubRowSelection: false, //disable sub row selection\n getSubRows: (row) => row.subRows,\n getRowCanExpand: () => true,\n getCoreRowModel: getCoreRowModel(),\n getFilteredRowModel: getFilteredRowModel(),\n getExpandedRowModel: getExpandedRowModel(),\n filterFromLeafRows: true,\n // EXPANDABLE\n onExpandedChange: updateExpanded,\n // SORTING\n getSortedRowModel: getSortedRowModel(),\n onSortingChange: updateSorting,\n columnResizeMode: 'onChange',\n onColumnPinningChange: columnPinningUpdater,\n onColumnSizingChange: updateColumnSizing,\n onColumnVisibilityChange: columnVisibilityUpdater,\n onColumnOrderChange: columnOrderUpdater,\n // @ts-ignore\n filterFns,\n state: {\n expanded,\n sorting,\n columnPinning: {\n left: [ROW_SELECTION_COLUMN_ID, ...(columnPinning.left || [])],\n right: columnPinning.right,\n },\n columnSizing,\n columnVisibility,\n columnOrder,\n },\n enableSorting: true,\n })\n\n const { rows } = table.getRowModel()\n\n // Register grid structure with selection context when rows or columns change\n useEffect(() => {\n const rowIds = rows.map((row) => row.id)\n const colIds = table.getAllLeafColumns().map((col) => col.id)\n const colIdsSortedByPinning = [...colIds].sort((a, b) => {\n if (ROW_SELECTION_COLUMN_ID === b) return 1\n const colA = columnPinning.left?.includes(a) ? 0 : 1\n const colB = columnPinning.left?.includes(b) ? 0 : 1\n return colA - colB\n })\n\n registerGrid(rowIds, colIdsSortedByPinning)\n }, [rows, table.getAllLeafColumns(), columnPinning, ROW_SELECTION_COLUMN_ID, registerGrid])\n\n const visibleColumns = table.getVisibleLeafColumns()\n\n // Use the column virtualization hook\n const { columnVirtualizer, virtualPaddingLeft, virtualPaddingRight } = useColumnVirtualization({\n visibleColumns,\n tableContainerRef,\n columnPinning,\n })\n\n const columnSizeVars = useCustomColumnWidthVars(table, columnSizing)\n const readOnlyColumns = useMemo(\n () => attribs.filter((attrib) => attrib.readOnly).map((attrib) => 'attrib_' + attrib.name),\n [attribs],\n )\n\n return (\n <Styled.TableWrapper {...props}>\n <Styled.TableContainer\n ref={tableContainerRef}\n style={{ height: '100%', padding: 0 }}\n onScroll={(e) => fetchMoreOnBottomReached(e.currentTarget)}\n {...pt?.container}\n className={clsx('table-container', pt?.container?.className)}\n >\n <table\n style={{\n display: 'grid',\n borderCollapse: 'collapse',\n userSelect: 'none',\n ...columnSizeVars,\n width: table.getTotalSize(),\n }}\n >\n <TableHead\n columnVirtualizer={columnVirtualizer}\n table={table}\n virtualPaddingLeft={virtualPaddingLeft}\n virtualPaddingRight={virtualPaddingRight}\n isLoading={isLoading}\n readOnlyColumns={readOnlyColumns}\n {...pt?.head}\n />\n <TableBody\n columnVirtualizer={columnVirtualizer}\n table={table}\n tableContainerRef={tableContainerRef}\n virtualPaddingLeft={virtualPaddingLeft}\n virtualPaddingRight={virtualPaddingRight}\n showHierarchy={showHierarchy}\n attribs={attribs}\n onOpenNew={onOpenNew}\n />\n </table>\n </Styled.TableContainer>\n </Styled.TableWrapper>\n )\n}\n\ninterface TableHeadProps extends React.HTMLAttributes<HTMLTableSectionElement> {\n columnVirtualizer: Virtualizer<HTMLDivElement, HTMLTableCellElement>\n table: Table<TableRow>\n virtualPaddingLeft: number | undefined\n virtualPaddingRight: number | undefined\n isLoading: boolean\n readOnlyColumns?: string[]\n}\n\nconst TableHead = ({\n columnVirtualizer,\n table,\n virtualPaddingLeft,\n virtualPaddingRight,\n isLoading,\n readOnlyColumns,\n ...props\n}: TableHeadProps) => {\n return (\n <Styled.TableHeader {...props}>\n {table.getHeaderGroups().map((headerGroup) => (\n <TableHeadRow\n key={headerGroup.id}\n columnVirtualizer={columnVirtualizer}\n headerGroup={headerGroup}\n virtualPaddingLeft={virtualPaddingLeft}\n virtualPaddingRight={virtualPaddingRight}\n isLoading={isLoading}\n readOnlyColumns={readOnlyColumns}\n />\n ))}\n </Styled.TableHeader>\n )\n}\n\ninterface TableHeadRowProps {\n columnVirtualizer: Virtualizer<HTMLDivElement, HTMLTableCellElement>\n headerGroup: HeaderGroup<TableRow>\n virtualPaddingLeft: number | undefined\n virtualPaddingRight: number | undefined\n isLoading: boolean\n readOnlyColumns?: string[]\n}\n\nconst TableHeadRow = ({\n columnVirtualizer,\n headerGroup,\n virtualPaddingLeft,\n virtualPaddingRight,\n isLoading,\n readOnlyColumns,\n}: TableHeadRowProps) => {\n const virtualColumns = columnVirtualizer.getVirtualItems()\n return (\n <Styled.ColumnHeader key={headerGroup.id} style={{ display: 'flex' }}>\n {virtualPaddingLeft ? (\n //fake empty column to the left for virtualization scroll padding\n <th style={{ display: 'flex', width: virtualPaddingLeft }} />\n ) : null}\n {virtualColumns.map((virtualColumn) => {\n const header = headerGroup.headers[virtualColumn.index]\n return (\n <TableHeadCell\n key={header.id}\n header={header}\n isLoading={isLoading}\n isReadOnly={readOnlyColumns?.includes(header.id)}\n />\n )\n })}\n {virtualPaddingRight ? (\n //fake empty column to the right for virtualization scroll padding\n <th style={{ display: 'flex', width: virtualPaddingRight }} />\n ) : null}\n </Styled.ColumnHeader>\n )\n}\n\ninterface TableHeadCellProps {\n header: Header<TableRow, unknown>\n isLoading: boolean\n isReadOnly?: boolean\n}\n\nconst TableHeadCell = ({ header, isLoading, isReadOnly }: TableHeadCellProps) => {\n const { column } = header\n const isRowSelectionColumn = column.id === ROW_SELECTION_COLUMN_ID\n\n return (\n <Styled.HeaderCell\n className={clsx(header.id, 'shimmer-dark', {\n loading: isLoading,\n large: column.id === 'folderType',\n 'last-pinned-left': column.getIsPinned() === 'left' && column.getIsLastColumn('left'),\n })}\n key={header.id}\n style={{\n ...getCommonPinningStyles(column),\n width: `calc(var(--header-${header?.id}-size) * 1px)`,\n }}\n >\n {header.isPlaceholder ? null : (\n <Styled.TableCellContent\n className={clsx('bold', {\n large: column.id === 'folderType',\n })}\n >\n {flexRender(column.columnDef.header, header.getContext())}\n {isReadOnly && (\n <Icon icon=\"lock\" data-tooltip={'You only have permission to read this column.'} />\n )}\n\n <Styled.HeaderButtons className=\"actions\">\n {/* COLUMN HIDING */}\n <HeaderActionButton\n icon=\"visibility_off\"\n selected={!column.getIsVisible()}\n onClick={column.getToggleVisibilityHandler()}\n />\n {/* COLUMN SORTING */}\n <HeaderActionButton\n icon=\"push_pin\"\n selected={header.column.getIsPinned() === 'left'}\n onClick={() => {\n if (header.column.getIsPinned() === 'left') {\n header.column.pin(false)\n } else {\n header.column.pin('left')\n }\n }}\n />\n {/* COLUMN PINNING */}\n <HeaderActionButton\n icon={'sort'}\n style={{\n transform: (column.getIsSorted() as string) === 'asc' ? 'scaleY(-1)' : undefined,\n }}\n onClick={column.getToggleSortingHandler()}\n selected={!!column.getIsSorted()}\n />\n </Styled.HeaderButtons>\n {!isRowSelectionColumn && (\n <Styled.ResizedHandler\n {...{\n onDoubleClick: () => column.resetSize(),\n onMouseDown: header.getResizeHandler(),\n onTouchStart: header.getResizeHandler(),\n className: clsx('resize-handle', {\n resizing: column.getIsResizing(),\n }),\n }}\n />\n )}\n </Styled.TableCellContent>\n )}\n </Styled.HeaderCell>\n )\n}\n\ninterface TableBodyProps {\n columnVirtualizer: Virtualizer<HTMLDivElement, HTMLTableCellElement>\n table: Table<TableRow>\n tableContainerRef: React.RefObject<HTMLDivElement>\n showHierarchy: boolean\n virtualPaddingLeft: number | undefined\n virtualPaddingRight: number | undefined\n attribs: AttributeWithPermissions[]\n onOpenNew?: (type: 'folder' | 'task') => void\n}\n\nconst TableBody = ({\n columnVirtualizer,\n table,\n tableContainerRef,\n showHierarchy,\n virtualPaddingLeft,\n virtualPaddingRight,\n attribs,\n onOpenNew,\n}: TableBodyProps) => {\n const { handleTableBodyContextMenu } = useCellContextMenu({ attribs, onOpenNew })\n\n const { handlePreFetchTasks } = usePrefetchFolderTasks()\n\n const { rows } = table.getRowModel()\n\n const rowVirtualizer = useVirtualizer<HTMLDivElement, HTMLTableRowElement>({\n count: rows.length,\n estimateSize: () => (showHierarchy ? 36 : 40), //estimate row height for accurate scrollbar dragging\n getScrollElement: () => tableContainerRef.current,\n //measure dynamic row height, except in firefox because it measures table border height incorrectly\n measureElement:\n typeof window !== 'undefined' && navigator.userAgent.indexOf('Firefox') === -1\n ? (element) => element?.getBoundingClientRect().height\n : undefined,\n overscan: 5,\n })\n\n const virtualRows = rowVirtualizer.getVirtualItems()\n\n useKeyboardNavigation()\n\n return virtualRows.length ? (\n <tbody\n style={{\n height: `${rowVirtualizer.getTotalSize()}px`,\n position: 'relative',\n display: 'grid',\n }}\n onContextMenu={handleTableBodyContextMenu}\n onMouseOver={(e) => {\n handlePreFetchTasks(e)\n }}\n >\n {virtualRows.map((virtualRow) => {\n const row = rows[virtualRow.index] as Row<TableRow>\n return (\n <TableBodyRow\n key={row.id}\n columnVirtualizer={columnVirtualizer}\n row={row}\n rowVirtualizer={rowVirtualizer}\n virtualPaddingLeft={virtualPaddingLeft}\n virtualPaddingRight={virtualPaddingRight}\n virtualRow={virtualRow}\n showHierarchy={showHierarchy}\n />\n )\n })}\n </tbody>\n ) : (\n tableContainerRef.current &&\n createPortal(\n <EmptyPlaceholder message=\"No folders or tasks found\" />,\n tableContainerRef.current,\n )\n )\n}\n\ninterface TableBodyRowProps {\n columnVirtualizer: Virtualizer<HTMLDivElement, HTMLTableCellElement>\n row: Row<TableRow>\n rowVirtualizer: Virtualizer<HTMLDivElement, HTMLTableRowElement>\n virtualPaddingLeft: number | undefined\n virtualPaddingRight: number | undefined\n virtualRow: VirtualItem\n showHierarchy: boolean\n}\n\nconst TableBodyRow = ({\n columnVirtualizer,\n row,\n rowVirtualizer,\n virtualPaddingLeft,\n virtualPaddingRight,\n virtualRow,\n showHierarchy,\n}: TableBodyRowProps) => {\n // We should do this so that we don't re-render every time anything in projectTableContext changes\n const visibleCells = row.getVisibleCells()\n const virtualColumns = columnVirtualizer.getVirtualItems()\n\n return (\n <Styled.TR\n data-index={virtualRow.index} //needed for dynamic row height measurement\n ref={(node) => rowVirtualizer.measureElement(node)} //measure dynamic row height\n key={row.id}\n style={{\n transform: `translateY(${virtualRow.start}px)`, //this should always be a `style` as it changes on scroll\n }}\n >\n {virtualPaddingLeft ? (\n //fake empty column to the left for virtualization scroll padding\n <td style={{ display: 'flex', width: virtualPaddingLeft }} />\n ) : null}\n {virtualColumns.map((vc) => {\n const cell = visibleCells[vc.index]\n const cellId = getCellId(row.id, cell.column.id)\n return (\n <TableCellMemo\n cell={cell}\n cellId={cellId}\n rowId={row.id}\n key={cell.id}\n showHierarchy={showHierarchy}\n />\n )\n })}\n\n {virtualPaddingRight ? (\n //fake empty column to the right for virtualization scroll padding\n <td style={{ display: 'flex', width: virtualPaddingRight }} />\n ) : null}\n </Styled.TR>\n )\n}\n\ninterface TableCellProps {\n cell: Cell<TableRow, unknown>\n cellId: string\n rowId: string\n className?: string\n showHierarchy: boolean\n}\n\nconst TableCell = ({ cell, rowId, cellId, className, showHierarchy, ...props }: TableCellProps) => {\n const {\n isCellSelected,\n isCellFocused,\n startSelection,\n extendSelection,\n endSelection,\n selectCell,\n getCellBorderClasses,\n } = useSelectionCellsContext()\n\n const { isRowSelected } = useSelectedRowsContext()\n\n const { isEditing } = useCellEditing()\n\n const borderClasses = getCellBorderClasses(cellId)\n\n const isPinned = cell.column.getIsPinned()\n const isLastLeftPinnedColumn = isPinned === 'left' && cell.column.getIsLastColumn('left')\n const isRowSelectionColumn = cell.column.id === ROW_SELECTION_COLUMN_ID\n\n return (\n <Styled.TableCell\n {...props}\n tabIndex={0}\n key={cell.id}\n $isLastPinned={isLastLeftPinnedColumn} // is this column the last pinned column? Custom styling for borders.\n className={clsx(\n cell.column.id,\n cell.column.id === 'folderType' ? 'large' : '',\n {\n selected: isCellSelected(cellId),\n focused: isCellFocused(cellId),\n editing: isEditing(cellId),\n 'last-pinned-left': isLastLeftPinnedColumn,\n 'selected-row': isRowSelected(rowId),\n task: cell.row.original.entityType === 'task',\n },\n className,\n ...borderClasses,\n )}\n style={{\n ...getCommonPinningStyles(cell.column),\n width: `calc(var(--col-${cell.column.id}-size) * 1px)`,\n height: showHierarchy ? 36 : 40,\n }}\n onMouseDown={(e) => {\n // Only process left clicks (button 0), ignore right clicks\n if (e.button !== 0) return\n\n // check we are not clicking on expander\n if ((e.target as HTMLElement).closest('.expander')) return\n const additive = e.metaKey || e.ctrlKey || isRowSelectionColumn\n if (e.shiftKey) {\n // Shift+click extends selection from anchor cell\n selectCell(cellId, additive, true) // true for range selection\n } else {\n // Normal click starts a new selection\n startSelection(cellId, additive)\n }\n }}\n onMouseOver={(e) => {\n if (e.buttons === 1) {\n // Left button is pressed during mouse move - drag selection\n extendSelection(cellId, isRowSelectionColumn)\n }\n }}\n onMouseUp={() => {\n endSelection(cellId)\n }}\n onDoubleClick={(e) => {\n if (cell.column.id === 'name') {\n // select the row by selecting the row-selection cell\n const rowSelectionCellId = getCellId(cell.row.id, ROW_SELECTION_COLUMN_ID)\n if (!isCellSelected(rowSelectionCellId)) {\n const additive = e.metaKey || e.ctrlKey\n selectCell(rowSelectionCellId, additive, false)\n }\n }\n }}\n onContextMenu={(e) => {\n e.preventDefault()\n // if the cell is not selected, select it and deselect all others\n if (!isCellSelected(cellId)) {\n selectCell(cellId, false, false)\n }\n }}\n >\n {flexRender(cell.column.columnDef.cell, cell.getContext())}\n </Styled.TableCell>\n )\n}\n\nconst TableCellMemo = memo(TableCell)\n\nexport { FlexTableWithProviders as ProjectTreeTable }\n"],"names":["jsx","_a","loadingAttrib","loadingRows","Styled.TableWrapper","Styled.TableContainer","jsxs","Styled.TableHeader","Styled.ColumnHeader","Styled.HeaderCell","Styled.TableCellContent","Styled.HeaderButtons","Styled.ResizedHandler","Styled.TR","Styled.TableCell"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ProjectTreeTable.es.js","sources":["../../../../../src/containers/ProjectTreeTable/ProjectTreeTable.tsx"],"sourcesContent":["import { useMemo, useRef, useEffect, memo, CSSProperties } from 'react'\nimport { useVirtualizer, VirtualItem, Virtualizer } from '@tanstack/react-virtual'\n// TanStack Table imports\nimport {\n useReactTable,\n getCoreRowModel,\n getFilteredRowModel,\n getExpandedRowModel,\n filterFns,\n flexRender,\n Row,\n OnChangeFn,\n getSortedRowModel,\n Cell,\n Column,\n functionalUpdate,\n ColumnSizingState,\n Table,\n Header,\n HeaderGroup,\n} from '@tanstack/react-table'\n\n// Utility imports\nimport clsx from 'clsx'\n\n// Type imports\nimport type { FolderNodeMap, TableRow, TaskNodeMap } from './types/table'\n\n// Component imports\nimport ProjectTreeTableColumns from './ProjectTreeTableColumns'\nimport * as Styled from './ProjectTreeTable.styled'\nimport HeaderActionButton from './components/HeaderActionButton'\nimport EmptyPlaceholder from '../../components/EmptyPlaceholder'\n\n// Context imports\nimport { useCellEditing } from './context/CellEditingContext'\nimport { ROW_SELECTION_COLUMN_ID, useSelectionCellsContext } from './context/SelectionCellsContext'\nimport { ClipboardProvider } from './context/ClipboardContext'\nimport { useSelectedRowsContext } from './context/SelectedRowsContext'\nimport { useColumnSettings } from './context/ColumnSettingsContext'\n\n// Hook imports\nimport useCustomColumnWidthVars from './hooks/useCustomColumnWidthVars'\nimport usePrefetchFolderTasks from './hooks/usePrefetchFolderTasks'\nimport { useLocalStorage } from '../../hooks'\nimport useCellContextMenu from './hooks/useCellContextMenu'\nimport useColumnVirtualization from './hooks/useColumnVirtualization'\nimport useKeyboardNavigation from './hooks/useKeyboardNavigation'\n\n// Utility function imports\nimport { getCellId } from './utils/cellUtils'\nimport { generateLoadingRows, generateDummyAttributes } from './utils/loadingUtils'\nimport { createPortal } from 'react-dom'\nimport { Icon } from '@ynput/ayon-react-components'\nimport { AttributeEnumItem, AttributeWithPermissions, BuiltInFieldOptions } from './types'\nimport { useProjectTableContext } from './context/ProjectTableContext'\n\n//These are the important styles to make sticky column pinning work!\n//Apply styles like this using your CSS strategy of choice with this kind of logic to head cells, data cells, footer cells, etc.\n//View the index.css file for more needed styles such as border-collapse: separate\nconst getCommonPinningStyles = (column: Column<TableRow, unknown>): CSSProperties => {\n const isPinned = column.getIsPinned()\n\n return {\n left: isPinned === 'left' ? `${column.getStart('left')}px` : undefined,\n right: isPinned === 'right' ? `${column.getAfter('right')}px` : undefined,\n position: isPinned ? 'sticky' : 'relative',\n width: column.getSize(),\n zIndex: isPinned ? 100 : 0,\n }\n}\n\ninterface Props extends React.HTMLAttributes<HTMLDivElement> {\n scope: string\n options: BuiltInFieldOptions\n attribs: AttributeWithPermissions[]\n sliceId: string\n // metadata\n fetchMoreOnBottomReached: (element: HTMLDivElement | null) => void\n onOpenNew?: (type: 'folder' | 'task') => void\n // pass through props\n pt?: {\n container?: React.HTMLAttributes<HTMLDivElement>\n head?: Partial<TableHeadProps>\n }\n}\n\n// Component to wrap with all providers\nconst FlexTableWithProviders = (props: Props) => {\n return (\n <ClipboardProvider options={props.options}>\n <FlexTable {...props} />\n </ClipboardProvider>\n )\n}\n\nconst FlexTable = ({\n scope,\n attribs,\n options,\n sliceId,\n fetchMoreOnBottomReached,\n onOpenNew,\n pt,\n ...props\n}: Props) => {\n const {\n columnVisibility,\n columnVisibilityUpdater,\n columnPinning,\n columnPinningUpdater,\n columnOrder,\n columnOrderUpdater,\n } = useColumnSettings()\n\n const {\n tableData,\n isLoading,\n isInitialized,\n expanded,\n updateExpanded,\n toggleExpandAll,\n toggleExpanded,\n sorting,\n updateSorting,\n showHierarchy,\n } = useProjectTableContext()\n\n //The virtualizer needs to know the scrollable container element\n const tableContainerRef = useRef<HTMLDivElement>(null)\n\n // Selection context\n const { registerGrid } = useSelectionCellsContext()\n\n // COLUMN SIZING\n const [columnSizing, setColumnSizing] = useLocalStorage<ColumnSizingState>(\n `column-widths-${scope}`,\n {},\n )\n\n const updateColumnSizing: OnChangeFn<ColumnSizingState> = (columnSizingUpdater) => {\n setColumnSizing(functionalUpdate(columnSizingUpdater, columnSizing))\n }\n\n //a check on mount and after a fetch to see if the table is already scrolled to the bottom and immediately needs to fetch more data\n useEffect(() => {\n fetchMoreOnBottomReached(tableContainerRef.current)\n }, [fetchMoreOnBottomReached])\n\n // generate loading attrib and rows\n const { loadingAttrib, loadingRows } = useMemo(() => {\n // count the number of children in tbody\n const tableRowsCount = tableContainerRef.current?.querySelectorAll('tbody tr').length || 0\n const loadingAttrib = generateDummyAttributes()\n const loadingRows = generateLoadingRows(\n attribs,\n showHierarchy && tableData.length > 0 ? Math.min(tableRowsCount, 50) : 50,\n )\n return { loadingAttrib, loadingRows }\n }, [attribs, tableData, showHierarchy, tableContainerRef.current])\n\n const showLoadingRows = !isInitialized || isLoading\n\n const columns = ProjectTreeTableColumns({\n tableData: showLoadingRows ? loadingRows : tableData,\n columnSizing,\n attribs: isInitialized ? attribs : loadingAttrib,\n isLoading: !isInitialized,\n showHierarchy,\n sliceId,\n options,\n toggleExpandAll: (id: string) => toggleExpandAll([id]),\n toggleExpanded: (id: string) => toggleExpanded(id),\n })\n\n const table = useReactTable({\n data: showLoadingRows ? loadingRows : tableData,\n columns,\n enableRowSelection: true, //enable row selection for all rows\n getRowId: (row) => row.id,\n enableSubRowSelection: false, //disable sub row selection\n getSubRows: (row) => row.subRows,\n getRowCanExpand: () => true,\n getCoreRowModel: getCoreRowModel(),\n getFilteredRowModel: getFilteredRowModel(),\n getExpandedRowModel: getExpandedRowModel(),\n filterFromLeafRows: true,\n // EXPANDABLE\n onExpandedChange: updateExpanded,\n // SORTING\n getSortedRowModel: getSortedRowModel(),\n onSortingChange: updateSorting,\n columnResizeMode: 'onChange',\n onColumnPinningChange: columnPinningUpdater,\n onColumnSizingChange: updateColumnSizing,\n onColumnVisibilityChange: columnVisibilityUpdater,\n onColumnOrderChange: columnOrderUpdater,\n // @ts-ignore\n filterFns,\n state: {\n expanded,\n sorting,\n columnPinning: {\n left: [ROW_SELECTION_COLUMN_ID, ...(columnPinning.left || [])],\n right: columnPinning.right,\n },\n columnSizing,\n columnVisibility,\n columnOrder,\n },\n enableSorting: true,\n })\n\n const { rows } = table.getRowModel()\n\n // Register grid structure with selection context when rows or columns change\n useEffect(() => {\n const rowIds = rows.map((row) => row.id)\n const colIds = table.getAllLeafColumns().map((col) => col.id)\n const colIdsSortedByPinning = [...colIds].sort((a, b) => {\n if (ROW_SELECTION_COLUMN_ID === b) return 1\n const colA = columnPinning.left?.includes(a) ? 0 : 1\n const colB = columnPinning.left?.includes(b) ? 0 : 1\n return colA - colB\n })\n\n registerGrid(rowIds, colIdsSortedByPinning)\n }, [rows, table.getAllLeafColumns(), columnPinning, ROW_SELECTION_COLUMN_ID, registerGrid])\n\n const visibleColumns = table.getVisibleLeafColumns()\n\n // Use the column virtualization hook\n const { columnVirtualizer, virtualPaddingLeft, virtualPaddingRight } = useColumnVirtualization({\n visibleColumns,\n tableContainerRef,\n columnPinning,\n })\n\n const columnSizeVars = useCustomColumnWidthVars(table, columnSizing)\n const readOnlyColumns = useMemo(\n () => attribs.filter((attrib) => attrib.readOnly).map((attrib) => 'attrib_' + attrib.name),\n [attribs],\n )\n\n return (\n <Styled.TableWrapper {...props}>\n <Styled.TableContainer\n ref={tableContainerRef}\n style={{ height: '100%', padding: 0 }}\n onScroll={(e) => fetchMoreOnBottomReached(e.currentTarget)}\n {...pt?.container}\n className={clsx('table-container', pt?.container?.className)}\n >\n <table\n style={{\n display: 'grid',\n borderCollapse: 'collapse',\n userSelect: 'none',\n ...columnSizeVars,\n width: table.getTotalSize(),\n }}\n >\n <TableHead\n columnVirtualizer={columnVirtualizer}\n table={table}\n virtualPaddingLeft={virtualPaddingLeft}\n virtualPaddingRight={virtualPaddingRight}\n isLoading={isLoading}\n readOnlyColumns={readOnlyColumns}\n {...pt?.head}\n />\n <TableBody\n columnVirtualizer={columnVirtualizer}\n table={table}\n tableContainerRef={tableContainerRef}\n virtualPaddingLeft={virtualPaddingLeft}\n virtualPaddingRight={virtualPaddingRight}\n showHierarchy={showHierarchy}\n attribs={attribs}\n onOpenNew={onOpenNew}\n />\n </table>\n </Styled.TableContainer>\n </Styled.TableWrapper>\n )\n}\n\ninterface TableHeadProps extends React.HTMLAttributes<HTMLTableSectionElement> {\n columnVirtualizer: Virtualizer<HTMLDivElement, HTMLTableCellElement>\n table: Table<TableRow>\n virtualPaddingLeft: number | undefined\n virtualPaddingRight: number | undefined\n isLoading: boolean\n readOnlyColumns?: string[]\n}\n\nconst TableHead = ({\n columnVirtualizer,\n table,\n virtualPaddingLeft,\n virtualPaddingRight,\n isLoading,\n readOnlyColumns,\n ...props\n}: TableHeadProps) => {\n return (\n <Styled.TableHeader {...props}>\n {table.getHeaderGroups().map((headerGroup) => (\n <TableHeadRow\n key={headerGroup.id}\n columnVirtualizer={columnVirtualizer}\n headerGroup={headerGroup}\n virtualPaddingLeft={virtualPaddingLeft}\n virtualPaddingRight={virtualPaddingRight}\n isLoading={isLoading}\n readOnlyColumns={readOnlyColumns}\n />\n ))}\n </Styled.TableHeader>\n )\n}\n\ninterface TableHeadRowProps {\n columnVirtualizer: Virtualizer<HTMLDivElement, HTMLTableCellElement>\n headerGroup: HeaderGroup<TableRow>\n virtualPaddingLeft: number | undefined\n virtualPaddingRight: number | undefined\n isLoading: boolean\n readOnlyColumns?: string[]\n}\n\nconst TableHeadRow = ({\n columnVirtualizer,\n headerGroup,\n virtualPaddingLeft,\n virtualPaddingRight,\n isLoading,\n readOnlyColumns,\n}: TableHeadRowProps) => {\n const virtualColumns = columnVirtualizer.getVirtualItems()\n return (\n <Styled.ColumnHeader key={headerGroup.id} style={{ display: 'flex' }}>\n {virtualPaddingLeft ? (\n //fake empty column to the left for virtualization scroll padding\n <th style={{ display: 'flex', width: virtualPaddingLeft }} />\n ) : null}\n {virtualColumns.map((virtualColumn) => {\n const header = headerGroup.headers[virtualColumn.index]\n return (\n <TableHeadCell\n key={header.id}\n header={header}\n isLoading={isLoading}\n isReadOnly={readOnlyColumns?.includes(header.id)}\n />\n )\n })}\n {virtualPaddingRight ? (\n //fake empty column to the right for virtualization scroll padding\n <th style={{ display: 'flex', width: virtualPaddingRight }} />\n ) : null}\n </Styled.ColumnHeader>\n )\n}\n\ninterface TableHeadCellProps {\n header: Header<TableRow, unknown>\n isLoading: boolean\n isReadOnly?: boolean\n}\n\nconst TableHeadCell = ({ header, isLoading, isReadOnly }: TableHeadCellProps) => {\n const { column } = header\n const isRowSelectionColumn = column.id === ROW_SELECTION_COLUMN_ID\n\n return (\n <Styled.HeaderCell\n className={clsx(header.id, 'shimmer-dark', {\n loading: isLoading,\n large: column.id === 'folderType',\n 'last-pinned-left': column.getIsPinned() === 'left' && column.getIsLastColumn('left'),\n })}\n key={header.id}\n style={{\n ...getCommonPinningStyles(column),\n width: `calc(var(--header-${header?.id}-size) * 1px)`,\n }}\n >\n {header.isPlaceholder ? null : (\n <Styled.TableCellContent\n className={clsx('bold', {\n large: column.id === 'folderType',\n })}\n >\n {flexRender(column.columnDef.header, header.getContext())}\n {isReadOnly && (\n <Icon icon=\"lock\" data-tooltip={'You only have permission to read this column.'} />\n )}\n\n <Styled.HeaderButtons className=\"actions\">\n {/* COLUMN HIDING */}\n <HeaderActionButton\n icon=\"visibility_off\"\n selected={!column.getIsVisible()}\n onClick={column.getToggleVisibilityHandler()}\n />\n {/* COLUMN SORTING */}\n <HeaderActionButton\n icon=\"push_pin\"\n selected={header.column.getIsPinned() === 'left'}\n onClick={() => {\n if (header.column.getIsPinned() === 'left') {\n header.column.pin(false)\n } else {\n header.column.pin('left')\n }\n }}\n />\n {/* COLUMN PINNING */}\n <HeaderActionButton\n icon={'sort'}\n style={{\n transform: (column.getIsSorted() as string) === 'asc' ? 'scaleY(-1)' : undefined,\n }}\n onClick={column.getToggleSortingHandler()}\n selected={!!column.getIsSorted()}\n />\n </Styled.HeaderButtons>\n {!isRowSelectionColumn && (\n <Styled.ResizedHandler\n {...{\n onDoubleClick: () => column.resetSize(),\n onMouseDown: header.getResizeHandler(),\n onTouchStart: header.getResizeHandler(),\n className: clsx('resize-handle', {\n resizing: column.getIsResizing(),\n }),\n }}\n />\n )}\n </Styled.TableCellContent>\n )}\n </Styled.HeaderCell>\n )\n}\n\ninterface TableBodyProps {\n columnVirtualizer: Virtualizer<HTMLDivElement, HTMLTableCellElement>\n table: Table<TableRow>\n tableContainerRef: React.RefObject<HTMLDivElement>\n showHierarchy: boolean\n virtualPaddingLeft: number | undefined\n virtualPaddingRight: number | undefined\n attribs: AttributeWithPermissions[]\n onOpenNew?: (type: 'folder' | 'task') => void\n}\n\nconst TableBody = ({\n columnVirtualizer,\n table,\n tableContainerRef,\n showHierarchy,\n virtualPaddingLeft,\n virtualPaddingRight,\n attribs,\n onOpenNew,\n}: TableBodyProps) => {\n const { handleTableBodyContextMenu } = useCellContextMenu({ attribs, onOpenNew })\n\n const { handlePreFetchTasks } = usePrefetchFolderTasks()\n\n const { rows } = table.getRowModel()\n\n const rowVirtualizer = useVirtualizer<HTMLDivElement, HTMLTableRowElement>({\n count: rows.length,\n estimateSize: () => (showHierarchy ? 36 : 40), //estimate row height for accurate scrollbar dragging\n getScrollElement: () => tableContainerRef.current,\n //measure dynamic row height, except in firefox because it measures table border height incorrectly\n measureElement:\n typeof window !== 'undefined' && navigator.userAgent.indexOf('Firefox') === -1\n ? (element) => element?.getBoundingClientRect().height\n : undefined,\n overscan: 5,\n })\n\n const virtualRows = rowVirtualizer.getVirtualItems()\n\n useKeyboardNavigation()\n\n return virtualRows.length ? (\n <tbody\n style={{\n height: `${rowVirtualizer.getTotalSize()}px`,\n position: 'relative',\n display: 'grid',\n }}\n onContextMenu={handleTableBodyContextMenu}\n onMouseOver={(e) => {\n handlePreFetchTasks(e)\n }}\n >\n {virtualRows.map((virtualRow) => {\n const row = rows[virtualRow.index] as Row<TableRow>\n return (\n <TableBodyRow\n key={row.id}\n columnVirtualizer={columnVirtualizer}\n row={row}\n rowVirtualizer={rowVirtualizer}\n virtualPaddingLeft={virtualPaddingLeft}\n virtualPaddingRight={virtualPaddingRight}\n virtualRow={virtualRow}\n showHierarchy={showHierarchy}\n />\n )\n })}\n </tbody>\n ) : (\n tableContainerRef.current &&\n createPortal(\n <EmptyPlaceholder message=\"No folders or tasks found\" />,\n tableContainerRef.current,\n )\n )\n}\n\ninterface TableBodyRowProps {\n columnVirtualizer: Virtualizer<HTMLDivElement, HTMLTableCellElement>\n row: Row<TableRow>\n rowVirtualizer: Virtualizer<HTMLDivElement, HTMLTableRowElement>\n virtualPaddingLeft: number | undefined\n virtualPaddingRight: number | undefined\n virtualRow: VirtualItem\n showHierarchy: boolean\n}\n\nconst TableBodyRow = ({\n columnVirtualizer,\n row,\n rowVirtualizer,\n virtualPaddingLeft,\n virtualPaddingRight,\n virtualRow,\n showHierarchy,\n}: TableBodyRowProps) => {\n // We should do this so that we don't re-render every time anything in projectTableContext changes\n const visibleCells = row.getVisibleCells()\n const virtualColumns = columnVirtualizer.getVirtualItems()\n\n return (\n <Styled.TR\n data-index={virtualRow.index} //needed for dynamic row height measurement\n ref={(node) => rowVirtualizer.measureElement(node)} //measure dynamic row height\n key={row.id}\n style={{\n transform: `translateY(${virtualRow.start}px)`, //this should always be a `style` as it changes on scroll\n }}\n >\n {virtualPaddingLeft ? (\n //fake empty column to the left for virtualization scroll padding\n <td style={{ display: 'flex', width: virtualPaddingLeft }} />\n ) : null}\n {virtualColumns.map((vc) => {\n const cell = visibleCells[vc.index]\n const cellId = getCellId(row.id, cell.column.id)\n return (\n <TableCellMemo\n cell={cell}\n cellId={cellId}\n rowId={row.id}\n key={cell.id}\n showHierarchy={showHierarchy}\n />\n )\n })}\n\n {virtualPaddingRight ? (\n //fake empty column to the right for virtualization scroll padding\n <td style={{ display: 'flex', width: virtualPaddingRight }} />\n ) : null}\n </Styled.TR>\n )\n}\n\ninterface TableCellProps {\n cell: Cell<TableRow, unknown>\n cellId: string\n rowId: string\n className?: string\n showHierarchy: boolean\n}\n\nconst TableCell = ({ cell, rowId, cellId, className, showHierarchy, ...props }: TableCellProps) => {\n const {\n isCellSelected,\n isCellFocused,\n startSelection,\n extendSelection,\n endSelection,\n selectCell,\n getCellBorderClasses,\n } = useSelectionCellsContext()\n\n const { isRowSelected } = useSelectedRowsContext()\n\n const { isEditing } = useCellEditing()\n\n const borderClasses = getCellBorderClasses(cellId)\n\n const isPinned = cell.column.getIsPinned()\n const isLastLeftPinnedColumn = isPinned === 'left' && cell.column.getIsLastColumn('left')\n const isRowSelectionColumn = cell.column.id === ROW_SELECTION_COLUMN_ID\n\n return (\n <Styled.TableCell\n {...props}\n tabIndex={0}\n key={cell.id}\n $isLastPinned={isLastLeftPinnedColumn} // is this column the last pinned column? Custom styling for borders.\n className={clsx(\n cell.column.id,\n cell.column.id === 'folderType' ? 'large' : '',\n {\n selected: isCellSelected(cellId),\n focused: isCellFocused(cellId),\n editing: isEditing(cellId),\n 'last-pinned-left': isLastLeftPinnedColumn,\n 'selected-row': isRowSelected(rowId),\n task: cell.row.original.entityType === 'task',\n },\n className,\n ...borderClasses,\n )}\n style={{\n ...getCommonPinningStyles(cell.column),\n width: `calc(var(--col-${cell.column.id}-size) * 1px)`,\n height: showHierarchy ? 36 : 40,\n }}\n onMouseDown={(e) => {\n // Only process left clicks (button 0), ignore right clicks\n if (e.button !== 0) return\n\n // check we are not clicking on expander\n if ((e.target as HTMLElement).closest('.expander')) return\n const additive = e.metaKey || e.ctrlKey || isRowSelectionColumn\n if (e.shiftKey) {\n // Shift+click extends selection from anchor cell\n selectCell(cellId, additive, true) // true for range selection\n } else {\n // Normal click starts a new selection\n startSelection(cellId, additive)\n }\n }}\n onMouseOver={(e) => {\n if (e.buttons === 1) {\n // Left button is pressed during mouse move - drag selection\n extendSelection(cellId, isRowSelectionColumn)\n }\n }}\n onMouseUp={() => {\n endSelection(cellId)\n }}\n onDoubleClick={(e) => {\n if (cell.column.id === 'name') {\n // select the row by selecting the row-selection cell\n const rowSelectionCellId = getCellId(cell.row.id, ROW_SELECTION_COLUMN_ID)\n if (!isCellSelected(rowSelectionCellId)) {\n const additive = e.metaKey || e.ctrlKey\n selectCell(rowSelectionCellId, additive, false)\n }\n }\n }}\n onContextMenu={(e) => {\n e.preventDefault()\n // if the cell is not selected, select it and deselect all others\n if (!isCellSelected(cellId)) {\n selectCell(cellId, false, false)\n }\n }}\n >\n {flexRender(cell.column.columnDef.cell, cell.getContext())}\n </Styled.TableCell>\n )\n}\n\nconst TableCellMemo = memo(TableCell)\n\nexport { FlexTableWithProviders as ProjectTreeTable }\n"],"names":["jsx","_a","loadingAttrib","loadingRows","Styled.TableWrapper","Styled.TableContainer","jsxs","Styled.TableHeader","Styled.ColumnHeader","Styled.HeaderCell","Styled.TableCellContent","Styled.HeaderButtons","Styled.ResizedHandler","Styled.TR","Styled.TableCell"],"mappings":"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"}
|
|
@@ -68,6 +68,10 @@ require("../api/queries/users/updateUsers.cjs.js");
|
|
|
68
68
|
require("../api/queries/watchers/getWatchers.cjs.js");
|
|
69
69
|
require("../../../_virtual/lodash.cjs.js");
|
|
70
70
|
require("react-toastify");
|
|
71
|
+
require("./ThumbnailUploaderContext.cjs.js");
|
|
72
|
+
require("./pip/PiPProvider.cjs.js");
|
|
73
|
+
require("react-dom");
|
|
74
|
+
require("./pip/PiPWrapper.cjs.js");
|
|
71
75
|
require("react-router-dom");
|
|
72
76
|
require("custom-protocol-check");
|
|
73
77
|
const DetailsPanelContext = React.createContext(void 0);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DetailsPanelContext.cjs.js","sources":["../../../../src/context/DetailsPanelContext.tsx"],"sourcesContent":["import React, { createContext, useContext, useCallback, ReactNode, useState } from 'react'\nimport { useLocalStorage } from '@shared/hooks'\nimport { DetailsPanelEntityType } from '@shared/api'\nimport type { UserModel } from '@shared/api'\n\nexport type FeedFilters = 'activity' | 'comments' | 'versions' | 'checklists'\n\nexport type DetailsPanelTab = FeedFilters | 'attribs' | 'files'\n\nexport type SlideOut = {\n entityId: string\n entityType: DetailsPanelEntityType\n projectName: string\n}\n\nexport type DetailsPanelPip = {\n entityType: DetailsPanelEntityType\n entities: { id: string; projectName: string }[]\n scope: string\n}\n\nexport interface OpenStateByScope {\n [scope: string]: boolean\n}\n\n// Create a new interface for managing tab state by scope\nexport interface TabStateByScope {\n [scope: string]: DetailsPanelTab\n}\n\n// these props get forwarded to the details panel value\n// it's mainly redux callbacks that cannot be used in shared library\nexport interface DetailsPanelContextProps {\n dispatch?: any // this is a redux dispatch function and it's quite annoying we need to do this\n user: UserModel\n viewer?: {\n reviewableIds: string[]\n taskId?: string\n folderId?: string\n }\n // redux callback actions\n onOpenImage?: (args: any) => void\n onGoToFrame?: (frame: number) => void\n onOpenViewer?: (args: any) => void\n}\n\n// Interface for our simplified context\nexport interface DetailsPanelContextType extends DetailsPanelContextProps {\n // Open state for the panel by scope\n panelOpenByScope: OpenStateByScope\n getOpenForScope: (scope: string) => boolean\n setPanelOpen: (scope: string, isOpen: boolean) => void\n setPanelOpenByScope: (newState: OpenStateByScope) => void\n\n // Tab preferences by scope\n tabsByScope: TabStateByScope\n getTabForScope: (scope: string) => DetailsPanelTab\n setTab: (scope: string, tab: DetailsPanelTab) => void\n\n // Slide out state\n slideOut: null | SlideOut\n openSlideOut: (slideOut: SlideOut) => void\n closeSlideOut: () => void\n\n // Highlighted activities\n highlightedActivities: string[]\n setHighlightedActivities: (activities: string[]) => void\n\n // PiP state\n pip: DetailsPanelPip | null\n openPip: (pip: DetailsPanelPip) => void\n closePip: () => void\n}\n\n// Create the context\nconst DetailsPanelContext = createContext<DetailsPanelContextType | undefined>(undefined)\n\n// Provider component\nexport interface DetailsPanelProviderProps extends DetailsPanelContextProps {\n children: ReactNode\n defaultTab?: DetailsPanelTab\n}\n\nexport const DetailsPanelProvider: React.FC<DetailsPanelProviderProps> = ({\n children,\n defaultTab = 'activity',\n ...forwardedProps\n}) => {\n // keep track of the currently open panel by scope\n const [panelOpenByScope, setPanelOpenByScope] = useState<OpenStateByScope>({})\n\n // get the current open state for a specific scope\n const getOpenForScope = useCallback(\n (scope: string): boolean => {\n // Check if we have a saved preference for this scope\n if (panelOpenByScope[scope]) {\n return panelOpenByScope[scope]\n }\n\n // Fall back to default\n return false\n },\n [panelOpenByScope],\n )\n // Set open state for a scope\n const setPanelOpen = useCallback(\n (scope: string, isOpen: boolean) => {\n // Create a new state object based on current open state\n const newState = { ...panelOpenByScope }\n newState[scope] = isOpen\n\n // Update the state with the new object\n setPanelOpenByScope(newState)\n },\n [panelOpenByScope],\n )\n\n // Use localStorage to persist tab preferences by scope\n const [tabsByScope, setTabsByScope] = useLocalStorage<TabStateByScope>(\n 'details/tabs-by-scope',\n {},\n )\n\n // Get the current tab for a specific scope\n const getTabForScope = useCallback(\n (scope: string): DetailsPanelTab => {\n // Check if we have a saved preference for this scope\n if (tabsByScope[scope]) {\n return tabsByScope[scope]\n }\n\n // Fall back to default\n return defaultTab\n },\n [tabsByScope, defaultTab],\n )\n\n // Set tab for a scope\n const setTab = useCallback(\n (scope: string, tab: DetailsPanelTab) => {\n // Create a new state object based on current tabsByScope\n const newState = { ...tabsByScope }\n newState[scope] = tab\n\n // Update the state with the new object\n setTabsByScope(newState)\n },\n [tabsByScope, setTabsByScope],\n )\n\n // is the slide out open?\n const [slideOut, setSlideOut] = useState<null | SlideOut>(null)\n\n // open the slide out\n const openSlideOut = useCallback<DetailsPanelContextType['openSlideOut']>((params) => {\n setSlideOut(params)\n }, [])\n\n // close the slide out\n const closeSlideOut = useCallback(() => {\n setSlideOut(null)\n setHighlightedActivities([])\n }, [])\n\n const [pip, setPip] = useState<DetailsPanelPip | null>(null)\n\n const openPip = useCallback((pip: DetailsPanelPip) => {\n setPip(pip)\n }, [])\n const closePip = useCallback(() => {\n setPip(null)\n }, [])\n\n const [highlightedActivities, setHighlightedActivities] = useState<string[]>([])\n\n const value = {\n // open state for the panel by scope\n panelOpenByScope,\n getOpenForScope,\n setPanelOpen,\n setPanelOpenByScope,\n // tab preferences\n tabsByScope,\n getTabForScope,\n setTab,\n // slide out state\n slideOut,\n openSlideOut,\n closeSlideOut,\n // highlighted activities\n highlightedActivities,\n setHighlightedActivities,\n // PiP state\n pip,\n openPip,\n closePip,\n ...forwardedProps,\n }\n\n return <DetailsPanelContext.Provider value={value}>{children}</DetailsPanelContext.Provider>\n}\n\n// Custom hook to use the details context\nexport const useDetailsPanelContext = (): DetailsPanelContextType => {\n const context = useContext(DetailsPanelContext)\n if (context === undefined) {\n throw new Error('useDetailsPanel must be used within a DetailsProvider')\n }\n return context\n}\n\n// Add a specialized hook for using a panel in a specific scope\nexport const useScopedDetailsPanel = (scope: string) => {\n const { getTabForScope, setTab, getOpenForScope, setPanelOpen } = useDetailsPanelContext()\n\n return {\n isOpen: getOpenForScope(scope),\n setOpen: (isOpen: boolean) => setPanelOpen(scope, isOpen),\n currentTab: getTabForScope(scope),\n setTab: (tab: DetailsPanelTab) => setTab(scope, tab),\n isFeed: ['activity', 'comments', 'versions', 'checklists'].includes(getTabForScope(scope)),\n }\n}\n"],"names":["createContext","useState","useCallback","useLocalStorage","pip","jsx","useContext"],"mappings":"
|
|
1
|
+
{"version":3,"file":"DetailsPanelContext.cjs.js","sources":["../../../../src/context/DetailsPanelContext.tsx"],"sourcesContent":["import React, { createContext, useContext, useCallback, ReactNode, useState } from 'react'\nimport { useLocalStorage } from '@shared/hooks'\nimport { DetailsPanelEntityType } from '@shared/api'\nimport type { UserModel } from '@shared/api'\n\nexport type FeedFilters = 'activity' | 'comments' | 'versions' | 'checklists'\n\nexport type DetailsPanelTab = FeedFilters | 'attribs' | 'files'\n\nexport type SlideOut = {\n entityId: string\n entityType: DetailsPanelEntityType\n projectName: string\n}\n\nexport type DetailsPanelPip = {\n entityType: DetailsPanelEntityType\n entities: { id: string; projectName: string }[]\n scope: string\n}\n\nexport interface OpenStateByScope {\n [scope: string]: boolean\n}\n\n// Create a new interface for managing tab state by scope\nexport interface TabStateByScope {\n [scope: string]: DetailsPanelTab\n}\n\n// these props get forwarded to the details panel value\n// it's mainly redux callbacks that cannot be used in shared library\nexport interface DetailsPanelContextProps {\n dispatch?: any // this is a redux dispatch function and it's quite annoying we need to do this\n user: UserModel\n viewer?: {\n reviewableIds: string[]\n taskId?: string\n folderId?: string\n }\n // redux callback actions\n onOpenImage?: (args: any) => void\n onGoToFrame?: (frame: number) => void\n onOpenViewer?: (args: any) => void\n onUpdateEntity?: (data: { operations: any[], entityType: string }) => void\n}\n\n// Interface for our simplified context\nexport interface DetailsPanelContextType extends DetailsPanelContextProps {\n // Open state for the panel by scope\n panelOpenByScope: OpenStateByScope\n getOpenForScope: (scope: string) => boolean\n setPanelOpen: (scope: string, isOpen: boolean) => void\n setPanelOpenByScope: (newState: OpenStateByScope) => void\n\n // Tab preferences by scope\n tabsByScope: TabStateByScope\n getTabForScope: (scope: string) => DetailsPanelTab\n setTab: (scope: string, tab: DetailsPanelTab) => void\n\n // Slide out state\n slideOut: null | SlideOut\n openSlideOut: (slideOut: SlideOut) => void\n closeSlideOut: () => void\n\n // Highlighted activities\n highlightedActivities: string[]\n setHighlightedActivities: (activities: string[]) => void\n\n // PiP state\n pip: DetailsPanelPip | null\n openPip: (pip: DetailsPanelPip) => void\n closePip: () => void\n}\n\n// Create the context\nconst DetailsPanelContext = createContext<DetailsPanelContextType | undefined>(undefined)\n\n// Provider component\nexport interface DetailsPanelProviderProps extends DetailsPanelContextProps {\n children: ReactNode\n defaultTab?: DetailsPanelTab\n}\n\nexport const DetailsPanelProvider: React.FC<DetailsPanelProviderProps> = ({\n children,\n defaultTab = 'activity',\n ...forwardedProps\n}) => {\n // keep track of the currently open panel by scope\n const [panelOpenByScope, setPanelOpenByScope] = useState<OpenStateByScope>({})\n\n // get the current open state for a specific scope\n const getOpenForScope = useCallback(\n (scope: string): boolean => {\n // Check if we have a saved preference for this scope\n if (panelOpenByScope[scope]) {\n return panelOpenByScope[scope]\n }\n\n // Fall back to default\n return false\n },\n [panelOpenByScope],\n )\n // Set open state for a scope\n const setPanelOpen = useCallback(\n (scope: string, isOpen: boolean) => {\n // Create a new state object based on current open state\n const newState = { ...panelOpenByScope }\n newState[scope] = isOpen\n\n // Update the state with the new object\n setPanelOpenByScope(newState)\n },\n [panelOpenByScope],\n )\n\n // Use localStorage to persist tab preferences by scope\n const [tabsByScope, setTabsByScope] = useLocalStorage<TabStateByScope>(\n 'details/tabs-by-scope',\n {},\n )\n\n // Get the current tab for a specific scope\n const getTabForScope = useCallback(\n (scope: string): DetailsPanelTab => {\n // Check if we have a saved preference for this scope\n if (tabsByScope[scope]) {\n return tabsByScope[scope]\n }\n\n // Fall back to default\n return defaultTab\n },\n [tabsByScope, defaultTab],\n )\n\n // Set tab for a scope\n const setTab = useCallback(\n (scope: string, tab: DetailsPanelTab) => {\n // Create a new state object based on current tabsByScope\n const newState = { ...tabsByScope }\n newState[scope] = tab\n\n // Update the state with the new object\n setTabsByScope(newState)\n },\n [tabsByScope, setTabsByScope],\n )\n\n // is the slide out open?\n const [slideOut, setSlideOut] = useState<null | SlideOut>(null)\n\n // open the slide out\n const openSlideOut = useCallback<DetailsPanelContextType['openSlideOut']>((params) => {\n setSlideOut(params)\n }, [])\n\n // close the slide out\n const closeSlideOut = useCallback(() => {\n setSlideOut(null)\n setHighlightedActivities([])\n }, [])\n\n const [pip, setPip] = useState<DetailsPanelPip | null>(null)\n\n const openPip = useCallback((pip: DetailsPanelPip) => {\n setPip(pip)\n }, [])\n const closePip = useCallback(() => {\n setPip(null)\n }, [])\n\n const [highlightedActivities, setHighlightedActivities] = useState<string[]>([])\n\n const value = {\n // open state for the panel by scope\n panelOpenByScope,\n getOpenForScope,\n setPanelOpen,\n setPanelOpenByScope,\n // tab preferences\n tabsByScope,\n getTabForScope,\n setTab,\n // slide out state\n slideOut,\n openSlideOut,\n closeSlideOut,\n // highlighted activities\n highlightedActivities,\n setHighlightedActivities,\n // PiP state\n pip,\n openPip,\n closePip,\n ...forwardedProps,\n }\n\n return <DetailsPanelContext.Provider value={value}>{children}</DetailsPanelContext.Provider>\n}\n\n// Custom hook to use the details context\nexport const useDetailsPanelContext = (): DetailsPanelContextType => {\n const context = useContext(DetailsPanelContext)\n if (context === undefined) {\n throw new Error('useDetailsPanel must be used within a DetailsProvider')\n }\n return context\n}\n\n// Add a specialized hook for using a panel in a specific scope\nexport const useScopedDetailsPanel = (scope: string) => {\n const { getTabForScope, setTab, getOpenForScope, setPanelOpen } = useDetailsPanelContext()\n\n return {\n isOpen: getOpenForScope(scope),\n setOpen: (isOpen: boolean) => setPanelOpen(scope, isOpen),\n currentTab: getTabForScope(scope),\n setTab: (tab: DetailsPanelTab) => setTab(scope, tab),\n isFeed: ['activity', 'comments', 'versions', 'checklists'].includes(getTabForScope(scope)),\n }\n}\n"],"names":["createContext","useState","useCallback","useLocalStorage","pip","jsx","useContext"],"mappings":"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"}
|
|
@@ -66,6 +66,10 @@ import "../api/queries/users/updateUsers.es.js";
|
|
|
66
66
|
import "../api/queries/watchers/getWatchers.es.js";
|
|
67
67
|
import "../../../_virtual/lodash.es.js";
|
|
68
68
|
import "react-toastify";
|
|
69
|
+
import "./ThumbnailUploaderContext.es.js";
|
|
70
|
+
import "./pip/PiPProvider.es.js";
|
|
71
|
+
import "react-dom";
|
|
72
|
+
import "./pip/PiPWrapper.es.js";
|
|
69
73
|
import "react-router-dom";
|
|
70
74
|
import "custom-protocol-check";
|
|
71
75
|
const DetailsPanelContext = createContext(void 0);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DetailsPanelContext.es.js","sources":["../../../../src/context/DetailsPanelContext.tsx"],"sourcesContent":["import React, { createContext, useContext, useCallback, ReactNode, useState } from 'react'\nimport { useLocalStorage } from '@shared/hooks'\nimport { DetailsPanelEntityType } from '@shared/api'\nimport type { UserModel } from '@shared/api'\n\nexport type FeedFilters = 'activity' | 'comments' | 'versions' | 'checklists'\n\nexport type DetailsPanelTab = FeedFilters | 'attribs' | 'files'\n\nexport type SlideOut = {\n entityId: string\n entityType: DetailsPanelEntityType\n projectName: string\n}\n\nexport type DetailsPanelPip = {\n entityType: DetailsPanelEntityType\n entities: { id: string; projectName: string }[]\n scope: string\n}\n\nexport interface OpenStateByScope {\n [scope: string]: boolean\n}\n\n// Create a new interface for managing tab state by scope\nexport interface TabStateByScope {\n [scope: string]: DetailsPanelTab\n}\n\n// these props get forwarded to the details panel value\n// it's mainly redux callbacks that cannot be used in shared library\nexport interface DetailsPanelContextProps {\n dispatch?: any // this is a redux dispatch function and it's quite annoying we need to do this\n user: UserModel\n viewer?: {\n reviewableIds: string[]\n taskId?: string\n folderId?: string\n }\n // redux callback actions\n onOpenImage?: (args: any) => void\n onGoToFrame?: (frame: number) => void\n onOpenViewer?: (args: any) => void\n}\n\n// Interface for our simplified context\nexport interface DetailsPanelContextType extends DetailsPanelContextProps {\n // Open state for the panel by scope\n panelOpenByScope: OpenStateByScope\n getOpenForScope: (scope: string) => boolean\n setPanelOpen: (scope: string, isOpen: boolean) => void\n setPanelOpenByScope: (newState: OpenStateByScope) => void\n\n // Tab preferences by scope\n tabsByScope: TabStateByScope\n getTabForScope: (scope: string) => DetailsPanelTab\n setTab: (scope: string, tab: DetailsPanelTab) => void\n\n // Slide out state\n slideOut: null | SlideOut\n openSlideOut: (slideOut: SlideOut) => void\n closeSlideOut: () => void\n\n // Highlighted activities\n highlightedActivities: string[]\n setHighlightedActivities: (activities: string[]) => void\n\n // PiP state\n pip: DetailsPanelPip | null\n openPip: (pip: DetailsPanelPip) => void\n closePip: () => void\n}\n\n// Create the context\nconst DetailsPanelContext = createContext<DetailsPanelContextType | undefined>(undefined)\n\n// Provider component\nexport interface DetailsPanelProviderProps extends DetailsPanelContextProps {\n children: ReactNode\n defaultTab?: DetailsPanelTab\n}\n\nexport const DetailsPanelProvider: React.FC<DetailsPanelProviderProps> = ({\n children,\n defaultTab = 'activity',\n ...forwardedProps\n}) => {\n // keep track of the currently open panel by scope\n const [panelOpenByScope, setPanelOpenByScope] = useState<OpenStateByScope>({})\n\n // get the current open state for a specific scope\n const getOpenForScope = useCallback(\n (scope: string): boolean => {\n // Check if we have a saved preference for this scope\n if (panelOpenByScope[scope]) {\n return panelOpenByScope[scope]\n }\n\n // Fall back to default\n return false\n },\n [panelOpenByScope],\n )\n // Set open state for a scope\n const setPanelOpen = useCallback(\n (scope: string, isOpen: boolean) => {\n // Create a new state object based on current open state\n const newState = { ...panelOpenByScope }\n newState[scope] = isOpen\n\n // Update the state with the new object\n setPanelOpenByScope(newState)\n },\n [panelOpenByScope],\n )\n\n // Use localStorage to persist tab preferences by scope\n const [tabsByScope, setTabsByScope] = useLocalStorage<TabStateByScope>(\n 'details/tabs-by-scope',\n {},\n )\n\n // Get the current tab for a specific scope\n const getTabForScope = useCallback(\n (scope: string): DetailsPanelTab => {\n // Check if we have a saved preference for this scope\n if (tabsByScope[scope]) {\n return tabsByScope[scope]\n }\n\n // Fall back to default\n return defaultTab\n },\n [tabsByScope, defaultTab],\n )\n\n // Set tab for a scope\n const setTab = useCallback(\n (scope: string, tab: DetailsPanelTab) => {\n // Create a new state object based on current tabsByScope\n const newState = { ...tabsByScope }\n newState[scope] = tab\n\n // Update the state with the new object\n setTabsByScope(newState)\n },\n [tabsByScope, setTabsByScope],\n )\n\n // is the slide out open?\n const [slideOut, setSlideOut] = useState<null | SlideOut>(null)\n\n // open the slide out\n const openSlideOut = useCallback<DetailsPanelContextType['openSlideOut']>((params) => {\n setSlideOut(params)\n }, [])\n\n // close the slide out\n const closeSlideOut = useCallback(() => {\n setSlideOut(null)\n setHighlightedActivities([])\n }, [])\n\n const [pip, setPip] = useState<DetailsPanelPip | null>(null)\n\n const openPip = useCallback((pip: DetailsPanelPip) => {\n setPip(pip)\n }, [])\n const closePip = useCallback(() => {\n setPip(null)\n }, [])\n\n const [highlightedActivities, setHighlightedActivities] = useState<string[]>([])\n\n const value = {\n // open state for the panel by scope\n panelOpenByScope,\n getOpenForScope,\n setPanelOpen,\n setPanelOpenByScope,\n // tab preferences\n tabsByScope,\n getTabForScope,\n setTab,\n // slide out state\n slideOut,\n openSlideOut,\n closeSlideOut,\n // highlighted activities\n highlightedActivities,\n setHighlightedActivities,\n // PiP state\n pip,\n openPip,\n closePip,\n ...forwardedProps,\n }\n\n return <DetailsPanelContext.Provider value={value}>{children}</DetailsPanelContext.Provider>\n}\n\n// Custom hook to use the details context\nexport const useDetailsPanelContext = (): DetailsPanelContextType => {\n const context = useContext(DetailsPanelContext)\n if (context === undefined) {\n throw new Error('useDetailsPanel must be used within a DetailsProvider')\n }\n return context\n}\n\n// Add a specialized hook for using a panel in a specific scope\nexport const useScopedDetailsPanel = (scope: string) => {\n const { getTabForScope, setTab, getOpenForScope, setPanelOpen } = useDetailsPanelContext()\n\n return {\n isOpen: getOpenForScope(scope),\n setOpen: (isOpen: boolean) => setPanelOpen(scope, isOpen),\n currentTab: getTabForScope(scope),\n setTab: (tab: DetailsPanelTab) => setTab(scope, tab),\n isFeed: ['activity', 'comments', 'versions', 'checklists'].includes(getTabForScope(scope)),\n }\n}\n"],"names":["pip","jsx"],"mappings":"
|
|
1
|
+
{"version":3,"file":"DetailsPanelContext.es.js","sources":["../../../../src/context/DetailsPanelContext.tsx"],"sourcesContent":["import React, { createContext, useContext, useCallback, ReactNode, useState } from 'react'\nimport { useLocalStorage } from '@shared/hooks'\nimport { DetailsPanelEntityType } from '@shared/api'\nimport type { UserModel } from '@shared/api'\n\nexport type FeedFilters = 'activity' | 'comments' | 'versions' | 'checklists'\n\nexport type DetailsPanelTab = FeedFilters | 'attribs' | 'files'\n\nexport type SlideOut = {\n entityId: string\n entityType: DetailsPanelEntityType\n projectName: string\n}\n\nexport type DetailsPanelPip = {\n entityType: DetailsPanelEntityType\n entities: { id: string; projectName: string }[]\n scope: string\n}\n\nexport interface OpenStateByScope {\n [scope: string]: boolean\n}\n\n// Create a new interface for managing tab state by scope\nexport interface TabStateByScope {\n [scope: string]: DetailsPanelTab\n}\n\n// these props get forwarded to the details panel value\n// it's mainly redux callbacks that cannot be used in shared library\nexport interface DetailsPanelContextProps {\n dispatch?: any // this is a redux dispatch function and it's quite annoying we need to do this\n user: UserModel\n viewer?: {\n reviewableIds: string[]\n taskId?: string\n folderId?: string\n }\n // redux callback actions\n onOpenImage?: (args: any) => void\n onGoToFrame?: (frame: number) => void\n onOpenViewer?: (args: any) => void\n onUpdateEntity?: (data: { operations: any[], entityType: string }) => void\n}\n\n// Interface for our simplified context\nexport interface DetailsPanelContextType extends DetailsPanelContextProps {\n // Open state for the panel by scope\n panelOpenByScope: OpenStateByScope\n getOpenForScope: (scope: string) => boolean\n setPanelOpen: (scope: string, isOpen: boolean) => void\n setPanelOpenByScope: (newState: OpenStateByScope) => void\n\n // Tab preferences by scope\n tabsByScope: TabStateByScope\n getTabForScope: (scope: string) => DetailsPanelTab\n setTab: (scope: string, tab: DetailsPanelTab) => void\n\n // Slide out state\n slideOut: null | SlideOut\n openSlideOut: (slideOut: SlideOut) => void\n closeSlideOut: () => void\n\n // Highlighted activities\n highlightedActivities: string[]\n setHighlightedActivities: (activities: string[]) => void\n\n // PiP state\n pip: DetailsPanelPip | null\n openPip: (pip: DetailsPanelPip) => void\n closePip: () => void\n}\n\n// Create the context\nconst DetailsPanelContext = createContext<DetailsPanelContextType | undefined>(undefined)\n\n// Provider component\nexport interface DetailsPanelProviderProps extends DetailsPanelContextProps {\n children: ReactNode\n defaultTab?: DetailsPanelTab\n}\n\nexport const DetailsPanelProvider: React.FC<DetailsPanelProviderProps> = ({\n children,\n defaultTab = 'activity',\n ...forwardedProps\n}) => {\n // keep track of the currently open panel by scope\n const [panelOpenByScope, setPanelOpenByScope] = useState<OpenStateByScope>({})\n\n // get the current open state for a specific scope\n const getOpenForScope = useCallback(\n (scope: string): boolean => {\n // Check if we have a saved preference for this scope\n if (panelOpenByScope[scope]) {\n return panelOpenByScope[scope]\n }\n\n // Fall back to default\n return false\n },\n [panelOpenByScope],\n )\n // Set open state for a scope\n const setPanelOpen = useCallback(\n (scope: string, isOpen: boolean) => {\n // Create a new state object based on current open state\n const newState = { ...panelOpenByScope }\n newState[scope] = isOpen\n\n // Update the state with the new object\n setPanelOpenByScope(newState)\n },\n [panelOpenByScope],\n )\n\n // Use localStorage to persist tab preferences by scope\n const [tabsByScope, setTabsByScope] = useLocalStorage<TabStateByScope>(\n 'details/tabs-by-scope',\n {},\n )\n\n // Get the current tab for a specific scope\n const getTabForScope = useCallback(\n (scope: string): DetailsPanelTab => {\n // Check if we have a saved preference for this scope\n if (tabsByScope[scope]) {\n return tabsByScope[scope]\n }\n\n // Fall back to default\n return defaultTab\n },\n [tabsByScope, defaultTab],\n )\n\n // Set tab for a scope\n const setTab = useCallback(\n (scope: string, tab: DetailsPanelTab) => {\n // Create a new state object based on current tabsByScope\n const newState = { ...tabsByScope }\n newState[scope] = tab\n\n // Update the state with the new object\n setTabsByScope(newState)\n },\n [tabsByScope, setTabsByScope],\n )\n\n // is the slide out open?\n const [slideOut, setSlideOut] = useState<null | SlideOut>(null)\n\n // open the slide out\n const openSlideOut = useCallback<DetailsPanelContextType['openSlideOut']>((params) => {\n setSlideOut(params)\n }, [])\n\n // close the slide out\n const closeSlideOut = useCallback(() => {\n setSlideOut(null)\n setHighlightedActivities([])\n }, [])\n\n const [pip, setPip] = useState<DetailsPanelPip | null>(null)\n\n const openPip = useCallback((pip: DetailsPanelPip) => {\n setPip(pip)\n }, [])\n const closePip = useCallback(() => {\n setPip(null)\n }, [])\n\n const [highlightedActivities, setHighlightedActivities] = useState<string[]>([])\n\n const value = {\n // open state for the panel by scope\n panelOpenByScope,\n getOpenForScope,\n setPanelOpen,\n setPanelOpenByScope,\n // tab preferences\n tabsByScope,\n getTabForScope,\n setTab,\n // slide out state\n slideOut,\n openSlideOut,\n closeSlideOut,\n // highlighted activities\n highlightedActivities,\n setHighlightedActivities,\n // PiP state\n pip,\n openPip,\n closePip,\n ...forwardedProps,\n }\n\n return <DetailsPanelContext.Provider value={value}>{children}</DetailsPanelContext.Provider>\n}\n\n// Custom hook to use the details context\nexport const useDetailsPanelContext = (): DetailsPanelContextType => {\n const context = useContext(DetailsPanelContext)\n if (context === undefined) {\n throw new Error('useDetailsPanel must be used within a DetailsProvider')\n }\n return context\n}\n\n// Add a specialized hook for using a panel in a specific scope\nexport const useScopedDetailsPanel = (scope: string) => {\n const { getTabForScope, setTab, getOpenForScope, setPanelOpen } = useDetailsPanelContext()\n\n return {\n isOpen: getOpenForScope(scope),\n setOpen: (isOpen: boolean) => setPanelOpen(scope, isOpen),\n currentTab: getTabForScope(scope),\n setTab: (tab: DetailsPanelTab) => setTab(scope, tab),\n isFeed: ['activity', 'comments', 'versions', 'checklists'].includes(getTabForScope(scope)),\n }\n}\n"],"names":["pip","jsx"],"mappings":"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"}
|
|
@@ -61,8 +61,15 @@ require("../api/queries/userDashboard/getUserDashboard.cjs.js");
|
|
|
61
61
|
require("../api/queries/users/getUsers.cjs.js");
|
|
62
62
|
require("../api/queries/users/updateUsers.cjs.js");
|
|
63
63
|
require("../api/queries/watchers/getWatchers.cjs.js");
|
|
64
|
+
require("../context/RemoteModulesContext.cjs.js");
|
|
65
|
+
const DetailsPanelContext = require("../context/DetailsPanelContext.cjs.js");
|
|
66
|
+
require("../context/ThumbnailUploaderContext.cjs.js");
|
|
67
|
+
require("../context/pip/PiPProvider.cjs.js");
|
|
68
|
+
require("react-dom");
|
|
69
|
+
require("../context/pip/PiPWrapper.cjs.js");
|
|
64
70
|
const useEntityUpdate = ({ entities, entityType }) => {
|
|
65
71
|
const [updateEntities] = updateEntity.useUpdateEntitiesMutation();
|
|
72
|
+
const { onUpdateEntity } = DetailsPanelContext.useDetailsPanelContext();
|
|
66
73
|
const updateEntity$1 = async (field, value) => {
|
|
67
74
|
if (value === null || value === void 0) {
|
|
68
75
|
console.error("value is null or undefined");
|
|
@@ -81,6 +88,7 @@ const useEntityUpdate = ({ entities, entityType }) => {
|
|
|
81
88
|
}
|
|
82
89
|
}));
|
|
83
90
|
await updateEntities({ operations, entityType });
|
|
91
|
+
onUpdateEntity == null ? void 0 : onUpdateEntity({ operations, entityType });
|
|
84
92
|
} catch (error) {
|
|
85
93
|
reactToastify.toast.error(`Error updating ${entityType}`);
|
|
86
94
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useEntityUpdate.cjs.js","sources":["../../../../src/hooks/useEntityUpdate.ts"],"sourcesContent":["import { toast } from 'react-toastify'\nimport { useUpdateEntitiesMutation } from '@shared/api'\n\ninterface Entity {\n id: string\n projectName: string\n users: string[]\n folderId?: string\n productId?: string\n}\n\nexport interface UseEntityUpdateParams {\n entities: Entity[]\n entityType: string\n}\n\n/**\n * Hook for updating entities with proper error handling and version-specific logic\n */\nexport const useEntityUpdate = ({ entities, entityType }: UseEntityUpdateParams) => {\n const [updateEntities] = useUpdateEntitiesMutation()\n\n /**\n * Updates entities with the specified field and value\n * @param field The field to update\n * @param value The new value for the field\n * @returns Promise that resolves when the update is complete\n */\n const updateEntity = async (field: string, value: any): Promise<void> => {\n if (value === null || value === undefined) {\n console.error('value is null or undefined')\n return\n }\n\n try {\n // Build entities operations array\n const operations = entities.map((entity) => ({\n id: entity.id,\n projectName: entity.projectName,\n data: {\n [field]: value,\n },\n currentAssignees: entity.users,\n meta: {\n folderId: entity.folderId,\n },\n }))\n\n await updateEntities({ operations, entityType })\n } catch (error) {\n toast.error(`Error updating ${entityType}`)\n }\n }\n\n return { updateEntity }\n}\n"],"names":["useUpdateEntitiesMutation","updateEntity","toast"],"mappings":"
|
|
1
|
+
{"version":3,"file":"useEntityUpdate.cjs.js","sources":["../../../../src/hooks/useEntityUpdate.ts"],"sourcesContent":["import { toast } from 'react-toastify'\nimport { useUpdateEntitiesMutation } from '@shared/api'\nimport { useContext } from 'react'\nimport { useDetailsPanelContext } from '@shared/context'\n\ninterface Entity {\n id: string\n projectName: string\n users: string[]\n folderId?: string\n productId?: string\n}\n\nexport interface UseEntityUpdateParams {\n entities: Entity[]\n entityType: string\n}\n\n/**\n * Hook for updating entities with proper error handling and version-specific logic\n */\nexport const useEntityUpdate = ({ entities, entityType }: UseEntityUpdateParams) => {\n const [updateEntities] = useUpdateEntitiesMutation()\n const { onUpdateEntity } = useDetailsPanelContext()\n\n /**\n * Updates entities with the specified field and value\n * @param field The field to update\n * @param value The new value for the field\n * @returns Promise that resolves when the update is complete\n */\n const updateEntity = async (field: string, value: any): Promise<void> => {\n if (value === null || value === undefined) {\n console.error('value is null or undefined')\n return\n }\n\n try {\n // Build entities operations array\n const operations = entities.map((entity) => ({\n id: entity.id,\n projectName: entity.projectName,\n data: {\n [field]: value,\n },\n currentAssignees: entity.users,\n meta: {\n folderId: entity.folderId,\n },\n }))\n\n await updateEntities({ operations, entityType })\n onUpdateEntity?.({ operations, entityType })\n } catch (error) {\n toast.error(`Error updating ${entityType}`)\n }\n }\n\n return { updateEntity }\n}\n"],"names":["useUpdateEntitiesMutation","useDetailsPanelContext","updateEntity","toast"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqBO,MAAM,kBAAkB,CAAC,EAAE,UAAU,iBAAwC;AAC5E,QAAA,CAAC,cAAc,IAAIA,uCAA0B;AAC7C,QAAA,EAAE,eAAe,IAAIC,2CAAuB;AAQ5C,QAAAC,iBAAe,OAAO,OAAe,UAA8B;AACnE,QAAA,UAAU,QAAQ,UAAU,QAAW;AACzC,cAAQ,MAAM,4BAA4B;AAC1C;AAAA,IAAA;AAGE,QAAA;AAEF,YAAM,aAAa,SAAS,IAAI,CAAC,YAAY;AAAA,QAC3C,IAAI,OAAO;AAAA,QACX,aAAa,OAAO;AAAA,QACpB,MAAM;AAAA,UACJ,CAAC,KAAK,GAAG;AAAA,QACX;AAAA,QACA,kBAAkB,OAAO;AAAA,QACzB,MAAM;AAAA,UACJ,UAAU,OAAO;AAAA,QAAA;AAAA,MACnB,EACA;AAEF,YAAM,eAAe,EAAE,YAAY,YAAY;AAC9B,uDAAA,EAAE,YAAY;aACxB,OAAO;AACRC,oBAAAA,MAAA,MAAM,kBAAkB,UAAU,EAAE;AAAA,IAAA;AAAA,EAE9C;AAEA,SAAO,EAAED,cAAAA,eAAa;AACxB;;"}
|
|
@@ -59,8 +59,15 @@ import "../api/queries/userDashboard/getUserDashboard.es.js";
|
|
|
59
59
|
import "../api/queries/users/getUsers.es.js";
|
|
60
60
|
import "../api/queries/users/updateUsers.es.js";
|
|
61
61
|
import "../api/queries/watchers/getWatchers.es.js";
|
|
62
|
+
import "../context/RemoteModulesContext.es.js";
|
|
63
|
+
import { useDetailsPanelContext } from "../context/DetailsPanelContext.es.js";
|
|
64
|
+
import "../context/ThumbnailUploaderContext.es.js";
|
|
65
|
+
import "../context/pip/PiPProvider.es.js";
|
|
66
|
+
import "react-dom";
|
|
67
|
+
import "../context/pip/PiPWrapper.es.js";
|
|
62
68
|
const useEntityUpdate = ({ entities, entityType }) => {
|
|
63
69
|
const [updateEntities] = useUpdateEntitiesMutation();
|
|
70
|
+
const { onUpdateEntity } = useDetailsPanelContext();
|
|
64
71
|
const updateEntity = async (field, value) => {
|
|
65
72
|
if (value === null || value === void 0) {
|
|
66
73
|
console.error("value is null or undefined");
|
|
@@ -79,6 +86,7 @@ const useEntityUpdate = ({ entities, entityType }) => {
|
|
|
79
86
|
}
|
|
80
87
|
}));
|
|
81
88
|
await updateEntities({ operations, entityType });
|
|
89
|
+
onUpdateEntity == null ? void 0 : onUpdateEntity({ operations, entityType });
|
|
82
90
|
} catch (error) {
|
|
83
91
|
toast.error(`Error updating ${entityType}`);
|
|
84
92
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useEntityUpdate.es.js","sources":["../../../../src/hooks/useEntityUpdate.ts"],"sourcesContent":["import { toast } from 'react-toastify'\nimport { useUpdateEntitiesMutation } from '@shared/api'\n\ninterface Entity {\n id: string\n projectName: string\n users: string[]\n folderId?: string\n productId?: string\n}\n\nexport interface UseEntityUpdateParams {\n entities: Entity[]\n entityType: string\n}\n\n/**\n * Hook for updating entities with proper error handling and version-specific logic\n */\nexport const useEntityUpdate = ({ entities, entityType }: UseEntityUpdateParams) => {\n const [updateEntities] = useUpdateEntitiesMutation()\n\n /**\n * Updates entities with the specified field and value\n * @param field The field to update\n * @param value The new value for the field\n * @returns Promise that resolves when the update is complete\n */\n const updateEntity = async (field: string, value: any): Promise<void> => {\n if (value === null || value === undefined) {\n console.error('value is null or undefined')\n return\n }\n\n try {\n // Build entities operations array\n const operations = entities.map((entity) => ({\n id: entity.id,\n projectName: entity.projectName,\n data: {\n [field]: value,\n },\n currentAssignees: entity.users,\n meta: {\n folderId: entity.folderId,\n },\n }))\n\n await updateEntities({ operations, entityType })\n } catch (error) {\n toast.error(`Error updating ${entityType}`)\n }\n }\n\n return { updateEntity }\n}\n"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useEntityUpdate.es.js","sources":["../../../../src/hooks/useEntityUpdate.ts"],"sourcesContent":["import { toast } from 'react-toastify'\nimport { useUpdateEntitiesMutation } from '@shared/api'\nimport { useContext } from 'react'\nimport { useDetailsPanelContext } from '@shared/context'\n\ninterface Entity {\n id: string\n projectName: string\n users: string[]\n folderId?: string\n productId?: string\n}\n\nexport interface UseEntityUpdateParams {\n entities: Entity[]\n entityType: string\n}\n\n/**\n * Hook for updating entities with proper error handling and version-specific logic\n */\nexport const useEntityUpdate = ({ entities, entityType }: UseEntityUpdateParams) => {\n const [updateEntities] = useUpdateEntitiesMutation()\n const { onUpdateEntity } = useDetailsPanelContext()\n\n /**\n * Updates entities with the specified field and value\n * @param field The field to update\n * @param value The new value for the field\n * @returns Promise that resolves when the update is complete\n */\n const updateEntity = async (field: string, value: any): Promise<void> => {\n if (value === null || value === undefined) {\n console.error('value is null or undefined')\n return\n }\n\n try {\n // Build entities operations array\n const operations = entities.map((entity) => ({\n id: entity.id,\n projectName: entity.projectName,\n data: {\n [field]: value,\n },\n currentAssignees: entity.users,\n meta: {\n folderId: entity.folderId,\n },\n }))\n\n await updateEntities({ operations, entityType })\n onUpdateEntity?.({ operations, entityType })\n } catch (error) {\n toast.error(`Error updating ${entityType}`)\n }\n }\n\n return { updateEntity }\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqBO,MAAM,kBAAkB,CAAC,EAAE,UAAU,iBAAwC;AAC5E,QAAA,CAAC,cAAc,IAAI,0BAA0B;AAC7C,QAAA,EAAE,eAAe,IAAI,uBAAuB;AAQ5C,QAAA,eAAe,OAAO,OAAe,UAA8B;AACnE,QAAA,UAAU,QAAQ,UAAU,QAAW;AACzC,cAAQ,MAAM,4BAA4B;AAC1C;AAAA,IAAA;AAGE,QAAA;AAEF,YAAM,aAAa,SAAS,IAAI,CAAC,YAAY;AAAA,QAC3C,IAAI,OAAO;AAAA,QACX,aAAa,OAAO;AAAA,QACpB,MAAM;AAAA,UACJ,CAAC,KAAK,GAAG;AAAA,QACX;AAAA,QACA,kBAAkB,OAAO;AAAA,QACzB,MAAM;AAAA,UACJ,UAAU,OAAO;AAAA,QAAA;AAAA,MACnB,EACA;AAEF,YAAM,eAAe,EAAE,YAAY,YAAY;AAC9B,uDAAA,EAAE,YAAY;aACxB,OAAO;AACR,YAAA,MAAM,kBAAkB,UAAU,EAAE;AAAA,IAAA;AAAA,EAE9C;AAEA,SAAO,EAAE,aAAa;AACxB;"}
|
|
@@ -32,6 +32,10 @@ export interface DetailsPanelContextProps {
|
|
|
32
32
|
onOpenImage?: (args: any) => void;
|
|
33
33
|
onGoToFrame?: (frame: number) => void;
|
|
34
34
|
onOpenViewer?: (args: any) => void;
|
|
35
|
+
onUpdateEntity?: (data: {
|
|
36
|
+
operations: any[];
|
|
37
|
+
entityType: string;
|
|
38
|
+
}) => void;
|
|
35
39
|
}
|
|
36
40
|
export interface DetailsPanelContextType extends DetailsPanelContextProps {
|
|
37
41
|
panelOpenByScope: OpenStateByScope;
|