@payloadcms/plugin-multi-tenant 3.44.0 → 3.45.0-canary.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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.client.d.ts","sourceRoot":"","sources":["../../../src/components/TenantField/index.client.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,SAAS,CAAA;AAG3D,OAAO,KAAK,MAAM,OAAO,CAAA;AAGzB,OAAO,cAAc,CAAA;AAIrB,KAAK,KAAK,GAAG;IACX,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB,GAAG,4BAA4B,CAAA;AAEhC,eAAO,MAAM,WAAW,SAAU,KAAK,6BA6CtC,CAAA"}
1
+ {"version":3,"file":"index.client.d.ts","sourceRoot":"","sources":["../../../src/components/TenantField/index.client.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,SAAS,CAAA;AAG3D,OAAO,KAAK,MAAM,OAAO,CAAA;AAGzB,OAAO,cAAc,CAAA;AAIrB,KAAK,KAAK,GAAG;IACX,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB,GAAG,4BAA4B,CAAA;AAEhC,eAAO,MAAM,WAAW,SAAU,KAAK,6BA2DtC,CAAA"}
@@ -1,6 +1,6 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { RelationshipField, useField } from '@payloadcms/ui';
3
+ import { RelationshipField, useField, useFormModified } from '@payloadcms/ui';
4
4
  import React from 'react';
5
5
  import { useTenantSelection } from '../../providers/TenantSelectionProvider/index.client.js';
6
6
  import './index.scss';
@@ -8,7 +8,8 @@ const baseClass = 'tenantField';
8
8
  export const TenantField = (args)=>{
9
9
  const { debug, unique } = args;
10
10
  const { setValue, value } = useField();
11
- const { options, selectedTenantID, setPreventRefreshOnChange, setTenant } = useTenantSelection();
11
+ const modified = useFormModified();
12
+ const { options, selectedTenantID, setEntityType: setEntityType, setModified, setTenant } = useTenantSelection();
12
13
  const hasSetValueRef = React.useRef(false);
13
14
  React.useEffect(()=>{
14
15
  if (!hasSetValueRef.current) {
@@ -29,7 +30,7 @@ export const TenantField = (args)=>{
29
30
  hasSetValueRef.current = true;
30
31
  } else if (!value || value !== selectedTenantID) {
31
32
  // Update the field on the document value when the tenant is changed
32
- setValue(selectedTenantID);
33
+ setValue(selectedTenantID, !value || value === selectedTenantID);
33
34
  }
34
35
  }, [
35
36
  value,
@@ -40,15 +41,23 @@ export const TenantField = (args)=>{
40
41
  unique
41
42
  ]);
42
43
  React.useEffect(()=>{
43
- if (!unique) {
44
- setPreventRefreshOnChange(true);
45
- }
44
+ setEntityType(unique ? 'global' : 'document');
46
45
  return ()=>{
47
- setPreventRefreshOnChange(false);
46
+ setEntityType(undefined);
48
47
  };
49
48
  }, [
50
49
  unique,
51
- setPreventRefreshOnChange
50
+ setEntityType
51
+ ]);
52
+ React.useEffect(()=>{
53
+ // sync form modified state with the tenant selection provider context
54
+ setModified(modified);
55
+ return ()=>{
56
+ setModified(false);
57
+ };
58
+ }, [
59
+ modified,
60
+ setModified
52
61
  ]);
53
62
  if (debug) {
54
63
  return /*#__PURE__*/ _jsxs("div", {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/TenantField/index.client.tsx"],"sourcesContent":["'use client'\n\nimport type { RelationshipFieldClientProps } from 'payload'\n\nimport { RelationshipField, useField } from '@payloadcms/ui'\nimport React from 'react'\n\nimport { useTenantSelection } from '../../providers/TenantSelectionProvider/index.client.js'\nimport './index.scss'\n\nconst baseClass = 'tenantField'\n\ntype Props = {\n debug?: boolean\n unique?: boolean\n} & RelationshipFieldClientProps\n\nexport const TenantField = (args: Props) => {\n const { debug, unique } = args\n const { setValue, value } = useField<number | string>()\n const { options, selectedTenantID, setPreventRefreshOnChange, setTenant } = useTenantSelection()\n\n const hasSetValueRef = React.useRef(false)\n\n React.useEffect(() => {\n if (!hasSetValueRef.current) {\n // set value on load\n if (value && value !== selectedTenantID) {\n setTenant({ id: value, refresh: unique })\n } else {\n // in the document view, the tenant field should always have a value\n const defaultValue = selectedTenantID || options[0]?.value\n setTenant({ id: defaultValue, refresh: unique })\n }\n hasSetValueRef.current = true\n } else if (!value || value !== selectedTenantID) {\n // Update the field on the document value when the tenant is changed\n setValue(selectedTenantID)\n }\n }, [value, selectedTenantID, setTenant, setValue, options, unique])\n\n React.useEffect(() => {\n if (!unique) {\n setPreventRefreshOnChange(true)\n }\n return () => {\n setPreventRefreshOnChange(false)\n }\n }, [unique, setPreventRefreshOnChange])\n\n if (debug) {\n return (\n <div className={baseClass}>\n <div className={`${baseClass}__wrapper`}>\n <RelationshipField {...args} />\n </div>\n <div className={`${baseClass}__hr`} />\n </div>\n )\n }\n\n return null\n}\n"],"names":["RelationshipField","useField","React","useTenantSelection","baseClass","TenantField","args","debug","unique","setValue","value","options","selectedTenantID","setPreventRefreshOnChange","setTenant","hasSetValueRef","useRef","useEffect","current","id","refresh","defaultValue","div","className"],"mappings":"AAAA;;AAIA,SAASA,iBAAiB,EAAEC,QAAQ,QAAQ,iBAAgB;AAC5D,OAAOC,WAAW,QAAO;AAEzB,SAASC,kBAAkB,QAAQ,0DAAyD;AAC5F,OAAO,eAAc;AAErB,MAAMC,YAAY;AAOlB,OAAO,MAAMC,cAAc,CAACC;IAC1B,MAAM,EAAEC,KAAK,EAAEC,MAAM,EAAE,GAAGF;IAC1B,MAAM,EAAEG,QAAQ,EAAEC,KAAK,EAAE,GAAGT;IAC5B,MAAM,EAAEU,OAAO,EAAEC,gBAAgB,EAAEC,yBAAyB,EAAEC,SAAS,EAAE,GAAGX;IAE5E,MAAMY,iBAAiBb,MAAMc,MAAM,CAAC;IAEpCd,MAAMe,SAAS,CAAC;QACd,IAAI,CAACF,eAAeG,OAAO,EAAE;YAC3B,oBAAoB;YACpB,IAAIR,SAASA,UAAUE,kBAAkB;gBACvCE,UAAU;oBAAEK,IAAIT;oBAAOU,SAASZ;gBAAO;YACzC,OAAO;gBACL,oEAAoE;gBACpE,MAAMa,eAAeT,oBAAoBD,OAAO,CAAC,EAAE,EAAED;gBACrDI,UAAU;oBAAEK,IAAIE;oBAAcD,SAASZ;gBAAO;YAChD;YACAO,eAAeG,OAAO,GAAG;QAC3B,OAAO,IAAI,CAACR,SAASA,UAAUE,kBAAkB;YAC/C,oEAAoE;YACpEH,SAASG;QACX;IACF,GAAG;QAACF;QAAOE;QAAkBE;QAAWL;QAAUE;QAASH;KAAO;IAElEN,MAAMe,SAAS,CAAC;QACd,IAAI,CAACT,QAAQ;YACXK,0BAA0B;QAC5B;QACA,OAAO;YACLA,0BAA0B;QAC5B;IACF,GAAG;QAACL;QAAQK;KAA0B;IAEtC,IAAIN,OAAO;QACT,qBACE,MAACe;YAAIC,WAAWnB;;8BACd,KAACkB;oBAAIC,WAAW,GAAGnB,UAAU,SAAS,CAAC;8BACrC,cAAA,KAACJ;wBAAmB,GAAGM,IAAI;;;8BAE7B,KAACgB;oBAAIC,WAAW,GAAGnB,UAAU,IAAI,CAAC;;;;IAGxC;IAEA,OAAO;AACT,EAAC"}
1
+ {"version":3,"sources":["../../../src/components/TenantField/index.client.tsx"],"sourcesContent":["'use client'\n\nimport type { RelationshipFieldClientProps } from 'payload'\n\nimport { RelationshipField, useField, useFormModified } from '@payloadcms/ui'\nimport React from 'react'\n\nimport { useTenantSelection } from '../../providers/TenantSelectionProvider/index.client.js'\nimport './index.scss'\n\nconst baseClass = 'tenantField'\n\ntype Props = {\n debug?: boolean\n unique?: boolean\n} & RelationshipFieldClientProps\n\nexport const TenantField = (args: Props) => {\n const { debug, unique } = args\n const { setValue, value } = useField<number | string>()\n const modified = useFormModified()\n const {\n options,\n selectedTenantID,\n setEntityType: setEntityType,\n setModified,\n setTenant,\n } = useTenantSelection()\n\n const hasSetValueRef = React.useRef(false)\n\n React.useEffect(() => {\n if (!hasSetValueRef.current) {\n // set value on load\n if (value && value !== selectedTenantID) {\n setTenant({ id: value, refresh: unique })\n } else {\n // in the document view, the tenant field should always have a value\n const defaultValue = selectedTenantID || options[0]?.value\n setTenant({ id: defaultValue, refresh: unique })\n }\n hasSetValueRef.current = true\n } else if (!value || value !== selectedTenantID) {\n // Update the field on the document value when the tenant is changed\n setValue(selectedTenantID, !value || value === selectedTenantID)\n }\n }, [value, selectedTenantID, setTenant, setValue, options, unique])\n\n React.useEffect(() => {\n setEntityType(unique ? 'global' : 'document')\n return () => {\n setEntityType(undefined)\n }\n }, [unique, setEntityType])\n\n React.useEffect(() => {\n // sync form modified state with the tenant selection provider context\n setModified(modified)\n\n return () => {\n setModified(false)\n }\n }, [modified, setModified])\n\n if (debug) {\n return (\n <div className={baseClass}>\n <div className={`${baseClass}__wrapper`}>\n <RelationshipField {...args} />\n </div>\n <div className={`${baseClass}__hr`} />\n </div>\n )\n }\n\n return null\n}\n"],"names":["RelationshipField","useField","useFormModified","React","useTenantSelection","baseClass","TenantField","args","debug","unique","setValue","value","modified","options","selectedTenantID","setEntityType","setModified","setTenant","hasSetValueRef","useRef","useEffect","current","id","refresh","defaultValue","undefined","div","className"],"mappings":"AAAA;;AAIA,SAASA,iBAAiB,EAAEC,QAAQ,EAAEC,eAAe,QAAQ,iBAAgB;AAC7E,OAAOC,WAAW,QAAO;AAEzB,SAASC,kBAAkB,QAAQ,0DAAyD;AAC5F,OAAO,eAAc;AAErB,MAAMC,YAAY;AAOlB,OAAO,MAAMC,cAAc,CAACC;IAC1B,MAAM,EAAEC,KAAK,EAAEC,MAAM,EAAE,GAAGF;IAC1B,MAAM,EAAEG,QAAQ,EAAEC,KAAK,EAAE,GAAGV;IAC5B,MAAMW,WAAWV;IACjB,MAAM,EACJW,OAAO,EACPC,gBAAgB,EAChBC,eAAeA,aAAa,EAC5BC,WAAW,EACXC,SAAS,EACV,GAAGb;IAEJ,MAAMc,iBAAiBf,MAAMgB,MAAM,CAAC;IAEpChB,MAAMiB,SAAS,CAAC;QACd,IAAI,CAACF,eAAeG,OAAO,EAAE;YAC3B,oBAAoB;YACpB,IAAIV,SAASA,UAAUG,kBAAkB;gBACvCG,UAAU;oBAAEK,IAAIX;oBAAOY,SAASd;gBAAO;YACzC,OAAO;gBACL,oEAAoE;gBACpE,MAAMe,eAAeV,oBAAoBD,OAAO,CAAC,EAAE,EAAEF;gBACrDM,UAAU;oBAAEK,IAAIE;oBAAcD,SAASd;gBAAO;YAChD;YACAS,eAAeG,OAAO,GAAG;QAC3B,OAAO,IAAI,CAACV,SAASA,UAAUG,kBAAkB;YAC/C,oEAAoE;YACpEJ,SAASI,kBAAkB,CAACH,SAASA,UAAUG;QACjD;IACF,GAAG;QAACH;QAAOG;QAAkBG;QAAWP;QAAUG;QAASJ;KAAO;IAElEN,MAAMiB,SAAS,CAAC;QACdL,cAAcN,SAAS,WAAW;QAClC,OAAO;YACLM,cAAcU;QAChB;IACF,GAAG;QAAChB;QAAQM;KAAc;IAE1BZ,MAAMiB,SAAS,CAAC;QACd,sEAAsE;QACtEJ,YAAYJ;QAEZ,OAAO;YACLI,YAAY;QACd;IACF,GAAG;QAACJ;QAAUI;KAAY;IAE1B,IAAIR,OAAO;QACT,qBACE,MAACkB;YAAIC,WAAWtB;;8BACd,KAACqB;oBAAIC,WAAW,GAAGtB,UAAU,SAAS,CAAC;8BACrC,cAAA,KAACL;wBAAmB,GAAGO,IAAI;;;8BAE7B,KAACmB;oBAAIC,WAAW,GAAGtB,UAAU,IAAI,CAAC;;;;IAGxC;IAEA,OAAO;AACT,EAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/TenantSelector/index.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AAUxC,OAAO,KAAK,MAAM,OAAO,CAAA;AAQzB,OAAO,cAAc,CAAA;AAIrB,eAAO,MAAM,cAAc,wBAAyB;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,SAAS,CAAA;CAAE,6BAqG1F,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/TenantSelector/index.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AAUxC,OAAO,KAAK,MAAM,OAAO,CAAA;AAQzB,OAAO,cAAc,CAAA;AAKrB,eAAO,MAAM,cAAc,wBAAyB;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,SAAS,CAAA;CAAE,6BAuH1F,CAAA"}
@@ -5,10 +5,11 @@ import { ConfirmationModal, SelectInput, Translation, useModal, useTranslation }
5
5
  import React from 'react';
6
6
  import { useTenantSelection } from '../../providers/TenantSelectionProvider/index.client.js';
7
7
  import './index.scss';
8
- const confirmSwitchTenantSlug = 'confirmSwitchTenant';
8
+ const confirmSwitchTenantSlug = 'confirm-switch-tenant';
9
+ const confirmLeaveWithoutSavingSlug = 'confirm-leave-without-saving';
9
10
  export const TenantSelector = ({ label, viewType })=>{
10
- const { options, preventRefreshOnChange, selectedTenantID, setTenant } = useTenantSelection();
11
- const { openModal } = useModal();
11
+ const { entityType, modified, options, selectedTenantID, setTenant } = useTenantSelection();
12
+ const { closeModal, openModal } = useModal();
12
13
  const { i18n, t } = useTranslation();
13
14
  const [tenantSelection, setTenantSelection] = React.useState();
14
15
  const selectedValue = React.useMemo(()=>{
@@ -45,17 +46,30 @@ export const TenantSelector = ({ label, viewType })=>{
45
46
  setTenant
46
47
  ]);
47
48
  const onChange = React.useCallback((option)=>{
48
- if (!preventRefreshOnChange) {
49
- switchTenant(option);
49
+ if (option && 'value' in option && option.value === selectedTenantID) {
50
+ // If the selected option is the same as the current tenant, do nothing
50
51
  return;
52
+ }
53
+ if (entityType !== 'document') {
54
+ if (entityType === 'global' && modified) {
55
+ // If the entityType is 'global' and there are unsaved changes, prompt for confirmation
56
+ setTenantSelection(option);
57
+ openModal(confirmLeaveWithoutSavingSlug);
58
+ } else {
59
+ // If the entityType is not 'document', switch tenant without confirmation
60
+ switchTenant(option);
61
+ }
51
62
  } else {
63
+ // non-unique documents should always prompt for confirmation
52
64
  setTenantSelection(option);
53
65
  openModal(confirmSwitchTenantSlug);
54
66
  }
55
67
  }, [
56
- openModal,
57
- preventRefreshOnChange,
58
- switchTenant
68
+ selectedTenantID,
69
+ entityType,
70
+ modified,
71
+ switchTenant,
72
+ openModal
59
73
  ]);
60
74
  if (options.length <= 1) {
61
75
  return null;
@@ -90,19 +104,26 @@ export const TenantSelector = ({ label, viewType })=>{
90
104
  toTenant: newSelectedValue?.label
91
105
  }
92
106
  }),
93
- heading: /*#__PURE__*/ _jsx(Translation, {
94
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
95
- // @ts-expect-error
96
- i18nKey: "plugin-multi-tenant:confirm-tenant-switch--heading",
97
- t: t,
98
- variables: {
99
- tenantLabel: getTranslation(label, i18n)
100
- }
107
+ heading: t('plugin-multi-tenant:confirm-tenant-switch--heading', {
108
+ tenantLabel: getTranslation(label, i18n)
101
109
  }),
102
110
  modalSlug: confirmSwitchTenantSlug,
103
111
  onConfirm: ()=>{
104
112
  switchTenant(tenantSelection);
105
113
  }
114
+ }),
115
+ /*#__PURE__*/ _jsx(ConfirmationModal, {
116
+ body: t('general:changesNotSaved'),
117
+ cancelLabel: t('general:stayOnThisPage'),
118
+ confirmLabel: t('general:leaveAnyway'),
119
+ heading: t('general:leaveWithoutSaving'),
120
+ modalSlug: confirmLeaveWithoutSavingSlug,
121
+ onCancel: ()=>{
122
+ closeModal(confirmLeaveWithoutSavingSlug);
123
+ },
124
+ onConfirm: ()=>{
125
+ switchTenant(tenantSelection);
126
+ }
106
127
  })
107
128
  ]
108
129
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/TenantSelector/index.tsx"],"sourcesContent":["'use client'\nimport type { ReactSelectOption } from '@payloadcms/ui'\nimport type { ViewTypes } from 'payload'\n\nimport { getTranslation } from '@payloadcms/translations'\nimport {\n ConfirmationModal,\n SelectInput,\n Translation,\n useModal,\n useTranslation,\n} from '@payloadcms/ui'\nimport React from 'react'\n\nimport type {\n PluginMultiTenantTranslationKeys,\n PluginMultiTenantTranslations,\n} from '../../translations/index.js'\n\nimport { useTenantSelection } from '../../providers/TenantSelectionProvider/index.client.js'\nimport './index.scss'\n\nconst confirmSwitchTenantSlug = 'confirmSwitchTenant'\n\nexport const TenantSelector = ({ label, viewType }: { label: string; viewType?: ViewTypes }) => {\n const { options, preventRefreshOnChange, selectedTenantID, setTenant } = useTenantSelection()\n const { openModal } = useModal()\n const { i18n, t } = useTranslation<\n PluginMultiTenantTranslations,\n PluginMultiTenantTranslationKeys\n >()\n const [tenantSelection, setTenantSelection] = React.useState<\n ReactSelectOption | ReactSelectOption[]\n >()\n\n const selectedValue = React.useMemo(() => {\n if (selectedTenantID) {\n return options.find((option) => option.value === selectedTenantID)\n }\n return undefined\n }, [options, selectedTenantID])\n\n const newSelectedValue = React.useMemo(() => {\n if (tenantSelection && 'value' in tenantSelection) {\n return options.find((option) => option.value === tenantSelection.value)\n }\n return undefined\n }, [options, tenantSelection])\n\n const switchTenant = React.useCallback(\n (option: ReactSelectOption | ReactSelectOption[] | undefined) => {\n if (option && 'value' in option) {\n setTenant({ id: option.value as string, refresh: true })\n } else {\n setTenant({ id: undefined, refresh: true })\n }\n },\n [setTenant],\n )\n\n const onChange = React.useCallback(\n (option: ReactSelectOption | ReactSelectOption[]) => {\n if (!preventRefreshOnChange) {\n switchTenant(option)\n return\n } else {\n setTenantSelection(option)\n openModal(confirmSwitchTenantSlug)\n }\n },\n [openModal, preventRefreshOnChange, switchTenant],\n )\n\n if (options.length <= 1) {\n return null\n }\n\n return (\n <div className=\"tenant-selector\">\n <SelectInput\n isClearable={viewType === 'list'}\n label={getTranslation(label, i18n)}\n name=\"setTenant\"\n onChange={onChange}\n options={options}\n path=\"setTenant\"\n value={selectedTenantID as string | undefined}\n />\n\n <ConfirmationModal\n body={\n <Translation\n elements={{\n 0: ({ children }) => {\n return <b>{children}</b>\n },\n }}\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-expect-error\n i18nKey=\"plugin-multi-tenant:confirm-tenant-switch--body\"\n t={t}\n variables={{\n fromTenant: selectedValue?.label,\n toTenant: newSelectedValue?.label,\n }}\n />\n }\n heading={\n <Translation\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-expect-error\n i18nKey=\"plugin-multi-tenant:confirm-tenant-switch--heading\"\n t={t}\n variables={{\n tenantLabel: getTranslation(label, i18n),\n }}\n />\n }\n modalSlug={confirmSwitchTenantSlug}\n onConfirm={() => {\n switchTenant(tenantSelection)\n }}\n />\n </div>\n )\n}\n"],"names":["getTranslation","ConfirmationModal","SelectInput","Translation","useModal","useTranslation","React","useTenantSelection","confirmSwitchTenantSlug","TenantSelector","label","viewType","options","preventRefreshOnChange","selectedTenantID","setTenant","openModal","i18n","t","tenantSelection","setTenantSelection","useState","selectedValue","useMemo","find","option","value","undefined","newSelectedValue","switchTenant","useCallback","id","refresh","onChange","length","div","className","isClearable","name","path","body","elements","children","b","i18nKey","variables","fromTenant","toTenant","heading","tenantLabel","modalSlug","onConfirm"],"mappings":"AAAA;;AAIA,SAASA,cAAc,QAAQ,2BAA0B;AACzD,SACEC,iBAAiB,EACjBC,WAAW,EACXC,WAAW,EACXC,QAAQ,EACRC,cAAc,QACT,iBAAgB;AACvB,OAAOC,WAAW,QAAO;AAOzB,SAASC,kBAAkB,QAAQ,0DAAyD;AAC5F,OAAO,eAAc;AAErB,MAAMC,0BAA0B;AAEhC,OAAO,MAAMC,iBAAiB,CAAC,EAAEC,KAAK,EAAEC,QAAQ,EAA2C;IACzF,MAAM,EAAEC,OAAO,EAAEC,sBAAsB,EAAEC,gBAAgB,EAAEC,SAAS,EAAE,GAAGR;IACzE,MAAM,EAAES,SAAS,EAAE,GAAGZ;IACtB,MAAM,EAAEa,IAAI,EAAEC,CAAC,EAAE,GAAGb;IAIpB,MAAM,CAACc,iBAAiBC,mBAAmB,GAAGd,MAAMe,QAAQ;IAI5D,MAAMC,gBAAgBhB,MAAMiB,OAAO,CAAC;QAClC,IAAIT,kBAAkB;YACpB,OAAOF,QAAQY,IAAI,CAAC,CAACC,SAAWA,OAAOC,KAAK,KAAKZ;QACnD;QACA,OAAOa;IACT,GAAG;QAACf;QAASE;KAAiB;IAE9B,MAAMc,mBAAmBtB,MAAMiB,OAAO,CAAC;QACrC,IAAIJ,mBAAmB,WAAWA,iBAAiB;YACjD,OAAOP,QAAQY,IAAI,CAAC,CAACC,SAAWA,OAAOC,KAAK,KAAKP,gBAAgBO,KAAK;QACxE;QACA,OAAOC;IACT,GAAG;QAACf;QAASO;KAAgB;IAE7B,MAAMU,eAAevB,MAAMwB,WAAW,CACpC,CAACL;QACC,IAAIA,UAAU,WAAWA,QAAQ;YAC/BV,UAAU;gBAAEgB,IAAIN,OAAOC,KAAK;gBAAYM,SAAS;YAAK;QACxD,OAAO;YACLjB,UAAU;gBAAEgB,IAAIJ;gBAAWK,SAAS;YAAK;QAC3C;IACF,GACA;QAACjB;KAAU;IAGb,MAAMkB,WAAW3B,MAAMwB,WAAW,CAChC,CAACL;QACC,IAAI,CAACZ,wBAAwB;YAC3BgB,aAAaJ;YACb;QACF,OAAO;YACLL,mBAAmBK;YACnBT,UAAUR;QACZ;IACF,GACA;QAACQ;QAAWH;QAAwBgB;KAAa;IAGnD,IAAIjB,QAAQsB,MAAM,IAAI,GAAG;QACvB,OAAO;IACT;IAEA,qBACE,MAACC;QAAIC,WAAU;;0BACb,KAAClC;gBACCmC,aAAa1B,aAAa;gBAC1BD,OAAOV,eAAeU,OAAOO;gBAC7BqB,MAAK;gBACLL,UAAUA;gBACVrB,SAASA;gBACT2B,MAAK;gBACLb,OAAOZ;;0BAGT,KAACb;gBACCuC,oBACE,KAACrC;oBACCsC,UAAU;wBACR,GAAG,CAAC,EAAEC,QAAQ,EAAE;4BACd,qBAAO,KAACC;0CAAGD;;wBACb;oBACF;oBACA,6DAA6D;oBAC7D,mBAAmB;oBACnBE,SAAQ;oBACR1B,GAAGA;oBACH2B,WAAW;wBACTC,YAAYxB,eAAeZ;wBAC3BqC,UAAUnB,kBAAkBlB;oBAC9B;;gBAGJsC,uBACE,KAAC7C;oBACC,6DAA6D;oBAC7D,mBAAmB;oBACnByC,SAAQ;oBACR1B,GAAGA;oBACH2B,WAAW;wBACTI,aAAajD,eAAeU,OAAOO;oBACrC;;gBAGJiC,WAAW1C;gBACX2C,WAAW;oBACTtB,aAAaV;gBACf;;;;AAIR,EAAC"}
1
+ {"version":3,"sources":["../../../src/components/TenantSelector/index.tsx"],"sourcesContent":["'use client'\nimport type { ReactSelectOption } from '@payloadcms/ui'\nimport type { ViewTypes } from 'payload'\n\nimport { getTranslation } from '@payloadcms/translations'\nimport {\n ConfirmationModal,\n SelectInput,\n Translation,\n useModal,\n useTranslation,\n} from '@payloadcms/ui'\nimport React from 'react'\n\nimport type {\n PluginMultiTenantTranslationKeys,\n PluginMultiTenantTranslations,\n} from '../../translations/index.js'\n\nimport { useTenantSelection } from '../../providers/TenantSelectionProvider/index.client.js'\nimport './index.scss'\n\nconst confirmSwitchTenantSlug = 'confirm-switch-tenant'\nconst confirmLeaveWithoutSavingSlug = 'confirm-leave-without-saving'\n\nexport const TenantSelector = ({ label, viewType }: { label: string; viewType?: ViewTypes }) => {\n const { entityType, modified, options, selectedTenantID, setTenant } = useTenantSelection()\n const { closeModal, openModal } = useModal()\n const { i18n, t } = useTranslation<\n PluginMultiTenantTranslations,\n PluginMultiTenantTranslationKeys\n >()\n const [tenantSelection, setTenantSelection] = React.useState<\n ReactSelectOption | ReactSelectOption[]\n >()\n\n const selectedValue = React.useMemo(() => {\n if (selectedTenantID) {\n return options.find((option) => option.value === selectedTenantID)\n }\n return undefined\n }, [options, selectedTenantID])\n\n const newSelectedValue = React.useMemo(() => {\n if (tenantSelection && 'value' in tenantSelection) {\n return options.find((option) => option.value === tenantSelection.value)\n }\n return undefined\n }, [options, tenantSelection])\n\n const switchTenant = React.useCallback(\n (option: ReactSelectOption | ReactSelectOption[] | undefined) => {\n if (option && 'value' in option) {\n setTenant({ id: option.value as string, refresh: true })\n } else {\n setTenant({ id: undefined, refresh: true })\n }\n },\n [setTenant],\n )\n\n const onChange = React.useCallback(\n (option: ReactSelectOption | ReactSelectOption[]) => {\n if (option && 'value' in option && option.value === selectedTenantID) {\n // If the selected option is the same as the current tenant, do nothing\n return\n }\n\n if (entityType !== 'document') {\n if (entityType === 'global' && modified) {\n // If the entityType is 'global' and there are unsaved changes, prompt for confirmation\n setTenantSelection(option)\n openModal(confirmLeaveWithoutSavingSlug)\n } else {\n // If the entityType is not 'document', switch tenant without confirmation\n switchTenant(option)\n }\n } else {\n // non-unique documents should always prompt for confirmation\n setTenantSelection(option)\n openModal(confirmSwitchTenantSlug)\n }\n },\n [selectedTenantID, entityType, modified, switchTenant, openModal],\n )\n\n if (options.length <= 1) {\n return null\n }\n\n return (\n <div className=\"tenant-selector\">\n <SelectInput\n isClearable={viewType === 'list'}\n label={getTranslation(label, i18n)}\n name=\"setTenant\"\n onChange={onChange}\n options={options}\n path=\"setTenant\"\n value={selectedTenantID as string | undefined}\n />\n\n <ConfirmationModal\n body={\n <Translation\n elements={{\n 0: ({ children }) => {\n return <b>{children}</b>\n },\n }}\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-expect-error\n i18nKey=\"plugin-multi-tenant:confirm-tenant-switch--body\"\n t={t}\n variables={{\n fromTenant: selectedValue?.label,\n toTenant: newSelectedValue?.label,\n }}\n />\n }\n heading={t('plugin-multi-tenant:confirm-tenant-switch--heading', {\n tenantLabel: getTranslation(label, i18n),\n })}\n modalSlug={confirmSwitchTenantSlug}\n onConfirm={() => {\n switchTenant(tenantSelection)\n }}\n />\n\n <ConfirmationModal\n body={t('general:changesNotSaved')}\n cancelLabel={t('general:stayOnThisPage')}\n confirmLabel={t('general:leaveAnyway')}\n heading={t('general:leaveWithoutSaving')}\n modalSlug={confirmLeaveWithoutSavingSlug}\n onCancel={() => {\n closeModal(confirmLeaveWithoutSavingSlug)\n }}\n onConfirm={() => {\n switchTenant(tenantSelection)\n }}\n />\n </div>\n )\n}\n"],"names":["getTranslation","ConfirmationModal","SelectInput","Translation","useModal","useTranslation","React","useTenantSelection","confirmSwitchTenantSlug","confirmLeaveWithoutSavingSlug","TenantSelector","label","viewType","entityType","modified","options","selectedTenantID","setTenant","closeModal","openModal","i18n","t","tenantSelection","setTenantSelection","useState","selectedValue","useMemo","find","option","value","undefined","newSelectedValue","switchTenant","useCallback","id","refresh","onChange","length","div","className","isClearable","name","path","body","elements","children","b","i18nKey","variables","fromTenant","toTenant","heading","tenantLabel","modalSlug","onConfirm","cancelLabel","confirmLabel","onCancel"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/WatchTenantCollection/index.tsx"],"names":[],"mappings":"AAeA,eAAO,MAAM,qBAAqB,YA0CjC,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/WatchTenantCollection/index.tsx"],"names":[],"mappings":"AAiBA,eAAO,MAAM,qBAAqB,YAmCjC,CAAA"}
@@ -1,17 +1,18 @@
1
1
  'use client';
2
- import { useConfig, useDocumentInfo, useDocumentTitle, useEffectEvent, useFormFields } from '@payloadcms/ui';
2
+ import { useConfig, useDocumentInfo, useDocumentTitle, useEffectEvent, useFormFields, useFormSubmitted, useOperation } from '@payloadcms/ui';
3
3
  import React from 'react';
4
4
  import { useTenantSelection } from '../../providers/TenantSelectionProvider/index.client.js';
5
5
  export const WatchTenantCollection = ()=>{
6
6
  const { id, collectionSlug } = useDocumentInfo();
7
+ const operation = useOperation();
8
+ const submitted = useFormSubmitted();
7
9
  const { title } = useDocumentTitle();
8
- const addedNewTenant = React.useRef(false);
9
10
  const { getEntityConfig } = useConfig();
10
11
  const [useAsTitleName] = React.useState(()=>getEntityConfig({
11
12
  collectionSlug
12
13
  }).admin.useAsTitle);
13
14
  const titleField = useFormFields(([fields])=>useAsTitleName ? fields[useAsTitleName] : {});
14
- const { options, updateTenants } = useTenantSelection();
15
+ const { syncTenants, updateTenants } = useTenantSelection();
15
16
  const syncTenantTitle = useEffectEvent(()=>{
16
17
  if (id) {
17
18
  updateTenants({
@@ -20,33 +21,26 @@ export const WatchTenantCollection = ()=>{
20
21
  });
21
22
  }
22
23
  });
23
- React.useEffect(()=>{
24
- if (!id || !title || addedNewTenant.current) {
25
- return;
26
- }
27
- // Track tenant creation and add it to the tenant selector
28
- const exists = options.some((opt)=>opt.value === id);
29
- if (!exists) {
30
- addedNewTenant.current = true;
31
- updateTenants({
32
- id,
33
- label: title
34
- });
35
- }
36
- // eslint-disable-next-line react-compiler/react-compiler
37
- // eslint-disable-next-line react-hooks/exhaustive-deps
38
- }, [
39
- id
40
- ]);
41
24
  React.useEffect(()=>{
42
25
  // only update the tenant selector when the document saves
43
26
  // → aka when initial value changes
44
27
  if (id && titleField?.initialValue) {
45
- syncTenantTitle();
28
+ void syncTenantTitle();
46
29
  }
47
30
  }, [
48
31
  id,
49
- titleField?.initialValue
32
+ titleField?.initialValue,
33
+ syncTenants
34
+ ]);
35
+ React.useEffect(()=>{
36
+ if (operation === 'create' && submitted) {
37
+ void syncTenants();
38
+ }
39
+ }, [
40
+ operation,
41
+ submitted,
42
+ syncTenants,
43
+ id
50
44
  ]);
51
45
  return null;
52
46
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/WatchTenantCollection/index.tsx"],"sourcesContent":["'use client'\n\nimport type { ClientCollectionConfig } from 'payload'\n\nimport {\n useConfig,\n useDocumentInfo,\n useDocumentTitle,\n useEffectEvent,\n useFormFields,\n} from '@payloadcms/ui'\nimport React from 'react'\n\nimport { useTenantSelection } from '../../providers/TenantSelectionProvider/index.client.js'\n\nexport const WatchTenantCollection = () => {\n const { id, collectionSlug } = useDocumentInfo()\n const { title } = useDocumentTitle()\n const addedNewTenant = React.useRef(false)\n\n const { getEntityConfig } = useConfig()\n const [useAsTitleName] = React.useState(\n () => (getEntityConfig({ collectionSlug }) as ClientCollectionConfig).admin.useAsTitle,\n )\n const titleField = useFormFields(([fields]) => (useAsTitleName ? fields[useAsTitleName] : {}))\n\n const { options, updateTenants } = useTenantSelection()\n\n const syncTenantTitle = useEffectEvent(() => {\n if (id) {\n updateTenants({ id, label: title })\n }\n })\n\n React.useEffect(() => {\n if (!id || !title || addedNewTenant.current) {\n return\n }\n // Track tenant creation and add it to the tenant selector\n const exists = options.some((opt) => opt.value === id)\n if (!exists) {\n addedNewTenant.current = true\n updateTenants({ id, label: title })\n }\n // eslint-disable-next-line react-compiler/react-compiler\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [id])\n\n React.useEffect(() => {\n // only update the tenant selector when the document saves\n // → aka when initial value changes\n if (id && titleField?.initialValue) {\n syncTenantTitle()\n }\n }, [id, titleField?.initialValue])\n\n return null\n}\n"],"names":["useConfig","useDocumentInfo","useDocumentTitle","useEffectEvent","useFormFields","React","useTenantSelection","WatchTenantCollection","id","collectionSlug","title","addedNewTenant","useRef","getEntityConfig","useAsTitleName","useState","admin","useAsTitle","titleField","fields","options","updateTenants","syncTenantTitle","label","useEffect","current","exists","some","opt","value","initialValue"],"mappings":"AAAA;AAIA,SACEA,SAAS,EACTC,eAAe,EACfC,gBAAgB,EAChBC,cAAc,EACdC,aAAa,QACR,iBAAgB;AACvB,OAAOC,WAAW,QAAO;AAEzB,SAASC,kBAAkB,QAAQ,0DAAyD;AAE5F,OAAO,MAAMC,wBAAwB;IACnC,MAAM,EAAEC,EAAE,EAAEC,cAAc,EAAE,GAAGR;IAC/B,MAAM,EAAES,KAAK,EAAE,GAAGR;IAClB,MAAMS,iBAAiBN,MAAMO,MAAM,CAAC;IAEpC,MAAM,EAAEC,eAAe,EAAE,GAAGb;IAC5B,MAAM,CAACc,eAAe,GAAGT,MAAMU,QAAQ,CACrC,IAAM,AAACF,gBAAgB;YAAEJ;QAAe,GAA8BO,KAAK,CAACC,UAAU;IAExF,MAAMC,aAAad,cAAc,CAAC,CAACe,OAAO,GAAML,iBAAiBK,MAAM,CAACL,eAAe,GAAG,CAAC;IAE3F,MAAM,EAAEM,OAAO,EAAEC,aAAa,EAAE,GAAGf;IAEnC,MAAMgB,kBAAkBnB,eAAe;QACrC,IAAIK,IAAI;YACNa,cAAc;gBAAEb;gBAAIe,OAAOb;YAAM;QACnC;IACF;IAEAL,MAAMmB,SAAS,CAAC;QACd,IAAI,CAAChB,MAAM,CAACE,SAASC,eAAec,OAAO,EAAE;YAC3C;QACF;QACA,0DAA0D;QAC1D,MAAMC,SAASN,QAAQO,IAAI,CAAC,CAACC,MAAQA,IAAIC,KAAK,KAAKrB;QACnD,IAAI,CAACkB,QAAQ;YACXf,eAAec,OAAO,GAAG;YACzBJ,cAAc;gBAAEb;gBAAIe,OAAOb;YAAM;QACnC;IACA,yDAAyD;IACzD,uDAAuD;IACzD,GAAG;QAACF;KAAG;IAEPH,MAAMmB,SAAS,CAAC;QACd,0DAA0D;QAC1D,mCAAmC;QACnC,IAAIhB,MAAMU,YAAYY,cAAc;YAClCR;QACF;IACF,GAAG;QAACd;QAAIU,YAAYY;KAAa;IAEjC,OAAO;AACT,EAAC"}
1
+ {"version":3,"sources":["../../../src/components/WatchTenantCollection/index.tsx"],"sourcesContent":["'use client'\n\nimport type { ClientCollectionConfig } from 'payload'\n\nimport {\n useConfig,\n useDocumentInfo,\n useDocumentTitle,\n useEffectEvent,\n useFormFields,\n useFormSubmitted,\n useOperation,\n} from '@payloadcms/ui'\nimport React from 'react'\n\nimport { useTenantSelection } from '../../providers/TenantSelectionProvider/index.client.js'\n\nexport const WatchTenantCollection = () => {\n const { id, collectionSlug } = useDocumentInfo()\n const operation = useOperation()\n const submitted = useFormSubmitted()\n const { title } = useDocumentTitle()\n\n const { getEntityConfig } = useConfig()\n const [useAsTitleName] = React.useState(\n () => (getEntityConfig({ collectionSlug }) as ClientCollectionConfig).admin.useAsTitle,\n )\n const titleField = useFormFields(([fields]) => (useAsTitleName ? fields[useAsTitleName] : {}))\n\n const { syncTenants, updateTenants } = useTenantSelection()\n\n const syncTenantTitle = useEffectEvent(() => {\n if (id) {\n updateTenants({ id, label: title })\n }\n })\n\n React.useEffect(() => {\n // only update the tenant selector when the document saves\n // aka when initial value changes\n if (id && titleField?.initialValue) {\n void syncTenantTitle()\n }\n }, [id, titleField?.initialValue, syncTenants])\n\n React.useEffect(() => {\n if (operation === 'create' && submitted) {\n void syncTenants()\n }\n }, [operation, submitted, syncTenants, id])\n\n return null\n}\n"],"names":["useConfig","useDocumentInfo","useDocumentTitle","useEffectEvent","useFormFields","useFormSubmitted","useOperation","React","useTenantSelection","WatchTenantCollection","id","collectionSlug","operation","submitted","title","getEntityConfig","useAsTitleName","useState","admin","useAsTitle","titleField","fields","syncTenants","updateTenants","syncTenantTitle","label","useEffect","initialValue"],"mappings":"AAAA;AAIA,SACEA,SAAS,EACTC,eAAe,EACfC,gBAAgB,EAChBC,cAAc,EACdC,aAAa,EACbC,gBAAgB,EAChBC,YAAY,QACP,iBAAgB;AACvB,OAAOC,WAAW,QAAO;AAEzB,SAASC,kBAAkB,QAAQ,0DAAyD;AAE5F,OAAO,MAAMC,wBAAwB;IACnC,MAAM,EAAEC,EAAE,EAAEC,cAAc,EAAE,GAAGV;IAC/B,MAAMW,YAAYN;IAClB,MAAMO,YAAYR;IAClB,MAAM,EAAES,KAAK,EAAE,GAAGZ;IAElB,MAAM,EAAEa,eAAe,EAAE,GAAGf;IAC5B,MAAM,CAACgB,eAAe,GAAGT,MAAMU,QAAQ,CACrC,IAAM,AAACF,gBAAgB;YAAEJ;QAAe,GAA8BO,KAAK,CAACC,UAAU;IAExF,MAAMC,aAAahB,cAAc,CAAC,CAACiB,OAAO,GAAML,iBAAiBK,MAAM,CAACL,eAAe,GAAG,CAAC;IAE3F,MAAM,EAAEM,WAAW,EAAEC,aAAa,EAAE,GAAGf;IAEvC,MAAMgB,kBAAkBrB,eAAe;QACrC,IAAIO,IAAI;YACNa,cAAc;gBAAEb;gBAAIe,OAAOX;YAAM;QACnC;IACF;IAEAP,MAAMmB,SAAS,CAAC;QACd,0DAA0D;QAC1D,mCAAmC;QACnC,IAAIhB,MAAMU,YAAYO,cAAc;YAClC,KAAKH;QACP;IACF,GAAG;QAACd;QAAIU,YAAYO;QAAcL;KAAY;IAE9Cf,MAAMmB,SAAS,CAAC;QACd,IAAId,cAAc,YAAYC,WAAW;YACvC,KAAKS;QACP;IACF,GAAG;QAACV;QAAWC;QAAWS;QAAaZ;KAAG;IAE1C,OAAO;AACT,EAAC"}
@@ -1,21 +1,34 @@
1
1
  import type { OptionObject } from 'payload';
2
2
  import React from 'react';
3
3
  type ContextType = {
4
+ /**
5
+ * What is the context of the selector? It is either 'document' | 'global' | undefined.
6
+ *
7
+ * - 'document' means you are viewing a document in the context of a tenant
8
+ * - 'global' means you are viewing a "global" (globals are collection documents but prevent you from viewing the list view) document in the context of a tenant
9
+ * - undefined means you are not viewing a document at all
10
+ */
11
+ entityType?: 'document' | 'global';
12
+ /**
13
+ * Hoists the forms modified state
14
+ */
15
+ modified?: boolean;
4
16
  /**
5
17
  * Array of options to select from
6
18
  */
7
19
  options: OptionObject[];
8
- preventRefreshOnChange: boolean;
9
20
  /**
10
21
  * The currently selected tenant ID
11
22
  */
12
23
  selectedTenantID: number | string | undefined;
13
24
  /**
14
- * Prevents a refresh when the tenant is changed
15
- *
16
- * If not switching tenants while viewing a "global", set to true
25
+ * Sets the entityType when a document is loaded and sets it to undefined when the document unmounts.
26
+ */
27
+ setEntityType: React.Dispatch<React.SetStateAction<'document' | 'global' | undefined>>;
28
+ /**
29
+ * Sets the modified state
17
30
  */
18
- setPreventRefreshOnChange: React.Dispatch<React.SetStateAction<boolean>>;
31
+ setModified: React.Dispatch<React.SetStateAction<boolean>>;
19
32
  /**
20
33
  * Sets the selected tenant ID
21
34
  *
@@ -26,6 +39,10 @@ type ContextType = {
26
39
  id: number | string | undefined;
27
40
  refresh?: boolean;
28
41
  }) => void;
42
+ /**
43
+ * Used to sync tenants displayed in the tenant selector when updates are made to the tenants collection.
44
+ */
45
+ syncTenants: () => Promise<void>;
29
46
  /**
30
47
  *
31
48
  */
@@ -34,11 +51,13 @@ type ContextType = {
34
51
  label: string;
35
52
  }) => void;
36
53
  };
37
- export declare const TenantSelectionProviderClient: ({ children, initialValue, tenantCookie, tenantOptions: tenantOptionsFromProps, }: {
54
+ export declare const TenantSelectionProviderClient: ({ children, initialValue, tenantCookie, tenantOptions: tenantOptionsFromProps, tenantsCollectionSlug, useAsTitle, }: {
38
55
  children: React.ReactNode;
39
56
  initialValue?: number | string;
40
57
  tenantCookie?: string;
41
58
  tenantOptions: OptionObject[];
59
+ tenantsCollectionSlug: string;
60
+ useAsTitle: string;
42
61
  }) => React.JSX.Element;
43
62
  export declare const useTenantSelection: () => ContextType;
44
63
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"index.client.d.ts","sourceRoot":"","sources":["../../../src/providers/TenantSelectionProvider/index.client.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAI3C,OAAO,KAAwB,MAAM,OAAO,CAAA;AAE5C,KAAK,WAAW,GAAG;IACjB;;OAEG;IACH,OAAO,EAAE,YAAY,EAAE,CAAA;IACvB,sBAAsB,EAAE,OAAO,CAAA;IAC/B;;OAEG;IACH,gBAAgB,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAA;IAC7C;;;;OAIG;IACH,yBAAyB,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAA;IACxE;;;;;OAKG;IACH,SAAS,EAAE,CAAC,IAAI,EAAE;QAAE,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;QAAC,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,CAAA;IACjF;;OAEG;IACH,aAAa,EAAE,CAAC,IAAI,EAAE;QAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAA;CACtE,CAAA;AAWD,eAAO,MAAM,6BAA6B,qFAKvC;IACD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,aAAa,EAAE,YAAY,EAAE,CAAA;CAC9B,sBAiIA,CAAA;AAED,eAAO,MAAM,kBAAkB,mBAA2B,CAAA"}
1
+ {"version":3,"file":"index.client.d.ts","sourceRoot":"","sources":["../../../src/providers/TenantSelectionProvider/index.client.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAI3C,OAAO,KAAwB,MAAM,OAAO,CAAA;AAE5C,KAAK,WAAW,GAAG;IACjB;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,UAAU,GAAG,QAAQ,CAAA;IAClC;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;;OAEG;IACH,OAAO,EAAE,YAAY,EAAE,CAAA;IACvB;;OAEG;IACH,gBAAgB,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAA;IAC7C;;OAEG;IACH,aAAa,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,UAAU,GAAG,QAAQ,GAAG,SAAS,CAAC,CAAC,CAAA;IACtF;;OAEG;IACH,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAA;IAC1D;;;;;OAKG;IACH,SAAS,EAAE,CAAC,IAAI,EAAE;QAAE,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;QAAC,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,CAAA;IACjF;;OAEG;IACH,WAAW,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAChC;;OAEG;IACH,aAAa,EAAE,CAAC,IAAI,EAAE;QAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAA;CACtE,CAAA;AAaD,eAAO,MAAM,6BAA6B,wHAOvC;IACD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,aAAa,EAAE,YAAY,EAAE,CAAA;IAC7B,qBAAqB,EAAE,MAAM,CAAA;IAC7B,UAAU,EAAE,MAAM,CAAA;CACnB,sBA8JA,CAAA;AAED,eAAO,MAAM,kBAAkB,mBAA2B,CAAA"}
@@ -1,20 +1,24 @@
1
1
  'use client';
2
2
  import { jsx as _jsx } from "react/jsx-runtime";
3
- import { useAuth } from '@payloadcms/ui';
3
+ import { toast, useAuth, useConfig } from '@payloadcms/ui';
4
4
  import { useRouter } from 'next/navigation.js';
5
5
  import React, { createContext } from 'react';
6
6
  const Context = /*#__PURE__*/ createContext({
7
+ entityType: undefined,
7
8
  options: [],
8
- preventRefreshOnChange: false,
9
9
  selectedTenantID: undefined,
10
- setPreventRefreshOnChange: ()=>null,
10
+ setEntityType: ()=>undefined,
11
+ setModified: ()=>undefined,
11
12
  setTenant: ()=>null,
13
+ syncTenants: ()=>Promise.resolve(),
12
14
  updateTenants: ()=>null
13
15
  });
14
- export const TenantSelectionProviderClient = ({ children, initialValue, tenantCookie, tenantOptions: tenantOptionsFromProps })=>{
16
+ export const TenantSelectionProviderClient = ({ children, initialValue, tenantCookie, tenantOptions: tenantOptionsFromProps, tenantsCollectionSlug, useAsTitle })=>{
15
17
  const [selectedTenantID, setSelectedTenantID] = React.useState(initialValue);
16
- const [preventRefreshOnChange, setPreventRefreshOnChange] = React.useState(false);
18
+ const [modified, setModified] = React.useState(false);
19
+ const [entityType, setEntityType] = React.useState(undefined);
17
20
  const { user } = useAuth();
21
+ const { config } = useConfig();
18
22
  const userID = React.useMemo(()=>user?.id, [
19
23
  user?.id
20
24
  ]);
@@ -35,96 +39,102 @@ export const TenantSelectionProviderClient = ({ children, initialValue, tenantCo
35
39
  const setTenant = React.useCallback(({ id, refresh })=>{
36
40
  if (id === undefined) {
37
41
  if (tenantOptions.length > 1) {
42
+ // users with multiple tenants can clear the tenant selection
38
43
  setSelectedTenantID(undefined);
39
44
  deleteCookie();
40
45
  } else {
46
+ // if there is only one tenant, force the selection of that tenant
41
47
  setSelectedTenantID(tenantOptions[0]?.value);
42
48
  setCookie(String(tenantOptions[0]?.value));
43
49
  }
50
+ } else if (!tenantOptions.find((option)=>option.value === id)) {
51
+ // if the tenant is not valid, set the first tenant as selected
52
+ if (tenantOptions?.[0]?.value) {
53
+ setTenant({
54
+ id: tenantOptions[0].value,
55
+ refresh: true
56
+ });
57
+ } else {
58
+ setTenant({
59
+ id: undefined,
60
+ refresh: true
61
+ });
62
+ }
44
63
  } else {
64
+ // if the tenant is in the options, set it as selected
45
65
  setSelectedTenantID(id);
46
66
  setCookie(String(id));
47
67
  }
48
- if (!preventRefreshOnChange && refresh) {
68
+ if (entityType !== 'document' && refresh) {
49
69
  router.refresh();
50
70
  }
51
71
  }, [
52
72
  deleteCookie,
53
- preventRefreshOnChange,
73
+ entityType,
54
74
  router,
55
75
  setCookie,
56
- setSelectedTenantID,
57
76
  tenantOptions
58
77
  ]);
78
+ const syncTenants = React.useCallback(async ()=>{
79
+ try {
80
+ const req = await fetch(`${config.serverURL}${config.routes.api}/${tenantsCollectionSlug}?select[${useAsTitle}]=true&limit=0&depth=0`, {
81
+ credentials: 'include',
82
+ method: 'GET'
83
+ });
84
+ const result = await req.json();
85
+ if (result.docs) {
86
+ setTenantOptions(result.docs.map((doc)=>({
87
+ label: doc[useAsTitle],
88
+ value: doc.id
89
+ })));
90
+ }
91
+ } catch (e) {
92
+ toast.error(`Error fetching tenants`);
93
+ }
94
+ }, [
95
+ config.serverURL,
96
+ config.routes.api,
97
+ tenantsCollectionSlug,
98
+ useAsTitle
99
+ ]);
59
100
  const updateTenants = React.useCallback(({ id, label })=>{
60
101
  setTenantOptions((prev)=>{
61
- const stringID = String(id);
62
- let exists = false;
63
- const updated = prev.map((currentTenant)=>{
64
- if (stringID === String(currentTenant.value)) {
65
- exists = true;
102
+ return prev.map((currentTenant)=>{
103
+ if (id === currentTenant.value) {
66
104
  return {
67
105
  label,
68
- value: stringID
106
+ value: id
69
107
  };
70
108
  }
71
109
  return currentTenant;
72
110
  });
73
- if (!exists) {
74
- updated.push({
75
- label,
76
- value: stringID
77
- });
78
- }
79
- // Sort alphabetically by label (or value as fallback)
80
- return updated.sort((a, b)=>{
81
- const aKey = typeof a.label === 'string' ? a.label : String(a.value);
82
- const bKey = typeof b.label === 'string' ? b.label : String(b.value);
83
- return aKey.localeCompare(bKey);
84
- });
85
111
  });
86
- }, []);
112
+ void syncTenants();
113
+ }, [
114
+ syncTenants
115
+ ]);
87
116
  React.useEffect(()=>{
88
- if (selectedTenantID && !tenantOptions.find((option)=>option.value === selectedTenantID)) {
89
- if (tenantOptions?.[0]?.value) {
90
- setTenant({
91
- id: tenantOptions[0].value,
92
- refresh: true
93
- });
94
- } else {
117
+ if (userID && !tenantCookie) {
118
+ if (tenantOptionsFromProps.length === 1) {
119
+ // Users with no cookie set and only 1 tenant should set that tenant automatically
95
120
  setTenant({
96
- id: undefined,
121
+ id: tenantOptionsFromProps[0]?.value,
97
122
  refresh: true
98
123
  });
124
+ setTenantOptions(tenantOptionsFromProps);
125
+ } else if ((!tenantOptions || tenantOptions.length === 0) && tenantOptionsFromProps) {
126
+ // If there are no tenant options, set them from the props
127
+ setTenantOptions(tenantOptionsFromProps);
99
128
  }
100
129
  }
101
130
  }, [
102
- tenantCookie,
103
- setTenant,
104
- selectedTenantID,
105
- tenantOptions,
106
131
  initialValue,
107
- setCookie
108
- ]);
109
- React.useEffect(()=>{
110
- if (userID && !tenantCookie) {
111
- // User is logged in, but does not have a tenant cookie, set it
112
- setSelectedTenantID(initialValue);
113
- setTenantOptions(tenantOptionsFromProps);
114
- if (initialValue) {
115
- setCookie(String(initialValue));
116
- } else {
117
- deleteCookie();
118
- }
119
- }
120
- }, [
121
- userID,
132
+ selectedTenantID,
122
133
  tenantCookie,
123
- initialValue,
124
- setCookie,
125
- deleteCookie,
126
- router,
127
- tenantOptionsFromProps
134
+ userID,
135
+ setTenant,
136
+ tenantOptionsFromProps,
137
+ tenantOptions
128
138
  ]);
129
139
  React.useEffect(()=>{
130
140
  if (!userID && tenantCookie) {
@@ -146,11 +156,14 @@ export const TenantSelectionProviderClient = ({ children, initialValue, tenantCo
146
156
  "data-selected-tenant-title": selectedTenantLabel,
147
157
  children: /*#__PURE__*/ _jsx(Context, {
148
158
  value: {
159
+ entityType,
160
+ modified,
149
161
  options: tenantOptions,
150
- preventRefreshOnChange,
151
162
  selectedTenantID,
152
- setPreventRefreshOnChange,
163
+ setEntityType,
164
+ setModified,
153
165
  setTenant,
166
+ syncTenants,
154
167
  updateTenants
155
168
  },
156
169
  children: children
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/providers/TenantSelectionProvider/index.client.tsx"],"sourcesContent":["'use client'\n\nimport type { OptionObject } from 'payload'\n\nimport { useAuth } from '@payloadcms/ui'\nimport { useRouter } from 'next/navigation.js'\nimport React, { createContext } from 'react'\n\ntype ContextType = {\n /**\n * Array of options to select from\n */\n options: OptionObject[]\n preventRefreshOnChange: boolean\n /**\n * The currently selected tenant ID\n */\n selectedTenantID: number | string | undefined\n /**\n * Prevents a refresh when the tenant is changed\n *\n * If not switching tenants while viewing a \"global\", set to true\n */\n setPreventRefreshOnChange: React.Dispatch<React.SetStateAction<boolean>>\n /**\n * Sets the selected tenant ID\n *\n * @param args.id - The ID of the tenant to select\n * @param args.refresh - Whether to refresh the page after changing the tenant\n */\n setTenant: (args: { id: number | string | undefined; refresh?: boolean }) => void\n /**\n *\n */\n updateTenants: (args: { id: number | string; label: string }) => void\n}\n\nconst Context = createContext<ContextType>({\n options: [],\n preventRefreshOnChange: false,\n selectedTenantID: undefined,\n setPreventRefreshOnChange: () => null,\n setTenant: () => null,\n updateTenants: () => null,\n})\n\nexport const TenantSelectionProviderClient = ({\n children,\n initialValue,\n tenantCookie,\n tenantOptions: tenantOptionsFromProps,\n}: {\n children: React.ReactNode\n initialValue?: number | string\n tenantCookie?: string\n tenantOptions: OptionObject[]\n}) => {\n const [selectedTenantID, setSelectedTenantID] = React.useState<number | string | undefined>(\n initialValue,\n )\n const [preventRefreshOnChange, setPreventRefreshOnChange] = React.useState(false)\n const { user } = useAuth()\n const userID = React.useMemo(() => user?.id, [user?.id])\n const [tenantOptions, setTenantOptions] = React.useState<OptionObject[]>(\n () => tenantOptionsFromProps,\n )\n const selectedTenantLabel = React.useMemo(\n () => tenantOptions.find((option) => option.value === selectedTenantID)?.label,\n [selectedTenantID, tenantOptions],\n )\n\n const router = useRouter()\n\n const setCookie = React.useCallback((value?: string) => {\n const expires = '; expires=Fri, 31 Dec 9999 23:59:59 GMT'\n document.cookie = 'payload-tenant=' + (value || '') + expires + '; path=/'\n }, [])\n\n const deleteCookie = React.useCallback(() => {\n // eslint-disable-next-line react-compiler/react-compiler -- TODO: fix\n document.cookie = 'payload-tenant=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/'\n }, [])\n\n const setTenant = React.useCallback<ContextType['setTenant']>(\n ({ id, refresh }) => {\n if (id === undefined) {\n if (tenantOptions.length > 1) {\n setSelectedTenantID(undefined)\n deleteCookie()\n } else {\n setSelectedTenantID(tenantOptions[0]?.value)\n setCookie(String(tenantOptions[0]?.value))\n }\n } else {\n setSelectedTenantID(id)\n setCookie(String(id))\n }\n if (!preventRefreshOnChange && refresh) {\n router.refresh()\n }\n },\n [deleteCookie, preventRefreshOnChange, router, setCookie, setSelectedTenantID, tenantOptions],\n )\n\n const updateTenants = React.useCallback<ContextType['updateTenants']>(({ id, label }) => {\n setTenantOptions((prev) => {\n const stringID = String(id)\n let exists = false\n const updated = prev.map((currentTenant) => {\n if (stringID === String(currentTenant.value)) {\n exists = true\n return {\n label,\n value: stringID,\n }\n }\n return currentTenant\n })\n\n if (!exists) {\n updated.push({ label, value: stringID })\n }\n\n // Sort alphabetically by label (or value as fallback)\n return updated.sort((a, b) => {\n const aKey = typeof a.label === 'string' ? a.label : String(a.value)\n const bKey = typeof b.label === 'string' ? b.label : String(b.value)\n return aKey.localeCompare(bKey)\n })\n })\n }, [])\n\n React.useEffect(() => {\n if (selectedTenantID && !tenantOptions.find((option) => option.value === selectedTenantID)) {\n if (tenantOptions?.[0]?.value) {\n setTenant({ id: tenantOptions[0].value, refresh: true })\n } else {\n setTenant({ id: undefined, refresh: true })\n }\n }\n }, [tenantCookie, setTenant, selectedTenantID, tenantOptions, initialValue, setCookie])\n\n React.useEffect(() => {\n if (userID && !tenantCookie) {\n // User is logged in, but does not have a tenant cookie, set it\n setSelectedTenantID(initialValue)\n setTenantOptions(tenantOptionsFromProps)\n if (initialValue) {\n setCookie(String(initialValue))\n } else {\n deleteCookie()\n }\n }\n }, [userID, tenantCookie, initialValue, setCookie, deleteCookie, router, tenantOptionsFromProps])\n\n React.useEffect(() => {\n if (!userID && tenantCookie) {\n // User is not logged in, but has a tenant cookie, delete it\n deleteCookie()\n setSelectedTenantID(undefined)\n } else if (userID) {\n // User changed, refresh\n router.refresh()\n }\n }, [userID, tenantCookie, deleteCookie, router])\n\n return (\n <span\n data-selected-tenant-id={selectedTenantID}\n data-selected-tenant-title={selectedTenantLabel}\n >\n <Context\n value={{\n options: tenantOptions,\n preventRefreshOnChange,\n selectedTenantID,\n setPreventRefreshOnChange,\n setTenant,\n updateTenants,\n }}\n >\n {children}\n </Context>\n </span>\n )\n}\n\nexport const useTenantSelection = () => React.use(Context)\n"],"names":["useAuth","useRouter","React","createContext","Context","options","preventRefreshOnChange","selectedTenantID","undefined","setPreventRefreshOnChange","setTenant","updateTenants","TenantSelectionProviderClient","children","initialValue","tenantCookie","tenantOptions","tenantOptionsFromProps","setSelectedTenantID","useState","user","userID","useMemo","id","setTenantOptions","selectedTenantLabel","find","option","value","label","router","setCookie","useCallback","expires","document","cookie","deleteCookie","refresh","length","String","prev","stringID","exists","updated","map","currentTenant","push","sort","a","b","aKey","bKey","localeCompare","useEffect","span","data-selected-tenant-id","data-selected-tenant-title","useTenantSelection","use"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/providers/TenantSelectionProvider/index.client.tsx"],"sourcesContent":["'use client'\n\nimport type { OptionObject } from 'payload'\n\nimport { toast, useAuth, useConfig } from '@payloadcms/ui'\nimport { useRouter } from 'next/navigation.js'\nimport React, { createContext } from 'react'\n\ntype ContextType = {\n /**\n * What is the context of the selector? It is either 'document' | 'global' | undefined.\n *\n * - 'document' means you are viewing a document in the context of a tenant\n * - 'global' means you are viewing a \"global\" (globals are collection documents but prevent you from viewing the list view) document in the context of a tenant\n * - undefined means you are not viewing a document at all\n */\n entityType?: 'document' | 'global'\n /**\n * Hoists the forms modified state\n */\n modified?: boolean\n /**\n * Array of options to select from\n */\n options: OptionObject[]\n /**\n * The currently selected tenant ID\n */\n selectedTenantID: number | string | undefined\n /**\n * Sets the entityType when a document is loaded and sets it to undefined when the document unmounts.\n */\n setEntityType: React.Dispatch<React.SetStateAction<'document' | 'global' | undefined>>\n /**\n * Sets the modified state\n */\n setModified: React.Dispatch<React.SetStateAction<boolean>>\n /**\n * Sets the selected tenant ID\n *\n * @param args.id - The ID of the tenant to select\n * @param args.refresh - Whether to refresh the page after changing the tenant\n */\n setTenant: (args: { id: number | string | undefined; refresh?: boolean }) => void\n /**\n * Used to sync tenants displayed in the tenant selector when updates are made to the tenants collection.\n */\n syncTenants: () => Promise<void>\n /**\n *\n */\n updateTenants: (args: { id: number | string; label: string }) => void\n}\n\nconst Context = createContext<ContextType>({\n entityType: undefined,\n options: [],\n selectedTenantID: undefined,\n setEntityType: () => undefined,\n setModified: () => undefined,\n setTenant: () => null,\n syncTenants: () => Promise.resolve(),\n updateTenants: () => null,\n})\n\nexport const TenantSelectionProviderClient = ({\n children,\n initialValue,\n tenantCookie,\n tenantOptions: tenantOptionsFromProps,\n tenantsCollectionSlug,\n useAsTitle,\n}: {\n children: React.ReactNode\n initialValue?: number | string\n tenantCookie?: string\n tenantOptions: OptionObject[]\n tenantsCollectionSlug: string\n useAsTitle: string\n}) => {\n const [selectedTenantID, setSelectedTenantID] = React.useState<number | string | undefined>(\n initialValue,\n )\n const [modified, setModified] = React.useState<boolean>(false)\n const [entityType, setEntityType] = React.useState<'document' | 'global' | undefined>(undefined)\n const { user } = useAuth()\n const { config } = useConfig()\n const userID = React.useMemo(() => user?.id, [user?.id])\n const [tenantOptions, setTenantOptions] = React.useState<OptionObject[]>(\n () => tenantOptionsFromProps,\n )\n const selectedTenantLabel = React.useMemo(\n () => tenantOptions.find((option) => option.value === selectedTenantID)?.label,\n [selectedTenantID, tenantOptions],\n )\n\n const router = useRouter()\n\n const setCookie = React.useCallback((value?: string) => {\n const expires = '; expires=Fri, 31 Dec 9999 23:59:59 GMT'\n document.cookie = 'payload-tenant=' + (value || '') + expires + '; path=/'\n }, [])\n\n const deleteCookie = React.useCallback(() => {\n // eslint-disable-next-line react-compiler/react-compiler -- TODO: fix\n document.cookie = 'payload-tenant=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/'\n }, [])\n\n const setTenant = React.useCallback<ContextType['setTenant']>(\n ({ id, refresh }) => {\n if (id === undefined) {\n if (tenantOptions.length > 1) {\n // users with multiple tenants can clear the tenant selection\n setSelectedTenantID(undefined)\n deleteCookie()\n } else {\n // if there is only one tenant, force the selection of that tenant\n setSelectedTenantID(tenantOptions[0]?.value)\n setCookie(String(tenantOptions[0]?.value))\n }\n } else if (!tenantOptions.find((option) => option.value === id)) {\n // if the tenant is not valid, set the first tenant as selected\n if (tenantOptions?.[0]?.value) {\n setTenant({ id: tenantOptions[0].value, refresh: true })\n } else {\n setTenant({ id: undefined, refresh: true })\n }\n } else {\n // if the tenant is in the options, set it as selected\n setSelectedTenantID(id)\n setCookie(String(id))\n }\n if (entityType !== 'document' && refresh) {\n router.refresh()\n }\n },\n [deleteCookie, entityType, router, setCookie, tenantOptions],\n )\n\n const syncTenants = React.useCallback(async () => {\n try {\n const req = await fetch(\n `${config.serverURL}${config.routes.api}/${tenantsCollectionSlug}?select[${useAsTitle}]=true&limit=0&depth=0`,\n {\n credentials: 'include',\n method: 'GET',\n },\n )\n\n const result = await req.json()\n\n if (result.docs) {\n setTenantOptions(\n result.docs.map((doc: Record<string, number | string>) => ({\n label: doc[useAsTitle],\n value: doc.id,\n })),\n )\n }\n } catch (e) {\n toast.error(`Error fetching tenants`)\n }\n }, [config.serverURL, config.routes.api, tenantsCollectionSlug, useAsTitle])\n\n const updateTenants = React.useCallback<ContextType['updateTenants']>(\n ({ id, label }) => {\n setTenantOptions((prev) => {\n return prev.map((currentTenant) => {\n if (id === currentTenant.value) {\n return {\n label,\n value: id,\n }\n }\n return currentTenant\n })\n })\n\n void syncTenants()\n },\n [syncTenants],\n )\n\n React.useEffect(() => {\n if (userID && !tenantCookie) {\n if (tenantOptionsFromProps.length === 1) {\n // Users with no cookie set and only 1 tenant should set that tenant automatically\n setTenant({ id: tenantOptionsFromProps[0]?.value, refresh: true })\n setTenantOptions(tenantOptionsFromProps)\n } else if ((!tenantOptions || tenantOptions.length === 0) && tenantOptionsFromProps) {\n // If there are no tenant options, set them from the props\n setTenantOptions(tenantOptionsFromProps)\n }\n }\n }, [\n initialValue,\n selectedTenantID,\n tenantCookie,\n userID,\n setTenant,\n tenantOptionsFromProps,\n tenantOptions,\n ])\n\n React.useEffect(() => {\n if (!userID && tenantCookie) {\n // User is not logged in, but has a tenant cookie, delete it\n deleteCookie()\n setSelectedTenantID(undefined)\n } else if (userID) {\n // User changed, refresh\n router.refresh()\n }\n }, [userID, tenantCookie, deleteCookie, router])\n\n return (\n <span\n data-selected-tenant-id={selectedTenantID}\n data-selected-tenant-title={selectedTenantLabel}\n >\n <Context\n value={{\n entityType,\n modified,\n options: tenantOptions,\n selectedTenantID,\n setEntityType,\n setModified,\n setTenant,\n syncTenants,\n updateTenants,\n }}\n >\n {children}\n </Context>\n </span>\n )\n}\n\nexport const useTenantSelection = () => React.use(Context)\n"],"names":["toast","useAuth","useConfig","useRouter","React","createContext","Context","entityType","undefined","options","selectedTenantID","setEntityType","setModified","setTenant","syncTenants","Promise","resolve","updateTenants","TenantSelectionProviderClient","children","initialValue","tenantCookie","tenantOptions","tenantOptionsFromProps","tenantsCollectionSlug","useAsTitle","setSelectedTenantID","useState","modified","user","config","userID","useMemo","id","setTenantOptions","selectedTenantLabel","find","option","value","label","router","setCookie","useCallback","expires","document","cookie","deleteCookie","refresh","length","String","req","fetch","serverURL","routes","api","credentials","method","result","json","docs","map","doc","e","error","prev","currentTenant","useEffect","span","data-selected-tenant-id","data-selected-tenant-title","useTenantSelection","use"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/providers/TenantSelectionProvider/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAgB,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAA;AAO1D,KAAK,IAAI,GAAG;IACV,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,OAAO,EAAE,OAAO,CAAA;IAChB,qBAAqB,EAAE,MAAM,CAAA;IAC7B,UAAU,EAAE,MAAM,CAAA;IAClB,IAAI,EAAE,IAAI,CAAA;CACX,CAAA;AAED,eAAO,MAAM,uBAAuB,oEAMjC,IAAI,yCAkDN,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/providers/TenantSelectionProvider/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAgB,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAA;AAO1D,KAAK,IAAI,GAAG;IACV,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,OAAO,EAAE,OAAO,CAAA;IAChB,qBAAqB,EAAE,MAAM,CAAA;IAC7B,UAAU,EAAE,MAAM,CAAA;IAClB,IAAI,EAAE,IAAI,CAAA;CACX,CAAA;AAED,eAAO,MAAM,uBAAuB,oEAMjC,IAAI,yCAoDN,CAAA"}
@@ -40,6 +40,8 @@ export const TenantSelectionProvider = async ({ children, payload, tenantsCollec
40
40
  initialValue: initialValue,
41
41
  tenantCookie: tenantCookie,
42
42
  tenantOptions: tenantOptions,
43
+ tenantsCollectionSlug: tenantsCollectionSlug,
44
+ useAsTitle: useAsTitle,
43
45
  children: children
44
46
  });
45
47
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/providers/TenantSelectionProvider/index.tsx"],"sourcesContent":["import type { OptionObject, Payload, User } from 'payload'\n\nimport { cookies as getCookies } from 'next/headers.js'\n\nimport { findTenantOptions } from '../../queries/findTenantOptions.js'\nimport { TenantSelectionProviderClient } from './index.client.js'\n\ntype Args = {\n children: React.ReactNode\n payload: Payload\n tenantsCollectionSlug: string\n useAsTitle: string\n user: User\n}\n\nexport const TenantSelectionProvider = async ({\n children,\n payload,\n tenantsCollectionSlug,\n useAsTitle,\n user,\n}: Args) => {\n let tenantOptions: OptionObject[] = []\n\n try {\n const { docs } = await findTenantOptions({\n limit: 0,\n payload,\n tenantsCollectionSlug,\n useAsTitle,\n user,\n })\n tenantOptions = docs.map((doc) => ({\n label: String(doc[useAsTitle]),\n value: doc.id,\n }))\n } catch (_) {\n // user likely does not have access\n }\n\n const cookies = await getCookies()\n let tenantCookie = cookies.get('payload-tenant')?.value\n let initialValue = undefined\n\n /**\n * Ensure the cookie is a valid tenant\n */\n if (tenantCookie) {\n const matchingOption = tenantOptions.find((option) => String(option.value) === tenantCookie)\n if (matchingOption) {\n initialValue = matchingOption.value\n }\n }\n\n /**\n * If the there was no cookie or the cookie was an invalid tenantID set intialValue\n */\n if (!initialValue) {\n tenantCookie = undefined\n initialValue = tenantOptions.length > 1 ? undefined : tenantOptions[0]?.value\n }\n\n return (\n <TenantSelectionProviderClient\n initialValue={initialValue}\n tenantCookie={tenantCookie}\n tenantOptions={tenantOptions}\n >\n {children}\n </TenantSelectionProviderClient>\n )\n}\n"],"names":["cookies","getCookies","findTenantOptions","TenantSelectionProviderClient","TenantSelectionProvider","children","payload","tenantsCollectionSlug","useAsTitle","user","tenantOptions","docs","limit","map","doc","label","String","value","id","_","tenantCookie","get","initialValue","undefined","matchingOption","find","option","length"],"mappings":";AAEA,SAASA,WAAWC,UAAU,QAAQ,kBAAiB;AAEvD,SAASC,iBAAiB,QAAQ,qCAAoC;AACtE,SAASC,6BAA6B,QAAQ,oBAAmB;AAUjE,OAAO,MAAMC,0BAA0B,OAAO,EAC5CC,QAAQ,EACRC,OAAO,EACPC,qBAAqB,EACrBC,UAAU,EACVC,IAAI,EACC;IACL,IAAIC,gBAAgC,EAAE;IAEtC,IAAI;QACF,MAAM,EAAEC,IAAI,EAAE,GAAG,MAAMT,kBAAkB;YACvCU,OAAO;YACPN;YACAC;YACAC;YACAC;QACF;QACAC,gBAAgBC,KAAKE,GAAG,CAAC,CAACC,MAAS,CAAA;gBACjCC,OAAOC,OAAOF,GAAG,CAACN,WAAW;gBAC7BS,OAAOH,IAAII,EAAE;YACf,CAAA;IACF,EAAE,OAAOC,GAAG;IACV,mCAAmC;IACrC;IAEA,MAAMnB,UAAU,MAAMC;IACtB,IAAImB,eAAepB,QAAQqB,GAAG,CAAC,mBAAmBJ;IAClD,IAAIK,eAAeC;IAEnB;;GAEC,GACD,IAAIH,cAAc;QAChB,MAAMI,iBAAiBd,cAAce,IAAI,CAAC,CAACC,SAAWV,OAAOU,OAAOT,KAAK,MAAMG;QAC/E,IAAII,gBAAgB;YAClBF,eAAeE,eAAeP,KAAK;QACrC;IACF;IAEA;;GAEC,GACD,IAAI,CAACK,cAAc;QACjBF,eAAeG;QACfD,eAAeZ,cAAciB,MAAM,GAAG,IAAIJ,YAAYb,aAAa,CAAC,EAAE,EAAEO;IAC1E;IAEA,qBACE,KAACd;QACCmB,cAAcA;QACdF,cAAcA;QACdV,eAAeA;kBAEdL;;AAGP,EAAC"}
1
+ {"version":3,"sources":["../../../src/providers/TenantSelectionProvider/index.tsx"],"sourcesContent":["import type { OptionObject, Payload, User } from 'payload'\n\nimport { cookies as getCookies } from 'next/headers.js'\n\nimport { findTenantOptions } from '../../queries/findTenantOptions.js'\nimport { TenantSelectionProviderClient } from './index.client.js'\n\ntype Args = {\n children: React.ReactNode\n payload: Payload\n tenantsCollectionSlug: string\n useAsTitle: string\n user: User\n}\n\nexport const TenantSelectionProvider = async ({\n children,\n payload,\n tenantsCollectionSlug,\n useAsTitle,\n user,\n}: Args) => {\n let tenantOptions: OptionObject[] = []\n\n try {\n const { docs } = await findTenantOptions({\n limit: 0,\n payload,\n tenantsCollectionSlug,\n useAsTitle,\n user,\n })\n tenantOptions = docs.map((doc) => ({\n label: String(doc[useAsTitle]),\n value: doc.id,\n }))\n } catch (_) {\n // user likely does not have access\n }\n\n const cookies = await getCookies()\n let tenantCookie = cookies.get('payload-tenant')?.value\n let initialValue = undefined\n\n /**\n * Ensure the cookie is a valid tenant\n */\n if (tenantCookie) {\n const matchingOption = tenantOptions.find((option) => String(option.value) === tenantCookie)\n if (matchingOption) {\n initialValue = matchingOption.value\n }\n }\n\n /**\n * If the there was no cookie or the cookie was an invalid tenantID set intialValue\n */\n if (!initialValue) {\n tenantCookie = undefined\n initialValue = tenantOptions.length > 1 ? undefined : tenantOptions[0]?.value\n }\n\n return (\n <TenantSelectionProviderClient\n initialValue={initialValue}\n tenantCookie={tenantCookie}\n tenantOptions={tenantOptions}\n tenantsCollectionSlug={tenantsCollectionSlug}\n useAsTitle={useAsTitle}\n >\n {children}\n </TenantSelectionProviderClient>\n )\n}\n"],"names":["cookies","getCookies","findTenantOptions","TenantSelectionProviderClient","TenantSelectionProvider","children","payload","tenantsCollectionSlug","useAsTitle","user","tenantOptions","docs","limit","map","doc","label","String","value","id","_","tenantCookie","get","initialValue","undefined","matchingOption","find","option","length"],"mappings":";AAEA,SAASA,WAAWC,UAAU,QAAQ,kBAAiB;AAEvD,SAASC,iBAAiB,QAAQ,qCAAoC;AACtE,SAASC,6BAA6B,QAAQ,oBAAmB;AAUjE,OAAO,MAAMC,0BAA0B,OAAO,EAC5CC,QAAQ,EACRC,OAAO,EACPC,qBAAqB,EACrBC,UAAU,EACVC,IAAI,EACC;IACL,IAAIC,gBAAgC,EAAE;IAEtC,IAAI;QACF,MAAM,EAAEC,IAAI,EAAE,GAAG,MAAMT,kBAAkB;YACvCU,OAAO;YACPN;YACAC;YACAC;YACAC;QACF;QACAC,gBAAgBC,KAAKE,GAAG,CAAC,CAACC,MAAS,CAAA;gBACjCC,OAAOC,OAAOF,GAAG,CAACN,WAAW;gBAC7BS,OAAOH,IAAII,EAAE;YACf,CAAA;IACF,EAAE,OAAOC,GAAG;IACV,mCAAmC;IACrC;IAEA,MAAMnB,UAAU,MAAMC;IACtB,IAAImB,eAAepB,QAAQqB,GAAG,CAAC,mBAAmBJ;IAClD,IAAIK,eAAeC;IAEnB;;GAEC,GACD,IAAIH,cAAc;QAChB,MAAMI,iBAAiBd,cAAce,IAAI,CAAC,CAACC,SAAWV,OAAOU,OAAOT,KAAK,MAAMG;QAC/E,IAAII,gBAAgB;YAClBF,eAAeE,eAAeP,KAAK;QACrC;IACF;IAEA;;GAEC,GACD,IAAI,CAACK,cAAc;QACjBF,eAAeG;QACfD,eAAeZ,cAAciB,MAAM,GAAG,IAAIJ,YAAYb,aAAa,CAAC,EAAE,EAAEO;IAC1E;IAEA,qBACE,KAACd;QACCmB,cAAcA;QACdF,cAAcA;QACdV,eAAeA;QACfH,uBAAuBA;QACvBC,YAAYA;kBAEXH;;AAGP,EAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@payloadcms/plugin-multi-tenant",
3
- "version": "3.44.0",
3
+ "version": "3.45.0-canary.0",
4
4
  "description": "Multi Tenant plugin for Payload",
5
5
  "keywords": [
6
6
  "payload",
@@ -80,15 +80,15 @@
80
80
  "types.d.ts"
81
81
  ],
82
82
  "devDependencies": {
83
- "@payloadcms/translations": "3.44.0",
84
- "@payloadcms/ui": "3.44.0",
85
83
  "@payloadcms/eslint-config": "3.28.0",
86
- "payload": "3.44.0"
84
+ "@payloadcms/translations": "3.45.0-canary.0",
85
+ "@payloadcms/ui": "3.45.0-canary.0",
86
+ "payload": "3.45.0-canary.0"
87
87
  },
88
88
  "peerDependencies": {
89
89
  "next": "^15.2.3",
90
- "@payloadcms/ui": "3.44.0",
91
- "payload": "3.44.0"
90
+ "@payloadcms/ui": "3.45.0-canary.0",
91
+ "payload": "3.45.0-canary.0"
92
92
  },
93
93
  "homepage:": "https://payloadcms.com",
94
94
  "scripts": {