@ynput/ayon-frontend-shared 0.4.2 → 0.4.3
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/ProjectTreeTable.cjs.js +1 -1
- package/dist/ProjectTreeTable.es.js +247 -243
- package/dist/_virtual/index.cjs22.js +1 -1
- package/dist/_virtual/index.cjs23.js +1 -1
- package/dist/_virtual/index.cjs24.js +1 -1
- package/dist/_virtual/index.cjs4.js +1 -1
- package/dist/_virtual/index.cjs5.js +1 -1
- package/dist/_virtual/index.cjs6.js +1 -1
- package/dist/_virtual/index.cjs8.js +1 -1
- package/dist/_virtual/index.es22.js +3 -3
- package/dist/_virtual/index.es23.js +5 -5
- package/dist/_virtual/index.es24.js +5 -5
- package/dist/_virtual/index.es4.js +2 -5
- package/dist/_virtual/index.es4.js.map +1 -1
- package/dist/_virtual/index.es5.js +5 -2
- package/dist/_virtual/index.es5.js.map +1 -1
- package/dist/_virtual/index.es6.js +2 -2
- package/dist/_virtual/index.es8.js +2 -2
- package/dist/api.cjs.js +1 -1
- package/dist/api.es.js +446 -445
- package/dist/index.cjs.js +1 -1
- package/dist/index.es.js +20 -9
- package/dist/index.es.js.map +1 -1
- package/dist/node_modules/match-sorter/dist/match-sorter.esm.cjs.js +1 -1
- package/dist/node_modules/match-sorter/dist/match-sorter.esm.es.js +1 -1
- package/dist/node_modules/parse-numeric-range/index.cjs.js +1 -1
- package/dist/node_modules/parse-numeric-range/index.es.js +1 -1
- package/dist/node_modules/rehype/node_modules/unified/lib/index.cjs.js +1 -1
- package/dist/node_modules/rehype/node_modules/unified/lib/index.es.js +2 -2
- package/dist/node_modules/rehype/node_modules/vfile/lib/index.cjs.js +1 -1
- package/dist/node_modules/rehype/node_modules/vfile/lib/index.es.js +1 -1
- package/dist/node_modules/rehype-parse/lib/index.cjs.js +1 -1
- package/dist/node_modules/rehype-parse/lib/index.es.js +1 -1
- package/dist/node_modules/remove-accents/index.cjs.js +1 -1
- package/dist/node_modules/remove-accents/index.es.js +1 -1
- package/dist/shared/node_modules/@module-federation/error-codes/dist/index.cjs.js +1 -1
- package/dist/shared/node_modules/@module-federation/error-codes/dist/index.es.js +1 -1
- package/dist/shared/node_modules/@module-federation/runtime/dist/index.cjs.js +1 -1
- package/dist/shared/node_modules/@module-federation/runtime/dist/index.es.js +1 -1
- package/dist/shared/node_modules/@module-federation/runtime-core/dist/index.cjs.js +1 -1
- package/dist/shared/node_modules/@module-federation/runtime-core/dist/index.es.js +1 -1
- package/dist/shared/node_modules/react-is/index.cjs.js +1 -1
- package/dist/shared/node_modules/react-is/index.es.js +1 -1
- package/dist/shared/src/api/generated/graphql.cjs.js +85 -28
- package/dist/shared/src/api/generated/graphql.cjs.js.map +1 -1
- package/dist/shared/src/api/generated/graphql.es.js +129 -68
- package/dist/shared/src/api/generated/graphql.es.js.map +1 -1
- package/dist/shared/src/api/queries/columnStats/metricTargets.cjs.js +1 -1
- package/dist/shared/src/api/queries/columnStats/metricTargets.cjs.js.map +1 -1
- package/dist/shared/src/api/queries/columnStats/metricTargets.es.js +36 -36
- package/dist/shared/src/api/queries/columnStats/metricTargets.es.js.map +1 -1
- package/dist/shared/src/components/Chips/Chips.cjs.js +12 -6
- package/dist/shared/src/components/Chips/Chips.cjs.js.map +1 -1
- package/dist/shared/src/components/Chips/Chips.es.js +69 -62
- package/dist/shared/src/components/Chips/Chips.es.js.map +1 -1
- package/dist/shared/src/components/DetailsPanelAttributes/components/RenderFieldWidget.cjs.js +1 -1
- package/dist/shared/src/components/DetailsPanelAttributes/components/RenderFieldWidget.cjs.js.map +1 -1
- package/dist/shared/src/components/DetailsPanelAttributes/components/RenderFieldWidget.es.js +32 -12
- package/dist/shared/src/components/DetailsPanelAttributes/components/RenderFieldWidget.es.js.map +1 -1
- package/dist/shared/src/components/ProjectTableSettings/ProjectTableSettings.cjs.js +2 -2
- package/dist/shared/src/components/ProjectTableSettings/ProjectTableSettings.cjs.js.map +1 -1
- package/dist/shared/src/components/ProjectTableSettings/ProjectTableSettings.es.js +33 -33
- package/dist/shared/src/components/ProjectTableSettings/ProjectTableSettings.es.js.map +1 -1
- package/dist/shared/src/components/RemotePage/RemotePageWrapper.cjs.js.map +1 -1
- package/dist/shared/src/components/RemotePage/RemotePageWrapper.es.js.map +1 -1
- package/dist/shared/src/components/SubtasksManager/SubtasksManagerWrapper.cjs.js +1 -1
- package/dist/shared/src/components/SubtasksManager/SubtasksManagerWrapper.cjs.js.map +1 -1
- package/dist/shared/src/components/SubtasksManager/SubtasksManagerWrapper.es.js +39 -8
- package/dist/shared/src/components/SubtasksManager/SubtasksManagerWrapper.es.js.map +1 -1
- package/dist/shared/src/containers/DetailsPanel/DetailsPanel.cjs.js +1 -1
- package/dist/shared/src/containers/DetailsPanel/DetailsPanel.cjs.js.map +1 -1
- package/dist/shared/src/containers/DetailsPanel/DetailsPanel.es.js +32 -31
- package/dist/shared/src/containers/DetailsPanel/DetailsPanel.es.js.map +1 -1
- package/dist/shared/src/containers/DetailsPanel/containers/FeedWrapper.cjs.js.map +1 -1
- package/dist/shared/src/containers/DetailsPanel/containers/FeedWrapper.es.js.map +1 -1
- package/dist/shared/src/containers/Feed/helpers/buildBackendFilter.cjs.js +1 -1
- package/dist/shared/src/containers/Feed/helpers/buildBackendFilter.cjs.js.map +1 -1
- package/dist/shared/src/containers/Feed/helpers/buildBackendFilter.es.js +24 -18
- package/dist/shared/src/containers/Feed/helpers/buildBackendFilter.es.js.map +1 -1
- package/dist/shared/src/containers/Feed/helpers/feedFilterAdapter.cjs.js +1 -1
- package/dist/shared/src/containers/Feed/helpers/feedFilterAdapter.cjs.js.map +1 -1
- package/dist/shared/src/containers/Feed/helpers/feedFilterAdapter.es.js +26 -25
- package/dist/shared/src/containers/Feed/helpers/feedFilterAdapter.es.js.map +1 -1
- package/dist/shared/src/containers/ListTable/ListTableCell.cjs.js +1 -1
- package/dist/shared/src/containers/ListTable/ListTableCell.cjs.js.map +1 -1
- package/dist/shared/src/containers/ListTable/ListTableCell.es.js +14 -2
- package/dist/shared/src/containers/ListTable/ListTableCell.es.js.map +1 -1
- package/dist/shared/src/containers/ProjectTreeTable/ProjectTreeTable.cjs.js +1 -1
- package/dist/shared/src/containers/ProjectTreeTable/ProjectTreeTable.cjs.js.map +1 -1
- package/dist/shared/src/containers/ProjectTreeTable/ProjectTreeTable.es.js +125 -126
- package/dist/shared/src/containers/ProjectTreeTable/ProjectTreeTable.es.js.map +1 -1
- package/dist/shared/src/containers/ProjectTreeTable/ProjectTreeTable.styled.cjs.js +6 -0
- package/dist/shared/src/containers/ProjectTreeTable/ProjectTreeTable.styled.cjs.js.map +1 -1
- package/dist/shared/src/containers/ProjectTreeTable/ProjectTreeTable.styled.es.js +14 -8
- package/dist/shared/src/containers/ProjectTreeTable/ProjectTreeTable.styled.es.js.map +1 -1
- package/dist/shared/src/containers/ProjectTreeTable/buildTreeTableColumns.cjs.js +1 -1
- package/dist/shared/src/containers/ProjectTreeTable/buildTreeTableColumns.cjs.js.map +1 -1
- package/dist/shared/src/containers/ProjectTreeTable/buildTreeTableColumns.es.js +200 -178
- package/dist/shared/src/containers/ProjectTreeTable/buildTreeTableColumns.es.js.map +1 -1
- package/dist/shared/src/containers/ProjectTreeTable/components/GroupSettingsFallback.cjs.js +1 -1
- package/dist/shared/src/containers/ProjectTreeTable/components/GroupSettingsFallback.cjs.js.map +1 -1
- package/dist/shared/src/containers/ProjectTreeTable/components/GroupSettingsFallback.es.js +14 -3
- package/dist/shared/src/containers/ProjectTreeTable/components/GroupSettingsFallback.es.js.map +1 -1
- package/dist/shared/src/containers/ProjectTreeTable/constants.cjs.js +1 -1
- package/dist/shared/src/containers/ProjectTreeTable/constants.cjs.js.map +1 -1
- package/dist/shared/src/containers/ProjectTreeTable/constants.es.js +6 -3
- package/dist/shared/src/containers/ProjectTreeTable/constants.es.js.map +1 -1
- package/dist/shared/src/containers/ProjectTreeTable/hooks/useSortBySettings.cjs.js +1 -1
- package/dist/shared/src/containers/ProjectTreeTable/hooks/useSortBySettings.cjs.js.map +1 -1
- package/dist/shared/src/containers/ProjectTreeTable/hooks/useSortBySettings.es.js +19 -19
- package/dist/shared/src/containers/ProjectTreeTable/hooks/useSortBySettings.es.js.map +1 -1
- package/dist/shared/src/containers/ProjectTreeTable/widgets/CellWidget.cjs.js +5 -3
- package/dist/shared/src/containers/ProjectTreeTable/widgets/CellWidget.cjs.js.map +1 -1
- package/dist/shared/src/containers/ProjectTreeTable/widgets/CellWidget.es.js +100 -97
- package/dist/shared/src/containers/ProjectTreeTable/widgets/CellWidget.es.js.map +1 -1
- package/dist/shared/src/containers/ProjectTreeTable/widgets/DateWidget.cjs.js +9 -1
- package/dist/shared/src/containers/ProjectTreeTable/widgets/DateWidget.cjs.js.map +1 -1
- package/dist/shared/src/containers/ProjectTreeTable/widgets/DateWidget.es.js +47 -31
- package/dist/shared/src/containers/ProjectTreeTable/widgets/DateWidget.es.js.map +1 -1
- package/dist/shared/src/containers/ProjectTreeTable/widgets/EntityNameWidget.cjs.js +28 -9
- package/dist/shared/src/containers/ProjectTreeTable/widgets/EntityNameWidget.cjs.js.map +1 -1
- package/dist/shared/src/containers/ProjectTreeTable/widgets/EntityNameWidget.es.js +58 -39
- package/dist/shared/src/containers/ProjectTreeTable/widgets/EntityNameWidget.es.js.map +1 -1
- package/dist/shared/src/containers/ProjectTreeTable/widgets/EnumCellValue.cjs.js +53 -25
- package/dist/shared/src/containers/ProjectTreeTable/widgets/EnumCellValue.cjs.js.map +1 -1
- package/dist/shared/src/containers/ProjectTreeTable/widgets/EnumCellValue.es.js +150 -103
- package/dist/shared/src/containers/ProjectTreeTable/widgets/EnumCellValue.es.js.map +1 -1
- package/dist/shared/src/containers/ProjectTreeTable/widgets/EnumWidget.cjs.js +9 -2
- package/dist/shared/src/containers/ProjectTreeTable/widgets/EnumWidget.cjs.js.map +1 -1
- package/dist/shared/src/containers/ProjectTreeTable/widgets/EnumWidget.es.js +66 -57
- package/dist/shared/src/containers/ProjectTreeTable/widgets/EnumWidget.es.js.map +1 -1
- package/dist/shared/src/containers/ProjectTreeTable/widgets/SubtasksWidget.cjs.js +1 -1
- package/dist/shared/src/containers/ProjectTreeTable/widgets/SubtasksWidget.cjs.js.map +1 -1
- package/dist/shared/src/containers/ProjectTreeTable/widgets/SubtasksWidget.es.js +9 -8
- package/dist/shared/src/containers/ProjectTreeTable/widgets/SubtasksWidget.es.js.map +1 -1
- package/dist/shared/src/containers/ProjectTreeTable/widgets/TextWidget.cjs.js +20 -4
- package/dist/shared/src/containers/ProjectTreeTable/widgets/TextWidget.cjs.js.map +1 -1
- package/dist/shared/src/containers/ProjectTreeTable/widgets/TextWidget.es.js +86 -67
- package/dist/shared/src/containers/ProjectTreeTable/widgets/TextWidget.es.js.map +1 -1
- package/dist/shared/src/containers/ProjectTreeTable/widgets/wrapMode.cjs.js +6 -0
- package/dist/shared/src/containers/ProjectTreeTable/widgets/wrapMode.cjs.js.map +1 -0
- package/dist/shared/src/containers/ProjectTreeTable/widgets/wrapMode.es.js +11 -0
- package/dist/shared/src/containers/ProjectTreeTable/widgets/wrapMode.es.js.map +1 -0
- package/dist/shared/src/containers/Views/context/ViewsContext.cjs.js +1 -1
- package/dist/shared/src/containers/Views/context/ViewsContext.cjs.js.map +1 -1
- package/dist/shared/src/containers/Views/context/ViewsContext.es.js +67 -62
- package/dist/shared/src/containers/Views/context/ViewsContext.es.js.map +1 -1
- package/dist/shared/src/containers/Views/utils/viewUpdateHelper.cjs.js +1 -1
- package/dist/shared/src/containers/Views/utils/viewUpdateHelper.cjs.js.map +1 -1
- package/dist/shared/src/containers/Views/utils/viewUpdateHelper.es.js +47 -46
- package/dist/shared/src/containers/Views/utils/viewUpdateHelper.es.js.map +1 -1
- package/dist/shared/src/context/ProjectContext.cjs.js +1 -1
- package/dist/shared/src/context/ProjectContext.cjs.js.map +1 -1
- package/dist/shared/src/context/ProjectContext.es.js +1 -1
- package/dist/shared/src/context/ProjectContext.es.js.map +1 -1
- package/dist/shared/src/util/buildHierarchicalTableRows.cjs.js +1 -1
- package/dist/shared/src/util/buildHierarchicalTableRows.cjs.js.map +1 -1
- package/dist/shared/src/util/buildHierarchicalTableRows.es.js +36 -33
- package/dist/shared/src/util/buildHierarchicalTableRows.es.js.map +1 -1
- package/dist/types/api/generated/graphql.d.ts +71 -0
- package/dist/types/api/queries/activities/getActivities.d.ts +28 -0
- package/dist/types/api/queries/entities/getEntity.d.ts +14 -0
- package/dist/types/api/queries/entities/getEntityPanel.d.ts +14 -0
- package/dist/types/api/queries/entities/updateEntity.d.ts +14 -0
- package/dist/types/api/queries/entityLists/getLists.d.ts +14 -0
- package/dist/types/api/queries/overview/getOverview.d.ts +14 -0
- package/dist/types/api/queries/project/getProject.d.ts +14 -0
- package/dist/types/api/queries/userDashboard/getUserDashboard.d.ts +14 -0
- package/dist/types/api/queries/users/getUsers.d.ts +14 -0
- package/dist/types/api/queries/versions/getVersionsProducts.d.ts +28 -0
- package/dist/types/components/SubtasksManager/SubtasksManagerWrapper.d.ts +4 -1
- package/dist/types/containers/Feed/helpers/buildBackendFilter.d.ts +1 -0
- package/dist/types/containers/ProjectTreeTable/buildTreeTableColumns.d.ts +1 -0
- package/dist/types/containers/ProjectTreeTable/constants.d.ts +3 -0
- package/dist/types/containers/ProjectTreeTable/widgets/SubtasksWidget.d.ts +1 -0
- package/dist/types/containers/ProjectTreeTable/widgets/wrapMode.d.ts +2 -0
- package/dist/types/containers/Views/context/ViewsContext.d.ts +1 -0
- package/dist/types/util/buildHierarchicalTableRows.d.ts +2 -0
- package/package.json +1 -1
|
@@ -92,20 +92,20 @@ import "../../../api/queries/users/updateUsers.es.js";
|
|
|
92
92
|
import "../../../api/queries/users/guests.es.js";
|
|
93
93
|
import "../../../api/queries/versions/updateVersions.es.js";
|
|
94
94
|
import "../../../api/queries/views/getViews.es.js";
|
|
95
|
-
import { useCreateViewMutation as A, useUpdateViewMutation as
|
|
95
|
+
import { useCreateViewMutation as A, useUpdateViewMutation as D, viewsQueries as M } from "../../../api/queries/views/updateViews.es.js";
|
|
96
96
|
import "../../../api/queries/watchers/getWatchers.es.js";
|
|
97
97
|
import "../../../api/queries/uris/getUris.es.js";
|
|
98
|
-
import { generateWorkingView as
|
|
99
|
-
import { toast as
|
|
100
|
-
import { useCallback as
|
|
101
|
-
import { useStore as
|
|
102
|
-
import { useViewsContext as
|
|
98
|
+
import { generateWorkingView as H } from "./generateWorkingView.es.js";
|
|
99
|
+
import { toast as N } from "react-toastify";
|
|
100
|
+
import { useCallback as k, useState as R, useRef as U } from "react";
|
|
101
|
+
import { useStore as q } from "react-redux";
|
|
102
|
+
import { useViewsContext as b } from "../context/ViewsContext.es.js";
|
|
103
103
|
let y = !1;
|
|
104
|
-
const
|
|
104
|
+
const L = () => {
|
|
105
105
|
y || (y = !0, queueMicrotask(() => {
|
|
106
106
|
y = !1;
|
|
107
107
|
}));
|
|
108
|
-
},
|
|
108
|
+
}, x = async (t, r, s, i = {}, p, w, V, e) => {
|
|
109
109
|
const {
|
|
110
110
|
viewSettings: m,
|
|
111
111
|
viewType: n,
|
|
@@ -113,37 +113,38 @@ const N = () => {
|
|
|
113
113
|
selectedView: o,
|
|
114
114
|
setSelectedView: d,
|
|
115
115
|
workingView: c,
|
|
116
|
-
onSettingsChanged: a
|
|
116
|
+
onSettingsChanged: a,
|
|
117
|
+
isErrorWorkingView: g
|
|
117
118
|
} = p;
|
|
118
119
|
if (!n) throw new Error("No view type provided for updating view settings");
|
|
119
|
-
const u = o?.id,
|
|
120
|
+
const u = o?.id, S = o?.working;
|
|
120
121
|
try {
|
|
121
122
|
r(s);
|
|
122
|
-
const { settings:
|
|
123
|
-
if (I === void 0) {
|
|
123
|
+
const { settings: v, workingViewId: W } = V(), I = v ?? m;
|
|
124
|
+
if (I === void 0 && !g) {
|
|
124
125
|
console.warn(
|
|
125
126
|
"updateViewSettings: no settings baseline available, aborting to prevent data loss."
|
|
126
127
|
);
|
|
127
128
|
return;
|
|
128
129
|
}
|
|
129
|
-
const
|
|
130
|
-
|
|
131
|
-
const
|
|
130
|
+
const C = { ...I, ...t }, h = H(C), f = W ?? c?.id;
|
|
131
|
+
f && (h.id = f);
|
|
132
|
+
const E = h.id, F = w(
|
|
132
133
|
{
|
|
133
|
-
payload:
|
|
134
|
+
payload: f ? { settings: C } : h,
|
|
134
135
|
viewType: n,
|
|
135
136
|
projectName: l
|
|
136
137
|
},
|
|
137
|
-
|
|
138
|
+
f
|
|
138
139
|
);
|
|
139
|
-
e(), (!
|
|
140
|
-
} catch (
|
|
141
|
-
r(null), u && d(u), o && !
|
|
142
|
-
const
|
|
143
|
-
|
|
140
|
+
e(), (!S || o?.id !== f) && (o && a(!0), d(E)), await F, r(null), i.successMessage && N.success(i.successMessage);
|
|
141
|
+
} catch (v) {
|
|
142
|
+
r(null), u && d(u), o && !S && a(!1), console.error(v);
|
|
143
|
+
const W = i.errorMessage || `Failed to update view settings: ${v}`;
|
|
144
|
+
N.error(W);
|
|
144
145
|
}
|
|
145
|
-
},
|
|
146
|
-
const [t] = A(), [r] =
|
|
146
|
+
}, P = () => {
|
|
147
|
+
const [t] = A(), [r] = D(), s = b(), i = q(), p = k(
|
|
147
148
|
async (e, m) => {
|
|
148
149
|
if (m) {
|
|
149
150
|
const n = {};
|
|
@@ -159,52 +160,52 @@ const N = () => {
|
|
|
159
160
|
return await t(e).unwrap();
|
|
160
161
|
},
|
|
161
162
|
[t, r]
|
|
162
|
-
), w =
|
|
163
|
+
), w = k(() => {
|
|
163
164
|
const { viewType: e, projectName: m, selectedView: n, workingView: l } = s;
|
|
164
165
|
if (!e) return {};
|
|
165
|
-
const o = i.getState(), d =
|
|
166
|
+
const o = i.getState(), d = M.endpoints.getWorkingView.select({
|
|
166
167
|
viewType: e,
|
|
167
168
|
projectName: m
|
|
168
|
-
})(o), a = d?.data?.id || l?.id,
|
|
169
|
+
})(o), a = d?.data?.id || l?.id, g = M.endpoints.getDefaultView.select({
|
|
169
170
|
viewType: e,
|
|
170
171
|
projectName: m
|
|
171
|
-
})(o),
|
|
172
|
-
return (!!a &&
|
|
172
|
+
})(o), u = g?.data?.id || n?.id;
|
|
173
|
+
return (!!a && u === a || y) && d?.data?.settings ? {
|
|
173
174
|
settings: d.data.settings,
|
|
174
175
|
workingViewId: a
|
|
175
|
-
} :
|
|
176
|
-
settings:
|
|
176
|
+
} : g?.data?.settings ? {
|
|
177
|
+
settings: g.data.settings,
|
|
177
178
|
workingViewId: a
|
|
178
179
|
} : { workingViewId: a };
|
|
179
180
|
}, [i, s]);
|
|
180
181
|
return {
|
|
181
|
-
updateViewSettings:
|
|
182
|
-
async (...e) => await
|
|
182
|
+
updateViewSettings: k(
|
|
183
|
+
async (...e) => await x(...e, s, p, w, L),
|
|
183
184
|
[s, p, w]
|
|
184
185
|
),
|
|
185
186
|
onCreateView: p,
|
|
186
187
|
getLatestSettings: w,
|
|
187
|
-
markCacheDirty:
|
|
188
|
+
markCacheDirty: L
|
|
188
189
|
};
|
|
189
|
-
},
|
|
190
|
+
}, T = (t, r) => r.split(".").reduce((s, i) => s?.[i], t), j = (t, r, s) => {
|
|
190
191
|
const [i, ...p] = r.split(".");
|
|
191
192
|
return i ? {
|
|
192
193
|
...t,
|
|
193
|
-
[i]: p.length ?
|
|
194
|
+
[i]: p.length ? j(t[i] || {}, p.join("."), s) : s
|
|
194
195
|
} : t;
|
|
195
|
-
},
|
|
196
|
-
const { viewSettings: s, isLoadingViews: i } =
|
|
196
|
+
}, Ri = (t, r) => {
|
|
197
|
+
const { viewSettings: s, isLoadingViews: i } = b(), { updateViewSettings: p, getLatestSettings: w } = P(), [V, e] = R(null), m = U(null), n = s, l = V !== null ? V : T(n, t) ?? r, o = k((c) => {
|
|
197
198
|
m.current = c, e(c);
|
|
198
|
-
}, []), d =
|
|
199
|
+
}, []), d = k(
|
|
199
200
|
(c) => {
|
|
200
201
|
if (i || !n) return;
|
|
201
|
-
const a = w().settings ?? n,
|
|
202
|
-
|
|
202
|
+
const a = w().settings ?? n, g = m.current !== null ? m.current : T(a, t) ?? r, u = typeof c == "function" ? c(
|
|
203
|
+
g
|
|
203
204
|
) : c;
|
|
204
205
|
p(
|
|
205
|
-
|
|
206
|
+
j(a, t, u),
|
|
206
207
|
o,
|
|
207
|
-
|
|
208
|
+
u,
|
|
208
209
|
{}
|
|
209
210
|
);
|
|
210
211
|
},
|
|
@@ -221,8 +222,8 @@ const N = () => {
|
|
|
221
222
|
return [l, d];
|
|
222
223
|
};
|
|
223
224
|
export {
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
225
|
+
x as updateViewSettings,
|
|
226
|
+
P as useViewUpdateHelper,
|
|
227
|
+
Ri as useViewsState
|
|
227
228
|
};
|
|
228
229
|
//# sourceMappingURL=viewUpdateHelper.es.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"viewUpdateHelper.es.js","sources":["../../../../../../src/containers/Views/utils/viewUpdateHelper.ts"],"sourcesContent":["/**\n * Shared helper for updating view settings with optimistic local state management.\n *\n * Sequential updateViewSettings calls in the same event tick MUST chain correctly:\n * the second call has to see the first call's changes. Closure-captured\n * `viewSettings` does not refresh between sync calls (no re-render yet), so we\n * read the latest settings from the RTK Query cache at call time instead.\n * RTK's updateView mutation performs an optimistic cache write in\n * `onQueryStarted`, so the cache is already up-to-date by the time the next\n * call reads it.\n */\n\nimport {\n EntityIdResponse,\n useCreateViewMutation,\n useUpdateViewMutation,\n viewsQueries,\n} from '@shared/api'\nimport { generateWorkingView } from './generateWorkingView'\nimport { toast } from 'react-toastify'\nimport { SetStateAction, useCallback, useRef, useState } from 'react'\nimport { useStore } from 'react-redux'\nimport { useViewsContext, ViewsContextValue } from '../context/ViewsContext'\n\ninterface UpdateOptions {\n successMessage?: string\n errorMessage?: string\n}\n\n// Module-level flag shared across every useViewUpdateHelper instance. Set true\n// when a mutation has been dispatched in the current tick (RTK cache is now\n// optimistically fresh); reset on the next microtask. Must be module-level so\n// that two different hook instances (e.g. ProjectOverviewDataProvider +\n// ProjectOverviewContext) coordinate correctly when writes flow through one\n// and subsequent reads come from the other in the same event tick.\nlet cacheDirtyThisTick = false\nconst markCacheDirty = () => {\n if (cacheDirtyThisTick) return\n cacheDirtyThisTick = true\n queueMicrotask(() => {\n cacheDirtyThisTick = false\n })\n}\n\nexport type UpdateViewSettingsFn = (\n updatedSettings: any,\n localStateSetter: (value: any) => void,\n newLocalValue: any,\n options: UpdateOptions,\n) => Promise<void>\n\nexport interface LatestSettingsResult {\n settings?: any\n workingViewId?: string\n}\n\nexport const updateViewSettings = async (\n updatedSettings: any,\n localStateSetter: (value: any) => void,\n newLocalValue: any,\n options: UpdateOptions = {},\n viewContext: ViewsContextValue,\n onApplyViewChanges: (arg: any, viewId?: string) => Promise<EntityIdResponse | void>,\n // Reads latest effective settings from RTK Query cache at call time. Required to\n // prevent stale-closure races when two updates fire in the same tick.\n getLatest: () => LatestSettingsResult,\n // Invoked synchronously right after the mutation is dispatched. The caller\n // uses this to flip a \"cache is fresh this tick\" flag so subsequent sync\n // calls in the same tick read the just-updated cache instead of stale state.\n markCacheDirty: () => void,\n): Promise<void> => {\n const {\n viewSettings,\n viewType,\n projectName,\n selectedView,\n setSelectedView,\n workingView,\n onSettingsChanged,\n } = viewContext\n\n if (!viewType) throw new Error('No view type provided for updating view settings')\n\n const previousSelectedViewId = selectedView?.id\n const wasWorking = selectedView?.working\n\n try {\n // Immediately update local state for fast UI response\n localStateSetter(newLocalValue)\n\n // Read latest settings from RTK cache (includes prior same-tick optimistic writes).\n // Fallback to closure-captured value if cache has nothing (first render, etc.).\n const { settings: latestSettingsFromCache, workingViewId: latestWorkingViewIdFromCache } =\n getLatest()\n const latestSettings = latestSettingsFromCache ?? viewSettings\n\n // If we have no settings baseline at all (neither from cache nor from context),\n // abort to prevent writing a partial payload that would overwrite saved settings.\n // This is a defence-in-depth guard; in normal flow isLoadingViews prevents callers\n // from triggering updates before data is available.\n if (latestSettings === undefined) {\n console.warn(\n 'updateViewSettings: no settings baseline available, aborting to prevent data loss.',\n )\n return\n }\n\n // Create settings with updates\n const newSettings = { ...latestSettings, ...updatedSettings }\n\n // always update the working view no matter what\n const newWorkingView = generateWorkingView(newSettings)\n\n // Ensure the payload uses the consistent ID if we already have a working view\n const viewId = latestWorkingViewIdFromCache ?? workingView?.id\n if (viewId) {\n newWorkingView.id = viewId\n }\n const newWorkingViewId = newWorkingView.id\n\n // Make API call in background\n // only include the fields that are updating (just settings)\n const payload = viewId ? { settings: newSettings } : newWorkingView\n\n const promise = onApplyViewChanges(\n {\n payload,\n viewType: viewType,\n projectName: projectName,\n },\n viewId,\n )\n\n // Mutation dispatch above ran onQueryStarted synchronously → RTK cache now\n // reflects `newSettings`. Signal this so any subsequent sync call in the\n // same tick reads the fresh cache instead of the stale closure baseline.\n markCacheDirty()\n\n // if not already on the working view: set that the settings have been changed to show the little blue save button and switch to the working view\n // Note: selectedView?.id is always a real UUID from the server, never the WORKING_VIEW_ID sentinel.\n if (!wasWorking || selectedView?.id !== viewId) {\n if (selectedView) {\n onSettingsChanged(true)\n }\n setSelectedView(newWorkingViewId as string)\n }\n\n await promise\n\n // Clear local state after successful API call - the server data will take over\n localStateSetter(null)\n\n if (options.successMessage) {\n toast.success(options.successMessage)\n }\n } catch (error) {\n // Revert local state on error\n localStateSetter(null)\n\n if (previousSelectedViewId) {\n setSelectedView(previousSelectedViewId)\n }\n\n if (selectedView && !wasWorking) {\n onSettingsChanged(false)\n }\n\n console.error(error)\n const errorMsg = options.errorMessage || `Failed to update view settings: ${error}`\n toast.error(errorMsg)\n }\n}\n\nexport const useViewUpdateHelper = () => {\n const [createView] = useCreateViewMutation()\n const [updateView] = useUpdateViewMutation()\n\n const viewContext = useViewsContext()\n const store = useStore()\n\n const onApplyViewChanges = useCallback(\n async (arg: any, viewId?: string) => {\n if (viewId) {\n // Filter the payload to only include valid patch fields\n // and ideally only include fields that are actually being updated.\n // Expecting the caller to provide only the fields they want to update in the payload.\n const patchPayload: any = {}\n const patchFields = ['label', 'owner', 'settings']\n patchFields.forEach((key) => {\n if (arg.payload[key] !== undefined) {\n patchPayload[key] = arg.payload[key]\n }\n })\n\n return await updateView({\n viewType: arg.viewType,\n projectName: arg.projectName,\n viewId,\n payload: patchPayload,\n }).unwrap()\n } else {\n return await createView(arg).unwrap()\n }\n },\n [createView, updateView],\n )\n\n // Returns cached settings when a same-tick prior write has refreshed the\n // cache. Otherwise returns undefined and the caller falls back to the\n // closure-captured viewSettings (correct baseline for the first write in a\n // tick, including the named-view → working-view fork).\n const getLatest = useCallback((): LatestSettingsResult => {\n const { viewType, projectName, selectedView, workingView } = viewContext\n if (!viewType) return {}\n\n const state = store.getState() as any\n\n // 1. Get the working view from the store — most authoritative after optimistic writes.\n const workingViewEntry = viewsQueries.endpoints.getWorkingView.select({\n viewType,\n projectName,\n })(state)\n const storeWorkingViewId = workingViewEntry?.data?.id\n // Prefer the store's working view ID over the potentially stale context closure value.\n const resolvedWorkingViewId = storeWorkingViewId || workingView?.id\n\n // 2. Determine the currently targeted view ID.\n // Use the store's getDefaultView cache (updated optimistically by setSelectedView) so that\n // an in-flight selection change is visible before React re-renders the context.\n const defaultViewEntry = viewsQueries.endpoints.getDefaultView.select({\n viewType,\n projectName,\n })(state)\n const targetViewId = defaultViewEntry?.data?.id || selectedView?.id\n\n // 3. Determine if the working view is active.\n // IMPORTANT: use !!resolvedWorkingViewId to avoid the undefined === undefined false-positive\n // that would occur on a new project before any working view exists.\n // Note: WORKING_VIEW_ID ('_working_') is a UI-only sentinel; it never appears in\n // server-side cache IDs, so there is no point checking for it here.\n const isWorkingViewActive =\n (!!resolvedWorkingViewId && targetViewId === resolvedWorkingViewId) || cacheDirtyThisTick\n\n // 4. If the working view is active, use its cache as the baseline to prevent stale merges.\n if (isWorkingViewActive && workingViewEntry?.data?.settings) {\n return {\n settings: workingViewEntry.data.settings,\n workingViewId: resolvedWorkingViewId,\n }\n }\n\n // 5. For named views: use the defaultView cache settings as the baseline.\n // This is populated by the initial useGetDefaultViewQuery fetch and is more reliable\n // than the getView endpoint cache (which is only fetched on-demand when editing).\n if (defaultViewEntry?.data?.settings) {\n return {\n settings: defaultViewEntry.data.settings,\n workingViewId: resolvedWorkingViewId,\n }\n }\n\n return { workingViewId: resolvedWorkingViewId }\n }, [store, viewContext])\n\n const updateViewSettingsHandler = useCallback<UpdateViewSettingsFn>(\n async (...args) =>\n await updateViewSettings(...args, viewContext, onApplyViewChanges, getLatest, markCacheDirty),\n [viewContext, onApplyViewChanges, getLatest],\n )\n\n return {\n updateViewSettings: updateViewSettingsHandler,\n onCreateView: onApplyViewChanges,\n getLatestSettings: getLatest,\n markCacheDirty,\n }\n}\n\ntype SettingsObject = Record<string, any>\n\nexport type PathKeys<T> = T extends SettingsObject\n ? {\n [K in keyof T & string]: NonNullable<T[K]> extends readonly any[]\n ? K\n : NonNullable<T[K]> extends SettingsObject\n ? K | `${K}.${PathKeys<NonNullable<T[K]>>}`\n : K\n }[keyof T & string]\n : never\n\nexport type PathValue<T, P extends string> = P extends `${infer K}.${infer Rest}`\n ? K extends keyof T\n ? PathValue<NonNullable<T[K]>, Rest>\n : never\n : P extends keyof T\n ? T[P]\n : never\n\nconst getNestedValue = <T extends SettingsObject, P extends PathKeys<T>>(\n settings: T | undefined,\n path: P,\n): PathValue<T, P> | undefined => {\n return path.split('.').reduce<any>((value, key) => value?.[key], settings)\n}\n\nconst setNestedValue = <T extends SettingsObject>(settings: T, path: string, value: any): T => {\n const [key, ...rest] = path.split('.')\n\n if (!key) return settings\n\n return {\n ...settings,\n [key]: rest.length\n ? setNestedValue((settings[key] as SettingsObject) || {}, rest.join('.'), value)\n : value,\n }\n}\n\nexport const useViewsState = <\n Settings extends SettingsObject = SettingsObject,\n P extends PathKeys<Settings> = PathKeys<Settings>,\n>(\n path: P,\n defaultValue?: PathValue<Settings, P>,\n): [\n PathValue<Settings, P> | undefined,\n (value: SetStateAction<PathValue<Settings, P>>) => void,\n] => {\n const { viewSettings, isLoadingViews } = useViewsContext()\n const { updateViewSettings, getLatestSettings } = useViewUpdateHelper()\n const [localValue, setLocalValueState] = useState<PathValue<Settings, P> | null>(null)\n const localValueRef = useRef<PathValue<Settings, P> | null>(null)\n\n const settings = viewSettings as Settings | undefined\n const value = localValue !== null ? localValue : getNestedValue(settings, path) ?? defaultValue\n\n const setLocalValue = useCallback((newValue: PathValue<Settings, P> | null) => {\n localValueRef.current = newValue\n setLocalValueState(newValue)\n }, [])\n\n const setValue = useCallback(\n (nextValue: SetStateAction<PathValue<Settings, P>>) => {\n if (isLoadingViews || !settings) return\n\n const latestSettings = (getLatestSettings().settings as Settings | undefined) ?? settings\n const currentValue =\n localValueRef.current !== null\n ? localValueRef.current\n : getNestedValue(latestSettings, path) ?? defaultValue\n const resolvedValue =\n typeof nextValue === 'function'\n ? (nextValue as (value: PathValue<Settings, P>) => PathValue<Settings, P>)(\n currentValue as PathValue<Settings, P>,\n )\n : nextValue\n\n void updateViewSettings(\n setNestedValue(latestSettings, path, resolvedValue),\n setLocalValue,\n resolvedValue,\n {},\n )\n },\n [\n defaultValue,\n getLatestSettings,\n isLoadingViews,\n path,\n settings,\n setLocalValue,\n updateViewSettings,\n ],\n )\n\n return [value, setValue]\n}\n"],"names":["cacheDirtyThisTick","markCacheDirty","updateViewSettings","updatedSettings","localStateSetter","newLocalValue","options","viewContext","onApplyViewChanges","getLatest","viewSettings","viewType","projectName","selectedView","setSelectedView","workingView","onSettingsChanged","previousSelectedViewId","wasWorking","latestSettingsFromCache","latestWorkingViewIdFromCache","latestSettings","newSettings","newWorkingView","generateWorkingView","viewId","newWorkingViewId","promise","toast","error","errorMsg","useViewUpdateHelper","createView","useCreateViewMutation","updateView","useUpdateViewMutation","useViewsContext","store","useStore","useCallback","arg","patchPayload","key","state","workingViewEntry","viewsQueries","resolvedWorkingViewId","defaultViewEntry","targetViewId","args","getNestedValue","settings","path","value","setNestedValue","rest","useViewsState","defaultValue","isLoadingViews","getLatestSettings","localValue","setLocalValueState","useState","localValueRef","useRef","setLocalValue","newValue","setValue","nextValue","currentValue","resolvedValue"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"viewUpdateHelper.es.js","sources":["../../../../../../src/containers/Views/utils/viewUpdateHelper.ts"],"sourcesContent":["/**\n * Shared helper for updating view settings with optimistic local state management.\n *\n * Sequential updateViewSettings calls in the same event tick MUST chain correctly:\n * the second call has to see the first call's changes. Closure-captured\n * `viewSettings` does not refresh between sync calls (no re-render yet), so we\n * read the latest settings from the RTK Query cache at call time instead.\n * RTK's updateView mutation performs an optimistic cache write in\n * `onQueryStarted`, so the cache is already up-to-date by the time the next\n * call reads it.\n */\n\nimport {\n EntityIdResponse,\n useCreateViewMutation,\n useUpdateViewMutation,\n viewsQueries,\n} from '@shared/api'\nimport { generateWorkingView } from './generateWorkingView'\nimport { toast } from 'react-toastify'\nimport { SetStateAction, useCallback, useRef, useState } from 'react'\nimport { useStore } from 'react-redux'\nimport { useViewsContext, ViewsContextValue } from '../context/ViewsContext'\n\ninterface UpdateOptions {\n successMessage?: string\n errorMessage?: string\n}\n\n// Module-level flag shared across every useViewUpdateHelper instance. Set true\n// when a mutation has been dispatched in the current tick (RTK cache is now\n// optimistically fresh); reset on the next microtask. Must be module-level so\n// that two different hook instances (e.g. ProjectOverviewDataProvider +\n// ProjectOverviewContext) coordinate correctly when writes flow through one\n// and subsequent reads come from the other in the same event tick.\nlet cacheDirtyThisTick = false\nconst markCacheDirty = () => {\n if (cacheDirtyThisTick) return\n cacheDirtyThisTick = true\n queueMicrotask(() => {\n cacheDirtyThisTick = false\n })\n}\n\nexport type UpdateViewSettingsFn = (\n updatedSettings: any,\n localStateSetter: (value: any) => void,\n newLocalValue: any,\n options: UpdateOptions,\n) => Promise<void>\n\nexport interface LatestSettingsResult {\n settings?: any\n workingViewId?: string\n}\n\nexport const updateViewSettings = async (\n updatedSettings: any,\n localStateSetter: (value: any) => void,\n newLocalValue: any,\n options: UpdateOptions = {},\n viewContext: ViewsContextValue,\n onApplyViewChanges: (arg: any, viewId?: string) => Promise<EntityIdResponse | void>,\n // Reads latest effective settings from RTK Query cache at call time. Required to\n // prevent stale-closure races when two updates fire in the same tick.\n getLatest: () => LatestSettingsResult,\n // Invoked synchronously right after the mutation is dispatched. The caller\n // uses this to flip a \"cache is fresh this tick\" flag so subsequent sync\n // calls in the same tick read the just-updated cache instead of stale state.\n markCacheDirty: () => void,\n): Promise<void> => {\n const {\n viewSettings,\n viewType,\n projectName,\n selectedView,\n setSelectedView,\n workingView,\n onSettingsChanged,\n isErrorWorkingView,\n } = viewContext\n\n if (!viewType) throw new Error('No view type provided for updating view settings')\n\n const previousSelectedViewId = selectedView?.id\n const wasWorking = selectedView?.working\n\n try {\n // Immediately update local state for fast UI response\n localStateSetter(newLocalValue)\n\n // Read latest settings from RTK cache (includes prior same-tick optimistic writes).\n // Fallback to closure-captured value if cache has nothing (first render, etc.).\n const { settings: latestSettingsFromCache, workingViewId: latestWorkingViewIdFromCache } =\n getLatest()\n const latestSettings = latestSettingsFromCache ?? viewSettings\n\n // If we have no settings baseline at all (neither from cache nor from context), AND there is no error\n // abort to prevent writing a partial payload that would overwrite saved settings.\n // This is a defence-in-depth guard; in normal flow isLoadingViews prevents callers\n // from triggering updates before data is available.\n if (latestSettings === undefined && !isErrorWorkingView) {\n console.warn(\n 'updateViewSettings: no settings baseline available, aborting to prevent data loss.',\n )\n return\n }\n\n // Create settings with updates\n const newSettings = { ...latestSettings, ...updatedSettings }\n\n // always update the working view no matter what\n const newWorkingView = generateWorkingView(newSettings)\n\n // Ensure the payload uses the consistent ID if we already have a working view\n const viewId = latestWorkingViewIdFromCache ?? workingView?.id\n if (viewId) {\n newWorkingView.id = viewId\n }\n const newWorkingViewId = newWorkingView.id\n\n // Make API call in background\n // only include the fields that are updating (just settings)\n const payload = viewId ? { settings: newSettings } : newWorkingView\n\n const promise = onApplyViewChanges(\n {\n payload,\n viewType: viewType,\n projectName: projectName,\n },\n viewId,\n )\n\n // Mutation dispatch above ran onQueryStarted synchronously → RTK cache now\n // reflects `newSettings`. Signal this so any subsequent sync call in the\n // same tick reads the fresh cache instead of the stale closure baseline.\n markCacheDirty()\n\n // if not already on the working view: set that the settings have been changed to show the little blue save button and switch to the working view\n // Note: selectedView?.id is always a real UUID from the server, never the WORKING_VIEW_ID sentinel.\n if (!wasWorking || selectedView?.id !== viewId) {\n if (selectedView) {\n onSettingsChanged(true)\n }\n setSelectedView(newWorkingViewId as string)\n }\n\n await promise\n\n // Clear local state after successful API call - the server data will take over\n localStateSetter(null)\n\n if (options.successMessage) {\n toast.success(options.successMessage)\n }\n } catch (error) {\n // Revert local state on error\n localStateSetter(null)\n\n if (previousSelectedViewId) {\n setSelectedView(previousSelectedViewId)\n }\n\n if (selectedView && !wasWorking) {\n onSettingsChanged(false)\n }\n\n console.error(error)\n const errorMsg = options.errorMessage || `Failed to update view settings: ${error}`\n toast.error(errorMsg)\n }\n}\n\nexport const useViewUpdateHelper = () => {\n const [createView] = useCreateViewMutation()\n const [updateView] = useUpdateViewMutation()\n\n const viewContext = useViewsContext()\n const store = useStore()\n\n const onApplyViewChanges = useCallback(\n async (arg: any, viewId?: string) => {\n if (viewId) {\n // Filter the payload to only include valid patch fields\n // and ideally only include fields that are actually being updated.\n // Expecting the caller to provide only the fields they want to update in the payload.\n const patchPayload: any = {}\n const patchFields = ['label', 'owner', 'settings']\n patchFields.forEach((key) => {\n if (arg.payload[key] !== undefined) {\n patchPayload[key] = arg.payload[key]\n }\n })\n\n return await updateView({\n viewType: arg.viewType,\n projectName: arg.projectName,\n viewId,\n payload: patchPayload,\n }).unwrap()\n } else {\n return await createView(arg).unwrap()\n }\n },\n [createView, updateView],\n )\n\n // Returns cached settings when a same-tick prior write has refreshed the\n // cache. Otherwise returns undefined and the caller falls back to the\n // closure-captured viewSettings (correct baseline for the first write in a\n // tick, including the named-view → working-view fork).\n const getLatest = useCallback((): LatestSettingsResult => {\n const { viewType, projectName, selectedView, workingView } = viewContext\n if (!viewType) return {}\n\n const state = store.getState() as any\n\n // 1. Get the working view from the store — most authoritative after optimistic writes.\n const workingViewEntry = viewsQueries.endpoints.getWorkingView.select({\n viewType,\n projectName,\n })(state)\n const storeWorkingViewId = workingViewEntry?.data?.id\n // Prefer the store's working view ID over the potentially stale context closure value.\n const resolvedWorkingViewId = storeWorkingViewId || workingView?.id\n\n // 2. Determine the currently targeted view ID.\n // Use the store's getDefaultView cache (updated optimistically by setSelectedView) so that\n // an in-flight selection change is visible before React re-renders the context.\n const defaultViewEntry = viewsQueries.endpoints.getDefaultView.select({\n viewType,\n projectName,\n })(state)\n const targetViewId = defaultViewEntry?.data?.id || selectedView?.id\n\n // 3. Determine if the working view is active.\n // IMPORTANT: use !!resolvedWorkingViewId to avoid the undefined === undefined false-positive\n // that would occur on a new project before any working view exists.\n // Note: WORKING_VIEW_ID ('_working_') is a UI-only sentinel; it never appears in\n // server-side cache IDs, so there is no point checking for it here.\n const isWorkingViewActive =\n (!!resolvedWorkingViewId && targetViewId === resolvedWorkingViewId) || cacheDirtyThisTick\n\n // 4. If the working view is active, use its cache as the baseline to prevent stale merges.\n if (isWorkingViewActive && workingViewEntry?.data?.settings) {\n return {\n settings: workingViewEntry.data.settings,\n workingViewId: resolvedWorkingViewId,\n }\n }\n\n // 5. For named views: use the defaultView cache settings as the baseline.\n // This is populated by the initial useGetDefaultViewQuery fetch and is more reliable\n // than the getView endpoint cache (which is only fetched on-demand when editing).\n if (defaultViewEntry?.data?.settings) {\n return {\n settings: defaultViewEntry.data.settings,\n workingViewId: resolvedWorkingViewId,\n }\n }\n\n return { workingViewId: resolvedWorkingViewId }\n }, [store, viewContext])\n\n const updateViewSettingsHandler = useCallback<UpdateViewSettingsFn>(\n async (...args) =>\n await updateViewSettings(...args, viewContext, onApplyViewChanges, getLatest, markCacheDirty),\n [viewContext, onApplyViewChanges, getLatest],\n )\n\n return {\n updateViewSettings: updateViewSettingsHandler,\n onCreateView: onApplyViewChanges,\n getLatestSettings: getLatest,\n markCacheDirty,\n }\n}\n\ntype SettingsObject = Record<string, any>\n\nexport type PathKeys<T> = T extends SettingsObject\n ? {\n [K in keyof T & string]: NonNullable<T[K]> extends readonly any[]\n ? K\n : NonNullable<T[K]> extends SettingsObject\n ? K | `${K}.${PathKeys<NonNullable<T[K]>>}`\n : K\n }[keyof T & string]\n : never\n\nexport type PathValue<T, P extends string> = P extends `${infer K}.${infer Rest}`\n ? K extends keyof T\n ? PathValue<NonNullable<T[K]>, Rest>\n : never\n : P extends keyof T\n ? T[P]\n : never\n\nconst getNestedValue = <T extends SettingsObject, P extends PathKeys<T>>(\n settings: T | undefined,\n path: P,\n): PathValue<T, P> | undefined => {\n return path.split('.').reduce<any>((value, key) => value?.[key], settings)\n}\n\nconst setNestedValue = <T extends SettingsObject>(settings: T, path: string, value: any): T => {\n const [key, ...rest] = path.split('.')\n\n if (!key) return settings\n\n return {\n ...settings,\n [key]: rest.length\n ? setNestedValue((settings[key] as SettingsObject) || {}, rest.join('.'), value)\n : value,\n }\n}\n\nexport const useViewsState = <\n Settings extends SettingsObject = SettingsObject,\n P extends PathKeys<Settings> = PathKeys<Settings>,\n>(\n path: P,\n defaultValue?: PathValue<Settings, P>,\n): [\n PathValue<Settings, P> | undefined,\n (value: SetStateAction<PathValue<Settings, P>>) => void,\n] => {\n const { viewSettings, isLoadingViews } = useViewsContext()\n const { updateViewSettings, getLatestSettings } = useViewUpdateHelper()\n const [localValue, setLocalValueState] = useState<PathValue<Settings, P> | null>(null)\n const localValueRef = useRef<PathValue<Settings, P> | null>(null)\n\n const settings = viewSettings as Settings | undefined\n const value = localValue !== null ? localValue : getNestedValue(settings, path) ?? defaultValue\n\n const setLocalValue = useCallback((newValue: PathValue<Settings, P> | null) => {\n localValueRef.current = newValue\n setLocalValueState(newValue)\n }, [])\n\n const setValue = useCallback(\n (nextValue: SetStateAction<PathValue<Settings, P>>) => {\n if (isLoadingViews || !settings) return\n\n const latestSettings = (getLatestSettings().settings as Settings | undefined) ?? settings\n const currentValue =\n localValueRef.current !== null\n ? localValueRef.current\n : getNestedValue(latestSettings, path) ?? defaultValue\n const resolvedValue =\n typeof nextValue === 'function'\n ? (nextValue as (value: PathValue<Settings, P>) => PathValue<Settings, P>)(\n currentValue as PathValue<Settings, P>,\n )\n : nextValue\n\n void updateViewSettings(\n setNestedValue(latestSettings, path, resolvedValue),\n setLocalValue,\n resolvedValue,\n {},\n )\n },\n [\n defaultValue,\n getLatestSettings,\n isLoadingViews,\n path,\n settings,\n setLocalValue,\n updateViewSettings,\n ],\n )\n\n return [value, setValue]\n}\n"],"names":["cacheDirtyThisTick","markCacheDirty","updateViewSettings","updatedSettings","localStateSetter","newLocalValue","options","viewContext","onApplyViewChanges","getLatest","viewSettings","viewType","projectName","selectedView","setSelectedView","workingView","onSettingsChanged","isErrorWorkingView","previousSelectedViewId","wasWorking","latestSettingsFromCache","latestWorkingViewIdFromCache","latestSettings","newSettings","newWorkingView","generateWorkingView","viewId","newWorkingViewId","promise","toast","error","errorMsg","useViewUpdateHelper","createView","useCreateViewMutation","updateView","useUpdateViewMutation","useViewsContext","store","useStore","useCallback","arg","patchPayload","key","state","workingViewEntry","viewsQueries","resolvedWorkingViewId","defaultViewEntry","targetViewId","args","getNestedValue","settings","path","value","setNestedValue","rest","useViewsState","defaultValue","isLoadingViews","getLatestSettings","localValue","setLocalValueState","useState","localValueRef","useRef","setLocalValue","newValue","setValue","nextValue","currentValue","resolvedValue"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const E=require("../../../_virtual/jsx-runtime.cjs.js"),i=require("react");require("../api/base/client.cjs.js");require("../api/generated/graphql.cjs.js");require("../api/generated/graphqlLinks.cjs.js");require("../api/generated/access.cjs.js");require("../api/generated/actions.cjs.js");require("../api/generated/activityFeed.cjs.js");require("../api/generated/addons.cjs.js");require("../api/generated/anatomy.cjs.js");require("../api/generated/attributes.cjs.js");require("../api/generated/authentication.cjs.js");require("../api/generated/bundles.cjs.js");require("../api/generated/configuration.cjs.js");require("../api/generated/dataImport.cjs.js");require("../api/generated/desktop.cjs.js");require("../api/generated/entityLists.cjs.js");require("../api/generated/events.cjs.js");require("../api/generated/files.cjs.js");require("../api/generated/folders.cjs.js");require("../api/generated/inbox.cjs.js");require("../api/generated/links.cjs.js");require("../api/generated/market.cjs.js");require("../api/generated/onboarding.cjs.js");require("../api/generated/operations.cjs.js");require("../api/generated/products.cjs.js");require("../api/generated/projectDashboard.cjs.js");require("../api/generated/projects.cjs.js");require("../api/generated/projectFolders.cjs.js");require("../api/generated/reviewables.cjs.js");require("../api/generated/services.cjs.js");require("../api/generated/system.cjs.js");require("../api/generated/tasks.cjs.js");require("../api/generated/teams.cjs.js");require("../api/generated/thumbnails.cjs.js");require("../api/generated/uRIs.cjs.js");require("../api/generated/users.cjs.js");require("../api/generated/versions.cjs.js");require("../api/generated/workfiles.cjs.js");require("../api/generated/ynputCloud.cjs.js");require("../api/generated/grouping.cjs.js");require("../api/generated/views.cjs.js");require("../api/queries/actions/getActions.cjs.js");require("../api/queries/activities/getActivities.cjs.js");require("../api/queries/activities/updateReaction.cjs.js");require("../api/queries/activities/getMentions.cjs.js");require("../api/queries/activities/getCategories.cjs.js");require("../api/queries/addons/getAddons.cjs.js");require("../api/queries/addons/updateAddons.cjs.js");require("../api/queries/attributes/getAttributes.cjs.js");require("../api/queries/attributes/updateAttributes.cjs.js");require("../api/queries/authentication/getAuthentication.cjs.js");require("../api/queries/bundles/getBundles.cjs.js");require("../api/queries/bundles/updateBundles.cjs.js");require("../api/queries/cloud/cloud.cjs.js");require("../api/queries/columnStats/metricTargets.cjs.js");require("../api/queries/columnStats/groupCounts.cjs.js");require("../api/queries/config/getConfig.cjs.js");require("../api/queries/config/updateConfig.cjs.js");require("../api/queries/entities/getEntity.cjs.js");require("../api/queries/entities/getEntityPanel.cjs.js");require("../api/queries/overview/getOverview.cjs.js");require("../api/queries/overview/updateOverview.cjs.js");require("../api/queries/versions/getVersionsProducts.cjs.js");require("../api/queries/links/getEntityLinks.cjs.js");require("../api/queries/entities/updateEntity.cjs.js");require("../api/queries/entityLists/getLists.cjs.js");require("../api/queries/entityLists/updateLists.cjs.js");require("../api/queries/entityLists/getListsAttributes.cjs.js");require("../api/queries/entityLists/listItemsColumnStats.cjs.js");require("../api/queries/entityLists/updateListsAttributes.cjs.js");require("../api/queries/entityLists/listFolders.cjs.js");require("../api/queries/folders/getFolders.cjs.js");require("../api/queries/folders/getFolderDeleteInfo.cjs.js");require("../api/queries/grouping/getGrouping.cjs.js");require("../api/queries/links/updateLinks.cjs.js");require("../api/queries/links/getLinks.cjs.js");require("../api/queries/permissions/getPermissions.cjs.js");require("../api/queries/products/createProduct.cjs.js");require("../api/queries/products/getFolderProducts.cjs.js");const l=require("../api/queries/project/getProject.cjs.js");require("../api/queries/project/updateProject.cjs.js");require("../api/queries/projectFolders/projectFolders.cjs.js");require("../api/queries/review/getReview.cjs.js");require("../api/queries/review/updateReview.cjs.js");require("../api/queries/share/share.cjs.js");require("../api/queries/system/getSystem.cjs.js");require("../api/queries/tasks/getTasks.cjs.js");require("../api/queries/tasks/updateTasks.cjs.js");require("../api/queries/teams/getTeams.cjs.js");require("../api/queries/userDashboard/getUserDashboard.cjs.js");require("../api/queries/users/getUsers.cjs.js");require("../api/queries/users/updateUsers.cjs.js");require("../api/queries/users/guests.cjs.js");require("../api/queries/versions/updateVersions.cjs.js");require("../api/queries/views/getViews.cjs.js");require("../api/queries/views/updateViews.cjs.js");require("../api/queries/watchers/getWatchers.cjs.js");require("../api/queries/uris/getUris.cjs.js");require("lodash");require("react-toastify");const y=require("../util/getEntityTypeIcon.cjs.js");require("uuid");require("../util/pubsub.cjs.js");const w=require("../api/queries/products/getProduct.cjs.js"),O={name:"",code:"",productTypes:[],folderTypes:[],taskTypes:[],tags:[],statuses:[],createdAt:"",updatedAt:"",active:!0,attrib:{},data:{},config:{},library:!1,linkTypes:[],ownAttrib:[]};function B(e){if(!e)return{productTypes:[],productBaseTypes:[]};const c=e.productTypes||[],u=new Map;return c.forEach(t=>{u.has(t.baseType)||u.set(t.baseType,{name:t.baseType,icon:t.icon,color:t.color})}),{productTypes:c,productBaseTypes:Array.from(u.values())}}const n=i.createContext(void 0),G=({projectName:e,children:c})=>{const{data:u,isLoading:t,isFetching:T,isSuccess:P,isUninitialized:f,error:b,refetch:a}=l.useGetProjectQuery({projectName:e},{skip:!e}),{data:p={},refetch:d}=l.useGetProjectAnatomyQuery({projectName:e},{skip:!e}),o=p.product_base_types?.default,{data:g}=w.useGetProductTypesQuery({projectName:e},{skip:!e}),{productTypes:s,productBaseTypes:x}=B(g),C=i.useCallback(q=>u?.folderTypes?.find(r=>r.name===q),[u]),j=i.useCallback(q=>u?.taskTypes?.find(r=>r.name===q),[u]),k=i.useCallback(q=>{const r=s.find(A=>A.name===q);return{icon:r?.icon||o?.icon||y.getEntityTypeIcon("product"),color:r?.color||o?.color}},[s,o]),v=i.useCallback(()=>s.map(r=>({value:r.name,label:r.name,icon:r.icon||o?.icon||y.getEntityTypeIcon("product"),color:r.color||o?.color||""})),[s,o]),h=i.useCallback(()=>{a(),d()},[a,d]),m={getFolderType:C,getTaskType:j,getProductType:k,getProductTypeOptions:v,refetch:h};return E.jsxRuntimeExports.jsx(n.Provider,{value:{...O,...u,projectName:e,productTypes:s,productBaseTypes:x,anatomy:p,isLoading:t||T,isSuccess:P,isUninitialized:f,error:b,...m},children:c})},I=()=>{const e=i.useContext(n);if(e===void 0)throw new Error("useProjectContext must be used within a
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const E=require("../../../_virtual/jsx-runtime.cjs.js"),i=require("react");require("../api/base/client.cjs.js");require("../api/generated/graphql.cjs.js");require("../api/generated/graphqlLinks.cjs.js");require("../api/generated/access.cjs.js");require("../api/generated/actions.cjs.js");require("../api/generated/activityFeed.cjs.js");require("../api/generated/addons.cjs.js");require("../api/generated/anatomy.cjs.js");require("../api/generated/attributes.cjs.js");require("../api/generated/authentication.cjs.js");require("../api/generated/bundles.cjs.js");require("../api/generated/configuration.cjs.js");require("../api/generated/dataImport.cjs.js");require("../api/generated/desktop.cjs.js");require("../api/generated/entityLists.cjs.js");require("../api/generated/events.cjs.js");require("../api/generated/files.cjs.js");require("../api/generated/folders.cjs.js");require("../api/generated/inbox.cjs.js");require("../api/generated/links.cjs.js");require("../api/generated/market.cjs.js");require("../api/generated/onboarding.cjs.js");require("../api/generated/operations.cjs.js");require("../api/generated/products.cjs.js");require("../api/generated/projectDashboard.cjs.js");require("../api/generated/projects.cjs.js");require("../api/generated/projectFolders.cjs.js");require("../api/generated/reviewables.cjs.js");require("../api/generated/services.cjs.js");require("../api/generated/system.cjs.js");require("../api/generated/tasks.cjs.js");require("../api/generated/teams.cjs.js");require("../api/generated/thumbnails.cjs.js");require("../api/generated/uRIs.cjs.js");require("../api/generated/users.cjs.js");require("../api/generated/versions.cjs.js");require("../api/generated/workfiles.cjs.js");require("../api/generated/ynputCloud.cjs.js");require("../api/generated/grouping.cjs.js");require("../api/generated/views.cjs.js");require("../api/queries/actions/getActions.cjs.js");require("../api/queries/activities/getActivities.cjs.js");require("../api/queries/activities/updateReaction.cjs.js");require("../api/queries/activities/getMentions.cjs.js");require("../api/queries/activities/getCategories.cjs.js");require("../api/queries/addons/getAddons.cjs.js");require("../api/queries/addons/updateAddons.cjs.js");require("../api/queries/attributes/getAttributes.cjs.js");require("../api/queries/attributes/updateAttributes.cjs.js");require("../api/queries/authentication/getAuthentication.cjs.js");require("../api/queries/bundles/getBundles.cjs.js");require("../api/queries/bundles/updateBundles.cjs.js");require("../api/queries/cloud/cloud.cjs.js");require("../api/queries/columnStats/metricTargets.cjs.js");require("../api/queries/columnStats/groupCounts.cjs.js");require("../api/queries/config/getConfig.cjs.js");require("../api/queries/config/updateConfig.cjs.js");require("../api/queries/entities/getEntity.cjs.js");require("../api/queries/entities/getEntityPanel.cjs.js");require("../api/queries/overview/getOverview.cjs.js");require("../api/queries/overview/updateOverview.cjs.js");require("../api/queries/versions/getVersionsProducts.cjs.js");require("../api/queries/links/getEntityLinks.cjs.js");require("../api/queries/entities/updateEntity.cjs.js");require("../api/queries/entityLists/getLists.cjs.js");require("../api/queries/entityLists/updateLists.cjs.js");require("../api/queries/entityLists/getListsAttributes.cjs.js");require("../api/queries/entityLists/listItemsColumnStats.cjs.js");require("../api/queries/entityLists/updateListsAttributes.cjs.js");require("../api/queries/entityLists/listFolders.cjs.js");require("../api/queries/folders/getFolders.cjs.js");require("../api/queries/folders/getFolderDeleteInfo.cjs.js");require("../api/queries/grouping/getGrouping.cjs.js");require("../api/queries/links/updateLinks.cjs.js");require("../api/queries/links/getLinks.cjs.js");require("../api/queries/permissions/getPermissions.cjs.js");require("../api/queries/products/createProduct.cjs.js");require("../api/queries/products/getFolderProducts.cjs.js");const l=require("../api/queries/project/getProject.cjs.js");require("../api/queries/project/updateProject.cjs.js");require("../api/queries/projectFolders/projectFolders.cjs.js");require("../api/queries/review/getReview.cjs.js");require("../api/queries/review/updateReview.cjs.js");require("../api/queries/share/share.cjs.js");require("../api/queries/system/getSystem.cjs.js");require("../api/queries/tasks/getTasks.cjs.js");require("../api/queries/tasks/updateTasks.cjs.js");require("../api/queries/teams/getTeams.cjs.js");require("../api/queries/userDashboard/getUserDashboard.cjs.js");require("../api/queries/users/getUsers.cjs.js");require("../api/queries/users/updateUsers.cjs.js");require("../api/queries/users/guests.cjs.js");require("../api/queries/versions/updateVersions.cjs.js");require("../api/queries/views/getViews.cjs.js");require("../api/queries/views/updateViews.cjs.js");require("../api/queries/watchers/getWatchers.cjs.js");require("../api/queries/uris/getUris.cjs.js");require("lodash");require("react-toastify");const y=require("../util/getEntityTypeIcon.cjs.js");require("uuid");require("../util/pubsub.cjs.js");const w=require("../api/queries/products/getProduct.cjs.js"),O={name:"",code:"",productTypes:[],folderTypes:[],taskTypes:[],tags:[],statuses:[],createdAt:"",updatedAt:"",active:!0,attrib:{},data:{},config:{},library:!1,linkTypes:[],ownAttrib:[]};function B(e){if(!e)return{productTypes:[],productBaseTypes:[]};const c=e.productTypes||[],u=new Map;return c.forEach(t=>{u.has(t.baseType)||u.set(t.baseType,{name:t.baseType,icon:t.icon,color:t.color})}),{productTypes:c,productBaseTypes:Array.from(u.values())}}const n=i.createContext(void 0),G=({projectName:e,children:c})=>{const{data:u,isLoading:t,isFetching:T,isSuccess:P,isUninitialized:f,error:b,refetch:a}=l.useGetProjectQuery({projectName:e},{skip:!e}),{data:p={},refetch:d}=l.useGetProjectAnatomyQuery({projectName:e},{skip:!e}),o=p.product_base_types?.default,{data:g}=w.useGetProductTypesQuery({projectName:e},{skip:!e}),{productTypes:s,productBaseTypes:x}=B(g),C=i.useCallback(q=>u?.folderTypes?.find(r=>r.name===q),[u]),j=i.useCallback(q=>u?.taskTypes?.find(r=>r.name===q),[u]),k=i.useCallback(q=>{const r=s.find(A=>A.name===q);return{icon:r?.icon||o?.icon||y.getEntityTypeIcon("product"),color:r?.color||o?.color}},[s,o]),v=i.useCallback(()=>s.map(r=>({value:r.name,label:r.name,icon:r.icon||o?.icon||y.getEntityTypeIcon("product"),color:r.color||o?.color||""})),[s,o]),h=i.useCallback(()=>{a(),d()},[a,d]),m={getFolderType:C,getTaskType:j,getProductType:k,getProductTypeOptions:v,refetch:h};return E.jsxRuntimeExports.jsx(n.Provider,{value:{...O,...u,projectName:e,productTypes:s,productBaseTypes:x,anatomy:p,isLoading:t||T,isSuccess:P,isUninitialized:f,error:b,...m},children:c})},I=()=>{const e=i.useContext(n);if(e===void 0)throw new Error("useProjectContext must be used within a ProjectContextProvider");return e},M=()=>i.useContext(n);exports.ProjectContextProvider=G;exports.useOptionalProjectContext=M;exports.useProjectContext=I;
|
|
2
2
|
//# sourceMappingURL=ProjectContext.cjs.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProjectContext.cjs.js","sources":["../../../../src/context/ProjectContext.tsx"],"sourcesContent":["import { createContext, useContext, useCallback } from 'react'\nimport { useGetProjectQuery, useGetProjectAnatomyQuery } from '@shared/api'\nimport { getEntityTypeIcon } from '@shared/util'\n\nimport type {\n FolderType,\n TaskType,\n ProductTypeListItem,\n ProjectModel,\n Anatomy,\n ProductType,\n ProductTypesList,\n} from '@shared/api'\nimport { useGetProductTypesQuery } from '@shared/api/queries/products/getProduct'\n\nexport type ProjectModelWithProducts = ProjectModel & {\n // Extend project with product types\n productTypes: ProductTypeListItem[]\n}\n\nconst emptyProject: ProjectModelWithProducts = {\n name: '',\n code: '',\n productTypes: [],\n folderTypes: [],\n taskTypes: [],\n tags: [],\n statuses: [],\n createdAt: '',\n updatedAt: '',\n active: true,\n attrib: {},\n data: {},\n config: {},\n library: false,\n linkTypes: [],\n ownAttrib: [],\n}\n\nfunction getProductTypesData(sourceData: ProductTypesList | undefined) {\n if (!sourceData) {\n return { productTypes: [], productBaseTypes: [] }\n }\n const productTypes = sourceData.productTypes || []\n\n // Create unique base types by mapping and filtering duplicates\n const baseTypesMap = new Map<string, ProductType>()\n\n productTypes.forEach((item: any) => {\n if (!baseTypesMap.has(item.baseType)) {\n baseTypesMap.set(item.baseType, {\n name: item.baseType,\n icon: item.icon,\n color: item.color,\n })\n }\n })\n\n return {\n productTypes,\n productBaseTypes: Array.from(baseTypesMap.values()),\n }\n}\n\nexport interface ProjectContextValue extends ProjectModelWithProducts {\n projectName: string\n isLoading: boolean\n isSuccess: boolean\n isUninitialized: boolean\n error: any\n anatomy: Anatomy\n productBaseTypes: ProductType[]\n\n refetch: () => void\n getProductType: (productType: string) => {\n icon: string\n color: string | undefined\n }\n getFolderType: (name: string) => FolderType | undefined\n getTaskType: (name: string) => TaskType | undefined\n getProductTypeOptions: () => { value: string; label: string; icon?: string; color?: string }[]\n}\n\nconst ProjectContext = createContext<ProjectContextValue | undefined>(undefined)\n\n//\n// ProjectProvider\n//\n\ninterface ProjectProviderProps {\n projectName: string\n children: React.ReactNode\n}\n\nexport const ProjectContextProvider: React.FC<ProjectProviderProps> = ({\n projectName,\n children,\n}: ProjectProviderProps) => {\n // PROJECT\n const {\n data: project,\n isLoading,\n isFetching,\n isSuccess,\n isUninitialized,\n error,\n refetch: refetchProject,\n } = useGetProjectQuery({ projectName }, { skip: !projectName })\n // ANATOMY\n const { data: anatomy = {}, refetch: refetchAnatomy } = useGetProjectAnatomyQuery(\n { projectName },\n { skip: !projectName },\n )\n\n // Shorthands to access project data and type casting\n // (we're referencing nested objects. no need to use useMemo for these)\n\n const defaultProductType = anatomy.product_base_types?.['default']\n\n const { data: productTypesAll } = useGetProductTypesQuery(\n { projectName: projectName },\n {\n skip: !projectName,\n },\n )\n\n const { productTypes, productBaseTypes } = getProductTypesData(productTypesAll)\n\n //\n // Magic functions\n //\n\n // Folder types\n const getFolderType = useCallback(\n (name: string): FolderType | undefined => {\n return project?.folderTypes?.find((type: FolderType) => type.name === name)\n },\n [project],\n )\n\n // Task types\n const getTaskType = useCallback(\n (name: string): TaskType | undefined => {\n return project?.taskTypes?.find((type: TaskType) => type.name === name)\n },\n [project],\n )\n\n // Product types\n const getProductType = useCallback(\n (productType: string) => {\n const type = productTypes.find((t) => t.name === productType)\n return {\n icon: type?.icon || defaultProductType?.icon || getEntityTypeIcon('product'),\n color: type?.color || defaultProductType?.color,\n }\n },\n [productTypes, defaultProductType],\n )\n\n const getProductTypeOptions = useCallback((): {\n value: string\n label: string\n icon: string\n }[] => {\n // Return a list of product type ready to be used in a select input\n const result = productTypes.map((type) => ({\n value: type.name,\n label: type.name,\n icon: type.icon || defaultProductType?.icon || getEntityTypeIcon('product'),\n color: type.color || defaultProductType?.color || '',\n }))\n return result\n }, [productTypes, defaultProductType])\n\n const refetch = useCallback(() => {\n refetchProject()\n refetchAnatomy()\n }, [refetchProject, refetchAnatomy])\n\n //\n // Put everything together\n //\n\n const functions = {\n getFolderType,\n getTaskType,\n getProductType,\n getProductTypeOptions,\n refetch,\n }\n\n return (\n <ProjectContext.Provider\n value={{\n ...emptyProject,\n ...project,\n projectName,\n productTypes,\n productBaseTypes,\n anatomy,\n isLoading: isLoading || isFetching,\n isSuccess: isSuccess,\n isUninitialized,\n error,\n ...functions,\n }}\n >\n {children}\n </ProjectContext.Provider>\n )\n}\n\nexport const useProjectContext = () => {\n const context = useContext(ProjectContext)\n if (context === undefined) {\n throw new Error('useProjectContext must be used within a
|
|
1
|
+
{"version":3,"file":"ProjectContext.cjs.js","sources":["../../../../src/context/ProjectContext.tsx"],"sourcesContent":["import { createContext, useContext, useCallback } from 'react'\nimport { useGetProjectQuery, useGetProjectAnatomyQuery } from '@shared/api'\nimport { getEntityTypeIcon } from '@shared/util'\n\nimport type {\n FolderType,\n TaskType,\n ProductTypeListItem,\n ProjectModel,\n Anatomy,\n ProductType,\n ProductTypesList,\n} from '@shared/api'\nimport { useGetProductTypesQuery } from '@shared/api/queries/products/getProduct'\n\nexport type ProjectModelWithProducts = ProjectModel & {\n // Extend project with product types\n productTypes: ProductTypeListItem[]\n}\n\nconst emptyProject: ProjectModelWithProducts = {\n name: '',\n code: '',\n productTypes: [],\n folderTypes: [],\n taskTypes: [],\n tags: [],\n statuses: [],\n createdAt: '',\n updatedAt: '',\n active: true,\n attrib: {},\n data: {},\n config: {},\n library: false,\n linkTypes: [],\n ownAttrib: [],\n}\n\nfunction getProductTypesData(sourceData: ProductTypesList | undefined) {\n if (!sourceData) {\n return { productTypes: [], productBaseTypes: [] }\n }\n const productTypes = sourceData.productTypes || []\n\n // Create unique base types by mapping and filtering duplicates\n const baseTypesMap = new Map<string, ProductType>()\n\n productTypes.forEach((item: any) => {\n if (!baseTypesMap.has(item.baseType)) {\n baseTypesMap.set(item.baseType, {\n name: item.baseType,\n icon: item.icon,\n color: item.color,\n })\n }\n })\n\n return {\n productTypes,\n productBaseTypes: Array.from(baseTypesMap.values()),\n }\n}\n\nexport interface ProjectContextValue extends ProjectModelWithProducts {\n projectName: string\n isLoading: boolean\n isSuccess: boolean\n isUninitialized: boolean\n error: any\n anatomy: Anatomy\n productBaseTypes: ProductType[]\n\n refetch: () => void\n getProductType: (productType: string) => {\n icon: string\n color: string | undefined\n }\n getFolderType: (name: string) => FolderType | undefined\n getTaskType: (name: string) => TaskType | undefined\n getProductTypeOptions: () => { value: string; label: string; icon?: string; color?: string }[]\n}\n\nconst ProjectContext = createContext<ProjectContextValue | undefined>(undefined)\n\n//\n// ProjectProvider\n//\n\ninterface ProjectProviderProps {\n projectName: string\n children: React.ReactNode\n}\n\nexport const ProjectContextProvider: React.FC<ProjectProviderProps> = ({\n projectName,\n children,\n}: ProjectProviderProps) => {\n // PROJECT\n const {\n data: project,\n isLoading,\n isFetching,\n isSuccess,\n isUninitialized,\n error,\n refetch: refetchProject,\n } = useGetProjectQuery({ projectName }, { skip: !projectName })\n // ANATOMY\n const { data: anatomy = {}, refetch: refetchAnatomy } = useGetProjectAnatomyQuery(\n { projectName },\n { skip: !projectName },\n )\n\n // Shorthands to access project data and type casting\n // (we're referencing nested objects. no need to use useMemo for these)\n\n const defaultProductType = anatomy.product_base_types?.['default']\n\n const { data: productTypesAll } = useGetProductTypesQuery(\n { projectName: projectName },\n {\n skip: !projectName,\n },\n )\n\n const { productTypes, productBaseTypes } = getProductTypesData(productTypesAll)\n\n //\n // Magic functions\n //\n\n // Folder types\n const getFolderType = useCallback(\n (name: string): FolderType | undefined => {\n return project?.folderTypes?.find((type: FolderType) => type.name === name)\n },\n [project],\n )\n\n // Task types\n const getTaskType = useCallback(\n (name: string): TaskType | undefined => {\n return project?.taskTypes?.find((type: TaskType) => type.name === name)\n },\n [project],\n )\n\n // Product types\n const getProductType = useCallback(\n (productType: string) => {\n const type = productTypes.find((t) => t.name === productType)\n return {\n icon: type?.icon || defaultProductType?.icon || getEntityTypeIcon('product'),\n color: type?.color || defaultProductType?.color,\n }\n },\n [productTypes, defaultProductType],\n )\n\n const getProductTypeOptions = useCallback((): {\n value: string\n label: string\n icon: string\n }[] => {\n // Return a list of product type ready to be used in a select input\n const result = productTypes.map((type) => ({\n value: type.name,\n label: type.name,\n icon: type.icon || defaultProductType?.icon || getEntityTypeIcon('product'),\n color: type.color || defaultProductType?.color || '',\n }))\n return result\n }, [productTypes, defaultProductType])\n\n const refetch = useCallback(() => {\n refetchProject()\n refetchAnatomy()\n }, [refetchProject, refetchAnatomy])\n\n //\n // Put everything together\n //\n\n const functions = {\n getFolderType,\n getTaskType,\n getProductType,\n getProductTypeOptions,\n refetch,\n }\n\n return (\n <ProjectContext.Provider\n value={{\n ...emptyProject,\n ...project,\n projectName,\n productTypes,\n productBaseTypes,\n anatomy,\n isLoading: isLoading || isFetching,\n isSuccess: isSuccess,\n isUninitialized,\n error,\n ...functions,\n }}\n >\n {children}\n </ProjectContext.Provider>\n )\n}\n\nexport const useProjectContext = () => {\n const context = useContext(ProjectContext)\n if (context === undefined) {\n throw new Error('useProjectContext must be used within a ProjectContextProvider')\n }\n return context\n}\n\n// non-throwing variant: returns undefined when no ProjectContextProvider is mounted\n// (e.g. the cross-project UserDashboard) so callers can supply their own provider\nexport const useOptionalProjectContext = () => useContext(ProjectContext)\n"],"names":["emptyProject","getProductTypesData","sourceData","productTypes","baseTypesMap","item","ProjectContext","createContext","ProjectContextProvider","projectName","children","project","isLoading","isFetching","isSuccess","isUninitialized","error","refetchProject","useGetProjectQuery","anatomy","refetchAnatomy","useGetProjectAnatomyQuery","defaultProductType","productTypesAll","useGetProductTypesQuery","productBaseTypes","getFolderType","useCallback","name","type","getTaskType","getProductType","productType","t","getEntityTypeIcon","getProductTypeOptions","refetch","functions","jsx","useProjectContext","context","useContext","useOptionalProjectContext"],"mappings":"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"}
|
|
@@ -207,7 +207,7 @@ const c = B(void 0), Lo = ({
|
|
|
207
207
|
}, Mo = () => {
|
|
208
208
|
const t = l(c);
|
|
209
209
|
if (t === void 0)
|
|
210
|
-
throw new Error("useProjectContext must be used within a
|
|
210
|
+
throw new Error("useProjectContext must be used within a ProjectContextProvider");
|
|
211
211
|
return t;
|
|
212
212
|
}, Oo = () => l(c);
|
|
213
213
|
export {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProjectContext.es.js","sources":["../../../../src/context/ProjectContext.tsx"],"sourcesContent":["import { createContext, useContext, useCallback } from 'react'\nimport { useGetProjectQuery, useGetProjectAnatomyQuery } from '@shared/api'\nimport { getEntityTypeIcon } from '@shared/util'\n\nimport type {\n FolderType,\n TaskType,\n ProductTypeListItem,\n ProjectModel,\n Anatomy,\n ProductType,\n ProductTypesList,\n} from '@shared/api'\nimport { useGetProductTypesQuery } from '@shared/api/queries/products/getProduct'\n\nexport type ProjectModelWithProducts = ProjectModel & {\n // Extend project with product types\n productTypes: ProductTypeListItem[]\n}\n\nconst emptyProject: ProjectModelWithProducts = {\n name: '',\n code: '',\n productTypes: [],\n folderTypes: [],\n taskTypes: [],\n tags: [],\n statuses: [],\n createdAt: '',\n updatedAt: '',\n active: true,\n attrib: {},\n data: {},\n config: {},\n library: false,\n linkTypes: [],\n ownAttrib: [],\n}\n\nfunction getProductTypesData(sourceData: ProductTypesList | undefined) {\n if (!sourceData) {\n return { productTypes: [], productBaseTypes: [] }\n }\n const productTypes = sourceData.productTypes || []\n\n // Create unique base types by mapping and filtering duplicates\n const baseTypesMap = new Map<string, ProductType>()\n\n productTypes.forEach((item: any) => {\n if (!baseTypesMap.has(item.baseType)) {\n baseTypesMap.set(item.baseType, {\n name: item.baseType,\n icon: item.icon,\n color: item.color,\n })\n }\n })\n\n return {\n productTypes,\n productBaseTypes: Array.from(baseTypesMap.values()),\n }\n}\n\nexport interface ProjectContextValue extends ProjectModelWithProducts {\n projectName: string\n isLoading: boolean\n isSuccess: boolean\n isUninitialized: boolean\n error: any\n anatomy: Anatomy\n productBaseTypes: ProductType[]\n\n refetch: () => void\n getProductType: (productType: string) => {\n icon: string\n color: string | undefined\n }\n getFolderType: (name: string) => FolderType | undefined\n getTaskType: (name: string) => TaskType | undefined\n getProductTypeOptions: () => { value: string; label: string; icon?: string; color?: string }[]\n}\n\nconst ProjectContext = createContext<ProjectContextValue | undefined>(undefined)\n\n//\n// ProjectProvider\n//\n\ninterface ProjectProviderProps {\n projectName: string\n children: React.ReactNode\n}\n\nexport const ProjectContextProvider: React.FC<ProjectProviderProps> = ({\n projectName,\n children,\n}: ProjectProviderProps) => {\n // PROJECT\n const {\n data: project,\n isLoading,\n isFetching,\n isSuccess,\n isUninitialized,\n error,\n refetch: refetchProject,\n } = useGetProjectQuery({ projectName }, { skip: !projectName })\n // ANATOMY\n const { data: anatomy = {}, refetch: refetchAnatomy } = useGetProjectAnatomyQuery(\n { projectName },\n { skip: !projectName },\n )\n\n // Shorthands to access project data and type casting\n // (we're referencing nested objects. no need to use useMemo for these)\n\n const defaultProductType = anatomy.product_base_types?.['default']\n\n const { data: productTypesAll } = useGetProductTypesQuery(\n { projectName: projectName },\n {\n skip: !projectName,\n },\n )\n\n const { productTypes, productBaseTypes } = getProductTypesData(productTypesAll)\n\n //\n // Magic functions\n //\n\n // Folder types\n const getFolderType = useCallback(\n (name: string): FolderType | undefined => {\n return project?.folderTypes?.find((type: FolderType) => type.name === name)\n },\n [project],\n )\n\n // Task types\n const getTaskType = useCallback(\n (name: string): TaskType | undefined => {\n return project?.taskTypes?.find((type: TaskType) => type.name === name)\n },\n [project],\n )\n\n // Product types\n const getProductType = useCallback(\n (productType: string) => {\n const type = productTypes.find((t) => t.name === productType)\n return {\n icon: type?.icon || defaultProductType?.icon || getEntityTypeIcon('product'),\n color: type?.color || defaultProductType?.color,\n }\n },\n [productTypes, defaultProductType],\n )\n\n const getProductTypeOptions = useCallback((): {\n value: string\n label: string\n icon: string\n }[] => {\n // Return a list of product type ready to be used in a select input\n const result = productTypes.map((type) => ({\n value: type.name,\n label: type.name,\n icon: type.icon || defaultProductType?.icon || getEntityTypeIcon('product'),\n color: type.color || defaultProductType?.color || '',\n }))\n return result\n }, [productTypes, defaultProductType])\n\n const refetch = useCallback(() => {\n refetchProject()\n refetchAnatomy()\n }, [refetchProject, refetchAnatomy])\n\n //\n // Put everything together\n //\n\n const functions = {\n getFolderType,\n getTaskType,\n getProductType,\n getProductTypeOptions,\n refetch,\n }\n\n return (\n <ProjectContext.Provider\n value={{\n ...emptyProject,\n ...project,\n projectName,\n productTypes,\n productBaseTypes,\n anatomy,\n isLoading: isLoading || isFetching,\n isSuccess: isSuccess,\n isUninitialized,\n error,\n ...functions,\n }}\n >\n {children}\n </ProjectContext.Provider>\n )\n}\n\nexport const useProjectContext = () => {\n const context = useContext(ProjectContext)\n if (context === undefined) {\n throw new Error('useProjectContext must be used within a
|
|
1
|
+
{"version":3,"file":"ProjectContext.es.js","sources":["../../../../src/context/ProjectContext.tsx"],"sourcesContent":["import { createContext, useContext, useCallback } from 'react'\nimport { useGetProjectQuery, useGetProjectAnatomyQuery } from '@shared/api'\nimport { getEntityTypeIcon } from '@shared/util'\n\nimport type {\n FolderType,\n TaskType,\n ProductTypeListItem,\n ProjectModel,\n Anatomy,\n ProductType,\n ProductTypesList,\n} from '@shared/api'\nimport { useGetProductTypesQuery } from '@shared/api/queries/products/getProduct'\n\nexport type ProjectModelWithProducts = ProjectModel & {\n // Extend project with product types\n productTypes: ProductTypeListItem[]\n}\n\nconst emptyProject: ProjectModelWithProducts = {\n name: '',\n code: '',\n productTypes: [],\n folderTypes: [],\n taskTypes: [],\n tags: [],\n statuses: [],\n createdAt: '',\n updatedAt: '',\n active: true,\n attrib: {},\n data: {},\n config: {},\n library: false,\n linkTypes: [],\n ownAttrib: [],\n}\n\nfunction getProductTypesData(sourceData: ProductTypesList | undefined) {\n if (!sourceData) {\n return { productTypes: [], productBaseTypes: [] }\n }\n const productTypes = sourceData.productTypes || []\n\n // Create unique base types by mapping and filtering duplicates\n const baseTypesMap = new Map<string, ProductType>()\n\n productTypes.forEach((item: any) => {\n if (!baseTypesMap.has(item.baseType)) {\n baseTypesMap.set(item.baseType, {\n name: item.baseType,\n icon: item.icon,\n color: item.color,\n })\n }\n })\n\n return {\n productTypes,\n productBaseTypes: Array.from(baseTypesMap.values()),\n }\n}\n\nexport interface ProjectContextValue extends ProjectModelWithProducts {\n projectName: string\n isLoading: boolean\n isSuccess: boolean\n isUninitialized: boolean\n error: any\n anatomy: Anatomy\n productBaseTypes: ProductType[]\n\n refetch: () => void\n getProductType: (productType: string) => {\n icon: string\n color: string | undefined\n }\n getFolderType: (name: string) => FolderType | undefined\n getTaskType: (name: string) => TaskType | undefined\n getProductTypeOptions: () => { value: string; label: string; icon?: string; color?: string }[]\n}\n\nconst ProjectContext = createContext<ProjectContextValue | undefined>(undefined)\n\n//\n// ProjectProvider\n//\n\ninterface ProjectProviderProps {\n projectName: string\n children: React.ReactNode\n}\n\nexport const ProjectContextProvider: React.FC<ProjectProviderProps> = ({\n projectName,\n children,\n}: ProjectProviderProps) => {\n // PROJECT\n const {\n data: project,\n isLoading,\n isFetching,\n isSuccess,\n isUninitialized,\n error,\n refetch: refetchProject,\n } = useGetProjectQuery({ projectName }, { skip: !projectName })\n // ANATOMY\n const { data: anatomy = {}, refetch: refetchAnatomy } = useGetProjectAnatomyQuery(\n { projectName },\n { skip: !projectName },\n )\n\n // Shorthands to access project data and type casting\n // (we're referencing nested objects. no need to use useMemo for these)\n\n const defaultProductType = anatomy.product_base_types?.['default']\n\n const { data: productTypesAll } = useGetProductTypesQuery(\n { projectName: projectName },\n {\n skip: !projectName,\n },\n )\n\n const { productTypes, productBaseTypes } = getProductTypesData(productTypesAll)\n\n //\n // Magic functions\n //\n\n // Folder types\n const getFolderType = useCallback(\n (name: string): FolderType | undefined => {\n return project?.folderTypes?.find((type: FolderType) => type.name === name)\n },\n [project],\n )\n\n // Task types\n const getTaskType = useCallback(\n (name: string): TaskType | undefined => {\n return project?.taskTypes?.find((type: TaskType) => type.name === name)\n },\n [project],\n )\n\n // Product types\n const getProductType = useCallback(\n (productType: string) => {\n const type = productTypes.find((t) => t.name === productType)\n return {\n icon: type?.icon || defaultProductType?.icon || getEntityTypeIcon('product'),\n color: type?.color || defaultProductType?.color,\n }\n },\n [productTypes, defaultProductType],\n )\n\n const getProductTypeOptions = useCallback((): {\n value: string\n label: string\n icon: string\n }[] => {\n // Return a list of product type ready to be used in a select input\n const result = productTypes.map((type) => ({\n value: type.name,\n label: type.name,\n icon: type.icon || defaultProductType?.icon || getEntityTypeIcon('product'),\n color: type.color || defaultProductType?.color || '',\n }))\n return result\n }, [productTypes, defaultProductType])\n\n const refetch = useCallback(() => {\n refetchProject()\n refetchAnatomy()\n }, [refetchProject, refetchAnatomy])\n\n //\n // Put everything together\n //\n\n const functions = {\n getFolderType,\n getTaskType,\n getProductType,\n getProductTypeOptions,\n refetch,\n }\n\n return (\n <ProjectContext.Provider\n value={{\n ...emptyProject,\n ...project,\n projectName,\n productTypes,\n productBaseTypes,\n anatomy,\n isLoading: isLoading || isFetching,\n isSuccess: isSuccess,\n isUninitialized,\n error,\n ...functions,\n }}\n >\n {children}\n </ProjectContext.Provider>\n )\n}\n\nexport const useProjectContext = () => {\n const context = useContext(ProjectContext)\n if (context === undefined) {\n throw new Error('useProjectContext must be used within a ProjectContextProvider')\n }\n return context\n}\n\n// non-throwing variant: returns undefined when no ProjectContextProvider is mounted\n// (e.g. the cross-project UserDashboard) so callers can supply their own provider\nexport const useOptionalProjectContext = () => useContext(ProjectContext)\n"],"names":["emptyProject","getProductTypesData","sourceData","productTypes","baseTypesMap","item","ProjectContext","createContext","ProjectContextProvider","projectName","children","project","isLoading","isFetching","isSuccess","isUninitialized","error","refetchProject","useGetProjectQuery","anatomy","refetchAnatomy","useGetProjectAnatomyQuery","defaultProductType","productTypesAll","useGetProductTypesQuery","productBaseTypes","getFolderType","useCallback","name","type","getTaskType","getProductType","productType","t","getEntityTypeIcon","getProductTypeOptions","refetch","functions","jsx","useProjectContext","context","useContext","useOptionalProjectContext"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const E=
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const E=b=>{const{folderNodes:m,rootFolderIds:p,showEmptyFolders:F,buildFolderRowId:w,createItemRow:y,sortFolderNodes:i,sortItems:a,getFolderLabel:R,getFolderIcon:I,getFolderColor:P,getItemCount:A,getFolderIsEmpty:N,getFolderDisabledMessage:C}=b,n=e=>e.hasAnyItems?!0:N?.(e.folder)===!1?!1:F,c=[],M=Array.from(m.values()).filter(e=>p.has(e.id)&&n(e)),u=i(M),s=[];for(let e=u.length-1;e>=0;e--)s.push({node:u[e],targetArray:c,isProcessed:!1,parentPath:[]});for(;s.length>0;){const e=s[s.length-1];if(e.isProcessed){s.pop();continue}e.isProcessed=!0;const{node:o,targetArray:T,parentPath:r}=e,l=R(o.folder),f=P(o.folder),h=C?.(o.folder),d={id:w(o.id),name:l,label:l,...r.length>0&&{parents:r},icon:I(o.folder),iconColor:f,iconFilled:!0,isDisabled:!!h,disabledMessage:h,subRows:[],data:{id:o.id,isGroupRow:!0,count:A(o),type:o.id,isFolder:!0,color:f}};T.push(d);const v=a?a(o.items):o.items;for(const t of v)d.subRows.push(y(t,o.id,[...r,l]));const D=Array.from(o.children.values()).filter(n),g=i(D);for(let t=g.length-1;t>=0;t--)s.push({node:g[t],targetArray:d.subRows,isProcessed:!1,parentPath:[...r,l]})}return c};exports.buildHierarchicalTableRows=E;
|
|
2
2
|
//# sourceMappingURL=buildHierarchicalTableRows.cjs.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"buildHierarchicalTableRows.cjs.js","sources":["../../../../src/util/buildHierarchicalTableRows.ts"],"sourcesContent":["import type { SimpleTableRow } from '@shared/containers/SimpleTable/SimpleTable.types'\n\n/**\n * Generic folder node structure for hierarchical data\n */\nexport interface HierarchicalFolderNode<TFolder, TItem> {\n id: string\n folder: TFolder\n children: Map<string, HierarchicalFolderNode<TFolder, TItem>>\n items: TItem[]\n hasAnyItems: boolean\n}\n\n/**\n * Configuration for building hierarchical table rows\n */\nexport interface BuildHierarchicalRowsConfig<TFolder, TItem> {\n /** Map of folder nodes */\n folderNodes: Map<string, HierarchicalFolderNode<TFolder, TItem>>\n /** Set of root folder IDs */\n rootFolderIds: Set<string>\n /** Whether to show empty folders */\n showEmptyFolders: boolean\n /** Function to build row ID from folder ID */\n buildFolderRowId: (folderId: string) => string\n /** Function to create a table row for an item */\n createItemRow: (item: TItem, parentId?: string, parentPath?: string[]) => SimpleTableRow\n /** Function to sort folder nodes */\n sortFolderNodes: (\n nodes: HierarchicalFolderNode<TFolder, TItem>[],\n ) => HierarchicalFolderNode<TFolder, TItem>[]\n /** Function to sort items within a folder */\n sortItems?: (items: TItem[]) => TItem[]\n /** Function to extract folder label */\n getFolderLabel: (folder: TFolder) => string\n /** Function to extract folder icon */\n getFolderIcon: (folder: TFolder) => string\n /** Function to extract folder color */\n getFolderColor: (folder: TFolder) => string | undefined\n /** Function to get item count for display */\n getItemCount: (node: HierarchicalFolderNode<TFolder, TItem>) => number\n /** Optional: returns true if the folder is genuinely empty, false if it has items the user can't see (e.g. restricted projects). Hides folders with restricted content regardless of showEmptyFolders. */\n getFolderIsEmpty?: (folder: TFolder) => boolean | undefined\n}\n\n/**\n * Builds table rows iteratively using depth-first traversal from a hierarchical folder structure.\n * This is a generic function that can be used for both projects and lists or any other hierarchical data.\n */\nexport const buildHierarchicalTableRows = <TFolder, TItem>(\n config: BuildHierarchicalRowsConfig<TFolder, TItem>,\n): SimpleTableRow[] => {\n const {\n folderNodes,\n rootFolderIds,\n showEmptyFolders,\n buildFolderRowId,\n createItemRow,\n sortFolderNodes,\n sortItems,\n getFolderLabel,\n getFolderIcon,\n getFolderColor,\n getItemCount,\n getFolderIsEmpty,\n } = config\n\n const isFolderVisible = (node: HierarchicalFolderNode<TFolder, TItem>): boolean => {\n if (node.hasAnyItems) return true\n if (getFolderIsEmpty?.(node.folder) === false) return false\n return showEmptyFolders\n }\n\n const result: SimpleTableRow[] = []\n\n // Get root folders and sort them\n const rootNodes = Array.from(folderNodes.values()).filter(\n (node) => rootFolderIds.has(node.id) && isFolderVisible(node),\n )\n const sortedRootNodes = sortFolderNodes(rootNodes)\n\n // Stack for iterative depth-first traversal\n type StackItem = {\n node: HierarchicalFolderNode<TFolder, TItem>\n targetArray: SimpleTableRow[]\n isProcessed: boolean\n parentPath: string[]\n }\n\n const stack: StackItem[] = []\n\n // Add root nodes to stack in reverse order (so first item is processed first)\n for (let i = sortedRootNodes.length - 1; i >= 0; i--) {\n stack.push({\n node: sortedRootNodes[i],\n targetArray: result,\n isProcessed: false,\n parentPath: [],\n })\n }\n\n while (stack.length > 0) {\n const item = stack[stack.length - 1] // Peek at top\n\n if (item.isProcessed) {\n // This node has been processed, remove from stack\n stack.pop()\n continue\n }\n\n // Mark as processed to avoid infinite loops\n item.isProcessed = true\n const { node, targetArray, parentPath } = item\n\n const folderLabel = getFolderLabel(node.folder)\n const folderColor = getFolderColor(node.folder)\n\n // Create folder row\n const folderRow: SimpleTableRow = {\n id: buildFolderRowId(node.id),\n name: folderLabel,\n label: folderLabel,\n ...(parentPath.length > 0 && { parents: parentPath }),\n icon: getFolderIcon(node.folder),\n iconColor: folderColor,\n iconFilled: true,\n subRows: [],\n data: {\n id: node.id,\n isGroupRow: true,\n count: getItemCount(node),\n type: node.id,\n isFolder: true,\n color: folderColor,\n },\n }\n\n // Add to target array\n targetArray.push(folderRow)\n\n // Add items to this folder (sorted if sort function provided)\n const itemsToAdd = sortItems ? sortItems(node.items) : node.items\n for (const item of itemsToAdd) {\n folderRow.subRows.push(createItemRow(item, node.id, [...parentPath, folderLabel]))\n }\n\n // Get child folders and sort them\n const childNodes = Array.from(node.children.values()).filter(isFolderVisible)\n const sortedChildNodes = sortFolderNodes(childNodes)\n\n // Add child folders to stack in reverse order (for correct processing order)\n for (let i = sortedChildNodes.length - 1; i >= 0; i--) {\n stack.push({\n node: sortedChildNodes[i],\n targetArray: folderRow.subRows,\n isProcessed: false,\n parentPath: [...parentPath, folderLabel],\n })\n }\n }\n\n return result\n}\n"],"names":["buildHierarchicalTableRows","config","folderNodes","rootFolderIds","showEmptyFolders","buildFolderRowId","createItemRow","sortFolderNodes","sortItems","getFolderLabel","getFolderIcon","getFolderColor","getItemCount","getFolderIsEmpty","isFolderVisible","node","result","rootNodes","sortedRootNodes","stack","i","item","targetArray","parentPath","folderLabel","folderColor","folderRow","itemsToAdd","childNodes","sortedChildNodes"],"mappings":"
|
|
1
|
+
{"version":3,"file":"buildHierarchicalTableRows.cjs.js","sources":["../../../../src/util/buildHierarchicalTableRows.ts"],"sourcesContent":["import type { SimpleTableRow } from '@shared/containers/SimpleTable/SimpleTable.types'\n\n/**\n * Generic folder node structure for hierarchical data\n */\nexport interface HierarchicalFolderNode<TFolder, TItem> {\n id: string\n folder: TFolder\n children: Map<string, HierarchicalFolderNode<TFolder, TItem>>\n items: TItem[]\n hasAnyItems: boolean\n}\n\n/**\n * Configuration for building hierarchical table rows\n */\nexport interface BuildHierarchicalRowsConfig<TFolder, TItem> {\n /** Map of folder nodes */\n folderNodes: Map<string, HierarchicalFolderNode<TFolder, TItem>>\n /** Set of root folder IDs */\n rootFolderIds: Set<string>\n /** Whether to show empty folders */\n showEmptyFolders: boolean\n /** Function to build row ID from folder ID */\n buildFolderRowId: (folderId: string) => string\n /** Function to create a table row for an item */\n createItemRow: (item: TItem, parentId?: string, parentPath?: string[]) => SimpleTableRow\n /** Function to sort folder nodes */\n sortFolderNodes: (\n nodes: HierarchicalFolderNode<TFolder, TItem>[],\n ) => HierarchicalFolderNode<TFolder, TItem>[]\n /** Function to sort items within a folder */\n sortItems?: (items: TItem[]) => TItem[]\n /** Function to extract folder label */\n getFolderLabel: (folder: TFolder) => string\n /** Function to extract folder icon */\n getFolderIcon: (folder: TFolder) => string\n /** Function to extract folder color */\n getFolderColor: (folder: TFolder) => string | undefined\n /** Function to get item count for display */\n getItemCount: (node: HierarchicalFolderNode<TFolder, TItem>) => number\n /** Optional: returns true if the folder is genuinely empty, false if it has items the user can't see (e.g. restricted projects). Hides folders with restricted content regardless of showEmptyFolders. */\n getFolderIsEmpty?: (folder: TFolder) => boolean | undefined\n /** Optional: why a folder can't be picked (row shown but not selectable); undefined = selectable */\n getFolderDisabledMessage?: (folder: TFolder) => string | undefined\n}\n\n/**\n * Builds table rows iteratively using depth-first traversal from a hierarchical folder structure.\n * This is a generic function that can be used for both projects and lists or any other hierarchical data.\n */\nexport const buildHierarchicalTableRows = <TFolder, TItem>(\n config: BuildHierarchicalRowsConfig<TFolder, TItem>,\n): SimpleTableRow[] => {\n const {\n folderNodes,\n rootFolderIds,\n showEmptyFolders,\n buildFolderRowId,\n createItemRow,\n sortFolderNodes,\n sortItems,\n getFolderLabel,\n getFolderIcon,\n getFolderColor,\n getItemCount,\n getFolderIsEmpty,\n getFolderDisabledMessage,\n } = config\n\n const isFolderVisible = (node: HierarchicalFolderNode<TFolder, TItem>): boolean => {\n if (node.hasAnyItems) return true\n if (getFolderIsEmpty?.(node.folder) === false) return false\n return showEmptyFolders\n }\n\n const result: SimpleTableRow[] = []\n\n // Get root folders and sort them\n const rootNodes = Array.from(folderNodes.values()).filter(\n (node) => rootFolderIds.has(node.id) && isFolderVisible(node),\n )\n const sortedRootNodes = sortFolderNodes(rootNodes)\n\n // Stack for iterative depth-first traversal\n type StackItem = {\n node: HierarchicalFolderNode<TFolder, TItem>\n targetArray: SimpleTableRow[]\n isProcessed: boolean\n parentPath: string[]\n }\n\n const stack: StackItem[] = []\n\n // Add root nodes to stack in reverse order (so first item is processed first)\n for (let i = sortedRootNodes.length - 1; i >= 0; i--) {\n stack.push({\n node: sortedRootNodes[i],\n targetArray: result,\n isProcessed: false,\n parentPath: [],\n })\n }\n\n while (stack.length > 0) {\n const item = stack[stack.length - 1] // Peek at top\n\n if (item.isProcessed) {\n // This node has been processed, remove from stack\n stack.pop()\n continue\n }\n\n // Mark as processed to avoid infinite loops\n item.isProcessed = true\n const { node, targetArray, parentPath } = item\n\n const folderLabel = getFolderLabel(node.folder)\n const folderColor = getFolderColor(node.folder)\n const folderDisabledMessage = getFolderDisabledMessage?.(node.folder)\n\n // Create folder row\n const folderRow: SimpleTableRow = {\n id: buildFolderRowId(node.id),\n name: folderLabel,\n label: folderLabel,\n ...(parentPath.length > 0 && { parents: parentPath }),\n icon: getFolderIcon(node.folder),\n iconColor: folderColor,\n iconFilled: true,\n isDisabled: !!folderDisabledMessage,\n disabledMessage: folderDisabledMessage,\n subRows: [],\n data: {\n id: node.id,\n isGroupRow: true,\n count: getItemCount(node),\n type: node.id,\n isFolder: true,\n color: folderColor,\n },\n }\n\n // Add to target array\n targetArray.push(folderRow)\n\n // Add items to this folder (sorted if sort function provided)\n const itemsToAdd = sortItems ? sortItems(node.items) : node.items\n for (const item of itemsToAdd) {\n folderRow.subRows.push(createItemRow(item, node.id, [...parentPath, folderLabel]))\n }\n\n // Get child folders and sort them\n const childNodes = Array.from(node.children.values()).filter(isFolderVisible)\n const sortedChildNodes = sortFolderNodes(childNodes)\n\n // Add child folders to stack in reverse order (for correct processing order)\n for (let i = sortedChildNodes.length - 1; i >= 0; i--) {\n stack.push({\n node: sortedChildNodes[i],\n targetArray: folderRow.subRows,\n isProcessed: false,\n parentPath: [...parentPath, folderLabel],\n })\n }\n }\n\n return result\n}\n"],"names":["buildHierarchicalTableRows","config","folderNodes","rootFolderIds","showEmptyFolders","buildFolderRowId","createItemRow","sortFolderNodes","sortItems","getFolderLabel","getFolderIcon","getFolderColor","getItemCount","getFolderIsEmpty","getFolderDisabledMessage","isFolderVisible","node","result","rootNodes","sortedRootNodes","stack","i","item","targetArray","parentPath","folderLabel","folderColor","folderDisabledMessage","folderRow","itemsToAdd","childNodes","sortedChildNodes"],"mappings":"gFAmDO,MAAMA,EACXC,GACqB,CACrB,KAAM,CACJ,YAAAC,EACA,cAAAC,EACA,iBAAAC,EACA,iBAAAC,EACA,cAAAC,EACA,gBAAAC,EACA,UAAAC,EACA,eAAAC,EACA,cAAAC,EACA,eAAAC,EACA,aAAAC,EACA,iBAAAC,EACA,yBAAAC,CAAA,EACEb,EAEEc,EAAmBC,GACnBA,EAAK,YAAoB,GACzBH,IAAmBG,EAAK,MAAM,IAAM,GAAc,GAC/CZ,EAGHa,EAA2B,CAAA,EAG3BC,EAAY,MAAM,KAAKhB,EAAY,OAAA,CAAQ,EAAE,OAChDc,GAASb,EAAc,IAAIa,EAAK,EAAE,GAAKD,EAAgBC,CAAI,CAAA,EAExDG,EAAkBZ,EAAgBW,CAAS,EAU3CE,EAAqB,CAAA,EAG3B,QAASC,EAAIF,EAAgB,OAAS,EAAGE,GAAK,EAAGA,IAC/CD,EAAM,KAAK,CACT,KAAMD,EAAgBE,CAAC,EACvB,YAAaJ,EACb,YAAa,GACb,WAAY,CAAA,CAAC,CACd,EAGH,KAAOG,EAAM,OAAS,GAAG,CACvB,MAAME,EAAOF,EAAMA,EAAM,OAAS,CAAC,EAEnC,GAAIE,EAAK,YAAa,CAEpBF,EAAM,IAAA,EACN,QACF,CAGAE,EAAK,YAAc,GACnB,KAAM,CAAE,KAAAN,EAAM,YAAAO,EAAa,WAAAC,CAAA,EAAeF,EAEpCG,EAAchB,EAAeO,EAAK,MAAM,EACxCU,EAAcf,EAAeK,EAAK,MAAM,EACxCW,EAAwBb,IAA2BE,EAAK,MAAM,EAG9DY,EAA4B,CAChC,GAAIvB,EAAiBW,EAAK,EAAE,EAC5B,KAAMS,EACN,MAAOA,EACP,GAAID,EAAW,OAAS,GAAK,CAAE,QAASA,CAAA,EACxC,KAAMd,EAAcM,EAAK,MAAM,EAC/B,UAAWU,EACX,WAAY,GACZ,WAAY,CAAC,CAACC,EACd,gBAAiBA,EACjB,QAAS,CAAA,EACT,KAAM,CACJ,GAAIX,EAAK,GACT,WAAY,GACZ,MAAOJ,EAAaI,CAAI,EACxB,KAAMA,EAAK,GACX,SAAU,GACV,MAAOU,CAAA,CACT,EAIFH,EAAY,KAAKK,CAAS,EAG1B,MAAMC,EAAarB,EAAYA,EAAUQ,EAAK,KAAK,EAAIA,EAAK,MAC5D,UAAWM,KAAQO,EACjBD,EAAU,QAAQ,KAAKtB,EAAcgB,EAAMN,EAAK,GAAI,CAAC,GAAGQ,EAAYC,CAAW,CAAC,CAAC,EAInF,MAAMK,EAAa,MAAM,KAAKd,EAAK,SAAS,OAAA,CAAQ,EAAE,OAAOD,CAAe,EACtEgB,EAAmBxB,EAAgBuB,CAAU,EAGnD,QAAST,EAAIU,EAAiB,OAAS,EAAGV,GAAK,EAAGA,IAChDD,EAAM,KAAK,CACT,KAAMW,EAAiBV,CAAC,EACxB,YAAaO,EAAU,QACvB,YAAa,GACb,WAAY,CAAC,GAAGJ,EAAYC,CAAW,CAAA,CACxC,CAEL,CAEA,OAAOR,CACT"}
|
|
@@ -1,63 +1,66 @@
|
|
|
1
1
|
const L = (p) => {
|
|
2
2
|
const {
|
|
3
|
-
folderNodes:
|
|
4
|
-
rootFolderIds:
|
|
3
|
+
folderNodes: b,
|
|
4
|
+
rootFolderIds: m,
|
|
5
5
|
showEmptyFolders: F,
|
|
6
|
-
buildFolderRowId:
|
|
7
|
-
createItemRow:
|
|
6
|
+
buildFolderRowId: w,
|
|
7
|
+
createItemRow: y,
|
|
8
8
|
sortFolderNodes: i,
|
|
9
9
|
sortItems: n,
|
|
10
|
-
getFolderLabel:
|
|
11
|
-
getFolderIcon:
|
|
12
|
-
getFolderColor:
|
|
13
|
-
getItemCount:
|
|
14
|
-
getFolderIsEmpty:
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
10
|
+
getFolderLabel: R,
|
|
11
|
+
getFolderIcon: I,
|
|
12
|
+
getFolderColor: A,
|
|
13
|
+
getItemCount: P,
|
|
14
|
+
getFolderIsEmpty: N,
|
|
15
|
+
getFolderDisabledMessage: C
|
|
16
|
+
} = p, a = (e) => e.hasAnyItems ? !0 : N?.(e.folder) === !1 ? !1 : F, c = [], D = Array.from(b.values()).filter(
|
|
17
|
+
(e) => m.has(e.id) && a(e)
|
|
18
|
+
), f = i(D), s = [];
|
|
19
|
+
for (let e = f.length - 1; e >= 0; e--)
|
|
20
|
+
s.push({
|
|
21
|
+
node: f[e],
|
|
21
22
|
targetArray: c,
|
|
22
23
|
isProcessed: !1,
|
|
23
24
|
parentPath: []
|
|
24
25
|
});
|
|
25
|
-
for (;
|
|
26
|
-
const e =
|
|
26
|
+
for (; s.length > 0; ) {
|
|
27
|
+
const e = s[s.length - 1];
|
|
27
28
|
if (e.isProcessed) {
|
|
28
|
-
|
|
29
|
+
s.pop();
|
|
29
30
|
continue;
|
|
30
31
|
}
|
|
31
32
|
e.isProcessed = !0;
|
|
32
|
-
const { node: o, targetArray:
|
|
33
|
-
id:
|
|
33
|
+
const { node: o, targetArray: M, parentPath: r } = e, l = R(o.folder), u = A(o.folder), h = C?.(o.folder), d = {
|
|
34
|
+
id: w(o.id),
|
|
34
35
|
name: l,
|
|
35
36
|
label: l,
|
|
36
|
-
...
|
|
37
|
-
icon:
|
|
38
|
-
iconColor:
|
|
37
|
+
...r.length > 0 && { parents: r },
|
|
38
|
+
icon: I(o.folder),
|
|
39
|
+
iconColor: u,
|
|
39
40
|
iconFilled: !0,
|
|
41
|
+
isDisabled: !!h,
|
|
42
|
+
disabledMessage: h,
|
|
40
43
|
subRows: [],
|
|
41
44
|
data: {
|
|
42
45
|
id: o.id,
|
|
43
46
|
isGroupRow: !0,
|
|
44
|
-
count:
|
|
47
|
+
count: P(o),
|
|
45
48
|
type: o.id,
|
|
46
49
|
isFolder: !0,
|
|
47
|
-
color:
|
|
50
|
+
color: u
|
|
48
51
|
}
|
|
49
52
|
};
|
|
50
|
-
|
|
53
|
+
M.push(d);
|
|
51
54
|
const v = n ? n(o.items) : o.items;
|
|
52
|
-
for (const
|
|
53
|
-
d.subRows.push(
|
|
54
|
-
const E = Array.from(o.children.values()).filter(a),
|
|
55
|
-
for (let
|
|
56
|
-
|
|
57
|
-
node:
|
|
55
|
+
for (const t of v)
|
|
56
|
+
d.subRows.push(y(t, o.id, [...r, l]));
|
|
57
|
+
const E = Array.from(o.children.values()).filter(a), g = i(E);
|
|
58
|
+
for (let t = g.length - 1; t >= 0; t--)
|
|
59
|
+
s.push({
|
|
60
|
+
node: g[t],
|
|
58
61
|
targetArray: d.subRows,
|
|
59
62
|
isProcessed: !1,
|
|
60
|
-
parentPath: [...
|
|
63
|
+
parentPath: [...r, l]
|
|
61
64
|
});
|
|
62
65
|
}
|
|
63
66
|
return c;
|