@firecms/user_management 3.0.0-canary.15 → 3.0.0-canary.151

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.umd.js CHANGED
@@ -1,2 +1,1652 @@
1
- (function(i,c){typeof exports=="object"&&typeof module<"u"?c(exports,require("react"),require("firebase/firestore"),require("react/jsx-runtime"),require("@firecms/ui"),require("yup"),require("@firecms/core"),require("@firecms/formex"),require("date-fns"),require("date-fns/locale")):typeof define=="function"&&define.amd?define(["exports","react","firebase/firestore","react/jsx-runtime","@firecms/ui","yup","@firecms/core","@firecms/formex","date-fns","date-fns/locale"],c):(i=typeof globalThis<"u"?globalThis:i||self,c(i.FireCMS={},i.React,i.firestore,i.jsxRuntime,i.ui,i.Yup,i.core,i.formex,i.dateFns,i.locales))})(this,function(i,c,N,e,l,se,S,P,re,ne){"use strict";function z(s){const r=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(s){for(const o in s)if(o!=="default"){const d=Object.getOwnPropertyDescriptor(s,o);Object.defineProperty(r,o,d.get?d:{enumerable:!0,get:()=>s[o]})}}return r.default=s,Object.freeze(r)}const B=z(se),ae=z(ne),te=["Admin"],ie={read:!1,edit:!1,create:!1,delete:!1};function J({collection:s,user:r}){const o=r?.roles;if(o){if(s.ownerId===r?.uid)return{read:!0,create:!0,edit:!0,delete:!0};{const d={read:!1,create:!1,edit:!1,delete:!1};return o.map(n=>ce(n,s.id)).reduce(Y,d)}}else return ie}function ce(s,r){const o={read:s.isAdmin||s.defaultPermissions?.read,create:s.isAdmin||s.defaultPermissions?.create,edit:s.isAdmin||s.defaultPermissions?.edit,delete:s.isAdmin||s.defaultPermissions?.delete};return s.collectionPermissions&&s.collectionPermissions[r]?Y(s.collectionPermissions[r],o):s.defaultPermissions?Y(s.defaultPermissions,o):o}const Y=(s,r)=>({read:s.read||r.read,create:s.create||r.create,edit:s.edit||r.edit,delete:s.delete||r.delete});function de(s,r){return s?r.roles?r.roles.map(o=>s.find(d=>d.id===o.id)).filter(Boolean):[]:void 0}const H=(s,r)=>{const o=s.map(n=>n.id),d=r.map(n=>n.id);return o.length===r.length&&o.every(n=>d.includes(n))};function he(s,r){if(!r)return;const o=Ce(r),d=new Date(o.exp*1e3);localStorage.setItem(`auth_token::${s}`,JSON.stringify({token:r,expiry:d}))}function fe(s){const r=localStorage.getItem(`auth_token::${s}`);if(r){const o=JSON.parse(r);if(o.expiry=new Date(o.expiry),o.expiry>new Date)return o.token}}function ge(){for(let s=0;s<localStorage.length;s++){const r=localStorage.key(s);r?.startsWith("auth_token::")&&localStorage.removeItem(r)}}function Ce(s){if(!s)throw new Error("No JWT token");const o=s.split(".")[1].replace(/-/g,"+").replace(/_/g,"/"),d=decodeURIComponent(window.atob(o).split("").map(function(n){return"%"+("00"+n.charCodeAt(0).toString(16)).slice(-2)}).join(""));return JSON.parse(d)}function pe(s,r=10){if(!/^#([0-9A-Fa-f]{3}){1,2}$/.test(s))throw new Error("Invalid color format");let o=s.substring(1).split("");o.length===3&&(o=[o[0],o[0],o[1],o[1],o[2],o[2]]);let d=parseInt(o[0]+o[1],16),n=parseInt(o[2]+o[3],16),g=parseInt(o[4]+o[5],16);return d=Math.floor(d*(1-r/100)),n=Math.floor(n*(1-r/100)),g=Math.floor(g*(1-r/100)),"#"+(d<16?"0":"")+d.toString(16)+(n<16?"0":"")+n.toString(16)+(g<16?"0":"")+g.toString(16)}function me(s,r=10){if(!/^#([0-9A-Fa-f]{3}){1,2}$/.test(s))throw new Error("Invalid color format");let o=s.substring(1).split("");o.length===3&&(o=[o[0],o[0],o[1],o[1],o[2],o[2]]);const d=parseInt(o[0]+o[1],16),n=parseInt(o[2]+o[3],16),g=parseInt(o[4]+o[5],16),u=r/100;return`rgba(${d}, ${n}, ${g}, ${u})`}function be({firebaseApp:s,usersPath:r="__FIRECMS/config/users",rolesPath:o="__FIRECMS/config/roles",usersLimit:d,canEditRoles:n=!0,allowDefaultRolesCreation:g,includeCollectionConfigPermissions:u}){const C=c.useRef(),[U,v]=c.useState(!0),[h,x]=c.useState(!0),[T,t]=c.useState([]),[m,I]=c.useState([]),w=m.map(b=>({...b,roles:T.filter(y=>b.roles?.includes(y.id))})),[q,V]=c.useState(),[p,f]=c.useState(),D=U||h;c.useEffect(()=>{s&&(C.current=N.getFirestore(s))},[s]),c.useEffect(()=>{if(!s||!o)return;const b=N.getFirestore(s);return N.onSnapshot(N.collection(b,o),{next:y=>{V(void 0);try{const k=ve(y.docs);t(k)}catch(k){V(k)}v(!1)},error:y=>{V(y),v(!1)}})},[s,o]),c.useEffect(()=>{if(!s||!r)return;const b=N.getFirestore(s);return N.onSnapshot(N.collection(b,r),{next:y=>{f(void 0);try{const k=ue(y.docs);I(k)}catch(k){f(k)}x(!1)},error:y=>{f(y),x(!1)}})},[s,r]);const F=c.useCallback(async b=>{const y=C.current;if(!y||!r)throw Error("useFirestoreConfigurationPersistence Firestore not initialised");console.debug("Persisting user",b);const k=b.roles?.map(ke=>ke.id),{uid:$,...W}=b;return N.setDoc(N.doc(y,r,$),{...W,roles:k},{merge:!0}).then(()=>b)},[r]),A=c.useCallback(b=>{const y=C.current;if(!y||!o)throw Error("useFirestoreConfigurationPersistence Firestore not initialised");console.debug("Persisting role",b);const{id:k,...$}=b,W=N.doc(y,o,k);return N.setDoc(W,$,{merge:!0})},[o]),a=c.useCallback(async b=>{const y=C.current;if(!y||!r)throw Error("useFirestoreConfigurationPersistence Firestore not initialised");console.debug("Deleting",b);const{uid:k}=b;return N.deleteDoc(N.doc(y,r,k))},[r]),E=c.useCallback(b=>{const y=C.current;if(!y||!o)throw Error("useFirestoreConfigurationPersistence Firestore not initialised");console.debug("Deleting",b);const{id:k}=b,$=N.doc(y,o,k);return N.deleteDoc($)},[o]),L=c.useCallback(({collection:b,user:y})=>J({collection:b,user:y}),[]),M=w.map(b=>b.uid),De=c.useCallback(b=>{if(!w)throw Error("Users not loaded");return w.find(k=>k.email?.toLowerCase()===b?.email?.toLowerCase())?.roles},[M]);return{loading:D,roles:T,users:w,saveUser:F,saveRole:A,deleteUser:a,deleteRole:E,usersLimit:d,canEditRoles:n===void 0?!0:n,allowDefaultRolesCreation:g===void 0?!0:g,includeCollectionConfigPermissions:!!u,collectionPermissions:L,defineRolesFor:De}}const ue=s=>s.map(r=>{const o=r.data();return{uid:r.id,...o,created_on:o?.created_on?.toDate(),updated_on:o?.updated_on?.toDate()}}),ve=s=>s.map(r=>({id:r.id,...r.data()})),j=c.createContext({});function G({children:s,userManagement:r}){return e.jsx(j.Provider,{value:r,children:s})}const _=()=>c.useContext(j);function O({role:s}){let r;return s.isAdmin?r="blueDarker":s.id==="editor"?r="yellowLight":s.id==="viewer"?r="grayLight":r=l.getColorSchemeForSeed(s.id),e.jsx(l.Chip,{colorScheme:r,children:s.name},s.id)}const K=B.object().shape({id:B.string().required("Required"),name:B.string().required("Required")});function Q({open:s,role:r,editable:o,handleClose:d,collections:n}){const{saveRole:g}=_(),u=!r,[C,U]=c.useState(),v=c.useCallback(a=>(U(void 0),g(a)),[g]),h=P.useCreateFormex({initialValues:r??{name:""},onSubmit:(a,E)=>v(a).then(()=>{E.resetForm({values:a}),d()}).catch(L=>U(L)),validation:a=>K.validate(a,{abortEarly:!1}).then(()=>({})).catch(E=>{const L={};return E.inner.forEach(M=>{L[M.path]=M.message}),L})}),{isSubmitting:x,touched:T,values:t,errors:m,handleChange:I,setFieldValue:w,dirty:q,setFieldTouched:V}=h,p=t.isAdmin??!1,f=t.defaultPermissions?.create??!1,D=t.defaultPermissions?.read??!1,F=t.defaultPermissions?.edit??!1,A=t.defaultPermissions?.delete??!1;return c.useEffect(()=>{!P.getIn(T,"id")&&t.name&&w("id",S.toSnakeCase(t.name))},[T,t.name]),e.jsx(l.Dialog,{open:s,maxWidth:"4xl",children:e.jsx(P.Formex,{value:h,children:e.jsxs("form",{noValidate:!0,autoComplete:"off",onSubmit:h.handleSubmit,style:{display:"flex",flexDirection:"column",position:"relative",height:"100%"},children:[e.jsxs(l.DialogContent,{className:"flex-grow",children:[e.jsx("div",{className:"flex flex-row pt-12 pb-8",children:e.jsx(l.Typography,{variant:"h4",className:"flex-grow",children:"Role"})}),e.jsxs("div",{className:"grid grid-cols-12 gap-8",children:[e.jsxs("div",{className:"col-span-12 md:col-span-8",children:[e.jsx(l.TextField,{name:"name",required:!0,error:T.name&&!!m.name,value:t.name,disabled:p||!o,onChange:I,"aria-describedby":"name-helper-text",label:"Name"}),e.jsx(S.FieldCaption,{children:T.name&&m.name?m.name:"Name of this role"})]}),e.jsxs("div",{className:"col-span-12 md:col-span-4",children:[e.jsx(l.TextField,{name:"id",required:!0,error:T.id&&!!m.id,value:t.id,disabled:!u||!o,onChange:a=>{I(a),V("id",!0)},"aria-describedby":"id-helper-text",label:"ID"}),e.jsx(S.FieldCaption,{children:T.id&&m.id?m.id:"ID of this role"})]}),e.jsxs("div",{className:"col-span-12",children:[e.jsx(l.Paper,{className:"bg-inherit",children:e.jsxs(l.Table,{children:[e.jsxs(l.TableHeader,{children:[e.jsx(l.TableCell,{}),e.jsx(l.TableCell,{align:"center",children:"Create entities"}),e.jsx(l.TableCell,{align:"center",children:"Read entities"}),e.jsx(l.TableCell,{align:"center",children:"Update entities"}),e.jsx(l.TableCell,{align:"center",children:"Delete entities"})]}),e.jsxs(l.TableBody,{children:[e.jsxs(l.TableRow,{children:[e.jsx(l.TableCell,{scope:"row",children:e.jsx("strong",{children:"All collections"})}),e.jsx(l.TableCell,{align:"center",children:e.jsx(l.Tooltip,{title:"Create entities in collections",children:e.jsx(l.Checkbox,{disabled:p||!o,checked:(p||f)??!1,onCheckedChange:a=>w("defaultPermissions.create",a)})})}),e.jsx(l.TableCell,{align:"center",children:e.jsx(l.Tooltip,{title:"Access all data in every collection",children:e.jsx(l.Checkbox,{disabled:p||!o,checked:(p||D)??!1,onCheckedChange:a=>w("defaultPermissions.read",a)})})}),e.jsx(l.TableCell,{align:"center",children:e.jsx(l.Tooltip,{title:"Update data in any collection",children:e.jsx(l.Checkbox,{disabled:p||!o,checked:(p||F)??!1,onCheckedChange:a=>w("defaultPermissions.edit",a)})})}),e.jsx(l.TableCell,{align:"center",children:e.jsx(l.Tooltip,{title:"Delete data in any collection",children:e.jsx(l.Checkbox,{disabled:p||!o,checked:(p||A)??!1,onCheckedChange:a=>w("defaultPermissions.delete",a)})})})]}),n&&n.map(a=>e.jsxs(l.TableRow,{children:[e.jsx(l.TableCell,{scope:"row",children:a.name}),e.jsx(l.TableCell,{align:"center",children:e.jsx(l.Checkbox,{disabled:p||f||!o,checked:(p||f||P.getIn(t,`collectionPermissions.${a.path}.create`))??!1,onCheckedChange:E=>w(`collectionPermissions.${a.path}.create`,E)})}),e.jsx(l.TableCell,{align:"center",children:e.jsx(l.Checkbox,{disabled:p||D||!o,checked:(p||D||P.getIn(t,`collectionPermissions.${a.path}.read`))??!1,onCheckedChange:E=>w(`collectionPermissions.${a.path}.read`,E)})}),e.jsx(l.TableCell,{align:"center",children:e.jsx(l.Checkbox,{disabled:p||F||!o,checked:(p||F||P.getIn(t,`collectionPermissions.${a.path}.edit`))??!1,onCheckedChange:E=>w(`collectionPermissions.${a.path}.edit`,E)})}),e.jsx(l.TableCell,{align:"center",children:e.jsx(l.Checkbox,{disabled:p||A||!o,checked:(p||A||P.getIn(t,`collectionPermissions.${a.path}.delete`))??!1,onCheckedChange:E=>w(`collectionPermissions.${a.path}.delete`,E)})})]},a.name))]})]})}),e.jsx(S.FieldCaption,{children:"You can customise the permissions that the users related to this role can perform in the entities of each collection"})]}),e.jsxs("div",{className:"col-span-12 md:col-span-4",children:[e.jsxs(l.Select,{error:T.config&&!!m.config,id:"createCollections",name:"createCollections",label:"Create collections",position:"item-aligned",disabled:p||!o,onChange:a=>w("config.createCollections",a.target.value==="true"),value:p||t.config?.createCollections?"true":"false",renderValue:a=>a==="true"?"Yes":"No",children:[e.jsx(l.SelectItem,{value:"true",children:" Yes "}),e.jsx(l.SelectItem,{value:"false",children:" No "})]}),e.jsx(S.FieldCaption,{children:T.config&&m.config?m.config:"Can the user create collections"})]}),e.jsxs("div",{className:"col-span-12 md:col-span-4",children:[e.jsxs(l.Select,{error:T.config&&!!m.config,id:"editCollections",name:"editCollections",label:"Edit collections",disabled:p||!o,position:"item-aligned",onChange:a=>w("config.editCollections",a.target.value==="own"?"own":a.target.value==="true"),value:p?"true":t.config?.editCollections==="own"?"own":t.config?.editCollections?"true":"false",renderValue:a=>a==="own"?"Own":a==="true"?"Yes":"No",children:[e.jsx(l.SelectItem,{value:"true",children:" Yes "}),e.jsx(l.SelectItem,{value:"false",children:" No "}),e.jsx(l.SelectItem,{value:"own",children:" Only his/her own "})]}),e.jsx(S.FieldCaption,{children:T.config&&m.config?m.config:"Can the user edit collections"})]}),e.jsxs("div",{className:"col-span-12 md:col-span-4",children:[e.jsxs(l.Select,{error:T.config&&!!m.config,id:"deleteCollections",name:"deleteCollections",label:"Delete collections",disabled:p||!o,position:"item-aligned",onChange:a=>w("config.deleteCollections",a.target.value==="own"?"own":a.target.value==="true"),value:p?"true":t.config?.deleteCollections==="own"?"own":t.config?.deleteCollections?"true":"false",renderValue:a=>a==="own"?"Own":a==="true"?"Yes":"No",children:[e.jsx(l.SelectItem,{value:"true",children:" Yes "}),e.jsx(l.SelectItem,{value:"false",children:" No "}),e.jsx(l.SelectItem,{value:"own",children:" Only his/her own "})]}),e.jsx(S.FieldCaption,{children:T.config&&m.config?m.config:"Can the user delete collections"})]})]})]}),e.jsxs(l.DialogActions,{position:"sticky",children:[C&&e.jsx(l.Typography,{className:"text-red-500",children:"There was an error saving this role"}),e.jsx(l.Button,{variant:"text",onClick:()=>{d()},children:"Cancel"}),e.jsx(l.LoadingButton,{variant:"filled",color:"primary",type:"submit",disabled:!q,loading:x,startIcon:e.jsx(l.DoneIcon,{}),children:u?"Create role":"Update"})]})]})})})}const we=[{id:"admin",name:"Admin",isAdmin:!0},{id:"editor",name:"Editor",isAdmin:!1,defaultPermissions:{read:!0,create:!0,edit:!0,delete:!0},config:{createCollections:!0,editCollections:"own",deleteCollections:"own"}},{id:"viewer",name:"Viewer",isAdmin:!1,defaultPermissions:{read:!0,create:!1,edit:!1,delete:!1}}];function X({onRoleClicked:s,editable:r}){const{roles:o,saveRole:d,deleteRole:n,allowDefaultRolesCreation:g}=_(),[u,C]=c.useState(void 0),[U,v]=c.useState(!1);return e.jsxs("div",{className:"w-full overflow-auto",children:[e.jsxs(l.Table,{children:[e.jsxs(l.TableHeader,{children:[e.jsx(l.TableCell,{header:!0,className:"w-16"}),e.jsx(l.TableCell,{header:!0,children:"Role"}),e.jsx(l.TableCell,{header:!0,className:"items-center",children:"Is Admin"}),e.jsx(l.TableCell,{header:!0,children:"Default permissions"})]}),e.jsxs(l.TableBody,{children:[o&&o.map(h=>{const x=h.isAdmin||h.defaultPermissions?.create,T=h.isAdmin||h.defaultPermissions?.read,t=h.isAdmin||h.defaultPermissions?.edit,m=h.isAdmin||h.defaultPermissions?.delete;return e.jsxs(l.TableRow,{onClick:()=>{s(h)},children:[e.jsx(l.TableCell,{style:{width:"64px"},children:!h.isAdmin&&e.jsx(l.Tooltip,{title:"Delete this role",children:e.jsx(l.IconButton,{size:"small",disabled:!r,onClick:I=>(I.stopPropagation(),C(h)),children:e.jsx(l.DeleteIcon,{})})})}),e.jsx(l.TableCell,{children:e.jsx(O,{role:h})}),e.jsx(l.TableCell,{className:"items-center",children:e.jsx(l.Checkbox,{checked:h.isAdmin??!1})}),e.jsx(l.TableCell,{children:e.jsxs("ul",{children:[x&&e.jsx("li",{children:"Create"}),T&&e.jsx("li",{children:"Read"}),t&&e.jsx("li",{children:"Update"}),m&&e.jsx("li",{children:"Delete"})]})})]},h.name)}),(!o||o.length===0)&&e.jsx(l.TableRow,{children:e.jsx(l.TableCell,{colspan:4,children:e.jsxs(l.CenteredView,{className:"flex flex-col gap-4 my-8 items-center",children:[e.jsx(l.Typography,{variant:"label",children:"You don't have any roles yet."}),g&&e.jsx(l.Button,{variant:"outlined",onClick:()=>{we.forEach(h=>{d(h)})},children:"Create default roles"})]})})})]})]}),e.jsx(S.DeleteConfirmationDialog,{open:!!u,loading:U,onAccept:()=>{u&&(v(!0),n(u).then(()=>{C(void 0)}).finally(()=>{v(!1)}))},onCancel:()=>{C(void 0)},title:e.jsx(e.Fragment,{children:"Delete?"}),body:e.jsx(e.Fragment,{children:"Are you sure you want to delete this role?"})})]})}const Z=c.memo(function({children:r}){const{collections:o}=S.useNavigationController(),[d,n]=c.useState(!1),[g,u]=c.useState(),{canEditRoles:C}=_(),U=c.useCallback(h=>{n(!0),u(h)},[]),v=()=>{u(void 0),n(!1)};return e.jsxs(l.Container,{className:"w-full flex flex-col py-4 gap-4",maxWidth:"6xl",children:[r,e.jsxs("div",{className:"flex items-center mt-12",children:[e.jsx(l.Typography,{gutterBottom:!0,variant:"h4",className:"flex-grow",component:"h4",children:"Roles"}),e.jsx(l.Tooltip,{title:C?void 0:"Update plans to customise roles",children:e.jsx(l.Button,{size:"large",disabled:!C,startIcon:e.jsx(l.AddIcon,{}),onClick:()=>n(!0),children:"Add role"})})]}),e.jsx(X,{onRoleClicked:U,editable:!!C}),e.jsx(Q,{open:d,role:g,editable:C,collections:o,handleClose:v},g?.id??"new")]})}),R=B.object().shape({displayName:B.string().required("Required"),email:B.string().email().required("Required"),roles:B.array().min(1)});function ye(s,r,o,d,n){const g=o.filter(v=>v.roles?.map(h=>h.id).includes("admin")),u=s.roles?.map(v=>v.id).includes("admin");if((!n||!H(n.roles??[],r.roles??[]))&&!u)throw new Error("Only admins can change roles");if(n&&n.roles?.map(v=>v.id).includes("admin")&&!r.roles?.map(v=>v.id).includes("admin")&&g.length===1)throw new Error("There must be at least one admin");return!0}function ee({open:s,user:r,handleClose:o}){const d=S.useSnackbarController(),{user:n}=S.useAuthController(),{saveUser:g,users:u,roles:C}=_(),U=!r,v=c.useCallback(f=>{if(!n)throw new Error("Logged user not found");try{return ye(n,f,u,C,r),g(f)}catch(D){return Promise.reject(D)}},[C,g,r,u,n]),h=P.useCreateFormex({initialValues:r??{displayName:"",email:"",roles:C.filter(f=>f.id==="editor")},validation:f=>R.validate(f,{abortEarly:!1}).then(()=>({})).catch(D=>D.inner.reduce((F,A)=>(F[A.path]=A.message,F),{})),onSubmit:(f,D)=>v(f).then(()=>{o(),D.resetForm({values:f})}).catch(F=>{d.open({type:"error",message:F.message})})}),{isSubmitting:x,touched:T,handleChange:t,values:m,errors:I,setFieldValue:w,dirty:q,handleSubmit:V,submitCount:p}=h;return e.jsx(l.Dialog,{open:s,onOpenChange:f=>f?void 0:o(),maxWidth:"4xl",children:e.jsx(P.Formex,{value:h,children:e.jsxs("form",{onSubmit:V,autoComplete:"off",noValidate:!0,style:{display:"flex",flexDirection:"column",position:"relative",height:"100%"},children:[e.jsxs(l.DialogContent,{className:"h-full flex-grow",children:[e.jsx("div",{className:"flex flex-row pt-4 pb-4",children:e.jsx(l.Typography,{variant:"h4",className:"flex-grow",children:"User"})}),e.jsxs("div",{className:"grid grid-cols-12 gap-8",children:[e.jsxs("div",{className:"col-span-12",children:[e.jsx(l.TextField,{name:"displayName",required:!0,error:p>0&&!!I.displayName,value:m.displayName??"",onChange:t,"aria-describedby":"name-helper-text",label:"Name"}),e.jsx(S.FieldCaption,{children:p>0&&I.displayName?I.displayName:"Name of this user"})]}),e.jsxs("div",{className:"col-span-12",children:[e.jsx(l.TextField,{required:!0,error:p>0&&!!I.email,name:"email",value:m.email??"",onChange:t,"aria-describedby":"email-helper-text",label:"Email"}),e.jsx(S.FieldCaption,{children:p>0&&I.email?I.email:"Email of this user"})]}),e.jsx("div",{className:"col-span-12",children:e.jsx(l.MultiSelect,{label:"Roles",value:m.roles?.map(f=>f.id)??[],onMultiValueChange:f=>w("roles",f.map(D=>C.find(F=>F.id===D))),renderValue:f=>{const D=C.find(F=>F.id===f);return D?e.jsx("div",{className:"flex flex-wrap space-x-2 space-y-2",children:e.jsx(O,{role:D},D?.id)}):null},children:C.map(f=>e.jsx(l.MultiSelectItem,{value:f.id,children:e.jsx(O,{role:f},f?.id)},f.id))})})]})]}),e.jsxs(l.DialogActions,{children:[e.jsx(l.Button,{variant:"text",onClick:()=>{o()},children:"Cancel"}),e.jsx(l.LoadingButton,{variant:"filled",color:"primary",type:"submit",disabled:!q,loading:x,startIcon:e.jsx(l.DoneIcon,{}),children:U?"Create user":"Update"})]})]})})})}function le({onUserClicked:s}){const{users:r,saveUser:o,deleteUser:d}=_(),n=S.useAuthController(),g=S.useSnackbarController(),u=S.useCustomizationController(),C=u?.locale?ae[u?.locale]:void 0,U=u?.dateTimeFormat??S.defaultDateFormat,[v,h]=c.useState(void 0),[x,T]=c.useState(!1);return e.jsxs("div",{className:"overflow-auto",children:[e.jsxs(l.Table,{children:[e.jsxs(l.TableHeader,{children:[e.jsx(l.TableCell,{className:"truncate w-16"}),e.jsx(l.TableCell,{children:"ID"}),e.jsx(l.TableCell,{children:"Email"}),e.jsx(l.TableCell,{children:"Name"}),e.jsx(l.TableCell,{children:"Roles"}),e.jsx(l.TableCell,{children:"Created on"})]}),e.jsxs(l.TableBody,{children:[r&&r.map(t=>{const m=t.roles,I=t.created_on?re.format(t.created_on,U,{locale:C}):"";return e.jsxs(l.TableRow,{onClick:()=>{s(t)},children:[e.jsx(l.TableCell,{className:"w-10",children:e.jsx(l.Tooltip,{title:"Delete this user",children:e.jsx(l.IconButton,{size:"small",onClick:w=>(w.stopPropagation(),h(t)),children:e.jsx(l.DeleteIcon,{})})})}),e.jsx(l.TableCell,{children:t.uid}),e.jsx(l.TableCell,{children:t.email}),e.jsx(l.TableCell,{className:"font-medium align-left",children:t.displayName}),e.jsx(l.TableCell,{className:"align-left",children:m?e.jsx("div",{className:"flex flex-wrap gap-2",children:m.map(w=>e.jsx(O,{role:w},w?.id))}):null}),e.jsx(l.TableCell,{children:I})]},"row_"+t.uid)}),(!r||r.length===0)&&e.jsx(l.TableRow,{children:e.jsx(l.TableCell,{colspan:6,children:e.jsxs(l.CenteredView,{className:"flex flex-col gap-4 my-8 items-center",children:[e.jsx(l.Typography,{variant:"label",children:"There are no users yet"}),e.jsx(l.Button,{variant:"outlined",onClick:()=>{if(!n.user?.uid)throw Error("UsersTable, authController misconfiguration");o({uid:n.user?.uid,email:n.user?.email,displayName:n.user?.displayName,photoURL:n.user?.photoURL,providerId:n.user?.providerId,isAnonymous:n.user?.isAnonymous,roles:[{id:"admin",name:"Admin"}],created_on:new Date}).then(()=>{g.open({type:"success",message:"User added successfully"})}).catch(t=>{g.open({type:"error",message:"Error adding user: "+t.message})})},children:"Add the logged user as an admin"})]})})})]})]}),e.jsx(S.DeleteConfirmationDialog,{open:!!v,loading:x,onAccept:()=>{v&&(T(!0),d(v).then(()=>{h(void 0)}).catch(t=>{g.open({type:"error",message:"Error deleting user: "+t.message})}).finally(()=>{T(!1)}))},onCancel:()=>{h(void 0)},title:e.jsx(e.Fragment,{children:"Delete?"}),body:e.jsx(e.Fragment,{children:"Are you sure you want to delete this user?"})})]})}const oe=function({children:r}){const[o,d]=c.useState(),[n,g]=c.useState(),{users:u,usersLimit:C}=_(),U=C!==void 0&&u&&u.length>=C,v=c.useCallback(x=>{g(x),d(!0)},[]),h=c.useCallback(()=>{d(!1),g(void 0)},[]);return e.jsxs(l.Container,{className:"w-full flex flex-col py-4 gap-4",maxWidth:"6xl",children:[r,e.jsxs("div",{className:"flex items-center mt-12",children:[e.jsx(l.Typography,{gutterBottom:!0,variant:"h4",className:"flex-grow",component:"h4",children:"Users"}),e.jsx(l.Button,{size:"large",disabled:U,startIcon:e.jsx(l.AddIcon,{}),onClick:()=>d(!0),children:"Add user"})]}),e.jsx(le,{onUserClicked:v}),e.jsx(ee,{open:o??!1,user:n,handleClose:h},n?.uid??"new")]})};function Te({userManagement:s}){return{key:"user_management",loading:s.loading,provider:{Component:G,props:{userManagement:s}}}}const Se=[{path:"users",name:"CMS Users",group:"Admin",icon:"face",view:e.jsx(oe,{})},{path:"roles",name:"Roles",group:"Admin",icon:"gpp_good",view:e.jsx(Z,{})}];i.RESERVED_GROUPS=te,i.RoleChip=O,i.RoleYupSchema=K,i.RolesDetailsForm=Q,i.RolesTable=X,i.RolesView=Z,i.UserDetailsForm=ee,i.UserManagementContext=j,i.UserManagementProvider=G,i.UserYupSchema=R,i.UsersTable=le,i.UsersView=oe,i.areRolesEqual=H,i.cacheDelegatedLoginToken=he,i.clearDelegatedLoginTokensCache=ge,i.darkenColor=pe,i.getDelegatedLoginTokenFromCache=fe,i.getUserRoles=de,i.hexToRgbaWithOpacity=me,i.resolveUserRolePermissions=J,i.useBuildFirestoreUserManagement=be,i.useUserManagement=_,i.useUserManagementPlugin=Te,i.userManagementAdminViews=Se,Object.defineProperty(i,Symbol.toStringTag,{value:"Module"})});
1
+ (function(global, factory) {
2
+ typeof exports === "object" && typeof module !== "undefined" ? factory(exports, require("react"), require("react-fast-compare"), require("@firecms/core"), require("react/jsx-runtime"), require("@firecms/ui"), require("yup"), require("@firecms/formex"), require("date-fns"), require("date-fns/locale")) : typeof define === "function" && define.amd ? define(["exports", "react", "react-fast-compare", "@firecms/core", "react/jsx-runtime", "@firecms/ui", "yup", "@firecms/formex", "date-fns", "date-fns/locale"], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self, factory(global.FireCMS = {}, global.React, global.equal, global.core, global.jsxRuntime, global.ui, global.Yup, global.formex, global.dateFns, global.locales));
3
+ })(this, function(exports2, React, equal, core, jsxRuntime, ui, Yup, formex, dateFns, locales) {
4
+ "use strict";
5
+ function _interopNamespaceDefault(e) {
6
+ const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
7
+ if (e) {
8
+ for (const k in e) {
9
+ if (k !== "default") {
10
+ const d = Object.getOwnPropertyDescriptor(e, k);
11
+ Object.defineProperty(n, k, d.get ? d : {
12
+ enumerable: true,
13
+ get: () => e[k]
14
+ });
15
+ }
16
+ }
17
+ }
18
+ n.default = e;
19
+ return Object.freeze(n);
20
+ }
21
+ const Yup__namespace = /* @__PURE__ */ _interopNamespaceDefault(Yup);
22
+ const locales__namespace = /* @__PURE__ */ _interopNamespaceDefault(locales);
23
+ const RESERVED_GROUPS = ["Admin"];
24
+ const DEFAULT_PERMISSIONS = {
25
+ read: false,
26
+ edit: false,
27
+ create: false,
28
+ delete: false
29
+ };
30
+ function resolveUserRolePermissions({
31
+ collection,
32
+ user
33
+ }) {
34
+ const roles = user?.roles;
35
+ if (!roles) {
36
+ return DEFAULT_PERMISSIONS;
37
+ } else if (collection.ownerId === user?.uid) {
38
+ return {
39
+ read: true,
40
+ create: true,
41
+ edit: true,
42
+ delete: true
43
+ };
44
+ } else {
45
+ const basePermissions = {
46
+ read: false,
47
+ create: false,
48
+ edit: false,
49
+ delete: false
50
+ };
51
+ return roles.map((role) => resolveCollectionRole(role, collection.id)).reduce(mergePermissions, basePermissions);
52
+ }
53
+ }
54
+ function resolveCollectionRole(role, id) {
55
+ const basePermissions = {
56
+ read: (role.isAdmin || role.defaultPermissions?.read) ?? false,
57
+ create: (role.isAdmin || role.defaultPermissions?.create) ?? false,
58
+ edit: (role.isAdmin || role.defaultPermissions?.edit) ?? false,
59
+ delete: (role.isAdmin || role.defaultPermissions?.delete) ?? false
60
+ };
61
+ const thisCollectionPermissions = role.collectionPermissions?.[id];
62
+ if (thisCollectionPermissions) {
63
+ return mergePermissions(thisCollectionPermissions, basePermissions);
64
+ } else if (role.defaultPermissions) {
65
+ return mergePermissions(role.defaultPermissions, basePermissions);
66
+ } else {
67
+ return basePermissions;
68
+ }
69
+ }
70
+ const mergePermissions = (permA, permB) => {
71
+ return {
72
+ read: permA.read || permB.read,
73
+ create: permA.create || permB.create,
74
+ edit: permA.edit || permB.edit,
75
+ delete: permA.delete || permB.delete
76
+ };
77
+ };
78
+ function getUserRoles(roles, fireCMSUser) {
79
+ return !roles ? void 0 : fireCMSUser.roles ? fireCMSUser.roles.map((role) => roles.find((r) => r.id === role.id)).filter(Boolean) : [];
80
+ }
81
+ const areRolesEqual = (rolesA, rolesB) => {
82
+ const rolesAIds = rolesA.map((r) => r.id);
83
+ const rolesBIds = rolesB.map((r) => r.id);
84
+ return rolesAIds.length === rolesB.length && rolesAIds.every((role) => rolesBIds.includes(role));
85
+ };
86
+ function cacheDelegatedLoginToken(projectId, delegatedToken) {
87
+ if (!delegatedToken) {
88
+ return;
89
+ }
90
+ const data = parseJwt(delegatedToken);
91
+ const expiry = new Date(data.exp * 1e3);
92
+ localStorage.setItem(`auth_token::${projectId}`, JSON.stringify({
93
+ token: delegatedToken,
94
+ expiry
95
+ }));
96
+ }
97
+ function getDelegatedLoginTokenFromCache(projectId) {
98
+ const entry = localStorage.getItem(`auth_token::${projectId}`);
99
+ if (entry) {
100
+ const data = JSON.parse(entry);
101
+ data.expiry = new Date(data.expiry);
102
+ if (data.expiry > /* @__PURE__ */ new Date()) {
103
+ return data.token;
104
+ }
105
+ }
106
+ return void 0;
107
+ }
108
+ function clearDelegatedLoginTokensCache() {
109
+ for (let i = 0; i < localStorage.length; i++) {
110
+ const key = localStorage.key(i);
111
+ if (key?.startsWith("auth_token::")) {
112
+ localStorage.removeItem(key);
113
+ }
114
+ }
115
+ }
116
+ function parseJwt(token) {
117
+ if (!token) {
118
+ throw new Error("No JWT token");
119
+ }
120
+ const base64Url = token.split(".")[1];
121
+ const base64 = base64Url.replace(/-/g, "+").replace(/_/g, "/");
122
+ const jsonPayload = decodeURIComponent(window.atob(base64).split("").map(function(c) {
123
+ return "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2);
124
+ }).join(""));
125
+ return JSON.parse(jsonPayload);
126
+ }
127
+ function darkenColor(hexColor, darkenBy = 10) {
128
+ if (!/^#([0-9A-Fa-f]{3}){1,2}$/.test(hexColor)) {
129
+ throw new Error("Invalid color format");
130
+ }
131
+ let color = hexColor.substring(1).split("");
132
+ if (color.length === 3) {
133
+ color = [color[0], color[0], color[1], color[1], color[2], color[2]];
134
+ }
135
+ let r = parseInt(color[0] + color[1], 16);
136
+ let g = parseInt(color[2] + color[3], 16);
137
+ let b = parseInt(color[4] + color[5], 16);
138
+ r = Math.floor(r * (1 - darkenBy / 100));
139
+ g = Math.floor(g * (1 - darkenBy / 100));
140
+ b = Math.floor(b * (1 - darkenBy / 100));
141
+ return "#" + (r < 16 ? "0" : "") + r.toString(16) + (g < 16 ? "0" : "") + g.toString(16) + (b < 16 ? "0" : "") + b.toString(16);
142
+ }
143
+ function hexToRgbaWithOpacity(hexColor, opacity = 10) {
144
+ if (!/^#([0-9A-Fa-f]{3}){1,2}$/.test(hexColor)) {
145
+ throw new Error("Invalid color format");
146
+ }
147
+ let color = hexColor.substring(1).split("");
148
+ if (color.length === 3) {
149
+ color = [color[0], color[0], color[1], color[1], color[2], color[2]];
150
+ }
151
+ const r = parseInt(color[0] + color[1], 16);
152
+ const g = parseInt(color[2] + color[3], 16);
153
+ const b = parseInt(color[4] + color[5], 16);
154
+ const alpha = opacity / 100;
155
+ return `rgba(${r}, ${g}, ${b}, ${alpha})`;
156
+ }
157
+ function useBuildUserManagement({
158
+ authController,
159
+ dataSourceDelegate,
160
+ usersPath = "__FIRECMS/config/users",
161
+ rolesPath = "__FIRECMS/config/roles",
162
+ usersLimit,
163
+ canEditRoles = true,
164
+ allowDefaultRolesCreation,
165
+ includeCollectionConfigPermissions
166
+ }) {
167
+ if (!authController) {
168
+ throw Error("useBuildUserManagement: You need to provide an authController since version 3.0.0-beta.11. Check https://firecms.co/docs/pro/migrating_from_v3_beta");
169
+ }
170
+ const [rolesLoading, setRolesLoading] = React.useState(true);
171
+ const [usersLoading, setUsersLoading] = React.useState(true);
172
+ const [roles, setRoles] = React.useState([]);
173
+ const [usersWithRoleIds, setUsersWithRoleIds] = React.useState([]);
174
+ const users = usersWithRoleIds.map((u) => ({
175
+ ...u,
176
+ roles: roles.filter((r) => u.roles?.includes(r.id))
177
+ }));
178
+ const [rolesError, setRolesError] = React.useState();
179
+ const [usersError, setUsersError] = React.useState();
180
+ const _usersLoading = usersLoading;
181
+ const _rolesLoading = rolesLoading;
182
+ const loading = _rolesLoading || _usersLoading;
183
+ React.useEffect(() => {
184
+ if (!dataSourceDelegate || !rolesPath) return;
185
+ if (dataSourceDelegate.initialised !== void 0 && !dataSourceDelegate.initialised) return;
186
+ if (authController?.initialLoading) return;
187
+ setRolesLoading(true);
188
+ return dataSourceDelegate.listenCollection?.({
189
+ path: rolesPath,
190
+ onUpdate(entities) {
191
+ setRolesError(void 0);
192
+ try {
193
+ const newRoles = entityToRoles(entities);
194
+ if (!equal(newRoles, roles)) {
195
+ setRoles(newRoles);
196
+ }
197
+ } catch (e) {
198
+ setRoles([]);
199
+ console.error("Error loading roles", e);
200
+ setRolesError(e);
201
+ }
202
+ setRolesLoading(false);
203
+ },
204
+ onError(e) {
205
+ setRoles([]);
206
+ console.error("Error loading roles", e);
207
+ setRolesError(e);
208
+ setRolesLoading(false);
209
+ }
210
+ });
211
+ }, [dataSourceDelegate?.initialised, authController?.initialLoading, authController?.user?.uid, rolesPath]);
212
+ React.useEffect(() => {
213
+ if (!dataSourceDelegate || !usersPath) return;
214
+ if (dataSourceDelegate.initialised !== void 0 && !dataSourceDelegate.initialised) {
215
+ return;
216
+ }
217
+ if (authController?.initialLoading) {
218
+ return;
219
+ }
220
+ setUsersLoading(true);
221
+ return dataSourceDelegate.listenCollection?.({
222
+ path: usersPath,
223
+ onUpdate(entities) {
224
+ console.debug("Updating users", entities);
225
+ setUsersError(void 0);
226
+ try {
227
+ const newUsers = entitiesToUsers(entities);
228
+ setUsersWithRoleIds(newUsers);
229
+ } catch (e) {
230
+ setUsersWithRoleIds([]);
231
+ console.error("Error loading users", e);
232
+ setUsersError(e);
233
+ }
234
+ setUsersLoading(false);
235
+ },
236
+ onError(e) {
237
+ console.error("Error loading users", e);
238
+ setUsersWithRoleIds([]);
239
+ setUsersError(e);
240
+ setUsersLoading(false);
241
+ }
242
+ });
243
+ }, [dataSourceDelegate?.initialised, authController?.initialLoading, authController?.user?.uid, usersPath]);
244
+ const saveUser = React.useCallback(async (user) => {
245
+ if (!dataSourceDelegate) throw Error("useBuildUserManagement Firebase not initialised");
246
+ if (!usersPath) throw Error("useBuildUserManagement Firestore not initialised");
247
+ console.debug("Persisting user", user);
248
+ const roleIds = user.roles?.map((r) => r.id);
249
+ const email = user.email?.toLowerCase().trim();
250
+ if (!email) throw Error("Email is required");
251
+ const userExists = users.find((u) => u.email?.toLowerCase() === email);
252
+ const data = {
253
+ ...user,
254
+ roles: roleIds ?? []
255
+ };
256
+ if (!userExists) {
257
+ data.created_on = /* @__PURE__ */ new Date();
258
+ }
259
+ return dataSourceDelegate.saveEntity({
260
+ status: "existing",
261
+ path: usersPath,
262
+ entityId: email,
263
+ values: core.removeUndefined(data)
264
+ }).then(() => user);
265
+ }, [usersPath, dataSourceDelegate?.initialised]);
266
+ const saveRole = React.useCallback((role) => {
267
+ if (!dataSourceDelegate) throw Error("useBuildUserManagement Firebase not initialised");
268
+ if (!rolesPath) throw Error("useBuildUserManagement Firestore not initialised");
269
+ console.debug("Persisting role", role);
270
+ const {
271
+ id,
272
+ ...roleData
273
+ } = role;
274
+ return dataSourceDelegate.saveEntity({
275
+ status: "existing",
276
+ path: rolesPath,
277
+ entityId: id,
278
+ values: core.removeUndefined(roleData)
279
+ }).then(() => {
280
+ return;
281
+ });
282
+ }, [rolesPath, dataSourceDelegate?.initialised]);
283
+ const deleteUser = React.useCallback(async (user) => {
284
+ if (!dataSourceDelegate) throw Error("useBuildUserManagement Firebase not initialised");
285
+ if (!usersPath) throw Error("useBuildUserManagement Firestore not initialised");
286
+ console.debug("Deleting", user);
287
+ const { uid } = user;
288
+ const entity = {
289
+ path: usersPath,
290
+ id: uid,
291
+ values: {}
292
+ };
293
+ await dataSourceDelegate.deleteEntity({ entity });
294
+ }, [usersPath, dataSourceDelegate?.initialised]);
295
+ const deleteRole = React.useCallback(async (role) => {
296
+ if (!dataSourceDelegate) throw Error("useBuildUserManagement Firebase not initialised");
297
+ if (!rolesPath) throw Error("useBuildUserManagement Firestore not initialised");
298
+ console.debug("Deleting", role);
299
+ const { id } = role;
300
+ const entity = {
301
+ path: rolesPath,
302
+ id,
303
+ values: {}
304
+ };
305
+ await dataSourceDelegate.deleteEntity({ entity });
306
+ }, [rolesPath, dataSourceDelegate?.initialised]);
307
+ const collectionPermissions = React.useCallback(({
308
+ collection,
309
+ user
310
+ }) => resolveUserRolePermissions({
311
+ collection,
312
+ user
313
+ }), []);
314
+ const defineRolesFor = React.useCallback((user) => {
315
+ if (!usersWithRoleIds) throw Error("Users not loaded");
316
+ const users2 = usersWithRoleIds.map((u) => ({
317
+ ...u,
318
+ roles: roles.filter((r) => u.roles?.includes(r.id))
319
+ }));
320
+ const mgmtUser = users2.find((u) => u.email?.toLowerCase() === user?.email?.toLowerCase());
321
+ return mgmtUser?.roles;
322
+ }, [roles, usersWithRoleIds]);
323
+ const authenticator = React.useCallback(({ user }) => {
324
+ if (loading) {
325
+ return false;
326
+ }
327
+ if (users.length === 0) {
328
+ console.warn("No users created yet");
329
+ return true;
330
+ }
331
+ const mgmtUser = users.find((u) => u.email?.toLowerCase() === user?.email?.toLowerCase());
332
+ if (mgmtUser) {
333
+ console.debug("User found in user management system", mgmtUser);
334
+ return true;
335
+ }
336
+ throw Error("Could not find a user with the provided email in the user management system.");
337
+ }, [loading, users]);
338
+ const userRoles = authController.user ? defineRolesFor(authController.user) : void 0;
339
+ const isAdmin = (userRoles ?? []).some((r) => r.id === "admin");
340
+ return {
341
+ loading,
342
+ roles,
343
+ users,
344
+ saveUser,
345
+ saveRole,
346
+ rolesError,
347
+ deleteUser,
348
+ deleteRole,
349
+ usersLimit,
350
+ usersError,
351
+ isAdmin,
352
+ canEditRoles: canEditRoles === void 0 ? true : canEditRoles,
353
+ allowDefaultRolesCreation: allowDefaultRolesCreation === void 0 ? true : allowDefaultRolesCreation,
354
+ includeCollectionConfigPermissions: Boolean(includeCollectionConfigPermissions),
355
+ collectionPermissions,
356
+ defineRolesFor,
357
+ authenticator,
358
+ ...authController,
359
+ initialLoading: authController.initialLoading || loading,
360
+ userRoles,
361
+ user: authController.user ? {
362
+ ...authController.user,
363
+ roles: userRoles
364
+ } : null
365
+ };
366
+ }
367
+ const entitiesToUsers = (docs) => {
368
+ return docs.map((doc) => {
369
+ const data = doc.values;
370
+ const newVar = {
371
+ uid: doc.id,
372
+ ...data,
373
+ created_on: data?.created_on,
374
+ updated_on: data?.updated_on
375
+ };
376
+ return newVar;
377
+ });
378
+ };
379
+ const entityToRoles = (entities) => {
380
+ return entities.map((doc) => ({
381
+ id: doc.id,
382
+ ...doc.values
383
+ }));
384
+ };
385
+ const UserManagementContext = React.createContext({});
386
+ function UserManagementProvider({
387
+ children,
388
+ userManagement
389
+ }) {
390
+ return /* @__PURE__ */ jsxRuntime.jsx(UserManagementContext.Provider, { value: userManagement, children });
391
+ }
392
+ const useUserManagement = () => React.useContext(UserManagementContext);
393
+ function RoleChip({ role }) {
394
+ let colorScheme;
395
+ if (role.isAdmin) {
396
+ colorScheme = "blueDarker";
397
+ } else if (role.id === "editor") {
398
+ colorScheme = "yellowLight";
399
+ } else if (role.id === "viewer") {
400
+ colorScheme = "grayLight";
401
+ } else {
402
+ colorScheme = ui.getColorSchemeForSeed(role.id);
403
+ }
404
+ return /* @__PURE__ */ jsxRuntime.jsx(
405
+ ui.Chip,
406
+ {
407
+ colorScheme,
408
+ children: role.name
409
+ },
410
+ role.id
411
+ );
412
+ }
413
+ const RoleYupSchema = Yup__namespace.object().shape({
414
+ id: Yup__namespace.string().required("Required"),
415
+ name: Yup__namespace.string().required("Required")
416
+ });
417
+ function canRoleBeEdited(loggedUser) {
418
+ const loggedUserIsAdmin = loggedUser.roles?.map((r) => r.id).includes("admin");
419
+ console.log("loggedUserIsAdmin", loggedUser);
420
+ if (!loggedUserIsAdmin) {
421
+ throw new Error("Only admins can edit roles");
422
+ }
423
+ return true;
424
+ }
425
+ function RolesDetailsForm({
426
+ open,
427
+ role,
428
+ editable,
429
+ handleClose,
430
+ collections
431
+ }) {
432
+ const { saveRole } = useUserManagement();
433
+ const isNewRole = !role;
434
+ const {
435
+ user: loggedInUser
436
+ } = core.useAuthController();
437
+ const [savingError, setSavingError] = React.useState();
438
+ const onRoleUpdated = React.useCallback((role2) => {
439
+ setSavingError(void 0);
440
+ if (!loggedInUser) throw new Error("User not found");
441
+ canRoleBeEdited(loggedInUser);
442
+ return saveRole(role2);
443
+ }, [saveRole, loggedInUser]);
444
+ const formex$1 = formex.useCreateFormex({
445
+ initialValues: role ?? {
446
+ name: ""
447
+ },
448
+ onSubmit: (role2, formexController) => {
449
+ try {
450
+ return onRoleUpdated(role2).then(() => {
451
+ formexController.resetForm({
452
+ values: role2
453
+ });
454
+ handleClose();
455
+ }).catch((e) => {
456
+ setSavingError(e);
457
+ });
458
+ } catch (e) {
459
+ setSavingError(e);
460
+ return Promise.resolve();
461
+ }
462
+ },
463
+ validation: (values2) => {
464
+ return RoleYupSchema.validate(values2, { abortEarly: false }).then(() => ({})).catch((e) => {
465
+ const errors2 = {};
466
+ e.inner.forEach((error) => {
467
+ errors2[error.path] = error.message;
468
+ });
469
+ return errors2;
470
+ });
471
+ }
472
+ });
473
+ const {
474
+ isSubmitting,
475
+ touched,
476
+ values,
477
+ errors,
478
+ handleChange,
479
+ setFieldValue,
480
+ dirty,
481
+ setFieldTouched
482
+ } = formex$1;
483
+ const isAdmin = values.isAdmin ?? false;
484
+ const defaultCreate = values.defaultPermissions?.create ?? false;
485
+ const defaultRead = values.defaultPermissions?.read ?? false;
486
+ const defaultEdit = values.defaultPermissions?.edit ?? false;
487
+ const defaultDelete = values.defaultPermissions?.delete ?? false;
488
+ React.useEffect(() => {
489
+ const idTouched = formex.getIn(touched, "id");
490
+ if (!idTouched && values.name) {
491
+ setFieldValue("id", core.toSnakeCase(values.name));
492
+ }
493
+ }, [touched, values.name]);
494
+ return /* @__PURE__ */ jsxRuntime.jsx(
495
+ ui.Dialog,
496
+ {
497
+ open,
498
+ maxWidth: "4xl",
499
+ children: /* @__PURE__ */ jsxRuntime.jsx(formex.Formex, { value: formex$1, children: /* @__PURE__ */ jsxRuntime.jsxs(
500
+ "form",
501
+ {
502
+ noValidate: true,
503
+ autoComplete: "off",
504
+ onSubmit: formex$1.handleSubmit,
505
+ style: {
506
+ display: "flex",
507
+ flexDirection: "column",
508
+ position: "relative",
509
+ height: "100%"
510
+ },
511
+ children: [
512
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.DialogContent, { className: "flex-grow", children: [
513
+ /* @__PURE__ */ jsxRuntime.jsx(
514
+ "div",
515
+ {
516
+ className: "flex flex-row pt-12 pb-8",
517
+ children: /* @__PURE__ */ jsxRuntime.jsx(
518
+ ui.Typography,
519
+ {
520
+ variant: "h4",
521
+ className: "flex-grow",
522
+ children: "Role"
523
+ }
524
+ )
525
+ }
526
+ ),
527
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-12 gap-8", children: [
528
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "col-span-12 md:col-span-8", children: [
529
+ /* @__PURE__ */ jsxRuntime.jsx(
530
+ ui.TextField,
531
+ {
532
+ name: "name",
533
+ required: true,
534
+ error: touched.name && Boolean(errors.name),
535
+ value: values.name,
536
+ disabled: isAdmin || !editable,
537
+ onChange: handleChange,
538
+ "aria-describedby": "name-helper-text",
539
+ label: "Name"
540
+ }
541
+ ),
542
+ /* @__PURE__ */ jsxRuntime.jsx(core.FieldCaption, { children: touched.name && Boolean(errors.name) ? errors.name : "Name of this role" })
543
+ ] }),
544
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "col-span-12 md:col-span-4", children: [
545
+ /* @__PURE__ */ jsxRuntime.jsx(
546
+ ui.TextField,
547
+ {
548
+ name: "id",
549
+ required: true,
550
+ error: touched.id && Boolean(errors.id),
551
+ value: values.id,
552
+ disabled: !isNewRole || !editable,
553
+ onChange: (e) => {
554
+ handleChange(e);
555
+ setFieldTouched("id", true);
556
+ },
557
+ "aria-describedby": "id-helper-text",
558
+ label: "ID"
559
+ }
560
+ ),
561
+ /* @__PURE__ */ jsxRuntime.jsx(core.FieldCaption, { children: touched.id && Boolean(errors.id) ? errors.id : "ID of this role" })
562
+ ] }),
563
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "col-span-12", children: [
564
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Paper, { className: "bg-inherit overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Table, { className: "w-full rounded-md", children: [
565
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.TableHeader, { className: "rounded-md", children: [
566
+ /* @__PURE__ */ jsxRuntime.jsx(ui.TableCell, {}),
567
+ /* @__PURE__ */ jsxRuntime.jsx(
568
+ ui.TableCell,
569
+ {
570
+ align: "center",
571
+ children: "Create entities"
572
+ }
573
+ ),
574
+ /* @__PURE__ */ jsxRuntime.jsx(
575
+ ui.TableCell,
576
+ {
577
+ align: "center",
578
+ children: "Read entities"
579
+ }
580
+ ),
581
+ /* @__PURE__ */ jsxRuntime.jsx(
582
+ ui.TableCell,
583
+ {
584
+ align: "center",
585
+ children: "Update entities"
586
+ }
587
+ ),
588
+ /* @__PURE__ */ jsxRuntime.jsx(
589
+ ui.TableCell,
590
+ {
591
+ align: "center",
592
+ children: "Delete entities"
593
+ }
594
+ ),
595
+ /* @__PURE__ */ jsxRuntime.jsx(
596
+ ui.TableCell,
597
+ {
598
+ align: "center"
599
+ }
600
+ )
601
+ ] }),
602
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.TableBody, { children: [
603
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.TableRow, { children: [
604
+ /* @__PURE__ */ jsxRuntime.jsx(
605
+ ui.TableCell,
606
+ {
607
+ scope: "row",
608
+ children: /* @__PURE__ */ jsxRuntime.jsx("strong", { children: "All collections" })
609
+ }
610
+ ),
611
+ /* @__PURE__ */ jsxRuntime.jsx(
612
+ ui.TableCell,
613
+ {
614
+ align: "center",
615
+ children: /* @__PURE__ */ jsxRuntime.jsx(
616
+ ui.Tooltip,
617
+ {
618
+ title: "Create entities in collections",
619
+ children: /* @__PURE__ */ jsxRuntime.jsx(
620
+ ui.Checkbox,
621
+ {
622
+ disabled: isAdmin || !editable,
623
+ checked: (isAdmin || defaultCreate) ?? false,
624
+ onCheckedChange: (checked) => setFieldValue("defaultPermissions.create", checked)
625
+ }
626
+ )
627
+ }
628
+ )
629
+ }
630
+ ),
631
+ /* @__PURE__ */ jsxRuntime.jsx(
632
+ ui.TableCell,
633
+ {
634
+ align: "center",
635
+ children: /* @__PURE__ */ jsxRuntime.jsx(
636
+ ui.Tooltip,
637
+ {
638
+ title: "Access all data in every collection",
639
+ children: /* @__PURE__ */ jsxRuntime.jsx(
640
+ ui.Checkbox,
641
+ {
642
+ disabled: isAdmin || !editable,
643
+ checked: (isAdmin || defaultRead) ?? false,
644
+ onCheckedChange: (checked) => setFieldValue("defaultPermissions.read", checked)
645
+ }
646
+ )
647
+ }
648
+ )
649
+ }
650
+ ),
651
+ /* @__PURE__ */ jsxRuntime.jsx(
652
+ ui.TableCell,
653
+ {
654
+ align: "center",
655
+ children: /* @__PURE__ */ jsxRuntime.jsx(
656
+ ui.Tooltip,
657
+ {
658
+ title: "Update data in any collection",
659
+ children: /* @__PURE__ */ jsxRuntime.jsx(
660
+ ui.Checkbox,
661
+ {
662
+ disabled: isAdmin || !editable,
663
+ checked: (isAdmin || defaultEdit) ?? false,
664
+ onCheckedChange: (checked) => setFieldValue("defaultPermissions.edit", checked)
665
+ }
666
+ )
667
+ }
668
+ )
669
+ }
670
+ ),
671
+ /* @__PURE__ */ jsxRuntime.jsx(
672
+ ui.TableCell,
673
+ {
674
+ align: "center",
675
+ children: /* @__PURE__ */ jsxRuntime.jsx(
676
+ ui.Tooltip,
677
+ {
678
+ title: "Delete data in any collection",
679
+ children: /* @__PURE__ */ jsxRuntime.jsx(
680
+ ui.Checkbox,
681
+ {
682
+ disabled: isAdmin || !editable,
683
+ checked: (isAdmin || defaultDelete) ?? false,
684
+ onCheckedChange: (checked) => setFieldValue("defaultPermissions.delete", checked)
685
+ }
686
+ )
687
+ }
688
+ )
689
+ }
690
+ ),
691
+ /* @__PURE__ */ jsxRuntime.jsx(
692
+ ui.TableCell,
693
+ {
694
+ align: "center"
695
+ }
696
+ )
697
+ ] }),
698
+ collections && collections.map((col) => /* @__PURE__ */ jsxRuntime.jsxs(ui.TableRow, { children: [
699
+ /* @__PURE__ */ jsxRuntime.jsx(
700
+ ui.TableCell,
701
+ {
702
+ scope: "row",
703
+ children: col.name
704
+ }
705
+ ),
706
+ /* @__PURE__ */ jsxRuntime.jsx(
707
+ ui.TableCell,
708
+ {
709
+ align: "center",
710
+ children: /* @__PURE__ */ jsxRuntime.jsx(
711
+ ui.Checkbox,
712
+ {
713
+ disabled: isAdmin || defaultCreate || !editable,
714
+ checked: (isAdmin || defaultCreate || formex.getIn(values, `collectionPermissions.${col.id}.create`)) ?? false,
715
+ onCheckedChange: (checked) => setFieldValue(`collectionPermissions.${col.id}.create`, checked)
716
+ }
717
+ )
718
+ }
719
+ ),
720
+ /* @__PURE__ */ jsxRuntime.jsx(
721
+ ui.TableCell,
722
+ {
723
+ align: "center",
724
+ children: /* @__PURE__ */ jsxRuntime.jsx(
725
+ ui.Checkbox,
726
+ {
727
+ disabled: isAdmin || defaultRead || !editable,
728
+ checked: (isAdmin || defaultRead || formex.getIn(values, `collectionPermissions.${col.id}.read`)) ?? false,
729
+ onCheckedChange: (checked) => setFieldValue(`collectionPermissions.${col.id}.read`, checked)
730
+ }
731
+ )
732
+ }
733
+ ),
734
+ /* @__PURE__ */ jsxRuntime.jsx(
735
+ ui.TableCell,
736
+ {
737
+ align: "center",
738
+ children: /* @__PURE__ */ jsxRuntime.jsx(
739
+ ui.Checkbox,
740
+ {
741
+ disabled: isAdmin || defaultEdit || !editable,
742
+ checked: (isAdmin || defaultEdit || formex.getIn(values, `collectionPermissions.${col.id}.edit`)) ?? false,
743
+ onCheckedChange: (checked) => setFieldValue(`collectionPermissions.${col.id}.edit`, checked)
744
+ }
745
+ )
746
+ }
747
+ ),
748
+ /* @__PURE__ */ jsxRuntime.jsx(
749
+ ui.TableCell,
750
+ {
751
+ align: "center",
752
+ children: /* @__PURE__ */ jsxRuntime.jsx(
753
+ ui.Checkbox,
754
+ {
755
+ disabled: isAdmin || defaultDelete || !editable,
756
+ checked: (isAdmin || defaultDelete || formex.getIn(values, `collectionPermissions.${col.id}.delete`)) ?? false,
757
+ onCheckedChange: (checked) => setFieldValue(`collectionPermissions.${col.id}.delete`, checked)
758
+ }
759
+ )
760
+ }
761
+ ),
762
+ /* @__PURE__ */ jsxRuntime.jsx(
763
+ ui.TableCell,
764
+ {
765
+ align: "center",
766
+ children: /* @__PURE__ */ jsxRuntime.jsx(
767
+ ui.Tooltip,
768
+ {
769
+ title: "Allow all permissions in this collections",
770
+ children: /* @__PURE__ */ jsxRuntime.jsx(
771
+ ui.Button,
772
+ {
773
+ className: "color-inherit",
774
+ onClick: () => {
775
+ setFieldValue(`collectionPermissions.${col.id}.create`, true);
776
+ setFieldValue(`collectionPermissions.${col.id}.read`, true);
777
+ setFieldValue(`collectionPermissions.${col.id}.edit`, true);
778
+ setFieldValue(`collectionPermissions.${col.id}.delete`, true);
779
+ },
780
+ disabled: isAdmin || !editable,
781
+ variant: "text",
782
+ children: "All"
783
+ }
784
+ )
785
+ }
786
+ )
787
+ }
788
+ )
789
+ ] }, col.name))
790
+ ] })
791
+ ] }) }),
792
+ /* @__PURE__ */ jsxRuntime.jsx(core.FieldCaption, { children: "You can customise the permissions that the users related to this role can perform in the entities of each collection" })
793
+ ] }),
794
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "col-span-12 md:col-span-4", children: [
795
+ /* @__PURE__ */ jsxRuntime.jsxs(
796
+ ui.Select,
797
+ {
798
+ error: touched.config && Boolean(errors.config),
799
+ id: "createCollections",
800
+ name: "createCollections",
801
+ label: "Create collections",
802
+ position: "item-aligned",
803
+ disabled: isAdmin || !editable,
804
+ onChange: (event) => setFieldValue("config.createCollections", event.target.value === "true"),
805
+ value: isAdmin || values.config?.createCollections ? "true" : "false",
806
+ renderValue: (value) => value === "true" ? "Yes" : "No",
807
+ children: [
808
+ /* @__PURE__ */ jsxRuntime.jsx(
809
+ ui.SelectItem,
810
+ {
811
+ value: "true",
812
+ children: " Yes "
813
+ }
814
+ ),
815
+ /* @__PURE__ */ jsxRuntime.jsx(
816
+ ui.SelectItem,
817
+ {
818
+ value: "false",
819
+ children: " No "
820
+ }
821
+ )
822
+ ]
823
+ }
824
+ ),
825
+ /* @__PURE__ */ jsxRuntime.jsx(core.FieldCaption, { children: touched.config && Boolean(errors.config) ? errors.config : "Can the user create collections" })
826
+ ] }),
827
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "col-span-12 md:col-span-4", children: [
828
+ /* @__PURE__ */ jsxRuntime.jsxs(
829
+ ui.Select,
830
+ {
831
+ error: touched.config && Boolean(errors.config),
832
+ id: "editCollections",
833
+ name: "editCollections",
834
+ label: "Edit collections",
835
+ disabled: isAdmin || !editable,
836
+ position: "item-aligned",
837
+ onChange: (event) => setFieldValue("config.editCollections", event.target.value === "own" ? "own" : event.target.value === "true"),
838
+ value: isAdmin ? "true" : values.config?.editCollections === "own" ? "own" : values.config?.editCollections ? "true" : "false",
839
+ renderValue: (value) => value === "own" ? "Own" : value === "true" ? "Yes" : "No",
840
+ children: [
841
+ /* @__PURE__ */ jsxRuntime.jsx(
842
+ ui.SelectItem,
843
+ {
844
+ value: "true",
845
+ children: " Yes "
846
+ }
847
+ ),
848
+ /* @__PURE__ */ jsxRuntime.jsx(
849
+ ui.SelectItem,
850
+ {
851
+ value: "false",
852
+ children: " No "
853
+ }
854
+ ),
855
+ /* @__PURE__ */ jsxRuntime.jsx(
856
+ ui.SelectItem,
857
+ {
858
+ value: "own",
859
+ children: " Only his/her own "
860
+ }
861
+ )
862
+ ]
863
+ }
864
+ ),
865
+ /* @__PURE__ */ jsxRuntime.jsx(core.FieldCaption, { children: touched.config && Boolean(errors.config) ? errors.config : "Can the user edit collections" })
866
+ ] }),
867
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "col-span-12 md:col-span-4", children: [
868
+ /* @__PURE__ */ jsxRuntime.jsxs(
869
+ ui.Select,
870
+ {
871
+ error: touched.config && Boolean(errors.config),
872
+ id: "deleteCollections",
873
+ name: "deleteCollections",
874
+ label: "Delete collections",
875
+ disabled: isAdmin || !editable,
876
+ position: "item-aligned",
877
+ onChange: (event) => setFieldValue("config.deleteCollections", event.target.value === "own" ? "own" : event.target.value === "true"),
878
+ value: isAdmin ? "true" : values.config?.deleteCollections === "own" ? "own" : values.config?.deleteCollections ? "true" : "false",
879
+ renderValue: (value) => value === "own" ? "Own" : value === "true" ? "Yes" : "No",
880
+ children: [
881
+ /* @__PURE__ */ jsxRuntime.jsx(
882
+ ui.SelectItem,
883
+ {
884
+ value: "true",
885
+ children: " Yes "
886
+ }
887
+ ),
888
+ /* @__PURE__ */ jsxRuntime.jsx(
889
+ ui.SelectItem,
890
+ {
891
+ value: "false",
892
+ children: " No "
893
+ }
894
+ ),
895
+ /* @__PURE__ */ jsxRuntime.jsx(
896
+ ui.SelectItem,
897
+ {
898
+ value: "own",
899
+ children: " Only his/her own "
900
+ }
901
+ )
902
+ ]
903
+ }
904
+ ),
905
+ /* @__PURE__ */ jsxRuntime.jsx(core.FieldCaption, { children: touched.config && Boolean(errors.config) ? errors.config : "Can the user delete collections" })
906
+ ] })
907
+ ] })
908
+ ] }),
909
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.DialogActions, { position: "sticky", children: [
910
+ savingError && /* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { className: "text-red-500 dark:text-red-500", children: savingError.message ?? "There was an error saving this role" }),
911
+ /* @__PURE__ */ jsxRuntime.jsx(
912
+ ui.Button,
913
+ {
914
+ variant: "text",
915
+ onClick: () => {
916
+ handleClose();
917
+ },
918
+ children: "Cancel"
919
+ }
920
+ ),
921
+ /* @__PURE__ */ jsxRuntime.jsx(
922
+ ui.LoadingButton,
923
+ {
924
+ variant: "filled",
925
+ color: "primary",
926
+ type: "submit",
927
+ disabled: !dirty,
928
+ loading: isSubmitting,
929
+ startIcon: /* @__PURE__ */ jsxRuntime.jsx(ui.DoneIcon, {}),
930
+ children: isNewRole ? "Create role" : "Update"
931
+ }
932
+ )
933
+ ] })
934
+ ]
935
+ }
936
+ ) })
937
+ }
938
+ );
939
+ }
940
+ const DEFAULT_ROLES = [
941
+ {
942
+ id: "admin",
943
+ name: "Admin",
944
+ isAdmin: true
945
+ },
946
+ {
947
+ id: "editor",
948
+ name: "Editor",
949
+ isAdmin: false,
950
+ defaultPermissions: {
951
+ read: true,
952
+ create: true,
953
+ edit: true,
954
+ delete: true
955
+ },
956
+ config: {
957
+ createCollections: true,
958
+ editCollections: "own",
959
+ deleteCollections: "own"
960
+ }
961
+ },
962
+ {
963
+ id: "viewer",
964
+ name: "Viewer",
965
+ isAdmin: false,
966
+ defaultPermissions: {
967
+ read: true,
968
+ create: false,
969
+ edit: false,
970
+ delete: false
971
+ }
972
+ }
973
+ ];
974
+ function RolesTable({
975
+ onRoleClicked,
976
+ editable
977
+ }) {
978
+ const {
979
+ roles,
980
+ saveRole,
981
+ deleteRole,
982
+ allowDefaultRolesCreation
983
+ } = useUserManagement();
984
+ const [roleToBeDeleted, setRoleToBeDeleted] = React.useState(void 0);
985
+ const [deleteInProgress, setDeleteInProgress] = React.useState(false);
986
+ return /* @__PURE__ */ jsxRuntime.jsxs(
987
+ "div",
988
+ {
989
+ className: "w-full overflow-auto",
990
+ children: [
991
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.Table, { className: "w-full", children: [
992
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.TableHeader, { children: [
993
+ /* @__PURE__ */ jsxRuntime.jsx(ui.TableCell, { header: true, className: "w-16" }),
994
+ /* @__PURE__ */ jsxRuntime.jsx(ui.TableCell, { header: true, children: "Role" }),
995
+ /* @__PURE__ */ jsxRuntime.jsx(ui.TableCell, { header: true, className: "items-center", children: "Is Admin" }),
996
+ /* @__PURE__ */ jsxRuntime.jsx(ui.TableCell, { header: true, children: "Default permissions" })
997
+ ] }),
998
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.TableBody, { children: [
999
+ roles && roles.map((role) => {
1000
+ const canCreateAll = role.isAdmin || role.defaultPermissions?.create;
1001
+ const canReadAll = role.isAdmin || role.defaultPermissions?.read;
1002
+ const canUpdateAll = role.isAdmin || role.defaultPermissions?.edit;
1003
+ const canDeleteAll = role.isAdmin || role.defaultPermissions?.delete;
1004
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1005
+ ui.TableRow,
1006
+ {
1007
+ onClick: () => {
1008
+ onRoleClicked(role);
1009
+ },
1010
+ children: [
1011
+ /* @__PURE__ */ jsxRuntime.jsx(ui.TableCell, { style: { width: "64px" }, children: !role.isAdmin && /* @__PURE__ */ jsxRuntime.jsx(
1012
+ ui.Tooltip,
1013
+ {
1014
+ asChild: true,
1015
+ title: "Delete this role",
1016
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1017
+ ui.IconButton,
1018
+ {
1019
+ size: "small",
1020
+ disabled: !editable,
1021
+ onClick: (event) => {
1022
+ event.stopPropagation();
1023
+ return setRoleToBeDeleted(role);
1024
+ },
1025
+ children: /* @__PURE__ */ jsxRuntime.jsx(ui.DeleteIcon, {})
1026
+ }
1027
+ )
1028
+ }
1029
+ ) }),
1030
+ /* @__PURE__ */ jsxRuntime.jsx(ui.TableCell, { children: /* @__PURE__ */ jsxRuntime.jsx(RoleChip, { role }) }),
1031
+ /* @__PURE__ */ jsxRuntime.jsx(ui.TableCell, { className: "items-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Checkbox, { checked: role.isAdmin ?? false }) }),
1032
+ /* @__PURE__ */ jsxRuntime.jsx(ui.TableCell, { children: /* @__PURE__ */ jsxRuntime.jsxs("ul", { children: [
1033
+ canCreateAll && /* @__PURE__ */ jsxRuntime.jsx("li", { children: "Create" }),
1034
+ canReadAll && /* @__PURE__ */ jsxRuntime.jsx("li", { children: "Read" }),
1035
+ canUpdateAll && /* @__PURE__ */ jsxRuntime.jsx("li", { children: "Update" }),
1036
+ canDeleteAll && /* @__PURE__ */ jsxRuntime.jsx("li", { children: "Delete" })
1037
+ ] }) })
1038
+ ]
1039
+ },
1040
+ role.name
1041
+ );
1042
+ }),
1043
+ (!roles || roles.length === 0) && /* @__PURE__ */ jsxRuntime.jsx(ui.TableRow, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.TableCell, { colspan: 4, children: /* @__PURE__ */ jsxRuntime.jsxs(ui.CenteredView, { className: "flex flex-col gap-4 my-8 items-center", children: [
1044
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { variant: "label", children: "You don't have any roles yet." }),
1045
+ allowDefaultRolesCreation && /* @__PURE__ */ jsxRuntime.jsx(
1046
+ ui.Button,
1047
+ {
1048
+ variant: "outlined",
1049
+ onClick: () => {
1050
+ DEFAULT_ROLES.forEach((role) => {
1051
+ saveRole(role);
1052
+ });
1053
+ },
1054
+ children: "Create default roles"
1055
+ }
1056
+ )
1057
+ ] }) }) })
1058
+ ] })
1059
+ ] }),
1060
+ /* @__PURE__ */ jsxRuntime.jsx(
1061
+ core.ConfirmationDialog,
1062
+ {
1063
+ open: Boolean(roleToBeDeleted),
1064
+ loading: deleteInProgress,
1065
+ onAccept: () => {
1066
+ if (roleToBeDeleted) {
1067
+ setDeleteInProgress(true);
1068
+ deleteRole(roleToBeDeleted).then(() => {
1069
+ setRoleToBeDeleted(void 0);
1070
+ }).finally(() => {
1071
+ setDeleteInProgress(false);
1072
+ });
1073
+ }
1074
+ },
1075
+ onCancel: () => {
1076
+ setRoleToBeDeleted(void 0);
1077
+ },
1078
+ title: /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: "Delete?" }),
1079
+ body: /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: "Are you sure you want to delete this role?" })
1080
+ }
1081
+ )
1082
+ ]
1083
+ }
1084
+ );
1085
+ }
1086
+ const RolesView = React.memo(
1087
+ function RolesView2({ children }) {
1088
+ const { collections } = core.useNavigationController();
1089
+ const [dialogOpen, setDialogOpen] = React.useState(false);
1090
+ const [selectedRole, setSelectedRole] = React.useState();
1091
+ const { canEditRoles } = useUserManagement();
1092
+ const onRoleClicked = React.useCallback((user) => {
1093
+ setDialogOpen(true);
1094
+ setSelectedRole(user);
1095
+ }, []);
1096
+ const handleClose = () => {
1097
+ setSelectedRole(void 0);
1098
+ setDialogOpen(false);
1099
+ };
1100
+ return /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "w-full flex flex-col py-4 gap-4", maxWidth: "6xl", children: [
1101
+ children,
1102
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center mt-12", children: [
1103
+ /* @__PURE__ */ jsxRuntime.jsx(
1104
+ ui.Typography,
1105
+ {
1106
+ gutterBottom: true,
1107
+ variant: "h4",
1108
+ className: "flex-grow",
1109
+ component: "h4",
1110
+ children: "Roles"
1111
+ }
1112
+ ),
1113
+ /* @__PURE__ */ jsxRuntime.jsx(
1114
+ ui.Tooltip,
1115
+ {
1116
+ asChild: true,
1117
+ title: !canEditRoles ? "Update plans to customise roles" : void 0,
1118
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1119
+ ui.Button,
1120
+ {
1121
+ size: "large",
1122
+ disabled: !canEditRoles,
1123
+ startIcon: /* @__PURE__ */ jsxRuntime.jsx(ui.AddIcon, {}),
1124
+ onClick: () => setDialogOpen(true),
1125
+ children: "Add role"
1126
+ }
1127
+ )
1128
+ }
1129
+ )
1130
+ ] }),
1131
+ /* @__PURE__ */ jsxRuntime.jsx(RolesTable, { onRoleClicked, editable: Boolean(canEditRoles) }),
1132
+ /* @__PURE__ */ jsxRuntime.jsx(
1133
+ RolesDetailsForm,
1134
+ {
1135
+ open: dialogOpen,
1136
+ role: selectedRole,
1137
+ editable: canEditRoles,
1138
+ collections,
1139
+ handleClose
1140
+ },
1141
+ selectedRole?.id ?? "new"
1142
+ )
1143
+ ] });
1144
+ }
1145
+ );
1146
+ const UserYupSchema = Yup__namespace.object().shape({
1147
+ displayName: Yup__namespace.string().required("Required"),
1148
+ email: Yup__namespace.string().email().required("Required"),
1149
+ roles: Yup__namespace.array().min(1)
1150
+ });
1151
+ function canUserBeEdited(loggedUser, user, users, roles, prevUser) {
1152
+ const admins = users.filter((u) => u.roles?.map((r) => r.id).includes("admin"));
1153
+ const loggedUserIsAdmin = loggedUser.roles?.map((r) => r.id).includes("admin");
1154
+ const didRolesChange = !prevUser || !areRolesEqual(prevUser.roles ?? [], user.roles ?? []);
1155
+ if (didRolesChange && !loggedUserIsAdmin) {
1156
+ throw new Error("Only admins can change roles");
1157
+ }
1158
+ const adminRoleRemoved = prevUser && prevUser.roles?.map((r) => r.id).includes("admin") && !user.roles?.map((r) => r.id).includes("admin");
1159
+ if (adminRoleRemoved && admins.length === 1) {
1160
+ throw new Error("There must be at least one admin");
1161
+ }
1162
+ return true;
1163
+ }
1164
+ function UserDetailsForm({
1165
+ open,
1166
+ user: userProp,
1167
+ handleClose
1168
+ }) {
1169
+ const snackbarController = core.useSnackbarController();
1170
+ const {
1171
+ user: loggedInUser
1172
+ } = core.useAuthController();
1173
+ const {
1174
+ saveUser,
1175
+ users,
1176
+ roles
1177
+ } = useUserManagement();
1178
+ const isNewUser = !userProp;
1179
+ const onUserUpdated = React.useCallback((savedUser) => {
1180
+ if (!loggedInUser) {
1181
+ throw new Error("Logged user not found");
1182
+ }
1183
+ try {
1184
+ canUserBeEdited(loggedInUser, savedUser, users, roles, userProp);
1185
+ return saveUser(savedUser);
1186
+ } catch (e) {
1187
+ return Promise.reject(e);
1188
+ }
1189
+ }, [roles, saveUser, userProp, users, loggedInUser]);
1190
+ const formex$1 = formex.useCreateFormex({
1191
+ initialValues: userProp ?? {
1192
+ displayName: "",
1193
+ email: "",
1194
+ roles: roles.filter((r) => r.id === "editor")
1195
+ },
1196
+ validation: (values2) => {
1197
+ return UserYupSchema.validate(values2, { abortEarly: false }).then(() => {
1198
+ return {};
1199
+ }).catch((e) => {
1200
+ return e.inner.reduce((acc, error) => {
1201
+ acc[error.path] = error.message;
1202
+ return acc;
1203
+ }, {});
1204
+ });
1205
+ },
1206
+ onSubmit: (user, formexController) => {
1207
+ return onUserUpdated(user).then(() => {
1208
+ handleClose();
1209
+ formexController.resetForm({
1210
+ values: user
1211
+ });
1212
+ }).catch((e) => {
1213
+ snackbarController.open({
1214
+ type: "error",
1215
+ message: e.message
1216
+ });
1217
+ });
1218
+ }
1219
+ });
1220
+ const {
1221
+ isSubmitting,
1222
+ touched,
1223
+ handleChange,
1224
+ values,
1225
+ errors,
1226
+ setFieldValue,
1227
+ dirty,
1228
+ handleSubmit,
1229
+ submitCount
1230
+ } = formex$1;
1231
+ return /* @__PURE__ */ jsxRuntime.jsx(
1232
+ ui.Dialog,
1233
+ {
1234
+ open,
1235
+ onOpenChange: (open2) => !open2 ? handleClose() : void 0,
1236
+ maxWidth: "4xl",
1237
+ children: /* @__PURE__ */ jsxRuntime.jsx(formex.Formex, { value: formex$1, children: /* @__PURE__ */ jsxRuntime.jsxs(
1238
+ "form",
1239
+ {
1240
+ onSubmit: handleSubmit,
1241
+ autoComplete: "off",
1242
+ noValidate: true,
1243
+ style: {
1244
+ display: "flex",
1245
+ flexDirection: "column",
1246
+ position: "relative",
1247
+ height: "100%"
1248
+ },
1249
+ children: [
1250
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.DialogContent, { className: "h-full flex-grow", children: [
1251
+ /* @__PURE__ */ jsxRuntime.jsx(
1252
+ "div",
1253
+ {
1254
+ className: "flex flex-row pt-4 pb-4",
1255
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1256
+ ui.Typography,
1257
+ {
1258
+ variant: "h4",
1259
+ className: "flex-grow",
1260
+ children: "User"
1261
+ }
1262
+ )
1263
+ }
1264
+ ),
1265
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-12 gap-8", children: [
1266
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "col-span-12", children: [
1267
+ /* @__PURE__ */ jsxRuntime.jsx(
1268
+ ui.TextField,
1269
+ {
1270
+ name: "displayName",
1271
+ required: true,
1272
+ error: submitCount > 0 && Boolean(errors.displayName),
1273
+ value: values.displayName ?? "",
1274
+ onChange: handleChange,
1275
+ "aria-describedby": "name-helper-text",
1276
+ label: "Name"
1277
+ }
1278
+ ),
1279
+ /* @__PURE__ */ jsxRuntime.jsx(core.FieldCaption, { children: submitCount > 0 && Boolean(errors.displayName) ? errors.displayName : "Name of this user" })
1280
+ ] }),
1281
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "col-span-12", children: [
1282
+ /* @__PURE__ */ jsxRuntime.jsx(
1283
+ ui.TextField,
1284
+ {
1285
+ required: true,
1286
+ error: submitCount > 0 && Boolean(errors.email),
1287
+ name: "email",
1288
+ value: values.email ?? "",
1289
+ onChange: handleChange,
1290
+ "aria-describedby": "email-helper-text",
1291
+ label: "Email"
1292
+ }
1293
+ ),
1294
+ /* @__PURE__ */ jsxRuntime.jsx(core.FieldCaption, { children: submitCount > 0 && Boolean(errors.email) ? errors.email : "Email of this user" })
1295
+ ] }),
1296
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "col-span-12", children: /* @__PURE__ */ jsxRuntime.jsx(
1297
+ ui.MultiSelect,
1298
+ {
1299
+ className: "w-full",
1300
+ label: "Roles",
1301
+ value: values.roles?.map((r) => r.id) ?? [],
1302
+ onValueChange: (value) => setFieldValue("roles", value.map((id) => roles.find((r) => r.id === id))),
1303
+ children: roles.map((userRole) => /* @__PURE__ */ jsxRuntime.jsx(
1304
+ ui.MultiSelectItem,
1305
+ {
1306
+ value: userRole.id,
1307
+ children: /* @__PURE__ */ jsxRuntime.jsx(RoleChip, { role: userRole }, userRole?.id)
1308
+ },
1309
+ userRole.id
1310
+ ))
1311
+ }
1312
+ ) })
1313
+ ] })
1314
+ ] }),
1315
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.DialogActions, { children: [
1316
+ /* @__PURE__ */ jsxRuntime.jsx(
1317
+ ui.Button,
1318
+ {
1319
+ variant: "text",
1320
+ onClick: () => {
1321
+ handleClose();
1322
+ },
1323
+ children: "Cancel"
1324
+ }
1325
+ ),
1326
+ /* @__PURE__ */ jsxRuntime.jsx(
1327
+ ui.LoadingButton,
1328
+ {
1329
+ variant: "filled",
1330
+ color: "primary",
1331
+ type: "submit",
1332
+ disabled: !dirty,
1333
+ loading: isSubmitting,
1334
+ startIcon: /* @__PURE__ */ jsxRuntime.jsx(ui.DoneIcon, {}),
1335
+ children: isNewUser ? "Create user" : "Update"
1336
+ }
1337
+ )
1338
+ ] })
1339
+ ]
1340
+ }
1341
+ ) })
1342
+ }
1343
+ );
1344
+ }
1345
+ function UsersTable({ onUserClicked }) {
1346
+ const {
1347
+ users,
1348
+ saveUser,
1349
+ deleteUser
1350
+ } = useUserManagement();
1351
+ const authController = core.useAuthController();
1352
+ const snackbarController = core.useSnackbarController();
1353
+ const customizationController = core.useCustomizationController();
1354
+ const dateUtilsLocale = customizationController?.locale ? locales__namespace[customizationController?.locale] : void 0;
1355
+ const dateFormat = customizationController?.dateTimeFormat ?? core.defaultDateFormat;
1356
+ const [userToBeDeleted, setUserToBeDeleted] = React.useState(void 0);
1357
+ const [deleteInProgress, setDeleteInProgress] = React.useState(false);
1358
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "overflow-auto", children: [
1359
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.Table, { className: "w-full", children: [
1360
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.TableHeader, { children: [
1361
+ /* @__PURE__ */ jsxRuntime.jsx(ui.TableCell, { className: "truncate w-16" }),
1362
+ /* @__PURE__ */ jsxRuntime.jsx(ui.TableCell, { children: "Email" }),
1363
+ /* @__PURE__ */ jsxRuntime.jsx(ui.TableCell, { children: "Name" }),
1364
+ /* @__PURE__ */ jsxRuntime.jsx(ui.TableCell, { children: "Roles" }),
1365
+ /* @__PURE__ */ jsxRuntime.jsx(ui.TableCell, { children: "Created on" })
1366
+ ] }),
1367
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.TableBody, { children: [
1368
+ users && users.map((user) => {
1369
+ const userRoles = user.roles;
1370
+ const formattedDate = user.created_on ? dateFns.format(user.created_on, dateFormat, { locale: dateUtilsLocale }) : "";
1371
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1372
+ ui.TableRow,
1373
+ {
1374
+ onClick: () => {
1375
+ onUserClicked(user);
1376
+ },
1377
+ children: [
1378
+ /* @__PURE__ */ jsxRuntime.jsx(ui.TableCell, { className: "w-10", children: /* @__PURE__ */ jsxRuntime.jsx(
1379
+ ui.Tooltip,
1380
+ {
1381
+ asChild: true,
1382
+ title: "Delete this user",
1383
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1384
+ ui.IconButton,
1385
+ {
1386
+ size: "small",
1387
+ onClick: (event) => {
1388
+ event.stopPropagation();
1389
+ return setUserToBeDeleted(user);
1390
+ },
1391
+ children: /* @__PURE__ */ jsxRuntime.jsx(ui.DeleteIcon, {})
1392
+ }
1393
+ )
1394
+ }
1395
+ ) }),
1396
+ /* @__PURE__ */ jsxRuntime.jsx(ui.TableCell, { children: user.email }),
1397
+ /* @__PURE__ */ jsxRuntime.jsx(ui.TableCell, { className: "font-medium align-left", children: user.displayName }),
1398
+ /* @__PURE__ */ jsxRuntime.jsx(ui.TableCell, { className: "align-left", children: userRoles ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-2", children: userRoles.map(
1399
+ (userRole) => /* @__PURE__ */ jsxRuntime.jsx(RoleChip, { role: userRole }, userRole?.id)
1400
+ ) }) : null }),
1401
+ /* @__PURE__ */ jsxRuntime.jsx(ui.TableCell, { children: formattedDate })
1402
+ ]
1403
+ },
1404
+ "row_" + user.uid
1405
+ );
1406
+ }),
1407
+ (!users || users.length === 0) && /* @__PURE__ */ jsxRuntime.jsx(ui.TableRow, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.TableCell, { colspan: 6, children: /* @__PURE__ */ jsxRuntime.jsxs(ui.CenteredView, { className: "flex flex-col gap-4 my-8 items-center", children: [
1408
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { variant: "label", children: "There are no users yet" }),
1409
+ /* @__PURE__ */ jsxRuntime.jsx(
1410
+ ui.Button,
1411
+ {
1412
+ variant: "outlined",
1413
+ onClick: () => {
1414
+ if (!authController.user?.uid) {
1415
+ throw Error("UsersTable, authController misconfiguration");
1416
+ }
1417
+ saveUser({
1418
+ uid: authController.user?.uid,
1419
+ email: authController.user?.email,
1420
+ displayName: authController.user?.displayName,
1421
+ photoURL: authController.user?.photoURL,
1422
+ providerId: authController.user?.providerId,
1423
+ isAnonymous: authController.user?.isAnonymous,
1424
+ roles: [{ id: "admin", name: "Admin" }],
1425
+ created_on: /* @__PURE__ */ new Date()
1426
+ }).then(() => {
1427
+ snackbarController.open({
1428
+ type: "success",
1429
+ message: "User added successfully"
1430
+ });
1431
+ }).catch((error) => {
1432
+ snackbarController.open({
1433
+ type: "error",
1434
+ message: "Error adding user: " + error.message
1435
+ });
1436
+ });
1437
+ },
1438
+ children: "Add the logged user as an admin"
1439
+ }
1440
+ )
1441
+ ] }) }) })
1442
+ ] })
1443
+ ] }),
1444
+ /* @__PURE__ */ jsxRuntime.jsx(
1445
+ core.ConfirmationDialog,
1446
+ {
1447
+ open: Boolean(userToBeDeleted),
1448
+ loading: deleteInProgress,
1449
+ onAccept: () => {
1450
+ if (userToBeDeleted) {
1451
+ setDeleteInProgress(true);
1452
+ deleteUser(userToBeDeleted).then(() => {
1453
+ setUserToBeDeleted(void 0);
1454
+ }).catch((error) => {
1455
+ snackbarController.open({
1456
+ type: "error",
1457
+ message: "Error deleting user: " + error.message
1458
+ });
1459
+ }).finally(() => {
1460
+ setDeleteInProgress(false);
1461
+ });
1462
+ }
1463
+ },
1464
+ onCancel: () => {
1465
+ setUserToBeDeleted(void 0);
1466
+ },
1467
+ title: /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: "Delete?" }),
1468
+ body: /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: "Are you sure you want to delete this user?" })
1469
+ }
1470
+ )
1471
+ ] });
1472
+ }
1473
+ const UsersView = function UsersView2({ children }) {
1474
+ const [dialogOpen, setDialogOpen] = React.useState();
1475
+ const [selectedUser, setSelectedUser] = React.useState();
1476
+ const { users, usersLimit } = useUserManagement();
1477
+ const reachedUsersLimit = usersLimit !== void 0 && (users && users.length >= usersLimit);
1478
+ const onUserClicked = React.useCallback((user) => {
1479
+ setSelectedUser(user);
1480
+ setDialogOpen(true);
1481
+ }, []);
1482
+ const handleClose = React.useCallback(() => {
1483
+ setDialogOpen(false);
1484
+ setSelectedUser(void 0);
1485
+ }, []);
1486
+ return /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "w-full flex flex-col py-4 gap-4", maxWidth: "6xl", children: [
1487
+ children,
1488
+ /* @__PURE__ */ jsxRuntime.jsxs(
1489
+ "div",
1490
+ {
1491
+ className: "flex items-center mt-12",
1492
+ children: [
1493
+ /* @__PURE__ */ jsxRuntime.jsx(
1494
+ ui.Typography,
1495
+ {
1496
+ gutterBottom: true,
1497
+ variant: "h4",
1498
+ className: "flex-grow",
1499
+ component: "h4",
1500
+ children: "Users"
1501
+ }
1502
+ ),
1503
+ /* @__PURE__ */ jsxRuntime.jsx(
1504
+ ui.Button,
1505
+ {
1506
+ size: "large",
1507
+ disabled: reachedUsersLimit,
1508
+ startIcon: /* @__PURE__ */ jsxRuntime.jsx(ui.AddIcon, {}),
1509
+ onClick: () => setDialogOpen(true),
1510
+ children: "Add user"
1511
+ }
1512
+ )
1513
+ ]
1514
+ }
1515
+ ),
1516
+ /* @__PURE__ */ jsxRuntime.jsx(UsersTable, { onUserClicked }),
1517
+ /* @__PURE__ */ jsxRuntime.jsx(
1518
+ UserDetailsForm,
1519
+ {
1520
+ open: dialogOpen ?? false,
1521
+ user: selectedUser,
1522
+ handleClose
1523
+ },
1524
+ selectedUser?.uid ?? "new"
1525
+ )
1526
+ ] });
1527
+ };
1528
+ function useUserManagementPlugin({ userManagement }) {
1529
+ const noUsers = userManagement.users.length === 0;
1530
+ const noRoles = userManagement.roles.length === 0;
1531
+ return {
1532
+ key: "user_management",
1533
+ loading: userManagement.loading,
1534
+ homePage: {
1535
+ additionalChildrenStart: noUsers || noRoles ? /* @__PURE__ */ jsxRuntime.jsx(
1536
+ IntroWidget,
1537
+ {
1538
+ noUsers,
1539
+ noRoles,
1540
+ userManagement
1541
+ }
1542
+ ) : void 0
1543
+ },
1544
+ provider: {
1545
+ Component: UserManagementProvider,
1546
+ props: {
1547
+ userManagement
1548
+ }
1549
+ }
1550
+ };
1551
+ }
1552
+ function IntroWidget({
1553
+ noUsers,
1554
+ noRoles,
1555
+ userManagement
1556
+ }) {
1557
+ const authController = core.useAuthController();
1558
+ const snackbarController = core.useSnackbarController();
1559
+ const buttonLabel = noUsers && noRoles ? "Create default roles and add current user as admin" : noUsers ? "Add current user as admin" : noRoles ? "Create default roles" : void 0;
1560
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1561
+ ui.Paper,
1562
+ {
1563
+ className: "my-4 flex flex-col px-4 py-6 bg-white dark:bg-surface-accent-800 gap-2",
1564
+ children: [
1565
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { variant: "subtitle2", className: "uppercase", children: "Create your users and roles" }),
1566
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Typography, { children: "You have no users or roles defined. You can create default roles and add the current user as admin." }),
1567
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.Button, { onClick: () => {
1568
+ if (!authController.user?.uid) {
1569
+ throw Error("UsersTable, authController misconfiguration");
1570
+ }
1571
+ if (noUsers) {
1572
+ userManagement.saveUser({
1573
+ uid: authController.user?.uid,
1574
+ email: authController.user?.email,
1575
+ displayName: authController.user?.displayName,
1576
+ photoURL: authController.user?.photoURL,
1577
+ providerId: authController.user?.providerId,
1578
+ isAnonymous: authController.user?.isAnonymous,
1579
+ roles: [{
1580
+ id: "admin",
1581
+ name: "Admin"
1582
+ }],
1583
+ created_on: /* @__PURE__ */ new Date()
1584
+ }).then(() => {
1585
+ snackbarController.open({
1586
+ type: "success",
1587
+ message: "User added successfully"
1588
+ });
1589
+ }).catch((error) => {
1590
+ snackbarController.open({
1591
+ type: "error",
1592
+ message: "Error adding user: " + error.message
1593
+ });
1594
+ });
1595
+ }
1596
+ if (noRoles) {
1597
+ DEFAULT_ROLES.forEach((role) => {
1598
+ userManagement.saveRole(role);
1599
+ });
1600
+ }
1601
+ }, children: [
1602
+ /* @__PURE__ */ jsxRuntime.jsx(ui.AddIcon, {}),
1603
+ buttonLabel
1604
+ ] })
1605
+ ]
1606
+ }
1607
+ );
1608
+ }
1609
+ const userManagementAdminViews = [
1610
+ {
1611
+ path: "users",
1612
+ name: "CMS Users",
1613
+ group: "Admin",
1614
+ icon: "face",
1615
+ view: /* @__PURE__ */ jsxRuntime.jsx(UsersView, {})
1616
+ },
1617
+ {
1618
+ path: "roles",
1619
+ name: "Roles",
1620
+ group: "Admin",
1621
+ icon: "gpp_good",
1622
+ view: /* @__PURE__ */ jsxRuntime.jsx(RolesView, {})
1623
+ }
1624
+ ];
1625
+ exports2.IntroWidget = IntroWidget;
1626
+ exports2.RESERVED_GROUPS = RESERVED_GROUPS;
1627
+ exports2.RoleChip = RoleChip;
1628
+ exports2.RoleYupSchema = RoleYupSchema;
1629
+ exports2.RolesDetailsForm = RolesDetailsForm;
1630
+ exports2.RolesTable = RolesTable;
1631
+ exports2.RolesView = RolesView;
1632
+ exports2.UserDetailsForm = UserDetailsForm;
1633
+ exports2.UserManagementContext = UserManagementContext;
1634
+ exports2.UserManagementProvider = UserManagementProvider;
1635
+ exports2.UserYupSchema = UserYupSchema;
1636
+ exports2.UsersTable = UsersTable;
1637
+ exports2.UsersView = UsersView;
1638
+ exports2.areRolesEqual = areRolesEqual;
1639
+ exports2.cacheDelegatedLoginToken = cacheDelegatedLoginToken;
1640
+ exports2.clearDelegatedLoginTokensCache = clearDelegatedLoginTokensCache;
1641
+ exports2.darkenColor = darkenColor;
1642
+ exports2.getDelegatedLoginTokenFromCache = getDelegatedLoginTokenFromCache;
1643
+ exports2.getUserRoles = getUserRoles;
1644
+ exports2.hexToRgbaWithOpacity = hexToRgbaWithOpacity;
1645
+ exports2.resolveUserRolePermissions = resolveUserRolePermissions;
1646
+ exports2.useBuildUserManagement = useBuildUserManagement;
1647
+ exports2.useUserManagement = useUserManagement;
1648
+ exports2.useUserManagementPlugin = useUserManagementPlugin;
1649
+ exports2.userManagementAdminViews = userManagementAdminViews;
1650
+ Object.defineProperty(exports2, Symbol.toStringTag, { value: "Module" });
1651
+ });
2
1652
  //# sourceMappingURL=index.umd.js.map