@collabdt/core 0.0.49 → 0.0.51

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.
Files changed (25) hide show
  1. package/dist/core/components/AppSidebarContent.d.ts.map +1 -1
  2. package/dist/core/components/AppSidebarContent.js +28 -19
  3. package/dist/core/components/AppSidebarContent.js.map +1 -1
  4. package/dist/core/components/authentication/Signin.d.ts.map +1 -1
  5. package/dist/core/components/authentication/Signin.js +7 -8
  6. package/dist/core/components/authentication/Signin.js.map +1 -1
  7. package/dist/core/components/index.d.ts +1 -0
  8. package/dist/core/components/index.d.ts.map +1 -1
  9. package/dist/core/components/index.js +1 -0
  10. package/dist/core/components/index.js.map +1 -1
  11. package/dist/core/components/organizationConfig/index.d.ts +2 -0
  12. package/dist/core/components/organizationConfig/index.d.ts.map +1 -0
  13. package/dist/core/components/organizationConfig/index.js +66 -0
  14. package/dist/core/components/organizationConfig/index.js.map +1 -0
  15. package/dist/core/components/organizationConfig/src/organizationConfigContent.d.ts +2 -0
  16. package/dist/core/components/organizationConfig/src/organizationConfigContent.d.ts.map +1 -0
  17. package/dist/core/components/organizationConfig/src/organizationConfigContent.js +229 -0
  18. package/dist/core/components/organizationConfig/src/organizationConfigContent.js.map +1 -0
  19. package/dist/core/components/ui/AppSidebar.d.ts.map +1 -1
  20. package/dist/core/components/ui/AppSidebar.js +30 -15
  21. package/dist/core/components/ui/AppSidebar.js.map +1 -1
  22. package/dist/core/components/viewers/Data/files/DatatableFileAdder.d.ts.map +1 -1
  23. package/dist/core/components/viewers/Data/files/DatatableFileAdder.js +3 -0
  24. package/dist/core/components/viewers/Data/files/DatatableFileAdder.js.map +1 -1
  25. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"AppSidebarContent.d.ts","sourceRoot":"","sources":["../../../src/core/components/AppSidebarContent.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAI9B,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AA2BvC,OAAO,EAAE,YAAY,EAAY,MAAM,kBAAkB,CAAA;AAKzD,eAAO,MAAM,kBAAkB,GAC7B,QAAQ,WAAW,EACnB,iBAAiB,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,EAC1D,iBAAiB,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,EAC1D,iBAAiB,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,EAC1D,SAAS,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,GAAG,QAAQ,CAAC,CAAC,EACjE,eAAe,GAAG,SAYnB,CAAA;AAED,UAAU,eAAe;IACvB,YAAY,EAAE,YAAY,CAAA;IAC1B,uBAAuB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClD;AAED,wBAAgB,iBAAiB,CAAC,EAAE,YAAY,EAAE,uBAAuB,EAAE,EAAE,eAAe,qBAwT3F"}
1
+ {"version":3,"file":"AppSidebarContent.d.ts","sourceRoot":"","sources":["../../../src/core/components/AppSidebarContent.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAI9B,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AA2BvC,OAAO,EAAE,YAAY,EAAY,MAAM,kBAAkB,CAAA;AAKzD,eAAO,MAAM,kBAAkB,GAC7B,QAAQ,WAAW,EACnB,iBAAiB,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,EAC1D,iBAAiB,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,EAC1D,iBAAiB,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,EAC1D,SAAS,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,GAAG,QAAQ,CAAC,CAAC,EACjE,eAAe,GAAG,SAYnB,CAAA;AAED,UAAU,eAAe;IACvB,YAAY,EAAE,YAAY,CAAA;IAC1B,uBAAuB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClD;AAED,wBAAgB,iBAAiB,CAAC,EAAE,YAAY,EAAE,uBAAuB,EAAE,EAAE,eAAe,qBA0U3F"}
@@ -175,6 +175,7 @@ function AppSidebarContent({ organization, countrySubdivisionsData }) {
175
175
  if (item.accessibleTo == null) return true;
176
176
  return item.accessibleTo.some((role) => normalizedUserRoles.has(role.toLowerCase()));
177
177
  }, [normalizedUserRoles]);
178
+ const visibleDatasetItems = datasetItems.filter((item) => !appContent || appContent.includes(item.id)).filter(canRenderItem);
178
179
  return /* @__PURE__ */ jsxs(Fragment, { children: [
179
180
  /* @__PURE__ */ jsxs(SidebarContent, { className: "overflow-hidden", children: [
180
181
  /* @__PURE__ */ jsx(SidebarHeader, { className: `w-full pt-7 flex items-center justify-center ${isCollapsed ? "items-center" : "pl-4 items-start"}`, children: /* @__PURE__ */ jsxs("div", { className: "flex flex-row items-center gap-3", children: [
@@ -202,25 +203,33 @@ function AppSidebarContent({ organization, countrySubdivisionsData }) {
202
203
  ) }) }, item.title);
203
204
  }) }) })
204
205
  ] }),
205
- isCollapsed && /* @__PURE__ */ jsx(Separator, { className: "z-30 w-2/3 mx-auto" }),
206
- /* @__PURE__ */ jsxs(SidebarGroup, { children: [
207
- /* @__PURE__ */ jsx(SidebarGroupLabel, { children: t("data") }),
208
- /* @__PURE__ */ jsx(SidebarGroupContent, { children: /* @__PURE__ */ jsx(SidebarMenu, { children: datasetItems.filter((item) => !appContent || appContent.includes(item.id)).filter(canRenderItem).map((item) => {
209
- const active = item.id === currentViewer;
210
- return /* @__PURE__ */ jsx(SidebarMenuItem, { children: /* @__PURE__ */ jsx(SidebarMenuButton, { asChild: true, children: /* @__PURE__ */ jsxs(
211
- Button,
212
- {
213
- onClick: item.onClick,
214
- title: isCollapsed ? item.title : void 0,
215
- className: buildBtnClass(active),
216
- variant: "ghost",
217
- children: [
218
- /* @__PURE__ */ jsx(item.icon, { className: buildIconClass(active) }),
219
- /* @__PURE__ */ jsx("span", { className: `${isCollapsed ? "hidden" : "inline"} ${active ? "font-bold text-primary" : ""}`, children: item.title })
220
- ]
221
- }
222
- ) }) }, item.title);
223
- }) }) })
206
+ visibleDatasetItems.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
207
+ isCollapsed && /* @__PURE__ */ jsx(Separator, { className: "z-30 w-2/3 mx-auto" }),
208
+ /* @__PURE__ */ jsxs(SidebarGroup, { children: [
209
+ /* @__PURE__ */ jsx(SidebarGroupLabel, { children: t("data") }),
210
+ /* @__PURE__ */ jsx(SidebarGroupContent, { children: /* @__PURE__ */ jsx(SidebarMenu, { children: visibleDatasetItems.map((item) => {
211
+ const active = item.id === currentViewer;
212
+ return /* @__PURE__ */ jsx(SidebarMenuItem, { children: /* @__PURE__ */ jsx(SidebarMenuButton, { asChild: true, children: /* @__PURE__ */ jsxs(
213
+ Button,
214
+ {
215
+ onClick: item.onClick,
216
+ title: isCollapsed ? item.title : void 0,
217
+ className: buildBtnClass(active),
218
+ variant: "ghost",
219
+ children: [
220
+ /* @__PURE__ */ jsx(item.icon, { className: buildIconClass(active) }),
221
+ /* @__PURE__ */ jsx(
222
+ "span",
223
+ {
224
+ className: `${isCollapsed ? "hidden" : "inline"} ${active ? "font-bold text-primary" : ""}`,
225
+ children: item.title
226
+ }
227
+ )
228
+ ]
229
+ }
230
+ ) }) }, item.title);
231
+ }) }) })
232
+ ] })
224
233
  ] }),
225
234
  isCollapsed && /* @__PURE__ */ jsx(Separator, { className: "z-30 w-2/3 mx-auto" }),
226
235
  /* @__PURE__ */ jsxs(SidebarGroup, { children: [
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/core/components/AppSidebarContent.tsx"],"sourcesContent":["'use client'\r\nimport * as React from 'react'\r\n\r\n// Dependencies\r\nimport { AppConfigContext, MapContext, useMenusContext } from '../store'\r\nimport { ViewerNames } from '../types/'\r\n\r\n// Shadcn Components\r\nimport {\r\n SidebarContent,\r\n SidebarGroup,\r\n SidebarGroupContent,\r\n SidebarGroupLabel,\r\n SidebarMenu,\r\n SidebarMenuButton,\r\n SidebarMenuItem,\r\n SidebarHeader,\r\n SidebarFooter,\r\n useSidebar,\r\n} from '../components/ui/Sidebar'\r\n\r\nimport { Button } from './ui/Button'\r\n\r\n// Custom Components\r\nimport LanguageSwitch from './LanguageSwitch'\r\n\r\n// Icons\r\nimport * as LR from 'lucide-react'\r\n\r\nimport { Logo } from './Logo'\r\nimport { Separator } from './ui/Separator'\r\nimport { useTranslations } from 'next-intl'\r\nimport { Organization, Language } from '../types/dbTypes'\r\nimport { RoleNames } from '../types/global'\r\nimport { useSession } from 'next-auth/react'\r\nimport { useUserRole } from '../hooks/users/users'\r\n\r\nexport const handleChangeViewer = (\r\n viewer: ViewerNames,\r\n setSelectedItem: React.Dispatch<React.SetStateAction<any>>,\r\n setSelectedSite: React.Dispatch<React.SetStateAction<any>>,\r\n setSelectedFile: React.Dispatch<React.SetStateAction<any>>,\r\n setView: React.Dispatch<React.SetStateAction<'table' | 'detail'>>,\r\n menusDispatch: any,\r\n) => {\r\n // Reset selected item, file, & view when changing viewer\r\n setSelectedItem(null)\r\n setSelectedSite(null)\r\n setSelectedFile(null)\r\n setView('table')\r\n\r\n menusDispatch({\r\n type: 'SET_VIEWER',\r\n payload: { currentViewer: viewer },\r\n })\r\n}\r\n\r\ninterface AppSidebarProps {\r\n organization: Organization\r\n countrySubdivisionsData?: Record<string, string>;\r\n}\r\n\r\nexport function AppSidebarContent({ organization, countrySubdivisionsData }: AppSidebarProps) {\r\n // Translations\r\n const t = useTranslations('AppSidebar')\r\n\r\n const { dispatch: appConfigDispatch } = React.useContext(AppConfigContext)\r\n const { dispatch: mapDispatch } = React.useContext(MapContext)\r\n\r\n React.useEffect(() => {\r\n appConfigDispatch({\r\n type: 'SET_ORGANIZATION',\r\n payload: { organization },\r\n })\r\n }, [organization, appConfigDispatch])\r\n \r\n React.useEffect(() => {\r\n if (countrySubdivisionsData) {\r\n mapDispatch({\r\n type: 'SET_COUNTRY_SUBDIVISIONS',\r\n payload: { countrySubdivisionsData, organizationCountry: organization.country },\r\n })\r\n }\r\n }, [countrySubdivisionsData, mapDispatch, organization.country])\r\n\r\n const sidebarTitle = organization?.title ?? organization.name ?? 'CDT Platform'\r\n\r\n const allViewers: ViewerNames[] = [ViewerNames.extensions, ViewerNames.bim, ViewerNames.pointcloud, ViewerNames.sites, ViewerNames.infrastructure, ViewerNames.buildings, ViewerNames.files,];\r\n const appContent: ViewerNames[] = [ViewerNames.map];\r\n\r\n if (organization.appContent && organization.appContent.length > 0) {\r\n appContent.push(...organization.appContent as ViewerNames[]);\r\n } else {\r\n appContent.push(...allViewers);\r\n }\r\n\r\n const logoKey = organization?.logoKey\r\n const minioBaseUrl = process.env.NEXT_PUBLIC_MINIO_BUCKET_URL\r\n const logoUrl = minioBaseUrl && logoKey\r\n ? `${minioBaseUrl}/org-logos/${logoKey}`\r\n : '/images/cdt-logo-stroke.svg'\r\n\r\n const { dispatch: menusDispatch, state: menusState } = useMenusContext()\r\n const { setSelectedItem, setSelectedSite, setSelectedFile, setView } = useMenusContext()\r\n\r\n const { data: session } = useSession()\r\n const { userRole } = useUserRole(session?.user?.id || '')\r\n const normalizedUserRoles = React.useMemo(\r\n () => new Set(userRole?.name ? [userRole.name.trim().toLowerCase()] : []),\r\n [userRole]\r\n )\r\n\r\n const { sidebarState, setOpenInfo, isMobile, openMobile } = useSidebar()\r\n\r\n const changeViewer = (viewer: ViewerNames) => {\r\n handleChangeViewer(viewer, setSelectedItem, setSelectedSite, setSelectedFile, setView, menusDispatch)\r\n setOpenInfo(false)\r\n }\r\n\r\n const handleMapClick = () => {\r\n changeViewer(ViewerNames.map)\r\n }\r\n\r\n interface MenuItem {\r\n title: string\r\n id: ViewerNames | string\r\n icon: React.ElementType\r\n onClick?: () => void\r\n accessibleTo?: RoleNames[],\r\n url?: string\r\n tooltip?: string\r\n }\r\n\r\n // Sidebar menu items\r\n const viewerItems: MenuItem[] = [\r\n {\r\n title: t('mapTitle'),\r\n id: ViewerNames.map,\r\n icon: LR.Map,\r\n onClick: handleMapClick,\r\n },\r\n {\r\n title: t('bimTitle'),\r\n id: ViewerNames.bim,\r\n icon: LR.Box,\r\n onClick: () => changeViewer(ViewerNames.bim),\r\n },\r\n {\r\n title: t('pointCloudTitle'),\r\n id: ViewerNames.pointcloud,\r\n icon: LR.Grip,\r\n onClick: () => changeViewer(ViewerNames.pointcloud),\r\n }\r\n ]\r\n\r\n const datasetItems: MenuItem[] = [\r\n {\r\n title: t('siteTitle'),\r\n id: ViewerNames.sites,\r\n onClick: () => changeViewer(ViewerNames.sites),\r\n icon: LR.BoxSelect,\r\n },\r\n {\r\n title: t('buildingsTitle'),\r\n id: ViewerNames.buildings,\r\n icon: LR.Building2,\r\n onClick: () => changeViewer(ViewerNames.buildings),\r\n },\r\n {\r\n title: t('filesTitle'),\r\n id: ViewerNames.files,\r\n icon: LR.GalleryVerticalEnd,\r\n onClick: () => changeViewer(ViewerNames.files),\r\n },\r\n // {\r\n // title: t('landTitle'),\r\n // id: ViewerNames.land,\r\n // icon: LR.Mountain,\r\n // onClick: () => changeViewer(ViewerNames.land),\r\n // },\r\n {\r\n title: t('infrastructureTitle'),\r\n id: ViewerNames.infrastructure,\r\n icon: LR.TrainTrack,\r\n onClick: () => changeViewer(ViewerNames.infrastructure),\r\n },\r\n\r\n ]\r\n\r\n const managementItems: MenuItem[] = [\r\n // {\r\n // title: t('users'),\r\n // id: ViewerNames.users,\r\n // onClick: () => changeViewer(ViewerNames.users),\r\n // icon: LR.Users,\r\n // accessibleTo: [RoleNames.admin],\r\n // },\r\n {\r\n title: t('addExtensions'),\r\n id: ViewerNames.extensions,\r\n icon: LR.Blocks,\r\n onClick: () => changeViewer(ViewerNames.extensions),\r\n }\r\n ]\r\n\r\n // Sidebar footer items\r\n const serviceItems: MenuItem[] = [\r\n {\r\n title: t('support'),\r\n id: 'support',\r\n url: 'mailto:info@collabdt.org?subject=Support Request - CDT Platform',\r\n icon: LR.LifeBuoy,\r\n tooltip: t('contact')\r\n },\r\n // {\r\n // title: t('feedback'),\r\n // url: 'mailto:info@collabdt.org?subject=Feedback - CDT Platform',\r\n // icon: LR.Send,\r\n // },\r\n ]\r\n const { currentViewer } = menusState.menus\r\n\r\n // On mobile, treat the sheet open as expanded so labels render when the drawer is visible\r\n const isCollapsed = isMobile ? !openMobile : sidebarState === 'collapsed'\r\n\r\n const buildBtnClass = (active: boolean) => [\r\n 'text-sm flex items-center gap-2 w-full cursor-pointer transition-colors rounded-md',\r\n isCollapsed ? 'justify-center p-2' : 'justify-start p-2',\r\n active ? 'bg-primary/5 hover:bg-primary/10 border border-primary/15' : 'hover:bg-muted/50',\r\n ].join(' ')\r\n\r\n const buildIconClass = (active: boolean) => [\r\n 'h-4 w-4 shrink-0',\r\n active ? 'text-primary stroke-2' : 'text-muted-foreground'\r\n ].join(' ')\r\n\r\n const canRenderItem = React.useCallback((item: MenuItem) => {\r\n if (item.accessibleTo == null) return true\r\n return item.accessibleTo.some(role => normalizedUserRoles.has(role.toLowerCase()))\r\n }, [normalizedUserRoles])\r\n\r\n return (\r\n <>\r\n <SidebarContent className='overflow-hidden'>\r\n <SidebarHeader className={`w-full pt-7 flex items-center justify-center ${isCollapsed ? 'items-center' : 'pl-4 items-start'}`}>\r\n <div className='flex flex-row items-center gap-3'>\r\n <Logo image={logoUrl} />\r\n {sidebarState === 'expanded'\r\n && <h1 className=\"text-sm font-bold max-w-36\">{sidebarTitle}</h1>}\r\n </div>\r\n </SidebarHeader>\r\n {isCollapsed && <Separator className=\"z-30 w-2/3 mx-auto\" />}\r\n\r\n <div className='overflow-y-auto overflow-x-hidden'>\r\n <SidebarGroup>\r\n <SidebarGroupLabel>{t('3dViewer')}</SidebarGroupLabel>\r\n <SidebarGroupContent>\r\n <SidebarMenu>\r\n {viewerItems.filter(item => !appContent || appContent.includes(item.id as ViewerNames))\r\n .filter(canRenderItem)\r\n .map(item => {\r\n const active = item.id === currentViewer;\r\n return (\r\n <SidebarMenuItem key={item.title}>\r\n <SidebarMenuButton asChild>\r\n <Button\r\n onClick={item.onClick}\r\n title={isCollapsed ? item.title : undefined}\r\n className={buildBtnClass(active)}\r\n variant=\"ghost\"\r\n >\r\n <item.icon className={buildIconClass(active)} />\r\n <span className={`${isCollapsed ? 'hidden' : 'inline'} ${active ? 'font-bold text-primary' : ''}`}>{item.title}</span>\r\n </Button>\r\n </SidebarMenuButton>\r\n </SidebarMenuItem>\r\n );\r\n })\r\n }\r\n </SidebarMenu>\r\n </SidebarGroupContent>\r\n </SidebarGroup>\r\n {isCollapsed && <Separator className=\"z-30 w-2/3 mx-auto\" />}\r\n <SidebarGroup>\r\n <SidebarGroupLabel>{t('data')}</SidebarGroupLabel>\r\n <SidebarGroupContent>\r\n <SidebarMenu>\r\n {datasetItems.filter(item => !appContent || appContent.includes(item.id as ViewerNames))\r\n .filter(canRenderItem)\r\n .map(item => {\r\n const active = item.id === currentViewer\r\n return (\r\n <SidebarMenuItem key={item.title}>\r\n <SidebarMenuButton asChild>\r\n <Button\r\n onClick={item.onClick}\r\n title={isCollapsed ? item.title : undefined}\r\n className={buildBtnClass(active)}\r\n variant=\"ghost\"\r\n >\r\n <item.icon className={buildIconClass(active)} />\r\n <span className={`${isCollapsed ? 'hidden' : 'inline'} ${active ? 'font-bold text-primary' : ''}`}>{item.title}</span>\r\n </Button>\r\n </SidebarMenuButton>\r\n </SidebarMenuItem>\r\n )\r\n })}\r\n </SidebarMenu>\r\n </SidebarGroupContent>\r\n </SidebarGroup>\r\n {isCollapsed && <Separator className=\"z-30 w-2/3 mx-auto\" />}\r\n <SidebarGroup>\r\n <SidebarGroupLabel>{t('extensions')}</SidebarGroupLabel>\r\n <SidebarGroupContent>\r\n <SidebarMenu>\r\n {managementItems.filter(canRenderItem).map(item => {\r\n const active = item.id === currentViewer\r\n return (\r\n <SidebarMenuItem key={item.title}>\r\n <SidebarMenuButton asChild>\r\n <Button\r\n onClick={item.onClick}\r\n title={isCollapsed ? item.title : undefined}\r\n className={buildBtnClass(active)}\r\n variant=\"ghost\"\r\n >\r\n <item.icon className={buildIconClass(active)} />\r\n <span className={`${isCollapsed ? 'hidden' : 'inline'} ${active ? 'font-bold text-primary' : ''}`}>{item.title}</span>\r\n </Button>\r\n </SidebarMenuButton>\r\n </SidebarMenuItem>\r\n )\r\n })}\r\n </SidebarMenu>\r\n </SidebarGroupContent>\r\n </SidebarGroup>\r\n </div>\r\n </SidebarContent>\r\n {/* Footer Content - only show when not in BIM mode or when collapsed */}\r\n <SidebarFooter className={`w-full flex flex-col gap-4 ${isCollapsed ? 'items-center justify-center px-0 pb-4' : 'items-start justify-start px-2 pb-4'}`}>\r\n {/* Preferences */}\r\n {organization.languages?.length > 1 && (\r\n <SidebarGroup>\r\n <SidebarGroupLabel>{t('preferences')}</SidebarGroupLabel>\r\n <SidebarMenu>\r\n <SidebarMenuItem>\r\n <LanguageSwitch showLabel={sidebarState === 'expanded'} languages={organization.languages as Language[]} />\r\n </SidebarMenuItem>\r\n </SidebarMenu>\r\n </SidebarGroup>\r\n )}\r\n {/* Services */}\r\n <SidebarGroup>\r\n <SidebarGroupLabel>{t('service')}</SidebarGroupLabel>\r\n <SidebarMenu>\r\n {serviceItems.map((item, index) => (\r\n <SidebarMenuItem key={index}>\r\n <SidebarMenuButton asChild>\r\n <a \r\n href={item.url} \r\n className={`text-xs flex items-center gap-2 w-full ${isCollapsed ? 'justify-center p-2' : 'justify-start p-2'}`}\r\n title={item.tooltip}\r\n >\r\n <item.icon className=\"h-4 w-4\" />\r\n <span className={isCollapsed ? 'hidden' : 'inline'}>{item.title}</span>\r\n </a>\r\n </SidebarMenuButton>\r\n </SidebarMenuItem>\r\n ))}\r\n </SidebarMenu>\r\n </SidebarGroup>\r\n </SidebarFooter>\r\n </>\r\n )\r\n}"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/core/components/AppSidebarContent.tsx"],"sourcesContent":["'use client'\r\nimport * as React from 'react'\r\n\r\n// Dependencies\r\nimport { AppConfigContext, MapContext, useMenusContext } from '../store'\r\nimport { ViewerNames } from '../types/'\r\n\r\n// Shadcn Components\r\nimport {\r\n SidebarContent,\r\n SidebarGroup,\r\n SidebarGroupContent,\r\n SidebarGroupLabel,\r\n SidebarMenu,\r\n SidebarMenuButton,\r\n SidebarMenuItem,\r\n SidebarHeader,\r\n SidebarFooter,\r\n useSidebar,\r\n} from '../components/ui/Sidebar'\r\n\r\nimport { Button } from './ui/Button'\r\n\r\n// Custom Components\r\nimport LanguageSwitch from './LanguageSwitch'\r\n\r\n// Icons\r\nimport * as LR from 'lucide-react'\r\n\r\nimport { Logo } from './Logo'\r\nimport { Separator } from './ui/Separator'\r\nimport { useTranslations } from 'next-intl'\r\nimport { Organization, Language } from '../types/dbTypes'\r\nimport { RoleNames } from '../types/global'\r\nimport { useSession } from 'next-auth/react'\r\nimport { useUserRole } from '../hooks/users/users'\r\n\r\nexport const handleChangeViewer = (\r\n viewer: ViewerNames,\r\n setSelectedItem: React.Dispatch<React.SetStateAction<any>>,\r\n setSelectedSite: React.Dispatch<React.SetStateAction<any>>,\r\n setSelectedFile: React.Dispatch<React.SetStateAction<any>>,\r\n setView: React.Dispatch<React.SetStateAction<'table' | 'detail'>>,\r\n menusDispatch: any,\r\n) => {\r\n // Reset selected item, file, & view when changing viewer\r\n setSelectedItem(null)\r\n setSelectedSite(null)\r\n setSelectedFile(null)\r\n setView('table')\r\n\r\n menusDispatch({\r\n type: 'SET_VIEWER',\r\n payload: { currentViewer: viewer },\r\n })\r\n}\r\n\r\ninterface AppSidebarProps {\r\n organization: Organization\r\n countrySubdivisionsData?: Record<string, string>;\r\n}\r\n\r\nexport function AppSidebarContent({ organization, countrySubdivisionsData }: AppSidebarProps) {\r\n // Translations\r\n const t = useTranslations('AppSidebar')\r\n\r\n const { dispatch: appConfigDispatch } = React.useContext(AppConfigContext)\r\n const { dispatch: mapDispatch } = React.useContext(MapContext)\r\n\r\n React.useEffect(() => {\r\n appConfigDispatch({\r\n type: 'SET_ORGANIZATION',\r\n payload: { organization },\r\n })\r\n }, [organization, appConfigDispatch])\r\n \r\n React.useEffect(() => {\r\n if (countrySubdivisionsData) {\r\n mapDispatch({\r\n type: 'SET_COUNTRY_SUBDIVISIONS',\r\n payload: { countrySubdivisionsData, organizationCountry: organization.country },\r\n })\r\n }\r\n }, [countrySubdivisionsData, mapDispatch, organization.country])\r\n\r\n const sidebarTitle = organization?.title ?? organization.name ?? 'CDT Platform'\r\n\r\n const allViewers: ViewerNames[] = [ViewerNames.extensions, ViewerNames.bim, ViewerNames.pointcloud, ViewerNames.sites, ViewerNames.infrastructure, ViewerNames.buildings, ViewerNames.files,];\r\n const appContent: ViewerNames[] = [ViewerNames.map];\r\n\r\n if (organization.appContent && organization.appContent.length > 0) {\r\n appContent.push(...organization.appContent as ViewerNames[]);\r\n } else {\r\n appContent.push(...allViewers);\r\n }\r\n\r\n const logoKey = organization?.logoKey\r\n const minioBaseUrl = process.env.NEXT_PUBLIC_MINIO_BUCKET_URL\r\n const logoUrl = minioBaseUrl && logoKey\r\n ? `${minioBaseUrl}/org-logos/${logoKey}`\r\n : '/images/cdt-logo-stroke.svg'\r\n\r\n const { dispatch: menusDispatch, state: menusState } = useMenusContext()\r\n const { setSelectedItem, setSelectedSite, setSelectedFile, setView } = useMenusContext()\r\n\r\n const { data: session } = useSession()\r\n const { userRole } = useUserRole(session?.user?.id || '')\r\n const normalizedUserRoles = React.useMemo(\r\n () => new Set(userRole?.name ? [userRole.name.trim().toLowerCase()] : []),\r\n [userRole]\r\n )\r\n\r\n const { sidebarState, setOpenInfo, isMobile, openMobile } = useSidebar()\r\n\r\n const changeViewer = (viewer: ViewerNames) => {\r\n handleChangeViewer(viewer, setSelectedItem, setSelectedSite, setSelectedFile, setView, menusDispatch)\r\n setOpenInfo(false)\r\n }\r\n\r\n const handleMapClick = () => {\r\n changeViewer(ViewerNames.map)\r\n }\r\n\r\n interface MenuItem {\r\n title: string\r\n id: ViewerNames | string\r\n icon: React.ElementType\r\n onClick?: () => void\r\n accessibleTo?: RoleNames[],\r\n url?: string\r\n tooltip?: string\r\n }\r\n\r\n // Sidebar menu items\r\n const viewerItems: MenuItem[] = [\r\n {\r\n title: t('mapTitle'),\r\n id: ViewerNames.map,\r\n icon: LR.Map,\r\n onClick: handleMapClick,\r\n },\r\n {\r\n title: t('bimTitle'),\r\n id: ViewerNames.bim,\r\n icon: LR.Box,\r\n onClick: () => changeViewer(ViewerNames.bim),\r\n },\r\n {\r\n title: t('pointCloudTitle'),\r\n id: ViewerNames.pointcloud,\r\n icon: LR.Grip,\r\n onClick: () => changeViewer(ViewerNames.pointcloud),\r\n }\r\n ]\r\n\r\n const datasetItems: MenuItem[] = [\r\n {\r\n title: t('siteTitle'),\r\n id: ViewerNames.sites,\r\n onClick: () => changeViewer(ViewerNames.sites),\r\n icon: LR.BoxSelect,\r\n },\r\n {\r\n title: t('buildingsTitle'),\r\n id: ViewerNames.buildings,\r\n icon: LR.Building2,\r\n onClick: () => changeViewer(ViewerNames.buildings),\r\n },\r\n {\r\n title: t('filesTitle'),\r\n id: ViewerNames.files,\r\n icon: LR.GalleryVerticalEnd,\r\n onClick: () => changeViewer(ViewerNames.files),\r\n },\r\n // {\r\n // title: t('landTitle'),\r\n // id: ViewerNames.land,\r\n // icon: LR.Mountain,\r\n // onClick: () => changeViewer(ViewerNames.land),\r\n // },\r\n {\r\n title: t('infrastructureTitle'),\r\n id: ViewerNames.infrastructure,\r\n icon: LR.TrainTrack,\r\n onClick: () => changeViewer(ViewerNames.infrastructure),\r\n },\r\n\r\n ]\r\n\r\n const managementItems: MenuItem[] = [\r\n // {\r\n // title: t('users'),\r\n // id: ViewerNames.users,\r\n // onClick: () => changeViewer(ViewerNames.users),\r\n // icon: LR.Users,\r\n // accessibleTo: [RoleNames.admin],\r\n // },\r\n {\r\n title: t('addExtensions'),\r\n id: ViewerNames.extensions,\r\n icon: LR.Blocks,\r\n onClick: () => changeViewer(ViewerNames.extensions),\r\n }\r\n ]\r\n\r\n // Sidebar footer items\r\n const serviceItems: MenuItem[] = [\r\n {\r\n title: t('support'),\r\n id: 'support',\r\n url: 'mailto:info@collabdt.org?subject=Support Request - CDT Platform',\r\n icon: LR.LifeBuoy,\r\n tooltip: t('contact')\r\n },\r\n // {\r\n // title: t('feedback'),\r\n // url: 'mailto:info@collabdt.org?subject=Feedback - CDT Platform',\r\n // icon: LR.Send,\r\n // },\r\n ]\r\n const { currentViewer } = menusState.menus\r\n\r\n // On mobile, treat the sheet open as expanded so labels render when the drawer is visible\r\n const isCollapsed = isMobile ? !openMobile : sidebarState === 'collapsed'\r\n\r\n const buildBtnClass = (active: boolean) => [\r\n 'text-sm flex items-center gap-2 w-full cursor-pointer transition-colors rounded-md',\r\n isCollapsed ? 'justify-center p-2' : 'justify-start p-2',\r\n active ? 'bg-primary/5 hover:bg-primary/10 border border-primary/15' : 'hover:bg-muted/50',\r\n ].join(' ')\r\n\r\n const buildIconClass = (active: boolean) => [\r\n 'h-4 w-4 shrink-0',\r\n active ? 'text-primary stroke-2' : 'text-muted-foreground'\r\n ].join(' ')\r\n\r\n const canRenderItem = React.useCallback((item: MenuItem) => {\r\n if (item.accessibleTo == null) return true\r\n return item.accessibleTo.some(role => normalizedUserRoles.has(role.toLowerCase()))\r\n }, [normalizedUserRoles])\r\n\r\n const visibleDatasetItems = datasetItems\r\n .filter(item => !appContent || appContent.includes(item.id as ViewerNames))\r\n .filter(canRenderItem)\r\n\r\n\r\n return (\r\n <>\r\n <SidebarContent className='overflow-hidden'>\r\n <SidebarHeader className={`w-full pt-7 flex items-center justify-center ${isCollapsed ? 'items-center' : 'pl-4 items-start'}`}>\r\n <div className='flex flex-row items-center gap-3'>\r\n <Logo image={logoUrl} />\r\n {sidebarState === 'expanded'\r\n && <h1 className=\"text-sm font-bold max-w-36\">{sidebarTitle}</h1>}\r\n </div>\r\n </SidebarHeader>\r\n {isCollapsed && <Separator className=\"z-30 w-2/3 mx-auto\" />}\r\n\r\n <div className='overflow-y-auto overflow-x-hidden'>\r\n <SidebarGroup>\r\n <SidebarGroupLabel>{t('3dViewer')}</SidebarGroupLabel>\r\n <SidebarGroupContent>\r\n <SidebarMenu>\r\n {viewerItems.filter(item => !appContent || appContent.includes(item.id as ViewerNames))\r\n .filter(canRenderItem)\r\n .map(item => {\r\n const active = item.id === currentViewer;\r\n return (\r\n <SidebarMenuItem key={item.title}>\r\n <SidebarMenuButton asChild>\r\n <Button\r\n onClick={item.onClick}\r\n title={isCollapsed ? item.title : undefined}\r\n className={buildBtnClass(active)}\r\n variant=\"ghost\"\r\n >\r\n <item.icon className={buildIconClass(active)} />\r\n <span className={`${isCollapsed ? 'hidden' : 'inline'} ${active ? 'font-bold text-primary' : ''}`}>{item.title}</span>\r\n </Button>\r\n </SidebarMenuButton>\r\n </SidebarMenuItem>\r\n );\r\n })\r\n }\r\n </SidebarMenu>\r\n </SidebarGroupContent>\r\n </SidebarGroup>\r\n\r\n\r\n {visibleDatasetItems.length > 0 && (\r\n <>\r\n {isCollapsed && <Separator className=\"z-30 w-2/3 mx-auto\" />}\r\n\r\n <SidebarGroup>\r\n <SidebarGroupLabel>{t('data')}</SidebarGroupLabel>\r\n\r\n <SidebarGroupContent>\r\n <SidebarMenu>\r\n {visibleDatasetItems.map(item => {\r\n const active = item.id === currentViewer\r\n\r\n return (\r\n <SidebarMenuItem key={item.title}>\r\n <SidebarMenuButton asChild>\r\n <Button\r\n onClick={item.onClick}\r\n title={isCollapsed ? item.title : undefined}\r\n className={buildBtnClass(active)}\r\n variant=\"ghost\"\r\n >\r\n <item.icon className={buildIconClass(active)} />\r\n <span\r\n className={`${isCollapsed ? 'hidden' : 'inline'} ${\r\n active ? 'font-bold text-primary' : ''\r\n }`}\r\n >\r\n {item.title}\r\n </span>\r\n </Button>\r\n </SidebarMenuButton>\r\n </SidebarMenuItem>\r\n )\r\n })}\r\n </SidebarMenu>\r\n </SidebarGroupContent>\r\n </SidebarGroup>\r\n </>\r\n )}\r\n {isCollapsed && <Separator className=\"z-30 w-2/3 mx-auto\" />}\r\n <SidebarGroup>\r\n <SidebarGroupLabel>{t('extensions')}</SidebarGroupLabel>\r\n <SidebarGroupContent>\r\n <SidebarMenu>\r\n {managementItems.filter(canRenderItem).map(item => {\r\n const active = item.id === currentViewer\r\n return (\r\n <SidebarMenuItem key={item.title}>\r\n <SidebarMenuButton asChild>\r\n <Button\r\n onClick={item.onClick}\r\n title={isCollapsed ? item.title : undefined}\r\n className={buildBtnClass(active)}\r\n variant=\"ghost\"\r\n >\r\n <item.icon className={buildIconClass(active)} />\r\n <span className={`${isCollapsed ? 'hidden' : 'inline'} ${active ? 'font-bold text-primary' : ''}`}>{item.title}</span>\r\n </Button>\r\n </SidebarMenuButton>\r\n </SidebarMenuItem>\r\n )\r\n })}\r\n </SidebarMenu>\r\n </SidebarGroupContent>\r\n </SidebarGroup>\r\n </div>\r\n </SidebarContent>\r\n {/* Footer Content - only show when not in BIM mode or when collapsed */}\r\n <SidebarFooter className={`w-full flex flex-col gap-4 ${isCollapsed ? 'items-center justify-center px-0 pb-4' : 'items-start justify-start px-2 pb-4'}`}>\r\n {/* Preferences */}\r\n {organization.languages?.length > 1 && (\r\n <SidebarGroup>\r\n <SidebarGroupLabel>{t('preferences')}</SidebarGroupLabel>\r\n <SidebarMenu>\r\n <SidebarMenuItem>\r\n <LanguageSwitch showLabel={sidebarState === 'expanded'} languages={organization.languages as Language[]} />\r\n </SidebarMenuItem>\r\n </SidebarMenu>\r\n </SidebarGroup>\r\n )}\r\n {/* Services */}\r\n <SidebarGroup>\r\n <SidebarGroupLabel>{t('service')}</SidebarGroupLabel>\r\n <SidebarMenu>\r\n {serviceItems.map((item, index) => (\r\n <SidebarMenuItem key={index}>\r\n <SidebarMenuButton asChild>\r\n <a \r\n href={item.url} \r\n className={`text-xs flex items-center gap-2 w-full ${isCollapsed ? 'justify-center p-2' : 'justify-start p-2'}`}\r\n title={item.tooltip}\r\n >\r\n <item.icon className=\"h-4 w-4\" />\r\n <span className={isCollapsed ? 'hidden' : 'inline'}>{item.title}</span>\r\n </a>\r\n </SidebarMenuButton>\r\n </SidebarMenuItem>\r\n ))}\r\n </SidebarMenu>\r\n </SidebarGroup>\r\n </SidebarFooter>\r\n </>\r\n )\r\n}"],"mappings":"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","names":[]}
@@ -1 +1 @@
1
- {"version":3,"file":"Signin.d.ts","sourceRoot":"","sources":["../../../../src/core/components/authentication/Signin.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AA4R9B,wBAAgB,MAAM,sBAMrB"}
1
+ {"version":3,"file":"Signin.d.ts","sourceRoot":"","sources":["../../../../src/core/components/authentication/Signin.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AA2R9B,wBAAgB,MAAM,sBAMrB"}
@@ -5,10 +5,7 @@ import { signIn } from "next-auth/react";
5
5
  import { useTranslations } from "next-intl";
6
6
  import * as LR from "lucide-react";
7
7
  import { toast, Toaster } from "sonner";
8
- import { Button } from "../ui/Button";
9
- import { GoogleIcon } from "../ui/Icons/GoogleIcon";
10
- import { Input } from "../ui/Input";
11
- import { LoadingSpinner } from "../ui/LoadingSpinner";
8
+ import { Button, GoogleIcon, Input, LoadingSpinner } from "../ui";
12
9
  import { AuthPage, useAuthTheme } from "./AuthPage";
13
10
  import { useParams, useSearchParams } from "next/navigation";
14
11
  import ReCAPTCHA from "react-google-recaptcha";
@@ -59,14 +56,16 @@ function SignInContent() {
59
56
  setIsLoading(true);
60
57
  setError("Too many failed login attempts. Please try again later.");
61
58
  return;
62
- } else if (result.code === "invalid_credentials") {
59
+ } else if (result.code === "whitelist_invalid_credentials") {
63
60
  setError("Invalid email or password");
64
61
  setIsLoading(false);
65
62
  return;
66
63
  } else if (!captchaStatus) {
67
- setTimeout(() => {
68
- setError("Captcha Verification Failed.");
69
- }, 500);
64
+ setError("Captcha Verification Failed.");
65
+ setIsLoading(false);
66
+ return;
67
+ } else if (result.code === "invalid_credentials") {
68
+ setError("Invalid email or password");
70
69
  setIsLoading(false);
71
70
  return;
72
71
  } else if (result.code === "mfa_required") {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/core/components/authentication/Signin.tsx"],"sourcesContent":["'use client'\r\n\r\nimport * as React from 'react'\r\nimport { signIn } from 'next-auth/react'\r\nimport { useTranslations } from 'next-intl'\r\nimport * as LR from 'lucide-react'\r\nimport { toast, Toaster } from 'sonner'\r\n// Direct file imports (not the ui barrel). The ui barrel\r\n// `src/core/components/ui/index.ts` re-exports dozens of components plus\r\n// `useFileUploadHandler` and `InfoSidebar`, the latter of which transitively\r\n// pulls in @thatopen and the BIM viewer tree. Importing through the barrel\r\n// would drag all of that into the auth pages; direct file imports avoid it.\r\nimport { Button } from '../ui/Button'\r\nimport { GoogleIcon } from '../ui/Icons/GoogleIcon'\r\nimport { Input } from '../ui/Input'\r\nimport { LoadingSpinner } from '../ui/LoadingSpinner'\r\nimport { AuthPage, useAuthTheme } from './AuthPage'\r\nimport { useParams, useSearchParams } from 'next/navigation'\r\nimport ReCAPTCHA from 'react-google-recaptcha'\r\n\r\nfunction SignInContent() {\r\n const [step, setStep] = React.useState<'login' | 'mfa'>('login')\r\n\r\n const [email, setEmail] = React.useState('')\r\n const [password, setPassword] = React.useState('')\r\n const [code, setCode] = React.useState('')\r\n\r\n const [captchaStatus, setCaptchaStatus] = React.useState(false)\r\n const [captchaToken, setCaptchaToken] = React.useState('')\r\n const [isLoading, setIsLoading] = React.useState(false)\r\n const [error, setError] = React.useState('')\r\n const [showPassword, setShowPassword] = React.useState(false)\r\n\r\n const searchParams = useSearchParams()\r\n const params = useParams()\r\n const orgName = params.instance ?? 'canada'\r\n const [googleError, setGoogleError] = React.useState(\r\n searchParams.get('error')\r\n )\r\n //Clean up the Google query error in URL, and have it only return /orgName/signin to clear frontend error responses \r\n React.useEffect(() => {\r\n if (googleError) {\r\n window.history.replaceState({}, '', `/${orgName}/signin`)\r\n }\r\n }, [googleError, orgName])\r\n\r\n const t = useTranslations('Signin')\r\n const tMfa = useTranslations('MFA')\r\n const authTheme = useAuthTheme()\r\n\r\n const reCaptchaSiteKey = `${process.env.NEXT_PUBLIC_RECAPTCHA_SITE_KEY}`\r\n\r\n const onReCaptchaSuccess = (token) => {\r\n setCaptchaToken(token)\r\n setCaptchaStatus(true)\r\n }\r\n\r\n // Initial LOGIN\r\n const handleSubmit = async (e) => {\r\n e.preventDefault()\r\n setGoogleError(null)\r\n setIsLoading(true)\r\n setError('')\r\n\r\n try {\r\n const result = await signIn('credentials', {\r\n redirect: false,\r\n email,\r\n password,\r\n captchaToken,\r\n })\r\n\r\n if (result?.error) {\r\n\r\n if (result.code === 'rate_limit_error') {\r\n\r\n setIsLoading(true)\r\n setError('Too many failed login attempts. Please try again later.')\r\n return\r\n }\r\n else if (result.code === 'invalid_credentials') {\r\n setError('Invalid email or password')\r\n setIsLoading(false)\r\n return\r\n }\r\n //Commenting out Captcha code for Development \r\n else if (!captchaStatus) {\r\n setTimeout(() => {\r\n setError('Captcha Verification Failed.')\r\n }, 500)\r\n setIsLoading(false)\r\n return\r\n }\r\n //MFA TRIGGER\r\n else if (result.code === 'mfa_required') {\r\n setStep('mfa')\r\n setIsLoading(false)\r\n return\r\n }\r\n\r\n else {\r\n setError('Captcha Verification Expired. Please try again later.')\r\n setIsLoading(false)\r\n return\r\n }\r\n }\r\n\r\n // Completed Login + MFA - Redirect to the Platform's Organization Dashboard \r\n window.location.href = `/${orgName}`\r\n\r\n } catch (err) {\r\n setError('Unexpected error. Please try again.')\r\n setIsLoading(false)\r\n }\r\n }\r\n\r\n // VERIFY OTP for MFA\r\n const handleVerifyOTP = async () => {\r\n setIsLoading(true)\r\n setError('')\r\n\r\n try {\r\n const res = await fetch('/api/mfa', {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify({ email, code }),\r\n })\r\n\r\n if (!res.ok) {\r\n toast.error(tMfa('invalidCode'))\r\n setIsLoading(false)\r\n return\r\n }\r\n\r\n toast.success(tMfa('success'))\r\n\r\n // FINAL LOGIN after successful MFA process\r\n await signIn('credentials', {\r\n email,\r\n password,\r\n mfaVerified: true,\r\n redirect: true,\r\n redirectTo: `/${orgName}`,\r\n })\r\n\r\n } catch (err) {\r\n toast.error(tMfa('verificationFailed'))\r\n setIsLoading(false)\r\n }\r\n }\r\n\r\n return (\r\n <>\r\n <Toaster richColors position=\"top-right\" />\r\n {/* Header */}\r\n <div className=\"space-y-2 text-left\">\r\n <h1 className=\"font-display font-bold\" style={{\r\n fontSize: '1.75rem',\r\n lineHeight: '1.1',\r\n letterSpacing: '-0.02em',\r\n color: 'var(--hp-on-surface)',\r\n }}>\r\n {step === 'login' ? t('title') : tMfa('title')}\r\n </h1>\r\n\r\n <p style={{ color: 'var(--hp-on-surface-variant)', fontSize: '0.9rem' }}>\r\n {step === 'login'\r\n ? t('message')\r\n : tMfa('subtitle', { email })}\r\n </p>\r\n </div>\r\n\r\n {/* LOGIN FORM */}\r\n {step === 'login' && (\r\n <form onSubmit={handleSubmit} className=\"space-y-4\">\r\n\r\n <Input\r\n type=\"email\"\r\n placeholder={t('placeholder1')}\r\n value={email}\r\n onChange={(e) => setEmail(e.target.value)}\r\n disabled={isLoading}\r\n required\r\n />\r\n\r\n <div className=\"relative\">\r\n <Input\r\n type={showPassword ? 'text' : 'password'}\r\n placeholder={t('placeholder2')}\r\n value={password}\r\n onChange={(e) => setPassword(e.target.value)}\r\n disabled={isLoading}\r\n required\r\n className=\"pr-10\"\r\n />\r\n <button\r\n type=\"button\"\r\n onClick={() => setShowPassword(v => !v)}\r\n tabIndex={-1}\r\n className=\"absolute right-3 top-1/2 -translate-y-1/2 transition-colors\"\r\n style={{ color: 'var(--hp-on-surface-variant)' }}\r\n >\r\n {showPassword ? <LR.EyeOff size={16} /> : <LR.Eye size={16} />}\r\n </button>\r\n </div>\r\n {/* Google Not Linked Error */}\r\n {googleError === 'google_not_linked' && (\r\n <div className=\"auth-pw-error\">\r\n Your Google account is not linked. Please sign in with your credentials first, then link your Google account.\r\n </div>\r\n )}\r\n {error && <div className=\"auth-pw-error\">{error}</div>}\r\n\r\n <div className=\"flex items-center gap-2\">\r\n <Button type=\"submit\" disabled={isLoading} className=\"flex-1 auth-btn-primary\">\r\n {isLoading ? <LoadingSpinner /> : 'Login'}\r\n </Button>\r\n\r\n {/* Google button */}\r\n {<button\r\n type=\"button\"\r\n onClick={() => signIn('google', { redirectTo: `/${orgName}` })}\r\n disabled={isLoading}\r\n aria-label=\"Sign in with Google\"\r\n className=\"auth-google-btn\"\r\n >\r\n <GoogleIcon size={20} />\r\n </button>}\r\n\r\n </div>\r\n\r\n {/* Reset Password link */}\r\n {/* <div className=\"flex justify-start\">\r\n <a\r\n href={`/${orgName}/auth/reset-password`}\r\n className=\"text-sm underline underline-offset-4 hover:opacity-80\"\r\n style={{ color: 'var(--hp-primary)' }}\r\n >\r\n Reset your password\r\n </a>\r\n </div> */}\r\n </form>\r\n )}\r\n\r\n {/* MFA FORM */}\r\n {step === 'mfa' && (\r\n <div className=\"space-y-4\">\r\n\r\n <Input\r\n placeholder={tMfa('placeholder')}\r\n value={code}\r\n onChange={(e) => setCode(e.target.value)}\r\n disabled={isLoading}\r\n />\r\n\r\n <Button onClick={handleVerifyOTP} disabled={isLoading} className=\"w-full\">\r\n {isLoading ? <LoadingSpinner /> : tMfa('verify')}\r\n </Button>\r\n\r\n {/* Back */}\r\n <Button\r\n variant=\"outline\"\r\n onClick={() => setStep('login')}\r\n className=\"w-full mt-3 inline-flex items-center justify-center gap-2\"\r\n >\r\n <LR.ArrowLeft size={16} />\r\n {tMfa('backToLogin')}\r\n </Button>\r\n </div>\r\n )}\r\n\r\n {/* CAPTCHA only on Credentials(Username and Password) Provider login */}\r\n {step === 'login' && (\r\n <div className=\"auth-captcha-wrapper\">\r\n <ReCAPTCHA\r\n key={`recaptcha-${authTheme}`}\r\n sitekey={reCaptchaSiteKey}\r\n onChange={onReCaptchaSuccess}\r\n theme={authTheme}\r\n />\r\n </div>\r\n )}\r\n </>\r\n )\r\n}\r\n\r\nexport function SignIn() {\r\n return (\r\n <AuthPage>\r\n <SignInContent />\r\n </AuthPage>\r\n )\r\n}\r\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../../src/core/components/authentication/Signin.tsx"],"sourcesContent":["'use client'\r\n\r\nimport * as React from 'react'\r\nimport { signIn } from 'next-auth/react'\r\nimport { useTranslations } from 'next-intl'\r\nimport * as LR from 'lucide-react'\r\nimport { toast, Toaster } from 'sonner'\r\nimport { Button, GoogleIcon, Input, LoadingSpinner } from '../ui'\r\nimport { AuthPage, useAuthTheme } from './AuthPage'\r\nimport { useParams, useSearchParams } from 'next/navigation'\r\nimport ReCAPTCHA from 'react-google-recaptcha'\r\n\r\nfunction SignInContent() {\r\n const [step, setStep] = React.useState<'login' | 'mfa'>('login')\r\n\r\n const [email, setEmail] = React.useState('')\r\n const [password, setPassword] = React.useState('')\r\n const [code, setCode] = React.useState('')\r\n\r\n const [captchaStatus, setCaptchaStatus] = React.useState(false)\r\n const [captchaToken, setCaptchaToken] = React.useState('')\r\n const [isLoading, setIsLoading] = React.useState(false)\r\n const [error, setError] = React.useState('')\r\n const [showPassword, setShowPassword] = React.useState(false)\r\n\r\n const searchParams = useSearchParams()\r\n const params = useParams()\r\n const orgName = params.instance ?? 'canada'\r\n const [googleError, setGoogleError] = React.useState(\r\n searchParams.get('error')\r\n )\r\n //Clean up the Google query error in URL, and have it only return /orgName/signin to clear frontend error responses \r\n React.useEffect(() => {\r\n if (googleError) {\r\n window.history.replaceState({}, '', `/${orgName}/signin`)\r\n }\r\n }, [googleError, orgName])\r\n\r\n const t = useTranslations('Signin')\r\n const tMfa = useTranslations('MFA')\r\n const authTheme = useAuthTheme()\r\n\r\n const reCaptchaSiteKey = `${process.env.NEXT_PUBLIC_RECAPTCHA_SITE_KEY}`\r\n\r\n const onReCaptchaSuccess = (token) => {\r\n setCaptchaToken(token)\r\n setCaptchaStatus(true)\r\n }\r\n\r\n // Initial LOGIN\r\n const handleSubmit = async (e) => {\r\n e.preventDefault()\r\n setGoogleError(null)\r\n setIsLoading(true)\r\n setError('')\r\n\r\n try {\r\n const result = await signIn('credentials', {\r\n redirect: false,\r\n email,\r\n password,\r\n captchaToken,\r\n })\r\n\r\n if (result?.error) {\r\n\r\n if (result.code === 'rate_limit_error') {\r\n\r\n setIsLoading(true)\r\n setError('Too many failed login attempts. Please try again later.')\r\n return\r\n }\r\n\r\n else if (result.code === 'whitelist_invalid_credentials') {\r\n setError('Invalid email or password')\r\n setIsLoading(false)\r\n return\r\n }\r\n\r\n else if (!captchaStatus) {\r\n\r\n setError('Captcha Verification Failed.')\r\n setIsLoading(false)\r\n return\r\n }\r\n\r\n else if (result.code === 'invalid_credentials') {\r\n setError('Invalid email or password')\r\n setIsLoading(false)\r\n return\r\n }\r\n //MFA TRIGGER\r\n else if (result.code === 'mfa_required') {\r\n setStep('mfa')\r\n setIsLoading(false)\r\n return\r\n }\r\n\r\n else { //result.code === 'expired_recaptcha_token\r\n setError('Captcha Verification Expired. Please try again later.')\r\n setIsLoading(false)\r\n return\r\n }\r\n }\r\n\r\n // Completed Login + MFA - Redirect to the Platform's Organization Dashboard \r\n window.location.href = `/${orgName}`\r\n\r\n } catch (err) {\r\n setError('Unexpected error. Please try again.')\r\n setIsLoading(false)\r\n }\r\n }\r\n\r\n // VERIFY OTP for MFA\r\n const handleVerifyOTP = async () => {\r\n setIsLoading(true)\r\n setError('')\r\n\r\n try {\r\n const res = await fetch('/api/mfa', {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify({ email, code }),\r\n })\r\n\r\n if (!res.ok) {\r\n toast.error(tMfa('invalidCode'))\r\n setIsLoading(false)\r\n return\r\n }\r\n\r\n toast.success(tMfa('success'))\r\n\r\n // FINAL LOGIN after successful MFA process\r\n await signIn('credentials', {\r\n email,\r\n password,\r\n mfaVerified: true,\r\n redirect: true,\r\n redirectTo: `/${orgName}`,\r\n })\r\n\r\n } catch (err) {\r\n toast.error(tMfa('verificationFailed'))\r\n setIsLoading(false)\r\n }\r\n }\r\n\r\n return (\r\n <>\r\n <Toaster richColors position=\"top-right\" />\r\n {/* Header */}\r\n <div className=\"space-y-2 text-left\">\r\n <h1 className=\"font-display font-bold\" style={{\r\n fontSize: '1.75rem',\r\n lineHeight: '1.1',\r\n letterSpacing: '-0.02em',\r\n color: 'var(--hp-on-surface)',\r\n }}>\r\n {step === 'login' ? t('title') : tMfa('title')}\r\n </h1>\r\n\r\n <p style={{ color: 'var(--hp-on-surface-variant)', fontSize: '0.9rem' }}>\r\n {step === 'login'\r\n ? t('message')\r\n : tMfa('subtitle', { email })}\r\n </p>\r\n </div>\r\n\r\n {/* LOGIN FORM */}\r\n {step === 'login' && (\r\n <form onSubmit={handleSubmit} className=\"space-y-4\">\r\n\r\n <Input\r\n type=\"email\"\r\n placeholder={t('placeholder1')}\r\n value={email}\r\n onChange={(e) => setEmail(e.target.value)}\r\n disabled={isLoading}\r\n required\r\n />\r\n\r\n <div className=\"relative\">\r\n <Input\r\n type={showPassword ? 'text' : 'password'}\r\n placeholder={t('placeholder2')}\r\n value={password}\r\n onChange={(e) => setPassword(e.target.value)}\r\n disabled={isLoading}\r\n required\r\n className=\"pr-10\"\r\n />\r\n <button\r\n type=\"button\"\r\n onClick={() => setShowPassword(v => !v)}\r\n tabIndex={-1}\r\n className=\"absolute right-3 top-1/2 -translate-y-1/2 transition-colors\"\r\n style={{ color: 'var(--hp-on-surface-variant)' }}\r\n >\r\n {showPassword ? <LR.EyeOff size={16} /> : <LR.Eye size={16} />}\r\n </button>\r\n </div>\r\n {/* Google Not Linked Error */}\r\n {googleError === 'google_not_linked' && (\r\n <div className=\"auth-pw-error\">\r\n Your Google account is not linked. Please sign in with your credentials first, then link your Google account.\r\n </div>\r\n )}\r\n {error && <div className=\"auth-pw-error\">{error}</div>}\r\n\r\n <div className=\"flex items-center gap-2\">\r\n <Button type=\"submit\" disabled={isLoading} className=\"flex-1 auth-btn-primary\">\r\n {isLoading ? <LoadingSpinner /> : 'Login'}\r\n </Button>\r\n\r\n {/* Google button */}\r\n {<button\r\n type=\"button\"\r\n onClick={() => signIn('google', { redirectTo: `/${orgName}` })}\r\n disabled={isLoading}\r\n aria-label=\"Sign in with Google\"\r\n className=\"auth-google-btn\"\r\n >\r\n <GoogleIcon size={20} />\r\n </button>}\r\n\r\n </div>\r\n\r\n {/*⚠️⚠️⚠️⚠️ DISABLED FOR NOW - Password Reset link, will implement in the future when we have the flow ready */}\r\n {/* Reset Password link */}\r\n {/* <div className=\"flex justify-start\">\r\n <a\r\n href={`/${orgName}/auth/reset-password`}\r\n className=\"text-sm underline underline-offset-4 hover:opacity-80\"\r\n style={{ color: 'var(--hp-primary)' }}\r\n >\r\n Reset your password\r\n </a>\r\n </div> */}\r\n </form>\r\n )}\r\n\r\n {/* MFA FORM */}\r\n {step === 'mfa' && (\r\n <div className=\"space-y-4\">\r\n\r\n <Input\r\n placeholder={tMfa('placeholder')}\r\n value={code}\r\n onChange={(e) => setCode(e.target.value)}\r\n disabled={isLoading}\r\n />\r\n\r\n <Button onClick={handleVerifyOTP} disabled={isLoading} className=\"w-full\">\r\n {isLoading ? <LoadingSpinner /> : tMfa('verify')}\r\n </Button>\r\n\r\n {/* Back */}\r\n <Button\r\n variant=\"outline\"\r\n onClick={() => setStep('login')}\r\n className=\"w-full mt-3 inline-flex items-center justify-center gap-2\"\r\n >\r\n <LR.ArrowLeft size={16} />\r\n {tMfa('backToLogin')}\r\n </Button>\r\n </div>\r\n )}\r\n\r\n {/* CAPTCHA only on Credentials(Username and Password) Provider login */}\r\n {step === 'login' && (\r\n <div className=\"auth-captcha-wrapper\">\r\n <ReCAPTCHA\r\n key={`recaptcha-${authTheme}`}\r\n sitekey={reCaptchaSiteKey}\r\n onChange={onReCaptchaSuccess}\r\n theme={authTheme}\r\n />\r\n </div>\r\n )}\r\n </>\r\n )\r\n}\r\n\r\nexport function SignIn() {\r\n return (\r\n <AuthPage>\r\n <SignInContent />\r\n </AuthPage>\r\n )\r\n}"],"mappings":"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","names":[]}
@@ -5,4 +5,5 @@ export * from './viewers';
5
5
  export * from './ui';
6
6
  export * from './Toolbar';
7
7
  export { InstanceNotFound } from './instance-not-found';
8
+ export * from './organizationConfig';
8
9
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/components/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAA;AACnC,cAAc,kBAAkB,CAAA;AAChC,cAAc,YAAY,CAAA;AAC1B,cAAc,WAAW,CAAA;AACzB,cAAc,MAAM,CAAA;AACpB,cAAc,WAAW,CAAA;AACzB,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/components/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAA;AACnC,cAAc,kBAAkB,CAAA;AAChC,cAAc,YAAY,CAAA;AAC1B,cAAc,WAAW,CAAA;AACzB,cAAc,MAAM,CAAA;AACpB,cAAc,WAAW,CAAA;AACzB,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AACvD,cAAc,sBAAsB,CAAA"}
@@ -5,6 +5,7 @@ export * from "./viewers";
5
5
  export * from "./ui";
6
6
  export * from "./Toolbar";
7
7
  import { InstanceNotFound } from "./instance-not-found";
8
+ export * from "./organizationConfig";
8
9
  export {
9
10
  InstanceNotFound
10
11
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/core/components/index.ts"],"sourcesContent":["export * from './AppSidebarContent'\r\nexport * from './authentication'\r\nexport * from './settings'\r\nexport * from './viewers'\r\nexport * from './ui'\r\nexport * from './Toolbar'\r\nexport { InstanceNotFound } from './instance-not-found'"],"mappings":"AAAA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,SAAS,wBAAwB;","names":[]}
1
+ {"version":3,"sources":["../../../src/core/components/index.ts"],"sourcesContent":["export * from './AppSidebarContent'\r\nexport * from './authentication'\r\nexport * from './settings'\r\nexport * from './viewers'\r\nexport * from './ui'\r\nexport * from './Toolbar'\r\nexport { InstanceNotFound } from './instance-not-found'\r\nexport * from './organizationConfig'"],"mappings":"AAAA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,SAAS,wBAAwB;AACjC,cAAc;","names":[]}
@@ -0,0 +1,2 @@
1
+ export default function OrganizationConfigPage(): import("react").JSX.Element;
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/core/components/organizationConfig/index.tsx"],"names":[],"mappings":"AAcA,MAAM,CAAC,OAAO,UAAU,sBAAsB,gCAiE7C"}
@@ -0,0 +1,66 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { useEffect, useState } from "react";
4
+ import { useScroll, useSpring, useTransform } from "framer-motion";
5
+ import { Toaster } from "sonner";
6
+ import { useLocale } from "next-intl";
7
+ import { useRouter } from "next/navigation";
8
+ import Navbar from "../ui/Navbar";
9
+ import AnimatedBackground from "../ui/AnimatedBackground";
10
+ import OrganizationConfigContent from "./src/organizationConfigContent";
11
+ function OrganizationConfigPage() {
12
+ const [theme, setTheme] = useState("dark");
13
+ const locale = useLocale();
14
+ const router = useRouter();
15
+ const { scrollY } = useScroll();
16
+ const navOpacity = useTransform(scrollY, [0, 100], [0.8, 1]);
17
+ const navY = useSpring(
18
+ useTransform(scrollY, [0, 100], [0, 0]),
19
+ {
20
+ stiffness: 300,
21
+ damping: 30
22
+ }
23
+ );
24
+ useEffect(() => {
25
+ const isDark = window.matchMedia(
26
+ "(prefers-color-scheme: dark)"
27
+ ).matches;
28
+ setTheme(isDark ? "dark" : "light");
29
+ document.documentElement.classList.toggle("dark", isDark);
30
+ }, []);
31
+ const toggleTheme = () => {
32
+ const newTheme = theme === "dark" ? "light" : "dark";
33
+ setTheme(newTheme);
34
+ document.documentElement.classList.toggle("dark", newTheme === "dark");
35
+ };
36
+ const toggleLanguage = () => {
37
+ const expires = /* @__PURE__ */ new Date();
38
+ expires.setFullYear(expires.getFullYear() + 1);
39
+ document.cookie = `NEXT_LOCALE=${locale}; expires=${expires.toUTCString()}; path=/; SameSite=Lax`;
40
+ router.refresh();
41
+ };
42
+ return /* @__PURE__ */ jsxs("div", { className: "min-h-screen bg-background text-foreground relative overflow-hidden", children: [
43
+ /* @__PURE__ */ jsx(AnimatedBackground, {}),
44
+ /* @__PURE__ */ jsx(Toaster, { richColors: true }),
45
+ /* @__PURE__ */ jsx(
46
+ Navbar,
47
+ {
48
+ activeSection: "",
49
+ theme,
50
+ locale,
51
+ navOpacity,
52
+ navY,
53
+ onToggleTheme: toggleTheme,
54
+ onToggleLanguage: toggleLanguage,
55
+ onScrollToSection: () => {
56
+ },
57
+ showNavigation: false
58
+ }
59
+ ),
60
+ /* @__PURE__ */ jsx(OrganizationConfigContent, {})
61
+ ] });
62
+ }
63
+ export {
64
+ OrganizationConfigPage as default
65
+ };
66
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/core/components/organizationConfig/index.tsx"],"sourcesContent":["'use client'\r\n\r\nimport { useEffect, useState } from 'react'\r\nimport { useScroll, useSpring, useTransform } from 'framer-motion'\r\nimport { Toaster } from 'sonner'\r\nimport { useLocale } from 'next-intl'\r\nimport { useRouter } from 'next/navigation'\r\n\r\nimport Navbar from '../ui/Navbar'\r\nimport AnimatedBackground from '../ui/AnimatedBackground'\r\nimport OrganizationConfigContent from './src/organizationConfigContent'\r\n\r\nimport { Language } from '../../types/dbTypes'\r\n\r\nexport default function OrganizationConfigPage() {\r\n const [theme, setTheme] = useState<'light' | 'dark'>('dark')\r\n\r\n const locale = useLocale() as Language\r\n const router = useRouter()\r\n\r\n const { scrollY } = useScroll()\r\n\r\n const navOpacity = useTransform(scrollY, [0, 100], [0.8, 1])\r\n\r\n const navY = useSpring(\r\n useTransform(scrollY, [0, 100], [0, 0]),\r\n {\r\n stiffness: 300,\r\n damping: 30,\r\n }\r\n )\r\n\r\n useEffect(() => {\r\n const isDark = window.matchMedia(\r\n '(prefers-color-scheme: dark)'\r\n ).matches\r\n\r\n setTheme(isDark ? 'dark' : 'light')\r\n\r\n document.documentElement.classList.toggle('dark', isDark)\r\n }, [])\r\n\r\n const toggleTheme = () => {\r\n const newTheme = theme === 'dark' ? 'light' : 'dark'\r\n\r\n setTheme(newTheme)\r\n document.documentElement.classList.toggle('dark', newTheme === 'dark')\r\n }\r\n\r\n const toggleLanguage = () => {\r\n const expires = new Date()\r\n expires.setFullYear(expires.getFullYear() + 1)\r\n\r\n document.cookie = `NEXT_LOCALE=${locale}; expires=${expires.toUTCString()}; path=/; SameSite=Lax`\r\n\r\n router.refresh()\r\n }\r\n\r\n return (\r\n <div className=\"min-h-screen bg-background text-foreground relative overflow-hidden\">\r\n <AnimatedBackground />\r\n\r\n <Toaster richColors />\r\n\r\n <Navbar\r\n activeSection=\"\"\r\n theme={theme}\r\n locale={locale}\r\n navOpacity={navOpacity}\r\n navY={navY}\r\n onToggleTheme={toggleTheme}\r\n onToggleLanguage={toggleLanguage}\r\n onScrollToSection={() => {}}\r\n showNavigation={false}\r\n />\r\n\r\n <OrganizationConfigContent />\r\n </div>\r\n )\r\n}"],"mappings":";AA2DI,SACE,KADF;AAzDJ,SAAS,WAAW,gBAAgB;AACpC,SAAS,WAAW,WAAW,oBAAoB;AACnD,SAAS,eAAe;AACxB,SAAS,iBAAiB;AAC1B,SAAS,iBAAiB;AAE1B,OAAO,YAAY;AACnB,OAAO,wBAAwB;AAC/B,OAAO,+BAAgC;AAIxB,SAAR,yBAA0C;AAC/C,QAAM,CAAC,OAAO,QAAQ,IAAI,SAA2B,MAAM;AAE3D,QAAM,SAAS,UAAU;AACzB,QAAM,SAAS,UAAU;AAEzB,QAAM,EAAE,QAAQ,IAAI,UAAU;AAE9B,QAAM,aAAa,aAAa,SAAS,CAAC,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC;AAE3D,QAAM,OAAO;AAAA,IACX,aAAa,SAAS,CAAC,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;AAAA,IACtC;AAAA,MACE,WAAW;AAAA,MACX,SAAS;AAAA,IACX;AAAA,EACF;AAEA,YAAU,MAAM;AACd,UAAM,SAAS,OAAO;AAAA,MACpB;AAAA,IACF,EAAE;AAEF,aAAS,SAAS,SAAS,OAAO;AAElC,aAAS,gBAAgB,UAAU,OAAO,QAAQ,MAAM;AAAA,EAC1D,GAAG,CAAC,CAAC;AAEL,QAAM,cAAc,MAAM;AACxB,UAAM,WAAW,UAAU,SAAS,UAAU;AAE9C,aAAS,QAAQ;AACjB,aAAS,gBAAgB,UAAU,OAAO,QAAQ,aAAa,MAAM;AAAA,EACvE;AAEA,QAAM,iBAAiB,MAAM;AAC3B,UAAM,UAAU,oBAAI,KAAK;AACzB,YAAQ,YAAY,QAAQ,YAAY,IAAI,CAAC;AAE7C,aAAS,SAAS,eAAe,MAAM,aAAa,QAAQ,YAAY,CAAC;AAEzE,WAAO,QAAQ;AAAA,EACjB;AAEA,SACE,qBAAC,SAAI,WAAU,uEACb;AAAA,wBAAC,sBAAmB;AAAA,IAEpB,oBAAC,WAAQ,YAAU,MAAC;AAAA,IAEpB;AAAA,MAAC;AAAA;AAAA,QACC,eAAc;AAAA,QACd;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,eAAe;AAAA,QACf,kBAAkB;AAAA,QAClB,mBAAmB,MAAM;AAAA,QAAC;AAAA,QAC1B,gBAAgB;AAAA;AAAA,IAClB;AAAA,IAEA,oBAAC,6BAA2B;AAAA,KAC9B;AAEJ;","names":[]}
@@ -0,0 +1,2 @@
1
+ export default function OrganizationConfigContent(): import("react").JSX.Element;
2
+ //# sourceMappingURL=organizationConfigContent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"organizationConfigContent.d.ts","sourceRoot":"","sources":["../../../../../src/core/components/organizationConfig/src/organizationConfigContent.tsx"],"names":[],"mappings":"AAaA,MAAM,CAAC,OAAO,UAAU,yBAAyB,gCAmRhD"}
@@ -0,0 +1,229 @@
1
+ "use client";
2
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
+ import { motion } from "framer-motion";
4
+ import { useState } from "react";
5
+ import { useRouter } from "next/navigation";
6
+ import { useTranslations } from "next-intl";
7
+ import { Button } from "../../ui/Button";
8
+ import { Card } from "../../ui/Card";
9
+ import { Input } from "../../ui/Input";
10
+ import { Textarea } from "../../ui/Textarea";
11
+ import Footer from "../../ui/Footer";
12
+ function OrganizationConfigContent() {
13
+ const t = useTranslations("OrganizationConfig");
14
+ const router = useRouter();
15
+ const [error, setError] = useState(null);
16
+ const [loading, setLoading] = useState(false);
17
+ function validateOrgName(name) {
18
+ const regex = /^[a-z0-9.-]{3,63}$/;
19
+ return regex.test(name);
20
+ }
21
+ async function handleSubmit(e) {
22
+ var _a;
23
+ e.preventDefault();
24
+ setError(null);
25
+ setLoading(true);
26
+ const formData = new FormData(e.currentTarget);
27
+ const orgLanguages = formData.getAll("orgLanguages").map(String);
28
+ const data = {
29
+ orgName: formData.get("orgName"),
30
+ orgTitle: formData.get("orgTitle"),
31
+ orgDescription: formData.get("orgDescription"),
32
+ orgLanguages,
33
+ adminName: formData.get("adminName"),
34
+ adminEmail: formData.get("adminEmail"),
35
+ adminPassword: formData.get("adminPassword")
36
+ };
37
+ try {
38
+ const res = await fetch("/api/setup", {
39
+ method: "POST",
40
+ headers: {
41
+ "Content-Type": "application/json"
42
+ },
43
+ body: JSON.stringify(data)
44
+ });
45
+ const json = await res.json();
46
+ if (res.ok && json.success) {
47
+ router.push(`/${data.orgName}/auth/signin`);
48
+ return;
49
+ }
50
+ setError((_a = json.error) != null ? _a : "Failed to initialize instance.");
51
+ } catch (e2) {
52
+ setError("Network error. Please try again.");
53
+ } finally {
54
+ setLoading(false);
55
+ }
56
+ }
57
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
58
+ /* @__PURE__ */ jsx("section", { className: "min-h-screen py-32 relative flex items-center z-10", children: /* @__PURE__ */ jsx("div", { className: "container mx-auto px-6", children: /* @__PURE__ */ jsxs(
59
+ motion.div,
60
+ {
61
+ initial: { opacity: 0, y: 30 },
62
+ animate: { opacity: 1, y: 0 },
63
+ className: "max-w-5xl mx-auto",
64
+ children: [
65
+ /* @__PURE__ */ jsxs("div", { className: "text-center mb-16 space-y-6", children: [
66
+ /* @__PURE__ */ jsx("h1", { className: "text-4xl md:text-5xl font-bold", children: t("title") }),
67
+ /* @__PURE__ */ jsx("p", { className: "text-lg text-muted-foreground max-w-3xl mx-auto", children: t("description") })
68
+ ] }),
69
+ /* @__PURE__ */ jsxs("div", { className: "grid lg:grid-cols-3 gap-8", children: [
70
+ /* @__PURE__ */ jsxs(Card, { className: "lg:col-span-2 p-8", children: [
71
+ /* @__PURE__ */ jsx("h3", { className: "text-2xl font-bold mb-6", children: t("setupTitle") }),
72
+ /* @__PURE__ */ jsx("p", { className: "text-muted-foreground mb-8", children: t("setupDescription") }),
73
+ /* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit, className: "space-y-6", children: [
74
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
75
+ /* @__PURE__ */ jsx("label", { className: "text-sm font-medium", children: "Organization Name / Slug" }),
76
+ /* @__PURE__ */ jsx(
77
+ Input,
78
+ {
79
+ name: "orgName",
80
+ placeholder: "my-org",
81
+ required: true,
82
+ minLength: 3,
83
+ maxLength: 63,
84
+ pattern: "^[a-z0-9.-]+$"
85
+ }
86
+ ),
87
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "3\u201363 characters. Lowercase letters, numbers, dots, and hyphens only." })
88
+ ] }),
89
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
90
+ /* @__PURE__ */ jsx("label", { className: "text-sm font-medium", children: "Organization Title" }),
91
+ /* @__PURE__ */ jsx(
92
+ Input,
93
+ {
94
+ name: "orgTitle",
95
+ placeholder: "Organization Title",
96
+ required: true
97
+ }
98
+ )
99
+ ] }),
100
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
101
+ /* @__PURE__ */ jsx("label", { className: "text-sm font-medium", children: "Organization Description" }),
102
+ /* @__PURE__ */ jsx(
103
+ Textarea,
104
+ {
105
+ name: "orgDescription",
106
+ placeholder: "Organization Description",
107
+ rows: 4,
108
+ required: true
109
+ }
110
+ )
111
+ ] }),
112
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
113
+ /* @__PURE__ */ jsx("label", { className: "text-sm font-medium", children: "Languages" }),
114
+ /* @__PURE__ */ jsxs(
115
+ "select",
116
+ {
117
+ name: "orgLanguages",
118
+ multiple: true,
119
+ defaultValue: ["En"],
120
+ className: "w-full rounded-md border border-input bg-background px-3 py-2 min-h-[100px]",
121
+ children: [
122
+ /* @__PURE__ */ jsx("option", { value: "En", children: "English" }),
123
+ /* @__PURE__ */ jsx("option", { value: "Fr", children: "French" }),
124
+ /* @__PURE__ */ jsx("option", { value: "Es", children: "Spanish" })
125
+ ]
126
+ }
127
+ ),
128
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "Hold Ctrl (Windows) / Cmd (Mac) to select multiple languages" })
129
+ ] }),
130
+ /* @__PURE__ */ jsxs("div", { className: "border-t pt-6", children: [
131
+ /* @__PURE__ */ jsx("h4", { className: "font-semibold mb-4", children: "Administrator Account" }),
132
+ /* @__PURE__ */ jsxs("div", { className: "grid sm:grid-cols-2 gap-4", children: [
133
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
134
+ /* @__PURE__ */ jsx("label", { className: "text-sm font-medium", children: "Admin Name" }),
135
+ /* @__PURE__ */ jsx(
136
+ Input,
137
+ {
138
+ name: "adminName",
139
+ placeholder: "Admin Name",
140
+ required: true
141
+ }
142
+ )
143
+ ] }),
144
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
145
+ /* @__PURE__ */ jsx("label", { className: "text-sm font-medium", children: "Admin Email" }),
146
+ /* @__PURE__ */ jsx(
147
+ Input,
148
+ {
149
+ name: "adminEmail",
150
+ type: "email",
151
+ placeholder: "admin@example.com",
152
+ required: true
153
+ }
154
+ )
155
+ ] })
156
+ ] }),
157
+ /* @__PURE__ */ jsxs("div", { className: "mt-4 flex flex-col gap-2", children: [
158
+ /* @__PURE__ */ jsx("label", { className: "text-sm font-medium", children: "Password" }),
159
+ /* @__PURE__ */ jsx(
160
+ Input,
161
+ {
162
+ name: "adminPassword",
163
+ type: "password",
164
+ placeholder: "Password",
165
+ minLength: 8,
166
+ required: true
167
+ }
168
+ )
169
+ ] })
170
+ ] }),
171
+ error && /* @__PURE__ */ jsx("div", { className: "rounded-md border border-red-500/20 bg-red-500/10 p-4 text-sm text-red-500", children: error }),
172
+ /* @__PURE__ */ jsx(
173
+ Button,
174
+ {
175
+ type: "submit",
176
+ size: "lg",
177
+ className: "gradient-button w-full",
178
+ disabled: loading,
179
+ children: loading ? "Initializing Instance..." : "Initialize Instance"
180
+ }
181
+ )
182
+ ] })
183
+ ] }),
184
+ /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
185
+ /* @__PURE__ */ jsxs(Card, { className: "p-6 hover-card", children: [
186
+ /* @__PURE__ */ jsx("h3", { className: "text-lg font-bold mb-3", children: t("contactInfoTitle") }),
187
+ /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
188
+ /* @__PURE__ */ jsxs("div", { children: [
189
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground mb-1", children: t("emailLabel") }),
190
+ /* @__PURE__ */ jsx(
191
+ "a",
192
+ {
193
+ href: "mailto:info@collabdt.org",
194
+ className: "text-primary hover:underline font-medium text-sm",
195
+ children: "info@collabdt.org"
196
+ }
197
+ )
198
+ ] }),
199
+ /* @__PURE__ */ jsxs("div", { children: [
200
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground mb-1", children: t("websiteLabel") }),
201
+ /* @__PURE__ */ jsx(
202
+ "a",
203
+ {
204
+ href: "https://collabdt.org",
205
+ target: "_blank",
206
+ rel: "noopener noreferrer",
207
+ className: "text-primary hover:underline font-medium text-sm",
208
+ children: "collabdt.org"
209
+ }
210
+ )
211
+ ] })
212
+ ] })
213
+ ] }),
214
+ /* @__PURE__ */ jsxs(Card, { className: "p-6 hover-card bg-primary/5 border-primary/20", children: [
215
+ /* @__PURE__ */ jsx("h3", { className: "text-lg font-bold mb-3", children: t("needHelpTitle") }),
216
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: t("needHelpDescription") })
217
+ ] })
218
+ ] })
219
+ ] })
220
+ ]
221
+ }
222
+ ) }) }),
223
+ /* @__PURE__ */ jsx(Footer, {})
224
+ ] });
225
+ }
226
+ export {
227
+ OrganizationConfigContent as default
228
+ };
229
+ //# sourceMappingURL=organizationConfigContent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../src/core/components/organizationConfig/src/organizationConfigContent.tsx"],"sourcesContent":["'use client'\r\n\r\nimport { motion } from 'framer-motion'\r\nimport { useState } from 'react'\r\nimport { useRouter } from 'next/navigation'\r\nimport { useTranslations } from 'next-intl'\r\n\r\nimport { Button } from '../../ui/Button'\r\nimport { Card } from '../../ui/Card'\r\nimport { Input } from '../../ui/Input'\r\nimport { Textarea } from '../../ui/Textarea'\r\nimport Footer from '../../ui/Footer'\r\n\r\nexport default function OrganizationConfigContent() {\r\n const t = useTranslations('OrganizationConfig')\r\n const router = useRouter()\r\n\r\n const [error, setError] = useState<string | null>(null)\r\n const [loading, setLoading] = useState(false)\r\n\r\n function validateOrgName(name: string) {\r\n const regex = /^[a-z0-9.-]{3,63}$/\r\n return regex.test(name)\r\n }\r\n\r\n async function handleSubmit(\r\n e: React.FormEvent<HTMLFormElement>\r\n ) {\r\n e.preventDefault()\r\n\r\n setError(null)\r\n setLoading(true)\r\n \r\n \r\n const formData = new FormData(e.currentTarget)\r\n \r\n const orgLanguages = formData\r\n .getAll('orgLanguages')\r\n .map(String)\r\n\r\n const data = {\r\n orgName: formData.get('orgName'),\r\n orgTitle: formData.get('orgTitle'),\r\n orgDescription: formData.get('orgDescription'),\r\n orgLanguages,\r\n adminName: formData.get('adminName'),\r\n adminEmail: formData.get('adminEmail'),\r\n adminPassword: formData.get('adminPassword'),\r\n }\r\n\r\n try {\r\n const res = await fetch('/api/setup', {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n body: JSON.stringify(data),\r\n })\r\n\r\n const json = await res.json()\r\n\r\n if (res.ok && json.success) {\r\n router.push(`/${data.orgName}/auth/signin`)\r\n return\r\n }\r\n\r\n setError(json.error ?? 'Failed to initialize instance.')\r\n } catch {\r\n setError('Network error. Please try again.')\r\n } finally {\r\n setLoading(false)\r\n }\r\n }\r\n\r\n return (\r\n <>\r\n <section className=\"min-h-screen py-32 relative flex items-center z-10\">\r\n <div className=\"container mx-auto px-6\">\r\n <motion.div\r\n initial={{ opacity: 0, y: 30 }}\r\n animate={{ opacity: 1, y: 0 }}\r\n className=\"max-w-5xl mx-auto\"\r\n >\r\n <div className=\"text-center mb-16 space-y-6\">\r\n <h1 className=\"text-4xl md:text-5xl font-bold\">\r\n {t('title')}\r\n </h1>\r\n\r\n <p className=\"text-lg text-muted-foreground max-w-3xl mx-auto\">\r\n {t('description')}\r\n </p>\r\n </div>\r\n\r\n <div className=\"grid lg:grid-cols-3 gap-8\">\r\n <Card className=\"lg:col-span-2 p-8\">\r\n <h3 className=\"text-2xl font-bold mb-6\">\r\n {t('setupTitle')}\r\n </h3>\r\n\r\n <p className=\"text-muted-foreground mb-8\">\r\n {t('setupDescription')}\r\n </p>\r\n\r\n <form onSubmit={handleSubmit} className=\"space-y-6\">\r\n\r\n {/* Org Name */}\r\n <div className=\"flex flex-col gap-2\">\r\n <label className=\"text-sm font-medium\">\r\n Organization Name / Slug\r\n </label>\r\n <Input\r\n name=\"orgName\"\r\n placeholder=\"my-org\"\r\n required\r\n minLength={3}\r\n maxLength={63}\r\n pattern=\"^[a-z0-9.-]+$\"\r\n />\r\n <p className=\"text-xs text-muted-foreground\">\r\n 3–63 characters. Lowercase letters, numbers, dots, and hyphens only.\r\n </p>\r\n </div>\r\n\r\n {/* Org Title */}\r\n <div className=\"flex flex-col gap-2\">\r\n <label className=\"text-sm font-medium\">\r\n Organization Title\r\n </label>\r\n <Input\r\n name=\"orgTitle\"\r\n placeholder=\"Organization Title\"\r\n required\r\n />\r\n </div>\r\n\r\n {/* Org Description */}\r\n <div className=\"flex flex-col gap-2\">\r\n <label className=\"text-sm font-medium\">\r\n Organization Description\r\n </label>\r\n <Textarea\r\n name=\"orgDescription\"\r\n placeholder=\"Organization Description\"\r\n rows={4}\r\n required\r\n />\r\n </div>\r\n\r\n {/* Languages */}\r\n <div className=\"flex flex-col gap-2\">\r\n <label className=\"text-sm font-medium\">\r\n Languages\r\n </label>\r\n\r\n <select\r\n name=\"orgLanguages\"\r\n multiple\r\n defaultValue={['En']}\r\n className=\"w-full rounded-md border border-input bg-background px-3 py-2 min-h-[100px]\"\r\n >\r\n <option value=\"En\">English</option>\r\n <option value=\"Fr\">French</option>\r\n <option value=\"Es\">Spanish</option>\r\n </select>\r\n\r\n <p className=\"text-xs text-muted-foreground\">\r\n Hold Ctrl (Windows) / Cmd (Mac) to select multiple languages\r\n </p>\r\n </div>\r\n\r\n {/* Admin Section */}\r\n <div className=\"border-t pt-6\">\r\n <h4 className=\"font-semibold mb-4\">\r\n Administrator Account\r\n </h4>\r\n\r\n <div className=\"grid sm:grid-cols-2 gap-4\">\r\n <div className=\"flex flex-col gap-2\">\r\n <label className=\"text-sm font-medium\">\r\n Admin Name\r\n </label>\r\n <Input\r\n name=\"adminName\"\r\n placeholder=\"Admin Name\"\r\n required\r\n />\r\n </div>\r\n\r\n <div className=\"flex flex-col gap-2\">\r\n <label className=\"text-sm font-medium\">\r\n Admin Email\r\n </label>\r\n <Input\r\n name=\"adminEmail\"\r\n type=\"email\"\r\n placeholder=\"admin@example.com\"\r\n required\r\n />\r\n </div>\r\n </div>\r\n\r\n <div className=\"mt-4 flex flex-col gap-2\">\r\n <label className=\"text-sm font-medium\">\r\n Password\r\n </label>\r\n <Input\r\n name=\"adminPassword\"\r\n type=\"password\"\r\n placeholder=\"Password\"\r\n minLength={8}\r\n required\r\n />\r\n </div>\r\n </div>\r\n\r\n {/* Error */}\r\n {error && (\r\n <div className=\"rounded-md border border-red-500/20 bg-red-500/10 p-4 text-sm text-red-500\">\r\n {error}\r\n </div>\r\n )}\r\n\r\n <Button\r\n type=\"submit\"\r\n size=\"lg\"\r\n className=\"gradient-button w-full\"\r\n disabled={loading}\r\n >\r\n {loading ? 'Initializing Instance...' : 'Initialize Instance'}\r\n </Button>\r\n </form>\r\n </Card>\r\n\r\n <div className=\"space-y-6\">\r\n <Card className=\"p-6 hover-card\">\r\n <h3 className=\"text-lg font-bold mb-3\">\r\n {t('contactInfoTitle')}\r\n </h3>\r\n\r\n <div className=\"space-y-4\">\r\n <div>\r\n <p className=\"text-sm text-muted-foreground mb-1\">\r\n {t('emailLabel')}\r\n </p>\r\n\r\n <a\r\n href=\"mailto:info@collabdt.org\"\r\n className=\"text-primary hover:underline font-medium text-sm\"\r\n >\r\n info@collabdt.org\r\n </a>\r\n </div>\r\n\r\n <div>\r\n <p className=\"text-sm text-muted-foreground mb-1\">\r\n {t('websiteLabel')}\r\n </p>\r\n\r\n <a\r\n href=\"https://collabdt.org\"\r\n target=\"_blank\"\r\n rel=\"noopener noreferrer\"\r\n className=\"text-primary hover:underline font-medium text-sm\"\r\n >\r\n collabdt.org\r\n </a>\r\n </div>\r\n </div>\r\n </Card>\r\n\r\n <Card className=\"p-6 hover-card bg-primary/5 border-primary/20\">\r\n <h3 className=\"text-lg font-bold mb-3\">\r\n {t('needHelpTitle')}\r\n </h3>\r\n\r\n <p className=\"text-sm text-muted-foreground\">\r\n {t('needHelpDescription')}\r\n </p>\r\n </Card>\r\n </div>\r\n </div>\r\n </motion.div>\r\n </div>\r\n </section>\r\n\r\n <Footer />\r\n </>\r\n )\r\n}"],"mappings":"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","names":["e"]}
@@ -1 +1 @@
1
- {"version":3,"file":"AppSidebar.d.ts","sourceRoot":"","sources":["../../../../src/core/components/ui/AppSidebar.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAY9B,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAGzC,eAAO,MAAM,kBAAkB,GAC7B,QAAQ,WAAW,EACnB,iBAAiB,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,EAC1D,iBAAiB,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,EAC1D,iBAAiB,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,EAC1D,SAAS,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,GAAG,QAAQ,CAAC,CAAC,EACjE,eAAe,GAAG,SAYnB,CAAA;AAED,UAAU,eAAe;IACvB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC1B,OAAO,EAAE,CAAC,OAAO,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAClF;AAED,wBAAgB,UAAU,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,eAAe,qBAqEhE"}
1
+ {"version":3,"file":"AppSidebar.d.ts","sourceRoot":"","sources":["../../../../src/core/components/ui/AppSidebar.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAY9B,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAGzC,eAAO,MAAM,kBAAkB,GAC7B,QAAQ,WAAW,EACnB,iBAAiB,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,EAC1D,iBAAiB,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,EAC1D,iBAAiB,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,EAC1D,SAAS,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,GAAG,QAAQ,CAAC,CAAC,EACjE,eAAe,GAAG,SAYnB,CAAA;AAED,UAAU,eAAe;IACvB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC1B,OAAO,EAAE,CAAC,OAAO,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAClF;AAED,wBAAgB,UAAU,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,eAAe,qBA4FhE"}
@@ -47,21 +47,36 @@ function AppSidebar({ children, signOut }) {
47
47
  }
48
48
  ) }),
49
49
  children,
50
- /* @__PURE__ */ jsxs("div", { className: `w-full flex flex-col ${sidebarState === "expanded" ? "items-center justify-center" : "justify-center"}`, children: [
51
- /* @__PURE__ */ jsx(NavUser, { signOut }),
52
- /* @__PURE__ */ jsx(Link, { href: "https://collabdt.org/", className: sidebarState === "expanded" ? "w-full" : "", target: "_blank", rel: "noopener noreferrer", children: /* @__PURE__ */ jsxs(
53
- Button,
54
- {
55
- title: isCollapsed ? t("home") : void 0,
56
- variant: "ghost",
57
- className: `text-xs scale-[85%] py-0 my-0 w-full ${sidebarState === "expanded" ? "flex flex-row items-center justify-center gap-2" : "flex flex-col items-center"}`,
58
- children: [
59
- !isCollapsed && /* @__PURE__ */ jsx(CdtIcon, { monochromatic: true }),
60
- /* @__PURE__ */ jsx("span", { className: isCollapsed ? "hidden" : "inline", children: t("home") })
61
- ]
62
- }
63
- ) })
64
- ] })
50
+ /* @__PURE__ */ jsxs(
51
+ "div",
52
+ {
53
+ className: `w-full flex flex-col ${sidebarState === "expanded" ? "items-center justify-center" : "justify-center"}`,
54
+ children: [
55
+ /* @__PURE__ */ jsx(NavUser, { signOut }),
56
+ /* @__PURE__ */ jsx(
57
+ Link,
58
+ {
59
+ href: "https://collabdt.org/",
60
+ className: sidebarState === "expanded" ? "w-full" : "",
61
+ target: "_blank",
62
+ rel: "noopener noreferrer",
63
+ children: /* @__PURE__ */ jsx(
64
+ Button,
65
+ {
66
+ title: isCollapsed ? t("home") : void 0,
67
+ variant: "ghost",
68
+ className: `text-xs scale-[85%] py-0 my-0 w-full ${sidebarState === "expanded" ? "flex flex-row items-center justify-center gap-2" : "flex flex-col items-center"}`,
69
+ children: /* @__PURE__ */ jsxs(Fragment, { children: [
70
+ /* @__PURE__ */ jsx("div", { className: isCollapsed ? "scale-75" : "", children: /* @__PURE__ */ jsx(CdtIcon, { monochromatic: true }) }),
71
+ !isCollapsed && /* @__PURE__ */ jsx("span", { children: t("home") })
72
+ ] })
73
+ }
74
+ )
75
+ }
76
+ )
77
+ ]
78
+ }
79
+ )
65
80
  ] })
66
81
  ] });
67
82
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/core/components/ui/AppSidebar.tsx"],"sourcesContent":["'use client'\r\nimport * as React from 'react'\r\n\r\n// Dependencies\r\nimport { Button } from './Button'\r\n\r\n// Icons\r\nimport * as LR from 'lucide-react'\r\n\r\nimport { useTranslations } from 'next-intl'\r\nimport { CdtIcon } from './Icons/CdtIcon'\r\nimport Link from 'next/link'\r\nimport { Sidebar, useSidebar, NavUser } from './'\r\nimport { ViewerNames } from '../../types'\r\nimport { useMenusContext } from '../../store'\r\n\r\nexport const handleChangeViewer = (\r\n viewer: ViewerNames,\r\n setSelectedItem: React.Dispatch<React.SetStateAction<any>>,\r\n setSelectedSite: React.Dispatch<React.SetStateAction<any>>,\r\n setSelectedFile: React.Dispatch<React.SetStateAction<any>>,\r\n setView: React.Dispatch<React.SetStateAction<'table' | 'detail'>>,\r\n menusDispatch: any,\r\n) => {\r\n // Reset selected item, file, & view when changing viewer\r\n setSelectedItem(null)\r\n setSelectedSite(null)\r\n setSelectedFile(null)\r\n setView('table')\r\n\r\n menusDispatch({\r\n type: 'SET_VIEWER',\r\n payload: { currentViewer: viewer },\r\n })\r\n}\r\n\r\ninterface AppSidebarProps {\r\n children?: React.ReactNode\r\n signOut: (options?: { redirectTo?: string; redirect?: boolean }) => Promise<void>\r\n}\r\n\r\nexport function AppSidebar({ children, signOut }: AppSidebarProps) {\r\n // Translations\r\n const t = useTranslations('AppSidebar')\r\n\r\n const { state: menusState } = useMenusContext()\r\n\r\n const { sidebarState, isMobile, openMobile, toggleMenuSidebar } = useSidebar()\r\n\r\n const { currentViewer } = menusState.menus\r\n\r\n // On mobile, treat the sheet open as expanded so labels render when the drawer is visible\r\n const isCollapsed = isMobile ? !openMobile : sidebarState === 'collapsed'\r\n\r\n // Determine the collapsible type based on the current viewer\r\n const collapsibleType = currentViewer === ViewerNames.auth ? 'offcanvas' : 'icon'\r\n\r\n return (\r\n <>\r\n {/* Always show toggle button on mobile when collapsed */}\r\n {isMobile && isCollapsed && (\r\n <div id='sidebar-toggle-button-mobile' className='fixed left-0 top-1/2 -translate-y-1/2 z-[100] flex items-center justify-center pointer-events-auto'>\r\n <button\r\n onClick={toggleMenuSidebar}\r\n className=\"text-muted-foreground hover:text-primary p-[2px] rounded-r-md bg-sidebar\"\r\n style={{ border: '1px solid rgba(128,128,128,0.2)', borderLeft: 'none', boxShadow: '4px 0 8px -4px rgba(0,0,0,0.12)' }}\r\n >\r\n <LR.ChevronRight className=\"w-5\" />\r\n </button>\r\n </div>\r\n )}\r\n <Sidebar collapsible={collapsibleType} className=\"border-none z-50 shadow-md relative\" >\r\n {/* Sidebar toggle button - right side inside Sidebar */}\r\n {(sidebarState === 'expanded') && (\r\n <div id='sidebar-toggle-button' className={`absolute right-2 top-2 flex items-center justify-center pointer-events-auto z-50 ${isMobile ? '' : ''}`}>\r\n <button onClick={toggleMenuSidebar} className='text-muted-foreground hover:text-primary p-1'>\r\n <LR.X className='w-5' />\r\n </button>\r\n </div>\r\n )}\r\n {/* Show collapsed toggle only on desktop */}\r\n {!isMobile && sidebarState !== 'expanded' && (\r\n <div id='sidebar-toggle-button' className='absolute -right-1 max-h-1 top-1/2 -translate-y-1/2 flex items-center justify-center pointer-events-auto z-50'>\r\n <button\r\n onClick={toggleMenuSidebar}\r\n className=\"text-muted-foreground hover:text-primary p-0 rounded-md bg-sidebar\"\r\n style={{ borderRight: '1px solid rgba(128,128,128,0.2)', boxShadow: '4px 0 8px -4px rgba(0,0,0,0.12)' }}\r\n >\r\n <LR.ChevronRight className=\"w-4\" />\r\n </button>\r\n </div>\r\n )}\r\n {children}\r\n <div className={`w-full flex flex-col ${sidebarState === 'expanded' ? 'items-center justify-center' : 'justify-center'}`}>\r\n {/* Nav User */}\r\n <NavUser signOut={signOut} />\r\n <Link href=\"https://collabdt.org/\" className={sidebarState === 'expanded' ? 'w-full' : ''} target=\"_blank\" rel=\"noopener noreferrer\">\r\n <Button\r\n title={isCollapsed ? t('home') : undefined}\r\n variant=\"ghost\"\r\n className={`text-xs scale-[85%] py-0 my-0 w-full ${sidebarState === 'expanded' ? 'flex flex-row items-center justify-center gap-2' : 'flex flex-col items-center'}`}\r\n >\r\n {!isCollapsed && <CdtIcon monochromatic={true} />}\r\n <span className={isCollapsed ? 'hidden' : 'inline'}>{t('home')}</span>\r\n </Button>\r\n </Link>\r\n </div>\r\n </Sidebar>\r\n </>\r\n )\r\n}"],"mappings":";AA0DI,mBASQ,KA8BA,YAvCR;AAtDJ,SAAS,cAAc;AAGvB,YAAY,QAAQ;AAEpB,SAAS,uBAAuB;AAChC,SAAS,eAAe;AACxB,OAAO,UAAU;AACjB,SAAS,SAAS,YAAY,eAAe;AAC7C,SAAS,mBAAmB;AAC5B,SAAS,uBAAuB;AAEzB,MAAM,qBAAqB,CAChC,QACA,iBACA,iBACA,iBACA,SACA,kBACG;AAEH,kBAAgB,IAAI;AACpB,kBAAgB,IAAI;AACpB,kBAAgB,IAAI;AACpB,UAAQ,OAAO;AAEf,gBAAc;AAAA,IACZ,MAAM;AAAA,IACN,SAAS,EAAE,eAAe,OAAO;AAAA,EACnC,CAAC;AACH;AAOO,SAAS,WAAW,EAAE,UAAU,QAAQ,GAAoB;AAEjE,QAAM,IAAI,gBAAgB,YAAY;AAEtC,QAAM,EAAE,OAAO,WAAW,IAAI,gBAAgB;AAE9C,QAAM,EAAE,cAAc,UAAU,YAAY,kBAAkB,IAAI,WAAW;AAE7E,QAAM,EAAE,cAAc,IAAI,WAAW;AAGrC,QAAM,cAAc,WAAW,CAAC,aAAa,iBAAiB;AAG9D,QAAM,kBAAkB,kBAAkB,YAAY,OAAO,cAAc;AAE3E,SACE,iCAEG;AAAA,gBAAY,eACX,oBAAC,SAAI,IAAG,gCAA+B,WAAU,sGAC/C;AAAA,MAAC;AAAA;AAAA,QACC,SAAS;AAAA,QACT,WAAU;AAAA,QACV,OAAO,EAAE,QAAQ,mCAAmC,YAAY,QAAQ,WAAW,kCAAkC;AAAA,QAErH,8BAAC,GAAG,cAAH,EAAgB,WAAU,OAAM;AAAA;AAAA,IACnC,GACF;AAAA,IAEF,qBAAC,WAAQ,aAAa,iBAAiB,WAAU,uCAE7C;AAAA,uBAAiB,cACjB,oBAAC,SAAI,IAAG,yBAAwB,WAAW,oFAAoF,WAAW,KAAK,EAAE,IAC/I,8BAAC,YAAO,SAAS,mBAAmB,WAAU,gDAC5C,8BAAC,GAAG,GAAH,EAAK,WAAU,OAAM,GACxB,GACF;AAAA,MAGD,CAAC,YAAY,iBAAiB,cAC7B,oBAAC,SAAI,IAAG,yBAAwB,WAAU,gHACxC;AAAA,QAAC;AAAA;AAAA,UACC,SAAS;AAAA,UACT,WAAU;AAAA,UACV,OAAO,EAAE,aAAa,mCAAmC,WAAW,kCAAkC;AAAA,UAEtG,8BAAC,GAAG,cAAH,EAAgB,WAAU,OAAM;AAAA;AAAA,MACnC,GACF;AAAA,MAED;AAAA,MACD,qBAAC,SAAI,WAAW,wBAAwB,iBAAiB,aAAa,gCAAgC,gBAAgB,IAEpH;AAAA,4BAAC,WAAQ,SAAkB;AAAA,QAC3B,oBAAC,QAAK,MAAK,yBAAwB,WAAW,iBAAiB,aAAa,WAAW,IAAI,QAAO,UAAS,KAAI,uBAC7G;AAAA,UAAC;AAAA;AAAA,YACC,OAAO,cAAc,EAAE,MAAM,IAAI;AAAA,YACjC,SAAQ;AAAA,YACR,WAAW,wCAAwC,iBAAiB,aAAa,oDAAoD,4BAA4B;AAAA,YAEhK;AAAA,eAAC,eAAe,oBAAC,WAAQ,eAAe,MAAM;AAAA,cAC/C,oBAAC,UAAK,WAAW,cAAc,WAAW,UAAW,YAAE,MAAM,GAAE;AAAA;AAAA;AAAA,QACjE,GACF;AAAA,SACF;AAAA,OACF;AAAA,KACF;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../../../src/core/components/ui/AppSidebar.tsx"],"sourcesContent":["'use client'\r\nimport * as React from 'react'\r\n\r\n// Dependencies\r\nimport { Button } from './Button'\r\n\r\n// Icons\r\nimport * as LR from 'lucide-react'\r\n\r\nimport { useTranslations } from 'next-intl'\r\nimport { CdtIcon } from './Icons/CdtIcon'\r\nimport Link from 'next/link'\r\nimport { Sidebar, useSidebar, NavUser } from './'\r\nimport { ViewerNames } from '../../types'\r\nimport { useMenusContext } from '../../store'\r\n\r\nexport const handleChangeViewer = (\r\n viewer: ViewerNames,\r\n setSelectedItem: React.Dispatch<React.SetStateAction<any>>,\r\n setSelectedSite: React.Dispatch<React.SetStateAction<any>>,\r\n setSelectedFile: React.Dispatch<React.SetStateAction<any>>,\r\n setView: React.Dispatch<React.SetStateAction<'table' | 'detail'>>,\r\n menusDispatch: any,\r\n) => {\r\n // Reset selected item, file, & view when changing viewer\r\n setSelectedItem(null)\r\n setSelectedSite(null)\r\n setSelectedFile(null)\r\n setView('table')\r\n\r\n menusDispatch({\r\n type: 'SET_VIEWER',\r\n payload: { currentViewer: viewer },\r\n })\r\n}\r\n\r\ninterface AppSidebarProps {\r\n children?: React.ReactNode\r\n signOut: (options?: { redirectTo?: string; redirect?: boolean }) => Promise<void>\r\n}\r\n\r\nexport function AppSidebar({ children, signOut }: AppSidebarProps) {\r\n // Translations\r\n const t = useTranslations('AppSidebar')\r\n\r\n const { state: menusState } = useMenusContext()\r\n\r\n const { sidebarState, isMobile, openMobile, toggleMenuSidebar } = useSidebar()\r\n\r\n const { currentViewer } = menusState.menus\r\n\r\n // On mobile, treat the sheet open as expanded so labels render when the drawer is visible\r\n const isCollapsed = isMobile ? !openMobile : sidebarState === 'collapsed'\r\n\r\n // Determine the collapsible type based on the current viewer\r\n const collapsibleType = currentViewer === ViewerNames.auth ? 'offcanvas' : 'icon'\r\n\r\n return (\r\n <>\r\n {/* Always show toggle button on mobile when collapsed */}\r\n {isMobile && isCollapsed && (\r\n <div id='sidebar-toggle-button-mobile' className='fixed left-0 top-1/2 -translate-y-1/2 z-[100] flex items-center justify-center pointer-events-auto'>\r\n <button\r\n onClick={toggleMenuSidebar}\r\n className=\"text-muted-foreground hover:text-primary p-[2px] rounded-r-md bg-sidebar\"\r\n style={{ border: '1px solid rgba(128,128,128,0.2)', borderLeft: 'none', boxShadow: '4px 0 8px -4px rgba(0,0,0,0.12)' }}\r\n >\r\n <LR.ChevronRight className=\"w-5\" />\r\n </button>\r\n </div>\r\n )}\r\n <Sidebar collapsible={collapsibleType} className=\"border-none z-50 shadow-md relative\" >\r\n {/* Sidebar toggle button - right side inside Sidebar */}\r\n {(sidebarState === 'expanded') && (\r\n <div id='sidebar-toggle-button' className={`absolute right-2 top-2 flex items-center justify-center pointer-events-auto z-50 ${isMobile ? '' : ''}`}>\r\n <button onClick={toggleMenuSidebar} className='text-muted-foreground hover:text-primary p-1'>\r\n <LR.X className='w-5' />\r\n </button>\r\n </div>\r\n )}\r\n {/* Show collapsed toggle only on desktop */}\r\n {!isMobile && sidebarState !== 'expanded' && (\r\n <div id='sidebar-toggle-button' className='absolute -right-1 max-h-1 top-1/2 -translate-y-1/2 flex items-center justify-center pointer-events-auto z-50'>\r\n <button\r\n onClick={toggleMenuSidebar}\r\n className=\"text-muted-foreground hover:text-primary p-0 rounded-md bg-sidebar\"\r\n style={{ borderRight: '1px solid rgba(128,128,128,0.2)', boxShadow: '4px 0 8px -4px rgba(0,0,0,0.12)' }}\r\n >\r\n <LR.ChevronRight className=\"w-4\" />\r\n </button>\r\n </div>\r\n )}\r\n {children}\r\n <div\r\n className={`w-full flex flex-col ${\r\n sidebarState === 'expanded'\r\n ? 'items-center justify-center'\r\n : 'justify-center'\r\n }`}\r\n >\r\n {/* Nav User */}\r\n <NavUser signOut={signOut} />\r\n\r\n <Link\r\n href=\"https://collabdt.org/\"\r\n className={sidebarState === 'expanded' ? 'w-full' : ''}\r\n target=\"_blank\"\r\n rel=\"noopener noreferrer\"\r\n >\r\n <Button\r\n title={isCollapsed ? t('home') : undefined}\r\n variant=\"ghost\"\r\n className={`text-xs scale-[85%] py-0 my-0 w-full ${\r\n sidebarState === 'expanded'\r\n ? 'flex flex-row items-center justify-center gap-2'\r\n : 'flex flex-col items-center'\r\n }`}\r\n >\r\n <>\r\n <div className={isCollapsed ? 'scale-75' : ''}>\r\n <CdtIcon monochromatic />\r\n </div>\r\n\r\n {!isCollapsed && (\r\n <span>{t('home')}</span>\r\n )}\r\n </>\r\n </Button>\r\n </Link>\r\n </div>\r\n </Sidebar>\r\n </>\r\n )\r\n}"],"mappings":";AAmEY,SAmDI,UAnDJ,KAmDI,YAnDJ;AA/DZ,SAAS,cAAc;AAGvB,YAAY,QAAQ;AAEpB,SAAS,uBAAuB;AAChC,SAAS,eAAe;AACxB,OAAO,UAAU;AACjB,SAAS,SAAS,YAAY,eAAe;AAC7C,SAAS,mBAAmB;AAC5B,SAAS,uBAAuB;AAEzB,MAAM,qBAAqB,CAChC,QACA,iBACA,iBACA,iBACA,SACA,kBACG;AAEH,kBAAgB,IAAI;AACpB,kBAAgB,IAAI;AACpB,kBAAgB,IAAI;AACpB,UAAQ,OAAO;AAEf,gBAAc;AAAA,IACZ,MAAM;AAAA,IACN,SAAS,EAAE,eAAe,OAAO;AAAA,EACnC,CAAC;AACH;AAOO,SAAS,WAAW,EAAE,UAAU,QAAQ,GAAoB;AAEjE,QAAM,IAAI,gBAAgB,YAAY;AAEtC,QAAM,EAAE,OAAO,WAAW,IAAI,gBAAgB;AAE9C,QAAM,EAAE,cAAc,UAAU,YAAY,kBAAkB,IAAI,WAAW;AAE7E,QAAM,EAAE,cAAc,IAAI,WAAW;AAGrC,QAAM,cAAc,WAAW,CAAC,aAAa,iBAAiB;AAG9D,QAAM,kBAAkB,kBAAkB,YAAY,OAAO,cAAc;AAE3E,SACE,iCAEG;AAAA,gBAAY,eACX,oBAAC,SAAI,IAAG,gCAA+B,WAAU,sGAC/C;AAAA,MAAC;AAAA;AAAA,QACC,SAAS;AAAA,QACT,WAAU;AAAA,QACV,OAAO,EAAE,QAAQ,mCAAmC,YAAY,QAAQ,WAAW,kCAAkC;AAAA,QAErH,8BAAC,GAAG,cAAH,EAAgB,WAAU,OAAM;AAAA;AAAA,IACnC,GACF;AAAA,IAEF,qBAAC,WAAQ,aAAa,iBAAiB,WAAU,uCAE7C;AAAA,uBAAiB,cACjB,oBAAC,SAAI,IAAG,yBAAwB,WAAW,oFAAoF,WAAW,KAAK,EAAE,IAC/I,8BAAC,YAAO,SAAS,mBAAmB,WAAU,gDAC5C,8BAAC,GAAG,GAAH,EAAK,WAAU,OAAM,GACxB,GACF;AAAA,MAGD,CAAC,YAAY,iBAAiB,cAC7B,oBAAC,SAAI,IAAG,yBAAwB,WAAU,gHACxC;AAAA,QAAC;AAAA;AAAA,UACC,SAAS;AAAA,UACT,WAAU;AAAA,UACV,OAAO,EAAE,aAAa,mCAAmC,WAAW,kCAAkC;AAAA,UAEtG,8BAAC,GAAG,cAAH,EAAgB,WAAU,OAAM;AAAA;AAAA,MACnC,GACF;AAAA,MAED;AAAA,MACD;AAAA,QAAC;AAAA;AAAA,UACG,WAAW,wBACT,iBAAiB,aACb,gCACA,gBACN;AAAA,UAGA;AAAA,gCAAC,WAAQ,SAAkB;AAAA,YAE3B;AAAA,cAAC;AAAA;AAAA,gBACC,MAAK;AAAA,gBACL,WAAW,iBAAiB,aAAa,WAAW;AAAA,gBACpD,QAAO;AAAA,gBACP,KAAI;AAAA,gBAEJ;AAAA,kBAAC;AAAA;AAAA,oBACC,OAAO,cAAc,EAAE,MAAM,IAAI;AAAA,oBACjC,SAAQ;AAAA,oBACR,WAAW,wCACT,iBAAiB,aACb,oDACA,4BACN;AAAA,oBAEA,2CACA;AAAA,0CAAC,SAAI,WAAW,cAAc,aAAa,IACzC,8BAAC,WAAQ,eAAa,MAAC,GACzB;AAAA,sBAEC,CAAC,eACA,oBAAC,UAAM,YAAE,MAAM,GAAE;AAAA,uBAErB;AAAA;AAAA,gBACA;AAAA;AAAA,YACF;AAAA;AAAA;AAAA,MACF;AAAA,OACJ;AAAA,KACF;AAEJ;","names":[]}
@@ -1 +1 @@
1
- {"version":3,"file":"DatatableFileAdder.d.ts","sourceRoot":"","sources":["../../../../../../src/core/components/viewers/Data/files/DatatableFileAdder.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAQ9B,MAAM,CAAC,OAAO,UAAU,kBAAkB,sBAqCzC"}
1
+ {"version":3,"file":"DatatableFileAdder.d.ts","sourceRoot":"","sources":["../../../../../../src/core/components/viewers/Data/files/DatatableFileAdder.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAU9B,MAAM,CAAC,OAAO,UAAU,kBAAkB,sBAuCzC"}
@@ -5,6 +5,7 @@ import { usePermissions } from "../../../../store";
5
5
  import { Button, LoadingSpinner } from "../../../../components/ui/";
6
6
  import * as LR from "lucide-react";
7
7
  import { useFileUploadWithProgress } from "../../../../components/ui/FilesManager";
8
+ import { toast } from "sonner";
8
9
  function DatatableFileAdder() {
9
10
  const t = useTranslations("HeadDatatableFileAddererButtons");
10
11
  const { ability } = usePermissions();
@@ -12,9 +13,11 @@ function DatatableFileAdder() {
12
13
  acceptedFileTypes: "*",
13
14
  onUploadSuccess: () => {
14
15
  console.log("File successfully uploaded to API");
16
+ toast.success(t("uploadSuccess"));
15
17
  },
16
18
  onUploadError: (error) => {
17
19
  console.error("Error uploading file:", error);
20
+ toast.error(error.message);
18
21
  }
19
22
  });
20
23
  return /* @__PURE__ */ jsx("div", { className: "inline-block", children: /* @__PURE__ */ jsxs(
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../src/core/components/viewers/Data/files/DatatableFileAdder.tsx"],"sourcesContent":["\"use client\"\r\n\r\nimport * as React from 'react'\r\nimport { useTranslations } from 'next-intl'\r\nimport { usePermissions } from '../../../../store'\r\n\r\nimport { Button, LoadingSpinner } from '../../../../components/ui/'\r\nimport * as LR from 'lucide-react'\r\nimport { useFileUploadWithProgress } from '../../../../components/ui/FilesManager'\r\n\r\nexport default function DatatableFileAdder() {\r\n\r\n // Translations\r\n const t = useTranslations('HeadDatatableFileAddererButtons')\r\n\r\n // Permissions\r\n const { ability } = usePermissions()\r\n\r\n // Use the reusable upload hook with progress\r\n const { handleAddFile, uploadState } = useFileUploadWithProgress({\r\n acceptedFileTypes: '*',\r\n onUploadSuccess: () => {\r\n console.log('File successfully uploaded to API')\r\n },\r\n onUploadError: (error) => {\r\n console.error('Error uploading file:', error)\r\n }\r\n })\r\n\r\n return (\r\n <div className=\"inline-block\">\r\n <Button \r\n variant=\"default\" \r\n onClick={handleAddFile}\r\n disabled={!ability.can('create', 'File') || uploadState.uploading}\r\n >\r\n {uploadState.uploading\r\n ? (\r\n <LoadingSpinner />\r\n )\r\n : (\r\n <LR.CirclePlus className=\"mr-2\" />\r\n )}\r\n {uploadState.uploading ? `${t('uploading')} ${uploadState.progress}%` : t('addFile')}\r\n </Button>\r\n </div>\r\n )\r\n}\r\n"],"mappings":";AA+BM,SAOQ,KAPR;AA5BN,SAAS,uBAAuB;AAChC,SAAS,sBAAsB;AAE/B,SAAS,QAAQ,sBAAsB;AACvC,YAAY,QAAQ;AACpB,SAAS,iCAAiC;AAE3B,SAAR,qBAAsC;AAG3C,QAAM,IAAI,gBAAgB,iCAAiC;AAG3D,QAAM,EAAE,QAAQ,IAAI,eAAe;AAGnC,QAAM,EAAE,eAAe,YAAY,IAAI,0BAA0B;AAAA,IAC/D,mBAAmB;AAAA,IACnB,iBAAiB,MAAM;AACrB,cAAQ,IAAI,mCAAmC;AAAA,IACjD;AAAA,IACA,eAAe,CAAC,UAAU;AACxB,cAAQ,MAAM,yBAAyB,KAAK;AAAA,IAC9C;AAAA,EACF,CAAC;AAED,SACE,oBAAC,SAAI,WAAU,gBACb;AAAA,IAAC;AAAA;AAAA,MACC,SAAQ;AAAA,MACR,SAAS;AAAA,MACT,UAAU,CAAC,QAAQ,IAAI,UAAU,MAAM,KAAK,YAAY;AAAA,MAEvD;AAAA,oBAAY,YAEP,oBAAC,kBAAe,IAGhB,oBAAC,GAAG,YAAH,EAAc,WAAU,QAAO;AAAA,QAErC,YAAY,YAAY,GAAG,EAAE,WAAW,CAAC,IAAI,YAAY,QAAQ,MAAM,EAAE,SAAS;AAAA;AAAA;AAAA,EACrF,GACF;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../../../../../src/core/components/viewers/Data/files/DatatableFileAdder.tsx"],"sourcesContent":["\"use client\"\r\n\r\nimport * as React from 'react'\r\nimport { useTranslations } from 'next-intl'\r\nimport { usePermissions } from '../../../../store'\r\n\r\nimport { Button, LoadingSpinner } from '../../../../components/ui/'\r\nimport * as LR from 'lucide-react'\r\nimport { useFileUploadWithProgress } from '../../../../components/ui/FilesManager'\r\n\r\nimport { toast } from 'sonner'\r\n\r\nexport default function DatatableFileAdder() {\r\n\r\n // Translations\r\n const t = useTranslations('HeadDatatableFileAddererButtons')\r\n\r\n // Permissions\r\n const { ability } = usePermissions()\r\n\r\n // Use the reusable upload hook with progress\r\n const { handleAddFile, uploadState } = useFileUploadWithProgress({\r\n acceptedFileTypes: '*',\r\n onUploadSuccess: () => {\r\n console.log('File successfully uploaded to API')\r\n toast.success(t('uploadSuccess'))\r\n },\r\n onUploadError: (error) => {\r\n console.error('Error uploading file:', error)\r\n toast.error(error.message)\r\n }\r\n })\r\n\r\n return (\r\n <div className=\"inline-block\">\r\n <Button \r\n variant=\"default\" \r\n onClick={handleAddFile}\r\n disabled={!ability.can('create', 'File') || uploadState.uploading}\r\n >\r\n {uploadState.uploading\r\n ? (\r\n <LoadingSpinner />\r\n )\r\n : (\r\n <LR.CirclePlus className=\"mr-2\" />\r\n )}\r\n {uploadState.uploading ? `${t('uploading')} ${uploadState.progress}%` : t('addFile')}\r\n </Button>\r\n </div>\r\n )\r\n}\r\n"],"mappings":";AAmCM,SAOQ,KAPR;AAhCN,SAAS,uBAAuB;AAChC,SAAS,sBAAsB;AAE/B,SAAS,QAAQ,sBAAsB;AACvC,YAAY,QAAQ;AACpB,SAAS,iCAAiC;AAE1C,SAAS,aAAa;AAEP,SAAR,qBAAsC;AAG3C,QAAM,IAAI,gBAAgB,iCAAiC;AAG3D,QAAM,EAAE,QAAQ,IAAI,eAAe;AAGnC,QAAM,EAAE,eAAe,YAAY,IAAI,0BAA0B;AAAA,IAC/D,mBAAmB;AAAA,IACnB,iBAAiB,MAAM;AACrB,cAAQ,IAAI,mCAAmC;AAC/C,YAAM,QAAQ,EAAE,eAAe,CAAC;AAAA,IAClC;AAAA,IACA,eAAe,CAAC,UAAU;AACxB,cAAQ,MAAM,yBAAyB,KAAK;AAC5C,YAAM,MAAM,MAAM,OAAO;AAAA,IAC3B;AAAA,EACF,CAAC;AAED,SACE,oBAAC,SAAI,WAAU,gBACb;AAAA,IAAC;AAAA;AAAA,MACC,SAAQ;AAAA,MACR,SAAS;AAAA,MACT,UAAU,CAAC,QAAQ,IAAI,UAAU,MAAM,KAAK,YAAY;AAAA,MAEvD;AAAA,oBAAY,YAEP,oBAAC,kBAAe,IAGhB,oBAAC,GAAG,YAAH,EAAc,WAAU,QAAO;AAAA,QAErC,YAAY,YAAY,GAAG,EAAE,WAAW,CAAC,IAAI,YAAY,QAAQ,MAAM,EAAE,SAAS;AAAA;AAAA;AAAA,EACrF,GACF;AAEJ;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@collabdt/core",
3
- "version": "0.0.49",
3
+ "version": "0.0.51",
4
4
  "description": "CDT Core contains all the core technology for your CDT platform",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",