@procore/saved-views 1.0.1-alpha.2 → 1.1.0-alpha.0

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.
@@ -3982,7 +3982,7 @@ var require_lodash = __commonJS({
3982
3982
  if (typeof func != "function") {
3983
3983
  throw new TypeError2(FUNC_ERROR_TEXT);
3984
3984
  }
3985
- return setTimeout2(function() {
3985
+ return setTimeout(function() {
3986
3986
  func.apply(undefined2, args);
3987
3987
  }, wait);
3988
3988
  }
@@ -5813,7 +5813,7 @@ var require_lodash = __commonJS({
5813
5813
  return object2[key];
5814
5814
  }
5815
5815
  var setData = shortOut(baseSetData);
5816
- var setTimeout2 = ctxSetTimeout || function(func, wait) {
5816
+ var setTimeout = ctxSetTimeout || function(func, wait) {
5817
5817
  return root.setTimeout(func, wait);
5818
5818
  };
5819
5819
  var setToString = shortOut(baseSetToString);
@@ -6605,7 +6605,7 @@ var require_lodash = __commonJS({
6605
6605
  }
6606
6606
  function leadingEdge(time) {
6607
6607
  lastInvokeTime = time;
6608
- timerId = setTimeout2(timerExpired, wait);
6608
+ timerId = setTimeout(timerExpired, wait);
6609
6609
  return leading ? invokeFunc(time) : result2;
6610
6610
  }
6611
6611
  function remainingWait(time) {
@@ -6621,7 +6621,7 @@ var require_lodash = __commonJS({
6621
6621
  if (shouldInvoke(time)) {
6622
6622
  return trailingEdge(time);
6623
6623
  }
6624
- timerId = setTimeout2(timerExpired, remainingWait(time));
6624
+ timerId = setTimeout(timerExpired, remainingWait(time));
6625
6625
  }
6626
6626
  function trailingEdge(time) {
6627
6627
  timerId = undefined2;
@@ -6652,12 +6652,12 @@ var require_lodash = __commonJS({
6652
6652
  }
6653
6653
  if (maxing) {
6654
6654
  clearTimeout(timerId);
6655
- timerId = setTimeout2(timerExpired, wait);
6655
+ timerId = setTimeout(timerExpired, wait);
6656
6656
  return invokeFunc(lastCallTime);
6657
6657
  }
6658
6658
  }
6659
6659
  if (timerId === undefined2) {
6660
- timerId = setTimeout2(timerExpired, wait);
6660
+ timerId = setTimeout(timerExpired, wait);
6661
6661
  }
6662
6662
  return result2;
6663
6663
  }
@@ -11385,7 +11385,7 @@ var SavedViewCollectionMenuItem = (props) => {
11385
11385
  loading: props.isUpdateProcessing
11386
11386
  },
11387
11387
  i18n.t("savedViews.actions.update")
11388
- )), (props.enableSharingViews ?? true) && props.item.view_level !== "default" && props.selected && !props.canUpdate && props.item.id !== "temporary" && /* @__PURE__ */ React15.createElement("div", null, /* @__PURE__ */ React15.createElement(
11388
+ )), props.item.view_level !== "default" && props.selected && !props.canUpdate && props.item.id !== "temporary" && /* @__PURE__ */ React15.createElement("div", null, /* @__PURE__ */ React15.createElement(
11389
11389
  Button2,
11390
11390
  {
11391
11391
  onClick: copyShareLink,
@@ -11433,12 +11433,199 @@ var ExpandedPanel = styled_components_esm_default(Panel)`
11433
11433
  `;
11434
11434
 
11435
11435
  // src/components/panels/PanelContent.tsx
11436
- import { Flex as Flex3, useI18nContext as useI18nContext4 } from "@procore/core-react";
11436
+ import { Flex as Flex3, useI18nContext as useI18nContext5 } from "@procore/core-react";
11437
11437
  import { useToastAlertContext as useToastAlertContext2 } from "@procore/toast-alert";
11438
11438
  import React17 from "react";
11439
11439
 
11440
+ // node_modules/@procore/core-http/dist/modern/index.js
11441
+ function getCSRFToken() {
11442
+ const token = document.cookie.match("(^|;)\\s*csrf_token\\s*=\\s*([^;]+)");
11443
+ return token ? decodeURIComponent(token.pop() || "") : "";
11444
+ }
11445
+ function getCSRFHeader() {
11446
+ const csrfToken = getCSRFToken();
11447
+ return csrfToken ? { "X-CSRF-TOKEN": csrfToken } : {};
11448
+ }
11449
+ function removeLeadingSlash(url) {
11450
+ return url.startsWith("/") ? url.substring(1, url.length) : url;
11451
+ }
11452
+ function removeTrailingSlash(url) {
11453
+ return url.endsWith("/") ? url.substring(0, url.length - 1) : url;
11454
+ }
11455
+ function applyBaseUrl(url, baseUrl) {
11456
+ return `${removeTrailingSlash(baseUrl)}/${removeLeadingSlash(url)}`;
11457
+ }
11458
+ function getOptions({ headers, ...options }) {
11459
+ const opts = {
11460
+ credentials: "same-origin",
11461
+ headers: {
11462
+ ...getCSRFHeader(),
11463
+ ...headers
11464
+ },
11465
+ mode: "same-origin",
11466
+ ...options
11467
+ };
11468
+ return opts;
11469
+ }
11470
+ function getUrl(url, baseUrl) {
11471
+ return baseUrl ? applyBaseUrl(url, baseUrl) : url;
11472
+ }
11473
+ function request(url, { baseUrl, ...options } = {}) {
11474
+ return fetch(getUrl(url, baseUrl), getOptions(options));
11475
+ }
11476
+ function requestJSON(url, requestParams = {}) {
11477
+ return request(url, requestParams).then(
11478
+ (response) => response.json()
11479
+ );
11480
+ }
11481
+
11482
+ // src/utils/api/queries.ts
11483
+ import { useQuery } from "@tanstack/react-query";
11484
+
11485
+ // src/utils/api/queriesHandler.ts
11486
+ import { useMutation, useQueryClient } from "@tanstack/react-query";
11487
+ import { useI18nContext as useI18nContext3 } from "@procore/core-react";
11488
+ var getBasePath = (companyId, projectId) => {
11489
+ if (projectId) {
11490
+ return `/rest/v2.0/companies/${companyId}/projects/${projectId}/saved_views`;
11491
+ }
11492
+ return `/rest/v2.0/companies/${companyId}/saved_views`;
11493
+ };
11494
+ var useApiRequest = (props, method, mutationKey) => {
11495
+ const { projectId, companyId, domain, tableName } = props;
11496
+ const queryClient2 = useQueryClient();
11497
+ const { locale: locale2 } = useI18nContext3();
11498
+ const basePath = getBasePath(companyId, projectId);
11499
+ const queryKeyContext = projectId ?? companyId;
11500
+ return useMutation({
11501
+ mutationKey,
11502
+ mutationFn: async (savedView) => {
11503
+ let url = "";
11504
+ if (method === "DELETE" || method === "PUT") {
11505
+ url = `${basePath}/${savedView.share_token}?permissions_domain=${domain}`;
11506
+ } else {
11507
+ url = `${basePath}?table_name=${tableName}&permissions_domain=${domain}`;
11508
+ }
11509
+ const response = await requestJSON(url, {
11510
+ method,
11511
+ body: JSON.stringify(savedView),
11512
+ headers: {
11513
+ "Content-Type": "application/json",
11514
+ "Accept-Language": locale2
11515
+ }
11516
+ });
11517
+ if (response.error) {
11518
+ throw response.error;
11519
+ }
11520
+ return response.data;
11521
+ },
11522
+ onSuccess: (savedView) => {
11523
+ if (method === "DELETE" || method === "POST") {
11524
+ queryClient2.invalidateQueries({
11525
+ queryKey: ["savedViews", domain, tableName, queryKeyContext]
11526
+ });
11527
+ return;
11528
+ } else {
11529
+ const oldData = queryClient2.getQueryData([
11530
+ "savedViews",
11531
+ domain,
11532
+ tableName,
11533
+ queryKeyContext
11534
+ ]);
11535
+ const oldView = oldData?.find(
11536
+ (item) => item.share_token === savedView.share_token
11537
+ );
11538
+ if (oldView?.name !== savedView.name) {
11539
+ queryClient2.invalidateQueries({
11540
+ queryKey: ["savedViews", domain, tableName, queryKeyContext]
11541
+ });
11542
+ return;
11543
+ }
11544
+ }
11545
+ queryClient2.setQueryData(
11546
+ ["savedViews", domain, tableName, queryKeyContext],
11547
+ (oldData) => {
11548
+ if (!oldData)
11549
+ return [savedView];
11550
+ return oldData.map(
11551
+ (item) => item.share_token === savedView.share_token ? savedView : item
11552
+ );
11553
+ }
11554
+ );
11555
+ }
11556
+ });
11557
+ };
11558
+
11440
11559
  // src/utils/constants/viewLevels.ts
11441
- var VIEW_LEVELS = ["company", "project", "personal"];
11560
+ var PROJECT_LEVEL_TOOL_VIEW_LEVELS = [
11561
+ "company",
11562
+ "project",
11563
+ "personal"
11564
+ ];
11565
+ var COMPANY_LEVEL_TOOL_VIEW_LEVELS = ["company", "personal"];
11566
+ var getViewLevels = (isProjectLevelTool) => isProjectLevelTool ? PROJECT_LEVEL_TOOL_VIEW_LEVELS : COMPANY_LEVEL_TOOL_VIEW_LEVELS;
11567
+
11568
+ // src/utils/api/queries.ts
11569
+ var PAGE_SIZE = 50 * PROJECT_LEVEL_TOOL_VIEW_LEVELS.length;
11570
+ var getBasePath2 = (companyId, projectId) => {
11571
+ if (projectId) {
11572
+ return `/rest/v2.0/companies/${companyId}/projects/${projectId}/saved_views`;
11573
+ }
11574
+ return `/rest/v2.0/companies/${companyId}/saved_views`;
11575
+ };
11576
+ var useSavedViewsQuery = (props) => {
11577
+ const { projectId, companyId, domain, tableName } = props;
11578
+ const basePath = getBasePath2(companyId, projectId);
11579
+ const url = `${basePath}?table_name=${tableName}&permissions_domain=${domain}`;
11580
+ return useQuery({
11581
+ queryKey: ["savedViews", domain, tableName, projectId ?? companyId],
11582
+ queryFn: async () => {
11583
+ const getUrl2 = `${url}&per_page=${PAGE_SIZE}`;
11584
+ const response = await requestJSON(getUrl2);
11585
+ return response.data;
11586
+ }
11587
+ });
11588
+ };
11589
+ var useSavedViewsPermissions = (props) => {
11590
+ const { projectId, companyId, domain } = props;
11591
+ const basePath = getBasePath2(companyId, projectId);
11592
+ const url = `${basePath}/permissions?permissions_domain=${domain}`;
11593
+ return useQuery({
11594
+ queryKey: ["savedViewsConfig", domain, projectId ?? companyId],
11595
+ queryFn: async () => {
11596
+ const response = await requestJSON(url);
11597
+ return response.data;
11598
+ }
11599
+ });
11600
+ };
11601
+ var useCreateSavedView = (props) => useApiRequest(props, "POST", [
11602
+ "createSavedView",
11603
+ props.domain,
11604
+ props.tableName
11605
+ ]);
11606
+ var useUpdateSavedView = (props) => useApiRequest(props, "PUT", [
11607
+ "updateSavedView",
11608
+ props.domain,
11609
+ props.tableName
11610
+ ]);
11611
+ var useDeleteSavedView = (props) => useApiRequest(props, "DELETE", [
11612
+ "deleteSavedView",
11613
+ props.domain,
11614
+ props.tableName
11615
+ ]);
11616
+ var useFetchSavedViewById = (savedViewToken, queryInput, enabled = true) => {
11617
+ const { projectId, companyId, domain } = queryInput;
11618
+ const basePath = getBasePath2(companyId, projectId);
11619
+ return useQuery({
11620
+ enabled: enabled && Boolean(savedViewToken),
11621
+ queryKey: ["savedView", savedViewToken, projectId ?? companyId],
11622
+ queryFn: async () => {
11623
+ const url = `${basePath}/${savedViewToken}?permissions_domain=${domain}`;
11624
+ const response = await requestJSON(url);
11625
+ return response.data;
11626
+ }
11627
+ });
11628
+ };
11442
11629
 
11443
11630
  // src/components/panels/PanelContentUtils.ts
11444
11631
  var import_lodash = __toESM(require_lodash());
@@ -11513,12 +11700,10 @@ var getColumnIdentifier = (col) => {
11513
11700
  };
11514
11701
  var updateTableConfig = (view, tableApi, provider) => {
11515
11702
  if (provider === "smart-grid") {
11516
- setTimeout(() => {
11517
- setSmartGridConfig(
11518
- tableApi,
11519
- view.table_config
11520
- );
11521
- }, 0);
11703
+ setSmartGridConfig(
11704
+ tableApi,
11705
+ view.table_config
11706
+ );
11522
11707
  } else {
11523
11708
  const dataTableApi = tableApi;
11524
11709
  const tableConfig = view.table_config;
@@ -11590,20 +11775,13 @@ var cleanObject = (table_config, provider) => {
11590
11775
  var normalizeForComparison = (config) => {
11591
11776
  if (!config?.columnState)
11592
11777
  return config;
11593
- const filteredColumnState = config.columnState.filter(
11594
- (col) => {
11595
- const colId = getColumnIdentifier(col);
11596
- return colId !== "drag_handle" && colId !== "ag-Grid-AutoColumn";
11597
- }
11598
- );
11599
11778
  return {
11600
- ...import_lodash.default.omit(config, ["enableRowGrouping", "enableColumnGrouping"]),
11601
- columnState: filteredColumnState.map((col) => {
11602
- const res = import_lodash.default.omit(col, ["aggFunc"]);
11779
+ ...config,
11780
+ columnState: config.columnState.map((col) => {
11603
11781
  if (col.flex) {
11604
- return import_lodash.default.omit(res, ["width", "flex"]);
11782
+ return import_lodash.default.omit(col, ["width", "flex"]);
11605
11783
  }
11606
- return res;
11784
+ return col;
11607
11785
  })
11608
11786
  };
11609
11787
  };
@@ -11616,9 +11794,10 @@ var isEqual = (viewTableConfig, tableConfig, defaultViewConfig, provider) => {
11616
11794
  );
11617
11795
  const normalizedViewConfig = normalizeForComparison(syncedViewTableConfig);
11618
11796
  const normalizedCurrentConfig = normalizeForComparison(tableConfig);
11619
- const cleanedViewConfig = cleanObject(normalizedViewConfig, provider);
11620
- const cleanedCurrentConfig = cleanObject(normalizedCurrentConfig, provider);
11621
- return import_lodash.default.isEqual(cleanedViewConfig, cleanedCurrentConfig);
11797
+ return import_lodash.default.isEqual(
11798
+ cleanObject(normalizedViewConfig, provider),
11799
+ cleanObject(normalizedCurrentConfig, provider)
11800
+ );
11622
11801
  };
11623
11802
  var hasPermissionForViewLevel = (viewLevel, permissions) => {
11624
11803
  switch (viewLevel) {
@@ -11635,9 +11814,10 @@ var hasPermissionForViewLevel = (viewLevel, permissions) => {
11635
11814
 
11636
11815
  // src/components/panels/useGroups.ts
11637
11816
  import { useState as useState2 } from "react";
11638
- var useGroups = () => {
11817
+ var useGroups = (isProjectLevelTool) => {
11818
+ const viewLevels = getViewLevels(isProjectLevelTool);
11639
11819
  const [groups, setGroups] = useState2(
11640
- Object.fromEntries(VIEW_LEVELS.map((level) => [level, true]))
11820
+ Object.fromEntries(viewLevels.map((level) => [level, true]))
11641
11821
  );
11642
11822
  const toggleGroup = (group) => {
11643
11823
  setGroups((groups2) => ({ ...groups2, [group]: !groups2[group] }));
@@ -11651,7 +11831,7 @@ import {
11651
11831
  Flex as Flex2,
11652
11832
  spacing,
11653
11833
  Typography,
11654
- useI18nContext as useI18nContext3
11834
+ useI18nContext as useI18nContext4
11655
11835
  } from "@procore/core-react";
11656
11836
  import React16 from "react";
11657
11837
  var groupIcon = (group) => {
@@ -11671,7 +11851,7 @@ var Header = styled_components_esm_default(Flex2)`
11671
11851
  }
11672
11852
  `;
11673
11853
  var ViewLevelHeader = ({ expanded, toggleGroup, group }) => {
11674
- const I18n = useI18nContext3();
11854
+ const I18n = useI18nContext4();
11675
11855
  return /* @__PURE__ */ React16.createElement(
11676
11856
  Header,
11677
11857
  {
@@ -11728,9 +11908,9 @@ var Panel2 = styled_components_esm_default(DetailPage.Card)`
11728
11908
  var PanelContent = (props) => {
11729
11909
  const { queryInput, selectedSavedView, tableConfig } = props;
11730
11910
  const { showToast } = useToastAlertContext2();
11731
- const I18n = useI18nContext4();
11732
- const { data: savedViewsFromQuery, error: savedViewsError } = props.backend.useSavedViewsQuery(props.queryInput);
11733
- const updateMutation = props.backend.useUpdateSavedView(queryInput);
11911
+ const I18n = useI18nContext5();
11912
+ const { data: savedViewsFromQuery, error: savedViewsError } = useSavedViewsQuery(props.queryInput);
11913
+ const updateMutation = useUpdateSavedView(queryInput);
11734
11914
  const { mutate: updateSavedView } = updateMutation;
11735
11915
  const isUpdateLoading = "isPending" in updateMutation ? updateMutation.isPending : updateMutation.isLoading ?? false;
11736
11916
  const savedViews = props.savedViews ?? savedViewsFromQuery;
@@ -11741,14 +11921,14 @@ var PanelContent = (props) => {
11741
11921
  errorToastRef.current = savedViewsError;
11742
11922
  }
11743
11923
  }, [savedViewsError, showToast, I18n]);
11744
- const { data: permissions } = props.backend.useSavedViewsPermissions(
11745
- props.queryInput
11746
- );
11924
+ const { data: permissions } = useSavedViewsPermissions(props.queryInput);
11747
11925
  const selectedRowRef = useScrollToRef(savedViews);
11748
- const { groups, toggleGroup } = useGroups();
11749
11926
  const isTemporarySelected = selectedSavedView?.id === "temporary";
11750
11927
  const temporaryView = savedViews?.find((view) => view.id === "temporary");
11751
11928
  const presetViews = props.presetViews || [props.defaultView];
11929
+ const isProjectLevelTool = !!queryInput.projectId;
11930
+ const viewLevels = getViewLevels(isProjectLevelTool);
11931
+ const { groups, toggleGroup } = useGroups(isProjectLevelTool);
11752
11932
  const onUpdate = (data) => {
11753
11933
  const newSavedView = {
11754
11934
  ...data,
@@ -11777,8 +11957,7 @@ var PanelContent = (props) => {
11777
11957
  {
11778
11958
  item: temporaryView,
11779
11959
  selected: isTemporarySelected,
11780
- onClearTemporary: props.onClearTemporary,
11781
- enableSharingViews: false
11960
+ onClearTemporary: props.onClearTemporary
11782
11961
  }
11783
11962
  )
11784
11963
  ), presetViews.map((presetView) => {
@@ -11795,12 +11974,11 @@ var PanelContent = (props) => {
11795
11974
  SavedViewCollectionMenuItem,
11796
11975
  {
11797
11976
  item: presetView,
11798
- selected: isSelected,
11799
- enableSharingViews: false
11977
+ selected: isSelected
11800
11978
  }
11801
11979
  )
11802
11980
  );
11803
- }), VIEW_LEVELS.map((level) => {
11981
+ }), viewLevels.map((level) => {
11804
11982
  const isExpanded = groups[level];
11805
11983
  const views = isExpanded && savedViews ? savedViews.filter(
11806
11984
  (view) => view.view_level === level && view.id !== "temporary"
@@ -11844,8 +12022,7 @@ var PanelContent = (props) => {
11844
12022
  isUpdateProcessing: isUpdateLoading,
11845
12023
  onEdit: () => props.openModal("update" /* UPDATE */),
11846
12024
  onDelete: props.onDelete,
11847
- permissions,
11848
- enableSharingViews: false
12025
+ permissions
11849
12026
  }
11850
12027
  )
11851
12028
  );
@@ -11862,7 +12039,7 @@ import {
11862
12039
  Tooltip,
11863
12040
  useI18nContext as useI18nContext11
11864
12041
  } from "@procore/core-react";
11865
- import React22, { useState as useState4, useEffect as useEffect4, useCallback as useCallback3 } from "react";
12042
+ import React22, { useState as useState4, useEffect as useEffect3, useCallback as useCallback3 } from "react";
11866
12043
  import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
11867
12044
  import { useToastAlertContext as useToastAlertContext3, ToastAlertProvider } from "@procore/toast-alert";
11868
12045
 
@@ -11872,7 +12049,7 @@ import {
11872
12049
  ConfirmModal,
11873
12050
  Modal,
11874
12051
  P as P2,
11875
- useI18nContext as useI18nContext5
12052
+ useI18nContext as useI18nContext6
11876
12053
  } from "@procore/core-react";
11877
12054
  import React18 from "react";
11878
12055
  var SavedViewsDeleteConfirmationModalShared = ({
@@ -11880,7 +12057,7 @@ var SavedViewsDeleteConfirmationModalShared = ({
11880
12057
  onDelete,
11881
12058
  open
11882
12059
  }) => {
11883
- const i18n = useI18nContext5();
12060
+ const i18n = useI18nContext6();
11884
12061
  return /* @__PURE__ */ React18.createElement(
11885
12062
  ConfirmModal,
11886
12063
  {
@@ -11911,7 +12088,7 @@ import {
11911
12088
  Modal as Modal2,
11912
12089
  spacing as spacing3,
11913
12090
  Typography as Typography2,
11914
- useI18nContext as useI18nContext6
12091
+ useI18nContext as useI18nContext7
11915
12092
  } from "@procore/core-react";
11916
12093
  import * as React19 from "react";
11917
12094
 
@@ -14208,10 +14385,11 @@ var TupleSchema = class extends Schema {
14208
14385
  create$1.prototype = TupleSchema.prototype;
14209
14386
 
14210
14387
  // src/components/modals/form-modal/FormModalBaseUtils.ts
14211
- var getViewLevelOptions = (permissions, i18n) => {
14388
+ var getViewLevelOptions = (permissions, i18n, isProjectLevelTool = true) => {
14212
14389
  const options = ["personal"];
14213
- if (permissions?.can_create_project_saved_views)
14390
+ if (isProjectLevelTool && permissions?.can_create_project_saved_views) {
14214
14391
  options.push("project");
14392
+ }
14215
14393
  if (permissions?.can_create_company_saved_views)
14216
14394
  options.push("company");
14217
14395
  return options.map((option) => ({
@@ -14241,7 +14419,6 @@ function extractMessage(error, I18n) {
14241
14419
  }
14242
14420
 
14243
14421
  // src/components/modals/form-modal/FormModalBase.tsx
14244
- var { useEffect: useEffect2, useRef: useRef2 } = React19;
14245
14422
  var ScrollContainer = styled_components_esm_default("div")`
14246
14423
  overflow: auto;
14247
14424
  `;
@@ -14258,38 +14435,22 @@ var FormModalBase = ({
14258
14435
  defaultView,
14259
14436
  selectedSavedView,
14260
14437
  setOpenEditCreateModal,
14261
- onSelect,
14262
- backend
14438
+ onSelect
14263
14439
  }) => {
14264
- const I18n = useI18nContext6();
14440
+ const I18n = useI18nContext7();
14265
14441
  const NAME_MAX_LENGTH = 150;
14266
- const originalBodyWidth = useRef2("");
14267
- useEffect2(() => {
14268
- if (open) {
14269
- originalBodyWidth.current = document.body.style.width || "";
14270
- document.body.style.width = "100%";
14271
- } else {
14272
- document.body.style.width = originalBodyWidth.current;
14273
- }
14274
- return () => {
14275
- if (originalBodyWidth.current !== void 0) {
14276
- document.body.style.width = originalBodyWidth.current;
14277
- }
14278
- };
14279
- }, [open]);
14280
- const { useCreateSavedView: useCreateSavedView2, useUpdateSavedView: useUpdateSavedView2, useSavedViewsPermissions: useSavedViewsPermissions2 } = backend;
14281
14442
  const {
14282
14443
  mutate: createSavedView,
14283
14444
  isPending: isCreating,
14284
14445
  error: createError,
14285
14446
  reset: resetCreateMutation
14286
- } = useCreateSavedView2(queryInput);
14447
+ } = useCreateSavedView(queryInput);
14287
14448
  const {
14288
14449
  mutate: updateSavedView,
14289
14450
  isPending: isUpdating,
14290
14451
  error: updateError,
14291
14452
  reset: resetUpdateMutation
14292
- } = useUpdateSavedView2(queryInput);
14453
+ } = useUpdateSavedView(queryInput);
14293
14454
  const resetMutations = () => {
14294
14455
  resetCreateMutation();
14295
14456
  resetUpdateMutation();
@@ -14298,7 +14459,7 @@ var FormModalBase = ({
14298
14459
  resetMutations();
14299
14460
  onCancel();
14300
14461
  };
14301
- const { data: permissions } = useSavedViewsPermissions2(queryInput);
14462
+ const { data: permissions } = useSavedViewsPermissions(queryInput);
14302
14463
  const isLoading = isCreating || isUpdating;
14303
14464
  const errors = extractMessage(createError || updateError, I18n);
14304
14465
  const handleOnSubmit = (data) => {
@@ -14329,7 +14490,12 @@ var FormModalBase = ({
14329
14490
  });
14330
14491
  }
14331
14492
  };
14332
- const viewLevelOptions = getViewLevelOptions(permissions, I18n);
14493
+ const isProjectLevelTool = !!queryInput.projectId;
14494
+ const viewLevelOptions = getViewLevelOptions(
14495
+ permissions,
14496
+ I18n,
14497
+ isProjectLevelTool
14498
+ );
14333
14499
  return /* @__PURE__ */ React19.createElement(
14334
14500
  Modal2,
14335
14501
  {
@@ -14409,7 +14575,6 @@ var FormModalBase = ({
14409
14575
  Form.Select,
14410
14576
  {
14411
14577
  name: "view_level",
14412
- qa: { label: "view-level" },
14413
14578
  options: viewLevelOptions,
14414
14579
  label: I18n.t("savedViews.modal.fields.viewLevel"),
14415
14580
  colWidth: 12,
@@ -14433,7 +14598,7 @@ var FormModalBase = ({
14433
14598
  };
14434
14599
 
14435
14600
  // src/components/modals/form-modal/FormModal.tsx
14436
- import { useI18nContext as useI18nContext7 } from "@procore/core-react";
14601
+ import { useI18nContext as useI18nContext8 } from "@procore/core-react";
14437
14602
  var FormModal = ({
14438
14603
  open,
14439
14604
  mode,
@@ -14444,10 +14609,9 @@ var FormModal = ({
14444
14609
  selectedSavedView,
14445
14610
  setOpenEditCreateModal,
14446
14611
  onSelect,
14447
- defaultView,
14448
- backend
14612
+ defaultView
14449
14613
  }) => {
14450
- const i18n = useI18nContext7();
14614
+ const i18n = useI18nContext8();
14451
14615
  return /* @__PURE__ */ React20.createElement(
14452
14616
  FormModalBase,
14453
14617
  {
@@ -14463,8 +14627,7 @@ var FormModal = ({
14463
14627
  selectedSavedView,
14464
14628
  setOpenEditCreateModal,
14465
14629
  onSelect,
14466
- defaultView,
14467
- backend
14630
+ defaultView
14468
14631
  }
14469
14632
  );
14470
14633
  };
@@ -14481,7 +14644,7 @@ import {
14481
14644
  P as P3,
14482
14645
  spacing as spacing4,
14483
14646
  Typography as Typography3,
14484
- useI18nContext as useI18nContext8
14647
+ useI18nContext as useI18nContext9
14485
14648
  } from "@procore/core-react";
14486
14649
  import * as React21 from "react";
14487
14650
  var SharedViewFormModal = ({
@@ -14494,7 +14657,7 @@ var SharedViewFormModal = ({
14494
14657
  isCreating,
14495
14658
  resetCreateError
14496
14659
  }) => {
14497
- const I18n = useI18nContext8();
14660
+ const I18n = useI18nContext9();
14498
14661
  const NAME_MAX_LENGTH = 150;
14499
14662
  const errors = extractMessage(createError, I18n);
14500
14663
  const handleNameChange = () => {
@@ -14624,9 +14787,9 @@ var SharedViewFormModal = ({
14624
14787
  };
14625
14788
 
14626
14789
  // src/utils/hooks/useViewSelection.ts
14627
- import { useState as useState3, useCallback as useCallback2, useEffect as useEffect3, useRef as useRef3, useMemo } from "react";
14790
+ import { useState as useState3, useCallback as useCallback2, useEffect as useEffect2, useRef as useRef2, useMemo } from "react";
14628
14791
  import { useSearchParams } from "react-router-dom";
14629
- import { useI18nContext as useI18nContext9 } from "@procore/core-react";
14792
+ import { useI18nContext as useI18nContext10 } from "@procore/core-react";
14630
14793
 
14631
14794
  // src/utils/viewStorage.ts
14632
14795
  var ViewStorage = {
@@ -14689,11 +14852,12 @@ var restoreUrlParameter = (currentParam, previousParam, setSearchParams) => {
14689
14852
  }
14690
14853
  };
14691
14854
  var useViewSelection = (config, savedViews, presetViews, openSharedViewModal) => {
14692
- const I18n = useI18nContext9();
14693
- const storageKey = `savedView_${config.domain}_${config.tableName}_${config.companyId}_${config.projectId}_${config.userId}`;
14855
+ const I18n = useI18nContext10();
14856
+ const projectIdSegment = config.projectId ?? "company";
14857
+ const storageKey = `savedView_${config.domain}_${config.tableName}_${config.companyId}_${projectIdSegment}_${config.userId}`;
14694
14858
  const temporaryStorageKey = `${storageKey}-temporary`;
14695
14859
  const [searchParams, setSearchParams] = useSearchParams();
14696
- const previousSavedViewParamRef = useRef3(null);
14860
+ const previousSavedViewParamRef = useRef2(null);
14697
14861
  const [selectedSavedView, setSelectedSavedView] = useState3(() => {
14698
14862
  const stored = ViewStorage.load(storageKey, config.defaultView);
14699
14863
  return stored ?? config.defaultView;
@@ -14764,7 +14928,7 @@ var useViewSelection = (config, savedViews, presetViews, openSharedViewModal) =>
14764
14928
  },
14765
14929
  [isViewAlreadySelected, openSharedViewModal, allViews, selectView]
14766
14930
  );
14767
- useEffect3(() => {
14931
+ useEffect2(() => {
14768
14932
  const savedViewId = searchParams.get("saved-view");
14769
14933
  restoreUrlParameter(
14770
14934
  savedViewId,
@@ -14788,177 +14952,6 @@ var useViewSelection = (config, savedViews, presetViews, openSharedViewModal) =>
14788
14952
  };
14789
14953
  };
14790
14954
 
14791
- // node_modules/@procore/core-http/dist/modern/index.js
14792
- function getCSRFToken() {
14793
- const token = document.cookie.match("(^|;)\\s*csrf_token\\s*=\\s*([^;]+)");
14794
- return token ? decodeURIComponent(token.pop() || "") : "";
14795
- }
14796
- function getCSRFHeader() {
14797
- const csrfToken = getCSRFToken();
14798
- return csrfToken ? { "X-CSRF-TOKEN": csrfToken } : {};
14799
- }
14800
- function removeLeadingSlash(url) {
14801
- return url.startsWith("/") ? url.substring(1, url.length) : url;
14802
- }
14803
- function removeTrailingSlash(url) {
14804
- return url.endsWith("/") ? url.substring(0, url.length - 1) : url;
14805
- }
14806
- function applyBaseUrl(url, baseUrl) {
14807
- return `${removeTrailingSlash(baseUrl)}/${removeLeadingSlash(url)}`;
14808
- }
14809
- function getOptions({ headers, ...options }) {
14810
- const opts = {
14811
- credentials: "same-origin",
14812
- headers: {
14813
- ...getCSRFHeader(),
14814
- ...headers
14815
- },
14816
- mode: "same-origin",
14817
- ...options
14818
- };
14819
- return opts;
14820
- }
14821
- function getUrl(url, baseUrl) {
14822
- return baseUrl ? applyBaseUrl(url, baseUrl) : url;
14823
- }
14824
- function request(url, { baseUrl, ...options } = {}) {
14825
- return fetch(getUrl(url, baseUrl), getOptions(options));
14826
- }
14827
- function requestJSON(url, requestParams = {}) {
14828
- return request(url, requestParams).then(
14829
- (response) => response.json()
14830
- );
14831
- }
14832
-
14833
- // src/utils/api/queries.ts
14834
- import { useQuery } from "@tanstack/react-query";
14835
-
14836
- // src/utils/api/queriesHandler.ts
14837
- import { useMutation, useQueryClient } from "@tanstack/react-query";
14838
- import { useI18nContext as useI18nContext10 } from "@procore/core-react";
14839
- var useApiRequest = (props, method, mutationKey) => {
14840
- const { projectId, companyId, domain, tableName } = props;
14841
- const queryClient2 = useQueryClient();
14842
- const { locale: locale2 } = useI18nContext10();
14843
- return useMutation({
14844
- mutationKey,
14845
- mutationFn: async (savedView) => {
14846
- let url = "";
14847
- if (method === "DELETE" || method === "PUT") {
14848
- url = `/rest/v2.0/companies/${companyId}/projects/${projectId}/saved_views/${savedView.share_token}?permissions_domain=${domain}`;
14849
- } else {
14850
- url = `/rest/v2.0/companies/${companyId}/projects/${projectId}/saved_views?table_name=${tableName}&permissions_domain=${domain}`;
14851
- }
14852
- const response = await requestJSON(url, {
14853
- method,
14854
- body: JSON.stringify(savedView),
14855
- headers: {
14856
- "Content-Type": "application/json",
14857
- "Accept-Language": locale2
14858
- }
14859
- });
14860
- if (response.error) {
14861
- throw response.error;
14862
- }
14863
- return response.data;
14864
- },
14865
- onSuccess: (savedView) => {
14866
- if (method === "DELETE" || method === "POST") {
14867
- queryClient2.invalidateQueries({
14868
- queryKey: ["savedViews", domain, tableName]
14869
- });
14870
- return;
14871
- } else {
14872
- const oldData = queryClient2.getQueryData([
14873
- "savedViews",
14874
- domain,
14875
- tableName
14876
- ]);
14877
- const oldView = oldData?.find(
14878
- (item) => item.share_token === savedView.share_token
14879
- );
14880
- if (oldView?.name !== savedView.name) {
14881
- queryClient2.invalidateQueries({
14882
- queryKey: ["savedViews", domain, tableName]
14883
- });
14884
- return;
14885
- }
14886
- }
14887
- queryClient2.setQueryData(
14888
- ["savedViews", domain, tableName],
14889
- (oldData) => {
14890
- if (!oldData)
14891
- return [savedView];
14892
- return oldData.map(
14893
- (item) => item.share_token === savedView.share_token ? savedView : item
14894
- );
14895
- }
14896
- );
14897
- }
14898
- });
14899
- };
14900
-
14901
- // src/utils/api/queries.ts
14902
- var PAGE_SIZE = 50 * VIEW_LEVELS.length;
14903
- var useSavedViewsQuery = (props) => {
14904
- const { projectId, companyId, domain, tableName } = props;
14905
- const url = `/rest/v2.0/companies/${companyId}/projects/${projectId}/saved_views?table_name=${tableName}&permissions_domain=${domain}`;
14906
- return useQuery({
14907
- queryKey: ["savedViews", domain, tableName],
14908
- queryFn: async () => {
14909
- const getUrl2 = `${url}&per_page=${PAGE_SIZE}`;
14910
- const response = await requestJSON(getUrl2);
14911
- return response.data;
14912
- }
14913
- });
14914
- };
14915
- var useSavedViewsPermissions = (props) => {
14916
- const { projectId, companyId, domain } = props;
14917
- const url = `/rest/v2.0/companies/${companyId}/projects/${projectId}/saved_views/permissions?permissions_domain=${domain}`;
14918
- return useQuery({
14919
- queryKey: ["savedViewsConfig", domain],
14920
- queryFn: async () => {
14921
- const response = await requestJSON(url);
14922
- return response.data;
14923
- }
14924
- });
14925
- };
14926
- var useCreateSavedView = (props) => useApiRequest(props, "POST", [
14927
- "createSavedView",
14928
- props.domain,
14929
- props.tableName
14930
- ]);
14931
- var useUpdateSavedView = (props) => useApiRequest(props, "PUT", [
14932
- "updateSavedView",
14933
- props.domain,
14934
- props.tableName
14935
- ]);
14936
- var useDeleteSavedView = (props) => useApiRequest(props, "DELETE", [
14937
- "deleteSavedView",
14938
- props.domain,
14939
- props.tableName
14940
- ]);
14941
- var useFetchSavedViewById = (savedViewToken, queryInput, enabled = true) => {
14942
- const { projectId, companyId } = queryInput;
14943
- return useQuery({
14944
- enabled: enabled && Boolean(savedViewToken),
14945
- queryKey: ["savedView", savedViewToken],
14946
- queryFn: async () => {
14947
- const url = `/rest/v2.0/companies/${companyId}/projects/${projectId}/saved_views/${savedViewToken}`;
14948
- const response = await requestJSON(url);
14949
- return response.data;
14950
- }
14951
- });
14952
- };
14953
- var createQueries = (customBackend) => ({
14954
- useSavedViewsQuery: customBackend?.useSavedViewsQuery ?? useSavedViewsQuery,
14955
- useSavedViewsPermissions: customBackend?.useSavedViewsPermissions ?? useSavedViewsPermissions,
14956
- useCreateSavedView: customBackend?.useCreateSavedView ?? useCreateSavedView,
14957
- useUpdateSavedView: customBackend?.useUpdateSavedView ?? useUpdateSavedView,
14958
- useDeleteSavedView: customBackend?.useDeleteSavedView ?? useDeleteSavedView,
14959
- useFetchSavedViewById: customBackend?.useFetchSavedViewById ?? useFetchSavedViewById
14960
- });
14961
-
14962
14955
  // src/components/saved-views/SavedViews.tsx
14963
14956
  var StyledPanel = styled_components_esm_default.div`
14964
14957
  border: ${({ provider }) => provider === "data-table" ? "1px solid #d6dadc" : "none"};
@@ -14966,15 +14959,14 @@ var StyledPanel = styled_components_esm_default.div`
14966
14959
  var queryClient = new QueryClient();
14967
14960
  var SavedViewsContent = (props) => {
14968
14961
  const { projectId, companyId } = props;
14969
- const backend = createQueries(props.backend);
14970
14962
  const queryInput = {
14971
14963
  domain: props.domain,
14972
14964
  tableName: props.tableName,
14973
- projectId,
14965
+ projectId: projectId ?? void 0,
14974
14966
  companyId
14975
14967
  };
14976
- const { data: savedViews } = backend.useSavedViewsQuery(queryInput);
14977
- const { mutate: deleteSavedView } = backend.useDeleteSavedView(queryInput);
14968
+ const { data: savedViews } = useSavedViewsQuery(queryInput);
14969
+ const { mutate: deleteSavedView } = useDeleteSavedView(queryInput);
14978
14970
  const { showToast } = useToastAlertContext3();
14979
14971
  const i18n = useI18nContext11();
14980
14972
  const [activeModal, setActiveModal] = useState4(null);
@@ -15002,7 +14994,7 @@ var SavedViewsContent = (props) => {
15002
14994
  domain: props.domain,
15003
14995
  tableName: props.tableName,
15004
14996
  userId: props.userId,
15005
- projectId,
14997
+ projectId: projectId ?? void 0,
15006
14998
  companyId,
15007
14999
  defaultView: props.defaultView,
15008
15000
  onSelect: props.onSelect
@@ -15011,7 +15003,7 @@ var SavedViewsContent = (props) => {
15011
15003
  props.presetViews,
15012
15004
  openSharedViewModal
15013
15005
  );
15014
- const { data: fetchedView, isError: fetchError } = backend.useFetchSavedViewById(
15006
+ const { data: fetchedView, isError: fetchError } = useFetchSavedViewById(
15015
15007
  modalData?.viewId ?? null,
15016
15008
  queryInput,
15017
15009
  Boolean(modalData?.viewId)
@@ -15021,8 +15013,8 @@ var SavedViewsContent = (props) => {
15021
15013
  isPending: isCreating,
15022
15014
  error: createError,
15023
15015
  reset: resetCreateError
15024
- } = backend.useCreateSavedView(queryInput);
15025
- useEffect4(() => {
15016
+ } = useCreateSavedView(queryInput);
15017
+ useEffect3(() => {
15026
15018
  if (fetchError) {
15027
15019
  showToast.error(i18n.t("savedViews.errors.notFound"));
15028
15020
  selectView(selectedView ?? props.defaultView);
@@ -15108,8 +15100,7 @@ var SavedViewsContent = (props) => {
15108
15100
  savedViews: allViews,
15109
15101
  provider: props.provider,
15110
15102
  userId: props.userId,
15111
- onClearTemporary: clearTemporaryView,
15112
- backend
15103
+ onClearTemporary: clearTemporaryView
15113
15104
  }
15114
15105
  ))
15115
15106
  ), (isModalOpen("create" /* CREATE */) || isModalOpen("update" /* UPDATE */)) && /* @__PURE__ */ React22.createElement(
@@ -15124,8 +15115,7 @@ var SavedViewsContent = (props) => {
15124
15115
  selectedSavedView: selectedView,
15125
15116
  onSelect: selectView,
15126
15117
  setOpenEditCreateModal: closeModal,
15127
- defaultView: props.defaultView,
15128
- backend
15118
+ defaultView: props.defaultView
15129
15119
  }
15130
15120
  ), selectedView && isModalOpen("delete" /* DELETE */) && /* @__PURE__ */ React22.createElement(
15131
15121
  SavedViewsDeleteConfirmationModalShared,
@@ -15170,37 +15160,27 @@ var DEFAULT_COLUMN_STATE = {
15170
15160
  rowGroupIndex: null,
15171
15161
  flex: null
15172
15162
  };
15173
- var isColGroupDef = (colDef) => {
15174
- return "children" in colDef && Array.isArray(colDef.children);
15175
- };
15163
+ var flattenColumnDefs = (defs) => defs.flatMap((d) => "children" in d ? flattenColumnDefs(d.children) : [d]);
15176
15164
  var getColumnStateFromDefs = (columnDefs) => {
15177
- return columnDefs.flatMap((colDef) => {
15178
- if (isColGroupDef(colDef)) {
15179
- return getColumnStateFromDefs(colDef.children);
15180
- }
15181
- return getColumnStateFromSingleDef(colDef);
15182
- }).filter(
15183
- (col) => col !== null
15184
- );
15185
- };
15186
- var getColumnStateFromSingleDef = (colDef) => {
15187
- const field = colDef.field ?? colDef.colId;
15188
- if (!field)
15189
- return null;
15190
- return {
15191
- colId: field,
15192
- hide: colDef.hide ?? false,
15193
- pinned: colDef.pinned ?? null,
15194
- width: colDef.width ?? colDef.minWidth ?? DEFAULT_COLUMN_STATE.width,
15195
- sort: null,
15196
- sortIndex: null,
15197
- pivot: false,
15198
- pivotIndex: null,
15199
- aggFunc: null,
15200
- rowGroup: false,
15201
- rowGroupIndex: null,
15202
- flex: colDef.flex ?? null
15203
- };
15165
+ return flattenColumnDefs(columnDefs).map((colDef) => {
15166
+ const field = colDef.field ?? colDef.colId;
15167
+ if (!field)
15168
+ return null;
15169
+ return {
15170
+ colId: field,
15171
+ hide: colDef.hide ?? false,
15172
+ pinned: colDef.pinned ?? null,
15173
+ width: colDef.width ?? colDef.minWidth ?? DEFAULT_COLUMN_STATE.width,
15174
+ sort: null,
15175
+ sortIndex: null,
15176
+ pivot: false,
15177
+ pivotIndex: null,
15178
+ aggFunc: null,
15179
+ rowGroup: false,
15180
+ rowGroupIndex: null,
15181
+ flex: colDef.flex ?? null
15182
+ };
15183
+ }).filter((col) => col !== null);
15204
15184
  };
15205
15185
  var extractDefaultView = (gridApi, receivedConfig) => {
15206
15186
  const columnDefs = gridApi.getColumnDefs() ?? [];
@@ -15227,7 +15207,7 @@ var useNormalizedDefaultViews = (defaultViews, gridApi) => {
15227
15207
  };
15228
15208
 
15229
15209
  // src/components/adapters/smart-grid/useSmartGridConfig.ts
15230
- import { useState as useState5, useEffect as useEffect5, useRef as useRef4 } from "react";
15210
+ import { useState as useState5, useEffect as useEffect4 } from "react";
15231
15211
  var GRID_STATE_EVENTS = [
15232
15212
  "sortChanged",
15233
15213
  "filterOpened",
@@ -15246,14 +15226,10 @@ var useSmartGridConfig = (gridApi) => {
15246
15226
  const [config, setConfig] = useState5(
15247
15227
  () => getSmartGridConfig(gridApi)
15248
15228
  );
15249
- const eventListenersDisabledRef = useRef4(false);
15250
- useEffect5(() => {
15229
+ useEffect4(() => {
15251
15230
  if (!gridApi)
15252
15231
  return;
15253
15232
  const updateConfig = () => {
15254
- if (eventListenersDisabledRef.current) {
15255
- return;
15256
- }
15257
15233
  setConfig(getSmartGridConfig(gridApi));
15258
15234
  };
15259
15235
  GRID_STATE_EVENTS.forEach((event) => {
@@ -15265,13 +15241,7 @@ var useSmartGridConfig = (gridApi) => {
15265
15241
  });
15266
15242
  };
15267
15243
  }, [gridApi]);
15268
- const disableEventListeners = () => {
15269
- eventListenersDisabledRef.current = true;
15270
- };
15271
- const enableEventListeners = () => {
15272
- eventListenersDisabledRef.current = false;
15273
- };
15274
- return { config, setConfig, disableEventListeners, enableEventListeners };
15244
+ return { config, setConfig };
15275
15245
  };
15276
15246
 
15277
15247
  // src/components/adapters/smart-grid/SmartGridSavedViews.tsx
@@ -15285,17 +15255,15 @@ var SmartGridSavedViews = (props) => {
15285
15255
  if (!gridApi)
15286
15256
  return item;
15287
15257
  const isPresetView = item.view_level === "default";
15288
- const newConfig = item.table_config;
15289
- const transformedConfig = props.transformSettings?.(newConfig) ?? newConfig;
15290
15258
  if (isPresetView) {
15291
15259
  updateTableConfig(item, gridApi, "smart-grid");
15292
- setTableConfig(transformedConfig);
15260
+ setTableConfig(item.table_config);
15293
15261
  return item;
15294
15262
  }
15295
15263
  const updatedView = {
15296
15264
  ...item,
15297
15265
  table_config: customAndConfigSync(
15298
- transformedConfig,
15266
+ item.table_config,
15299
15267
  tableConfig
15300
15268
  )
15301
15269
  };
@@ -15317,8 +15285,7 @@ var SmartGridSavedViews = (props) => {
15317
15285
  defaultView,
15318
15286
  presetViews,
15319
15287
  tableName: props.tableName,
15320
- tableConfig,
15321
- backend: props.backend
15288
+ tableConfig
15322
15289
  }
15323
15290
  );
15324
15291
  };