@compill/admin 1.0.100 → 1.0.102

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 (169) hide show
  1. package/dist/index.js +50 -0
  2. package/{src → dist}/lib/SectionTitle.d.ts +0 -1
  3. package/dist/lib/SectionTitle.jsx +3 -0
  4. package/{src → dist}/lib/breadcrumbs/BreadCrumbs.d.ts +0 -1
  5. package/dist/lib/breadcrumbs/BreadCrumbs.jsx +43 -0
  6. package/dist/lib/buttons/DialogButton.jsx +17 -0
  7. package/{src → dist}/lib/buttons/InvalidateButton.d.ts +0 -1
  8. package/dist/lib/buttons/InvalidateButton.jsx +10 -0
  9. package/{src → dist}/lib/buttons/NavigateButton.d.ts +0 -1
  10. package/dist/lib/buttons/NavigateButton.jsx +13 -0
  11. package/{src → dist}/lib/buttons/PublishButton.d.ts +0 -1
  12. package/dist/lib/buttons/PublishButton.jsx +18 -0
  13. package/{src → dist}/lib/buttons/UpdateButton.d.ts +0 -1
  14. package/dist/lib/buttons/UpdateButton.jsx +12 -0
  15. package/{src → dist}/lib/buttons/ViewButton.d.ts +1 -2
  16. package/dist/lib/buttons/ViewButton.jsx +14 -0
  17. package/{src → dist}/lib/cells/OrderCell.d.ts +0 -1
  18. package/dist/lib/cells/OrderCell.jsx +35 -0
  19. package/{src → dist}/lib/json/DetailsView.d.ts +0 -1
  20. package/dist/lib/json/DetailsView.jsx +96 -0
  21. package/{src → dist}/lib/json/EditItemView.d.ts +0 -1
  22. package/dist/lib/json/EditItemView.jsx +5 -0
  23. package/{src → dist}/lib/json/MultiQueryWrapper.d.ts +0 -1
  24. package/dist/lib/json/MultiQueryWrapper.jsx +60 -0
  25. package/{src → dist}/lib/json/QueryWrapper.d.ts +0 -1
  26. package/dist/lib/json/QueryWrapper.jsx +28 -0
  27. package/{src → dist}/lib/json/ScreenRenderer.d.ts +0 -1
  28. package/dist/lib/json/ScreenRenderer.jsx +18 -0
  29. package/{src → dist}/lib/json/ScreenTopBar.d.ts +0 -1
  30. package/dist/lib/json/ScreenTopBar.jsx +39 -0
  31. package/{src → dist}/lib/json/TabbedView.d.ts +0 -1
  32. package/dist/lib/json/TabbedView.jsx +28 -0
  33. package/{src → dist}/lib/json/buttons/ActionButton.d.ts +0 -1
  34. package/dist/lib/json/buttons/ActionButton.jsx +13 -0
  35. package/{src → dist}/lib/json/buttons/ConfirmationActionButton.d.ts +0 -1
  36. package/dist/lib/json/buttons/ConfirmationActionButton.jsx +37 -0
  37. package/{src → dist}/lib/json/dialog/DialogRenderer.d.ts +0 -1
  38. package/dist/lib/json/dialog/DialogRenderer.jsx +13 -0
  39. package/dist/lib/json/dialog/ItemDeleteDialog.jsx +36 -0
  40. package/dist/lib/json/dialog/ItemEditDialog.jsx +124 -0
  41. package/{src → dist}/lib/json/dialog/MultiQueryWrapperDialog.d.ts +0 -1
  42. package/dist/lib/json/dialog/MultiQueryWrapperDialog.jsx +22 -0
  43. package/{src → dist}/lib/json/dialog/QueryWrapperDialog.d.ts +0 -1
  44. package/dist/lib/json/dialog/QueryWrapperDialog.jsx +19 -0
  45. package/{src → dist}/lib/json/table/RefreshButton.d.ts +0 -1
  46. package/dist/lib/json/table/RefreshButton.jsx +12 -0
  47. package/{src → dist}/lib/json/table/TableRowActionsView.d.ts +0 -1
  48. package/dist/lib/json/table/TableRowActionsView.jsx +45 -0
  49. package/{src → dist}/lib/json/table/TableRowPublishPostButton.d.ts +0 -1
  50. package/dist/lib/json/table/TableRowPublishPostButton.jsx +21 -0
  51. package/{src → dist}/lib/json/table/TableView.d.ts +0 -1
  52. package/dist/lib/json/table/TableView.jsx +100 -0
  53. package/dist/lib/json/table/TableViewContext.jsx +57 -0
  54. package/dist/lib/json/table/useTableProps.jsx +56 -0
  55. package/{src → dist}/lib/json/types/DetailsView.d.ts +0 -1
  56. package/dist/lib/json/types/DetailsView.js +1 -0
  57. package/dist/lib/json/types/EditItemDialog.js +1 -0
  58. package/dist/lib/json/types/MultiQueryWrapper.js +1 -0
  59. package/dist/lib/json/types/MultiQueryWrapperDialog.js +1 -0
  60. package/dist/lib/json/types/QueryWrapper.js +1 -0
  61. package/dist/lib/json/types/QueryWrapperDialog.js +1 -0
  62. package/dist/lib/json/types/ScreenConfig.js +1 -0
  63. package/{src → dist}/lib/json/types/TabbedView.d.ts +0 -1
  64. package/dist/lib/json/types/TabbedView.js +1 -0
  65. package/{src → dist}/lib/json/types/TableView.d.ts +0 -1
  66. package/dist/lib/json/types/TableView.js +1 -0
  67. package/{src → dist}/lib/layout/AdminLayout.d.ts +0 -1
  68. package/dist/lib/layout/AdminLayout.jsx +24 -0
  69. package/{src → dist}/lib/layout/ButtonBar.d.ts +1 -1
  70. package/dist/lib/layout/ButtonBar.jsx +29 -0
  71. package/{src → dist}/lib/layout/Content.d.ts +0 -1
  72. package/dist/lib/layout/Content.jsx +10 -0
  73. package/{src → dist}/lib/layout/PageTitleBar.d.ts +0 -1
  74. package/dist/lib/layout/PageTitleBar.jsx +12 -0
  75. package/{src → dist}/lib/layout/Sidebar.d.ts +0 -1
  76. package/dist/lib/layout/Sidebar.jsx +24 -0
  77. package/{src → dist}/lib/layout/menu/Menu.d.ts +0 -1
  78. package/dist/lib/layout/menu/Menu.jsx +30 -0
  79. package/{src → dist}/lib/layout/menu/MenuButton.d.ts +0 -1
  80. package/dist/lib/layout/menu/MenuButton.jsx +7 -0
  81. package/dist/lib/layout/menu/MenuConfig.js +1 -0
  82. package/{src → dist}/lib/layout/menu/MenuItem.d.ts +0 -1
  83. package/dist/lib/layout/menu/MenuItem.jsx +20 -0
  84. package/{src → dist}/lib/layout/menu/NextMenuItem.d.ts +0 -1
  85. package/dist/lib/layout/menu/NextMenuItem.jsx +20 -0
  86. package/{src → dist}/lib/layout/menu/SelectedIndicator.d.ts +0 -1
  87. package/dist/lib/layout/menu/SelectedIndicator.jsx +3 -0
  88. package/{src → dist}/lib/layout/menu/UserBlock.d.ts +1 -2
  89. package/dist/lib/layout/menu/UserBlock.jsx +55 -0
  90. package/{src → dist}/lib/modal/AttachDialog.d.ts +0 -1
  91. package/dist/lib/modal/AttachDialog.jsx +109 -0
  92. package/dist/lib/modal/FormActionDialog.jsx +46 -0
  93. package/{src → dist}/lib/page/PageContainer.d.ts +0 -1
  94. package/dist/lib/page/PageContainer.jsx +4 -0
  95. package/{src → dist}/lib/page/PageContentEditor.d.ts +0 -1
  96. package/dist/lib/page/PageContentEditor.jsx +11 -0
  97. package/{src → dist}/lib/page/PageMain.d.ts +0 -1
  98. package/dist/lib/page/PageMain.jsx +4 -0
  99. package/dist/lib/page/PageQueryStateContainer.jsx +15 -0
  100. package/{src → dist}/lib/page/PageSectionTitle.d.ts +0 -1
  101. package/dist/lib/page/PageSectionTitle.jsx +3 -0
  102. package/{src → dist}/lib/page/PageSidebar.d.ts +0 -1
  103. package/dist/lib/page/PageSidebar.jsx +3 -0
  104. package/{src → dist}/lib/page/PageSidebarSection.d.ts +0 -1
  105. package/dist/lib/page/PageSidebarSection.jsx +7 -0
  106. package/dist/lib/page/PageStateContainer.jsx +9 -0
  107. package/{src → dist}/lib/page/PageSubSectionTitle.d.ts +0 -1
  108. package/dist/lib/page/PageSubSectionTitle.jsx +3 -0
  109. package/{src → dist}/lib/page/PageTitle.d.ts +0 -1
  110. package/dist/lib/page/PageTitle.jsx +3 -0
  111. package/dist/lib/page/PageTopBar.jsx +92 -0
  112. package/{src → dist}/lib/status/StatusBadge.d.ts +0 -1
  113. package/dist/lib/status/StatusBadge.jsx +20 -0
  114. package/dist/lib/table/TableColumnButton.d.ts +1 -0
  115. package/dist/lib/table/TableColumnButton.jsx +53 -0
  116. package/{src → dist}/lib/table/TableContainer.d.ts +0 -1
  117. package/dist/lib/table/TableContainer.jsx +11 -0
  118. package/dist/lib/table/TableContainerContext.jsx +39 -0
  119. package/{src → dist}/lib/table/TableCreateButton.d.ts +0 -1
  120. package/dist/lib/table/TableCreateButton.jsx +9 -0
  121. package/{src → dist}/lib/table/TableFilterButton.d.ts +0 -1
  122. package/dist/lib/table/TableFilterButton.jsx +16 -0
  123. package/{src → dist}/lib/table/TableFilters.d.ts +0 -1
  124. package/dist/lib/table/TableFilters.jsx +46 -0
  125. package/{src → dist}/lib/table/TableMassActions.d.ts +0 -1
  126. package/dist/lib/table/TableMassActions.jsx +15 -0
  127. package/{src → dist}/lib/table/TableRowActionBar.d.ts +0 -1
  128. package/dist/lib/table/TableRowActionBar.jsx +14 -0
  129. package/{src → dist}/lib/table/TableRowActionButton.d.ts +0 -1
  130. package/dist/lib/table/TableRowActionButton.jsx +7 -0
  131. package/{src → dist}/lib/table/TableRowActionDialogButton.d.ts +1 -2
  132. package/dist/lib/table/TableRowActionDialogButton.jsx +8 -0
  133. package/{src → dist}/lib/table/TableRowDeleteButton.d.ts +0 -1
  134. package/dist/lib/table/TableRowDeleteButton.jsx +5 -0
  135. package/{src → dist}/lib/table/TableRowEditButton.d.ts +0 -1
  136. package/dist/lib/table/TableRowEditButton.jsx +7 -0
  137. package/{src → dist}/lib/table/TableRowNavigateButton.d.ts +0 -1
  138. package/dist/lib/table/TableRowNavigateButton.jsx +13 -0
  139. package/{src → dist}/lib/table/TableRowPublishPostButton.d.ts +0 -1
  140. package/dist/lib/table/TableRowPublishPostButton.jsx +18 -0
  141. package/{src → dist}/lib/table/TableRowViewButton.d.ts +0 -1
  142. package/dist/lib/table/TableRowViewButton.jsx +12 -0
  143. package/{src → dist}/lib/table/TableTopBar.d.ts +1 -2
  144. package/dist/lib/table/TableTopBar.jsx +17 -0
  145. package/package.json +60 -4
  146. package/README.md +0 -7
  147. package/index.cjs.d.ts +0 -1
  148. package/index.cjs.js +0 -3710
  149. package/index.esm.d.ts +0 -1
  150. package/index.esm.js +0 -3662
  151. package/src/lib/table/TableColumnButton.d.ts +0 -0
  152. /package/{src → dist}/index.d.ts +0 -0
  153. /package/{src → dist}/lib/buttons/DialogButton.d.ts +0 -0
  154. /package/{src → dist}/lib/json/dialog/ItemDeleteDialog.d.ts +0 -0
  155. /package/{src → dist}/lib/json/dialog/ItemEditDialog.d.ts +0 -0
  156. /package/{src → dist}/lib/json/table/TableViewContext.d.ts +0 -0
  157. /package/{src → dist}/lib/json/table/useTableProps.d.ts +0 -0
  158. /package/{src → dist}/lib/json/types/EditItemDialog.d.ts +0 -0
  159. /package/{src → dist}/lib/json/types/MultiQueryWrapper.d.ts +0 -0
  160. /package/{src → dist}/lib/json/types/MultiQueryWrapperDialog.d.ts +0 -0
  161. /package/{src → dist}/lib/json/types/QueryWrapper.d.ts +0 -0
  162. /package/{src → dist}/lib/json/types/QueryWrapperDialog.d.ts +0 -0
  163. /package/{src → dist}/lib/json/types/ScreenConfig.d.ts +0 -0
  164. /package/{src → dist}/lib/layout/menu/MenuConfig.d.ts +0 -0
  165. /package/{src → dist}/lib/modal/FormActionDialog.d.ts +0 -0
  166. /package/{src → dist}/lib/page/PageQueryStateContainer.d.ts +0 -0
  167. /package/{src → dist}/lib/page/PageStateContainer.d.ts +0 -0
  168. /package/{src → dist}/lib/page/PageTopBar.d.ts +0 -0
  169. /package/{src → dist}/lib/table/TableContainerContext.d.ts +0 -0
@@ -0,0 +1 @@
1
+ export {};
@@ -1,4 +1,3 @@
1
- /// <reference types="react" />
2
1
  import { Color, ParentComponent, SoperioComponent } from "@soperio/react";
3
2
  import { MenuConfig } from "./menu/MenuConfig";
4
3
  interface LayoutProps extends SoperioComponent, ParentComponent {
@@ -0,0 +1,24 @@
1
+ import { useBoolean } from "@compill/hooks";
2
+ import { mdiArrowLeft } from "@mdi/js";
3
+ import { IconButton } from "@valerya/ui";
4
+ import { useHotkeys } from "react-hotkeys-hook";
5
+ import Content from "./Content";
6
+ import { Sidebar } from "./Sidebar";
7
+ export function AdminLayout({ color, darkMode, logo, title, menuConfig, userMenuConfig, userSettingsPath, ...props }) {
8
+ return (<div w="full" h="screen" dflex flexRow bgColor={`${color}-${darkMode ? "900" : "100"}`} {...props}>
9
+ <LeftPanel color={color} darkMode={darkMode} logo={logo} title={title} menuConfig={menuConfig} userMenuConfig={userMenuConfig} userSettingsPath={userSettingsPath}/>
10
+
11
+ <div w="screen" py="2" pe="2">
12
+ <Content bgColor="white" rounded="lg" shadow/>
13
+ </div>
14
+ </div>);
15
+ }
16
+ function LeftPanel({ color, darkMode, logo, title, menuConfig, userMenuConfig, userSettingsPath }) {
17
+ const [isOpen, __, toggle] = useBoolean(true);
18
+ useHotkeys('ctrl+t', () => toggle(), [toggle]);
19
+ return (<div ms={isOpen ? "0" : "-14.5rem"} transition="all" duration="500" transform>
20
+ <Sidebar flexShrink="0" color={color} darkMode={darkMode} logo={logo} title={title} menuConfig={menuConfig} userMenuConfig={userMenuConfig} userSettingsPath={userSettingsPath}/>
21
+
22
+ <IconButton icon={mdiArrowLeft} transition="all" duration="500" transform rotate={isOpen ? "0" : "180"} position="absolute" bottom="14" end="-5" size="lg" corners="pill" onClick={toggle} z="100"/>
23
+ </div>);
24
+ }
@@ -7,7 +7,7 @@ export type ButtonBarButtonProps = {
7
7
  icon?: string;
8
8
  } & ButtonProps;
9
9
  export declare const ButtonBarButton: React.ForwardRefExoticComponent<{
10
- icon?: string | undefined;
10
+ icon?: string;
11
11
  } & ButtonProps & React.RefAttributes<HTMLDivElement>>;
12
12
  export interface ButtonBarSubmitButtonProps extends ButtonBarButtonProps {
13
13
  useDirty?: boolean;
@@ -0,0 +1,29 @@
1
+ import { DialogButton } from "../buttons/DialogButton";
2
+ import { Button, Icon } from "@valerya/ui";
3
+ import { useFormikContext } from "formik";
4
+ import React from "react";
5
+ export function ButtonBar({ children, ...props }) {
6
+ return (<div dflex border="1px" borderColor="zinc-200" divideX="1px" divideColor="zinc-200" rounded="lg" overflow="hidden" {...props}>
7
+ {children}
8
+ </div>);
9
+ }
10
+ export const ButtonBarButton = React.forwardRef(function ({ icon, children, ...props }, ref) {
11
+ return (<Button scheme="dark" size="sm" aspectRatio={icon && !children ? "square" : undefined} variant="borderless" dflex alignItems="center" placeContent="center" corners="square" gap="2" {...props} ref={ref}>
12
+ {icon && <Icon path={icon}/>}
13
+ {children}
14
+ </Button>);
15
+ });
16
+ export const ButtonBarSubmitButton = React.forwardRef(function ({ useDirty, disabled, icon, children, ...props }, ref) {
17
+ const { dirty, handleSubmit } = useFormikContext() ?? { dirty: false, handleSubmit: undefined, values: {} };
18
+ const onSubmit = React.useCallback(() => handleSubmit(), [handleSubmit]);
19
+ return (<Button scheme="dark" size="sm" aspectRatio={icon && !children ? "square" : undefined} variant="borderless" dflex alignItems="center" placeContent="center" corners="square" gap="2" disabled={(useDirty && !dirty) || disabled} onClick={onSubmit} {...props} ref={ref}>
20
+ {icon && <Icon path={icon}/>}
21
+ {children}
22
+ </Button>);
23
+ });
24
+ export function ButtonBarDialogButton({ icon, children, ...props }) {
25
+ return (<DialogButton scheme="dark" size="sm" aspectRatio={icon && !children ? "square" : undefined} variant="borderless" dflex alignItems="center" placeContent="center" corners="square" gap="2" {...props}>
26
+ {icon && <Icon path={icon}/>}
27
+ {children}
28
+ </DialogButton>);
29
+ }
@@ -1,4 +1,3 @@
1
- /// <reference types="react" />
2
1
  import { SoperioComponent, ParentComponent } from "@soperio/react";
3
2
  interface ContentProps extends SoperioComponent, ParentComponent {
4
3
  }
@@ -0,0 +1,10 @@
1
+ import { Outlet } from "react-router-dom";
2
+ /**
3
+ *
4
+ *
5
+ */
6
+ export default function Content({ ...props }) {
7
+ return (<div w="100%" h="100%" overflowY="auto" {...props}>
8
+ <Outlet />
9
+ </div>);
10
+ }
@@ -1,4 +1,3 @@
1
- /// <reference types="react" />
2
1
  import { ParentComponent, SoperioComponent } from "@soperio/react";
3
2
  interface TableTopBarProps extends SoperioComponent, ParentComponent {
4
3
  title?: string;
@@ -0,0 +1,12 @@
1
+ export function PageTitleBar({ title, children, ...props }) {
2
+ return (<div dflex flexRow alignItems="center" gap="3" p="8"
3
+ // borderB="0.5"
4
+ // borderBColor="--bg-2"
5
+ {...props}>
6
+ {title && <h2 textSize="x2" fontWeight="600" textColor="#3f4254" textTransform="capitalize">{title}</h2>}
7
+
8
+ <div flexGrow>&nbsp;</div>
9
+
10
+ {children}
11
+ </div>);
12
+ }
@@ -1,4 +1,3 @@
1
- /// <reference types="react" />
2
1
  import { Color, ParentComponent, SoperioComponent } from "@soperio/react";
3
2
  import { MenuConfig } from "./menu/MenuConfig";
4
3
  interface SidebarProps extends SoperioComponent, ParentComponent {
@@ -0,0 +1,24 @@
1
+ import { FlexCenter } from "@compill/components";
2
+ import { Menu } from "./menu/Menu";
3
+ import { AppEnv } from "@compill/env";
4
+ import Image from "next/image";
5
+ import { UserBlock } from "./menu/UserBlock";
6
+ export function Sidebar({ show, logo, title, menuConfig, userMenuConfig, userSettingsPath, color, darkMode, ...props }) {
7
+ return (<div dflex flexCol w="full" md_w="64" minH="screen" p="0" textColor={darkMode ? "white" : "slate-800"} {...props}>
8
+ <FlexCenter placeContent="start" p="4" font="title" gap="3" borderB="px" borderBColor="slate-900" borderOpacity="5">
9
+ {logo ?? <Logo width={40} height={40} darkMode={darkMode}/>}
10
+ <h1 textSize="md">{title || AppEnv.appName()}</h1>
11
+ </FlexCenter>
12
+
13
+ <Menu overflowY="auto" flexGrow="1" p="4" darkMode={darkMode} config={menuConfig}/>
14
+
15
+ <div p="2">
16
+ <UserBlock darkMode={darkMode} color={color} menuConfig={userMenuConfig} path={userSettingsPath}/>
17
+ </div>
18
+ </div>);
19
+ }
20
+ export default function Logo({ width, height, darkMode, ...props }) {
21
+ return (<div {...props}>
22
+ <Image src={`/logo_${darkMode ? "light" : "dark"}.png`} alt={AppEnv.appName() || ""} width={width} height={height} priority unoptimized/>
23
+ </div>);
24
+ }
@@ -1,4 +1,3 @@
1
- /// <reference types="react" />
2
1
  import { ParentComponent, SoperioComponent } from "@soperio/react";
3
2
  import { MenuConfig } from "./MenuConfig";
4
3
  export interface MenuProps extends SoperioComponent, ParentComponent {
@@ -0,0 +1,30 @@
1
+ import { MenuItem } from "./MenuItem";
2
+ import { NextMenuItem } from "./NextMenuItem";
3
+ /**
4
+ *
5
+ *
6
+ */
7
+ export function Menu({ darkMode, config, useNextRouter, ...props }) {
8
+ const Comp = useNextRouter ? NextMenuItem : MenuItem;
9
+ return (<ul {...props}>
10
+ {config.map((item, index) => {
11
+ if (item.type == "divider")
12
+ return <Divider key={index} title={item.label}/>;
13
+ if (item.type == "item") {
14
+ return (<Comp key={index} icon={item.icon} path={item.path} depth={0} darkMode={darkMode} subMenu={item.children}>
15
+ {item.label}
16
+ </Comp>);
17
+ }
18
+ })}
19
+ </ul>);
20
+ }
21
+ function Divider({ title }) {
22
+ return (<div px="2" mt="5" mb="2" opacity="75" textTransform="capitalize" letterSpacing="widest" fontWeight="700" textSize="xs">
23
+ {title}
24
+ </div>);
25
+ }
26
+ function CategoryItem({ children, ...props }) {
27
+ return (<li ps="5" py="2" mt="5" textSize="sm" textColor="white" textOpacity="80" fontWeight="600" textTransform="uppercase">
28
+ {children}
29
+ </li>);
30
+ }
@@ -1,4 +1,3 @@
1
- /// <reference types="react" />
2
1
  import { ButtonProps } from "@valerya/ui";
3
2
  export declare function MenuButton({ depth, darkMode, icon, selected, children, ...props }: {
4
3
  depth?: number;
@@ -0,0 +1,7 @@
1
+ import { Button, Icon } from "@valerya/ui";
2
+ export function MenuButton({ depth, darkMode, icon, selected, children, ...props }) {
3
+ return (<Button as="li" minH="8" ms={`${(depth ?? 0) * 2}`} p="2" font="title" textColor={darkMode ? "white" : "black"} fontWeight="600" rounded="lg" textSize="sm" variant="borderless" hover_bgColor={darkMode ? "white" : "black"} hover_bgOpacity="10" hover_textColor={darkMode ? "white" : "zinc-800"} cursor="pointer" dflex alignItems="center" gap="3" {...props}>
4
+ {icon && <Icon path={icon} opacity={selected ? "100" : "60"}/>}
5
+ {children}
6
+ </Button>);
7
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -1,4 +1,3 @@
1
- /// <reference types="react" />
2
1
  import { ParentComponent, SoperioComponent } from "@soperio/react";
3
2
  import { Item } from "./MenuConfig";
4
3
  interface MenuItemProps extends SoperioComponent, ParentComponent {
@@ -0,0 +1,20 @@
1
+ import { SelectedIndicator } from "./SelectedIndicator";
2
+ import { Link, useLocation, useMatch } from "react-router-dom";
3
+ import { MenuButton } from "./MenuButton";
4
+ export function MenuItem({ icon, path, depth, darkMode, subMenu, ...props }) {
5
+ const location = useLocation();
6
+ const selected = path == "/" ? location.pathname == "/" : location.pathname.startsWith(path.startsWith("/") ? path : `/${path}`);
7
+ const match = useMatch("/" + path) != null;
8
+ // const selected = match != null
9
+ return (<>
10
+ <Link to={path} style={{ position: "relative" }}>
11
+ <MenuButton depth={depth} darkMode={darkMode} icon={icon} selected={selected} {...props}/>
12
+
13
+ {match && <SelectedIndicator darkMode={darkMode}/>}
14
+ </Link>
15
+
16
+ {subMenu?.map((item, index) => (<MenuItem key={index} icon={item.icon} path={item.path} depth={(depth ?? 0) + 1} darkMode={darkMode} subMenu={item.children}>
17
+ {item.label}
18
+ </MenuItem>))}
19
+ </>);
20
+ }
@@ -1,4 +1,3 @@
1
- /// <reference types="react" />
2
1
  import { ParentComponent, SoperioComponent } from "@soperio/react";
3
2
  import { Item } from "./MenuConfig";
4
3
  interface NextMenuItemProps extends SoperioComponent, ParentComponent {
@@ -0,0 +1,20 @@
1
+ import { MenuButton } from "./MenuButton";
2
+ import { SelectedIndicator } from "./SelectedIndicator";
3
+ import Link from "next/link";
4
+ import { useRouter } from "next/router";
5
+ export function NextMenuItem({ icon, path, depth, darkMode, subMenu, ...props }) {
6
+ const { pathname } = useRouter();
7
+ const selected = path == "/" ? pathname == "/" : pathname.startsWith(path.startsWith("/") ? path : `/${path}`);
8
+ const match = path == "/" ? pathname == "/" : pathname == (path.startsWith("/") ? path : `/${path}`);
9
+ return (<>
10
+ <Link href={path} style={{ position: "relative" }}>
11
+ <MenuButton depth={depth} darkMode={darkMode} icon={icon} selected={selected} {...props}/>
12
+
13
+ {match && <SelectedIndicator darkMode={darkMode}/>}
14
+ </Link>
15
+
16
+ {subMenu?.map((item, index) => (<NextMenuItem key={index} icon={item.icon} path={item.path} depth={(depth ?? 0) + 1} darkMode={darkMode} subMenu={item.children}>
17
+ {item.label}
18
+ </NextMenuItem>))}
19
+ </>);
20
+ }
@@ -1,4 +1,3 @@
1
- /// <reference types="react" />
2
1
  export declare function SelectedIndicator({ darkMode }: {
3
2
  darkMode?: boolean;
4
3
  }): JSX.Element;
@@ -0,0 +1,3 @@
1
+ export function SelectedIndicator({ darkMode }) {
2
+ return (<div position="absolute" bgColor={darkMode ? "white" : "black"} bgOpacity="90" w="0.5" h="6" top="1.5" start="-4"/>);
3
+ }
@@ -1,5 +1,4 @@
1
- /// <reference types="react" />
2
- import { MenuConfig } from "@compill/admin";
1
+ import { MenuConfig } from "./MenuConfig";
3
2
  interface UserBlockProps {
4
3
  color: string;
5
4
  darkMode?: boolean;
@@ -0,0 +1,55 @@
1
+ import { useSessionLogout, useSessionUser } from "@compill/auth";
2
+ import { mdiCog, mdiDotsVertical, mdiLogout } from "@mdi/js";
3
+ import { Avatar, Button, Icon, IconButton, Popup } from "@valerya/ui";
4
+ import { capitalize } from "es-toolkit";
5
+ import React from "react";
6
+ import { useNavigate } from "react-router-dom";
7
+ export function UserBlock({ color, darkMode, menuConfig, path }) {
8
+ const { isLoading, user } = useSessionUser();
9
+ const navigate = useNavigate();
10
+ const handleClick = React.useCallback(() => navigate(path), [navigate, path]);
11
+ if (isLoading)
12
+ return null;
13
+ return (<div dflex alignItems="center" border="0.5" borderColor={`${color}-${darkMode ? "800" : "200"}`} ps="3" py="1.5" textSize="md" rounded="lg" hover_bgColor={`${color}-${darkMode ? "800" : "200"}`} cursor="pointer" textColor={darkMode ? "white" : "slate-800"} onClick={handleClick}>
14
+ <Avatar size="sm" src={user?.media?.url ?? ""} name={`${user?.firstname} ${user?.lastname}`}/>
15
+
16
+ <span flexGrow ms="2">{`${capitalize(user?.firstname || user?.lastname || "")}`}</span>
17
+
18
+ <IconButton variant="borderless" corners="pill" scheme="dark" textColor={darkMode ? "white" : "slate-800"} hover_textColor={darkMode ? "white" : "slate-800"} hover_bgColor={`${color}-${darkMode ? "900" : "200"}`} icon={mdiCog} onClick={handleClick}/>
19
+
20
+ <OverflowMenu color={color} darkMode={darkMode} menuConfig={menuConfig}/>
21
+ </div>);
22
+ }
23
+ function OverflowMenu({ color, darkMode, menuConfig }) {
24
+ const [showPopup, setShowPopup] = React.useState(false);
25
+ const navigate = useNavigate();
26
+ const logout = useSessionLogout(false);
27
+ return (<>
28
+ <Popup show={showPopup} position="relative" side="bottom-end" onClick={(e) => { e.preventDefault(); e.stopPropagation(); setShowPopup((show) => !show); }} onHide={() => setShowPopup(false)}>
29
+ <IconButton icon={mdiDotsVertical} variant="borderless" corners="pill" scheme="dark" textColor={darkMode ? "white" : "slate-800"} hover_textColor={darkMode ? "white" : "slate-800"} hover_bgColor={`${color}-${darkMode ? "900" : "200"}`}/>
30
+
31
+ <div bgColor="white" rounded="sm" overflow="hidden" shadow mt="1" border="px" borderColor="gray-200" divideColor="gray-200" divideY="px" minW="40">
32
+ {menuConfig && menuConfig.length > 0 && menuConfig.map((item, index) => {
33
+ if (item.type == "item") {
34
+ return (<MenuItem key={index} icon={item.icon} onClick={() => navigate(item.path)}>
35
+ {item.label}
36
+ </MenuItem>);
37
+ }
38
+ return null;
39
+ })}
40
+ <MenuItem icon={mdiLogout} onClick={logout}>Logout</MenuItem>
41
+ </div>
42
+ </Popup>
43
+ </>);
44
+ }
45
+ function MenuItem({ icon, onClick, children, ...props }) {
46
+ const handleClick = React.useCallback((e) => {
47
+ e.preventDefault();
48
+ e.stopPropagation();
49
+ onClick?.(e);
50
+ }, []);
51
+ return (<Button variant="borderless" scheme="dark" size="sm" alignItems="center" dflex gap="2" px="2" py="1.5" w="full" onClick={handleClick} textColor="slate-700" {...props}>
52
+ {icon && <Icon path={icon} size="md"/>}
53
+ {children}
54
+ </Button>);
55
+ }
@@ -1,4 +1,3 @@
1
- /// <reference types="react" />
2
1
  import { QueryFunctionContext } from "@tanstack/react-query";
3
2
  import { ModalProps } from "@valerya/ui";
4
3
  import { FormikConfig } from "formik";
@@ -0,0 +1,109 @@
1
+ import { useApiMutation, useApiQuery } from "@compill/api";
2
+ import { ModalLoadingOverlay, QueryLoadingState, RetryOnError } from "@compill/components";
3
+ import { useQueryClient } from "@tanstack/react-query";
4
+ import { Button, Checkbox, Modal } from "@valerya/ui";
5
+ import { sortBy } from "es-toolkit";
6
+ import React from "react";
7
+ import { toast } from "react-toastify";
8
+ const defaultErrorMsg = "Oops, something went wrong...";
9
+ export function AttachDialog({ queryId, queryKey, queryFetchFn, queryFetchAllKey, queryFetchAllFn, querySaveFn, matchKey, size = "lg", show, onClose, itemLabel, onSuccess, onFetchError, fetchErrorMsg = defaultErrorMsg, onSaveError, saveErrorMsg = defaultErrorMsg, invalidateQueriesOnSuccess = true, retryText = "Retry", cancelLabel = "Cancel", saveLabel, formikProps, getItemName, ...props }) {
10
+ const queryClient = useQueryClient();
11
+ const { data: attached, isInitialLoading: fetchLoading, isError: fetchError, refetch, error } = useApiQuery(queryKey, queryFetchFn);
12
+ const { data, isInitialLoading: fetchAllLoading, isError: fetchAllError, refetch: refetchAll, error: errorAll } = useApiQuery(queryFetchAllKey, queryFetchAllFn);
13
+ const [selectedResources, setSelectedResources] = React.useState([]);
14
+ const isLoading = fetchLoading || fetchAllLoading;
15
+ const isError = fetchError || fetchAllError;
16
+ const mutation = useApiMutation(querySaveFn, queryKey, queryId);
17
+ const handleClick = React.useCallback((event) => {
18
+ const id = event?.currentTarget.dataset.id ?? "";
19
+ const arr = selectedResources.concat([]);
20
+ const i = selectedResources.indexOf(id);
21
+ if (i != -1)
22
+ arr.splice(i, 1);
23
+ else
24
+ arr.push(id);
25
+ setSelectedResources(arr);
26
+ }, [selectedResources, setSelectedResources]);
27
+ const retry = React.useCallback(() => {
28
+ if (fetchError)
29
+ refetch();
30
+ if (fetchAllError)
31
+ refetchAll();
32
+ }, [refetch, refetchAll, fetchError, fetchAllError]);
33
+ const saveItem = React.useCallback(() => {
34
+ // Clear mutation error if any
35
+ mutation.reset();
36
+ mutation.mutateAsync({ resources: selectedResources })
37
+ .then((response) => {
38
+ if (onSuccess)
39
+ onSuccess(response);
40
+ else
41
+ toast.success(`${itemLabel} saved`);
42
+ if (invalidateQueriesOnSuccess)
43
+ queryClient.invalidateQueries({ queryKey: queryKey });
44
+ // closing delete modal
45
+ onClose?.();
46
+ })
47
+ .catch(error => {
48
+ console.error("on error", error);
49
+ if (onSaveError)
50
+ onSaveError();
51
+ else
52
+ toast.error(`Error adding ${itemLabel}`);
53
+ });
54
+ }, [mutation, queryId, onSuccess, queryClient, onSaveError, onClose]);
55
+ const resources = React.useMemo(() => {
56
+ let r = [];
57
+ if (attached && data) {
58
+ r = [].concat(data);
59
+ attached.forEach((attachedItem) => r.splice(r.findIndex((item) => item.id == attachedItem[matchKey]), 1));
60
+ // TODO set keyField for name (could be title for example)
61
+ if (getItemName)
62
+ r = r.map((item) => { return { ...item, name: getItemName(item) }; });
63
+ r = sortBy(r, ["name"]);
64
+ }
65
+ return r;
66
+ }, [attached, data]);
67
+ return (<Modal size={size} show={show} onClose={onClose} scheme="light" transition
68
+ // closeOnMaskClick={false}
69
+ {...props}>
70
+ <Modal.Header>
71
+ {`Add ${itemLabel}`}
72
+ </Modal.Header>
73
+
74
+ {isLoading && (<Modal.Body>
75
+ <QueryLoadingState minW="72"/>
76
+ </Modal.Body>)}
77
+
78
+ {isError && (<Modal.Body>
79
+ <RetryOnError label={`${fetchErrorMsg} ${error}`} onClick={retry}/>
80
+ </Modal.Body>)}
81
+
82
+ {!isLoading && !isError &&
83
+ (<>
84
+ <Modal.Body px="0" pb="6" maxH="750px" overflow="auto">
85
+ <div dflex flexCol overflow="auto">
86
+
87
+ {resources.map(item => (<ListItem key={item.id} label={item.name} value={item.id} data-id={item.id} checked={selectedResources.includes(`${item.id}`)} onClick={handleClick}/>))}
88
+ </div>
89
+ </Modal.Body>
90
+
91
+ <Modal.Footer dflex placeContent="end" spaceX="3">
92
+ <Button disabled={mutation.isLoading} onClick={onClose} variant="borderless" me="2">
93
+ {cancelLabel}
94
+ </Button>
95
+ <Button type="submit" disabled={selectedResources.length == 0 || mutation.isLoading /* || !isValid*/} onClick={saveItem}>
96
+ {saveLabel ? saveLabel : (queryId ? "Update" : "Create")}
97
+ </Button>
98
+ </Modal.Footer>
99
+ </>)}
100
+
101
+ {mutation.isLoading && <ModalLoadingOverlay />}
102
+ </Modal>);
103
+ }
104
+ function ListItem({ label, value, checked, ...props }) {
105
+ return (<div dflex alignItems="center" hover_bgColor="slate-100" px="5" py="2" cursor="pointer" {...props}>
106
+ <span flexGrow>{label}</span>
107
+ <Checkbox name={`resources.${value}`} value={value} checked={checked}/>
108
+ </div>);
109
+ }
@@ -0,0 +1,46 @@
1
+ import { useMutate } from "@compill/api";
2
+ import { ModalLoadingOverlay } from "@compill/components";
3
+ import { SubmitButton, FormRenderer, FormProvider } from "@compill/form";
4
+ import { useApiMutation, useInvalidateParentMutation } from "@compill/api";
5
+ import { Button, Modal } from "@valerya/ui";
6
+ import React from "react";
7
+ export function FormActionDialog({ initialValues, itemLabel, queryId = "", queryKey, queryFn, queryOptions, onSuccess, successMsg, showSuccessMsg, onError, errorMsg, showErrorMsg, processInput, invalidateQueriesOnSuccess = true, cancelLabel = "Cancel", saveLabel = "Send", size = "lg", title, form, show, onClose, formikProps, ...props }) {
8
+ const mutation = invalidateQueriesOnSuccess ? useInvalidateParentMutation(queryFn, queryKey, queryOptions) : useApiMutation(queryFn, queryKey, queryId, queryOptions);
9
+ const mutate = useMutate(mutation, {
10
+ onSuccess,
11
+ successMsg,
12
+ showSuccessMsg,
13
+ onError,
14
+ errorMsg,
15
+ showErrorMsg,
16
+ processInput,
17
+ });
18
+ return (<Modal size={size} show={show} onClose={onClose} scheme="light" transition
19
+ // closeOnMaskClick={false}
20
+ {...props}>
21
+ <Modal.Header>
22
+ {title}
23
+ </Modal.Header>
24
+
25
+ {/* @ts-ignore */}
26
+ <FormProvider initialValues={initialValues ?? {}} onSubmit={mutate} {...formikProps}>
27
+ <Modal.Body pb="6">
28
+ {React.isValidElement(form) && form}
29
+
30
+ {Array.isArray(form) && <FormRenderer form={form}/>}
31
+ </Modal.Body>
32
+
33
+ <Modal.Footer dflex placeContent="end" spaceX="3">
34
+ <Button disabled={mutation.isLoading} onClick={onClose} variant="borderless" me="2">
35
+ {cancelLabel}
36
+ </Button>
37
+
38
+ <SubmitButton disabled={mutation.isLoading}>
39
+ {saveLabel}
40
+ </SubmitButton>
41
+ </Modal.Footer>
42
+ </FormProvider>
43
+
44
+ {mutation.isLoading && <ModalLoadingOverlay />}
45
+ </Modal>);
46
+ }
@@ -1,3 +1,2 @@
1
- /// <reference types="react" />
2
1
  import { ContainerProps } from "@valerya/ui";
3
2
  export declare function PageContainer({ children, ...props }: ContainerProps): JSX.Element;
@@ -0,0 +1,4 @@
1
+ import { Container } from "@valerya/ui";
2
+ export function PageContainer({ children, ...props }) {
3
+ return <Container center dflex flexCol gap="8" {...props}>{children}</Container>;
4
+ }
@@ -1,4 +1,3 @@
1
- /// <reference types="react" />
2
1
  import { SoperioComponent } from "@soperio/react";
3
2
  export declare function PageContentEditor({ name, ...props }: {
4
3
  name: string;
@@ -0,0 +1,11 @@
1
+ import { FormEditor } from "@compill/form-editor";
2
+ import { PageMain } from "./PageMain";
3
+ import { ImageExtension } from "@compill/editor";
4
+ export function PageContentEditor({ name, ...props }) {
5
+ const extensions = [ImageExtension];
6
+ return (<PageMain h="min" {...props}>
7
+ <FormEditor minH="128" minW="144" maxW={props.maxW}
8
+ // w={props.w}
9
+ name={name} placeHolder="Write here..." extensions={extensions}/>
10
+ </PageMain>);
11
+ }
@@ -1,3 +1,2 @@
1
- /// <reference types="react" />
2
1
  import { ParentComponent, SoperioComponent } from "@soperio/react";
3
2
  export declare function PageMain({ children, ...props }: SoperioComponent & ParentComponent): JSX.Element;
@@ -0,0 +1,4 @@
1
+ import { Tile } from "@valerya/ui";
2
+ export function PageMain({ children, ...props }) {
3
+ return <Tile scheme="light" p="5" {...props}>{children}</Tile>;
4
+ }
@@ -0,0 +1,15 @@
1
+ import { QueryLoadingState, RetryOnError } from "@compill/components";
2
+ import { useApiQuery, useInvalidateQuery } from "@compill/api";
3
+ import React from "react";
4
+ import { PageContainer } from "./PageContainer";
5
+ function PageQueryStateContainerInner({ queryId, api, apiFn, loadingStyles, errorStyles, children, ...props }) {
6
+ // @ts-ignore
7
+ const { data, isLoading, isError } = apiFn == "getAll" ? useApiQuery(api.queryKey, api.getAll, props.apiParams) : useApiQuery(api.queryKey, api.get, queryId);
8
+ const invalidate = useInvalidateQuery(api.queryKey, queryId);
9
+ if (isLoading)
10
+ return <QueryLoadingState w="full" h="100%" {...loadingStyles}/>;
11
+ if (isError)
12
+ return <RetryOnError p="0" onClick={invalidate} {...errorStyles}/>;
13
+ return <PageContainer {...props}>{apiFn == "get" ? children(data) : children(data)}</PageContainer>;
14
+ }
15
+ export const PageQueryStateContainer = React.forwardRef(PageQueryStateContainerInner);
@@ -1,3 +1,2 @@
1
- /// <reference types="react" />
2
1
  import { ParentComponent, SoperioComponent } from "@soperio/react";
3
2
  export declare function PageSectionTitle({ children, ...props }: SoperioComponent & ParentComponent): JSX.Element;
@@ -0,0 +1,3 @@
1
+ export function PageSectionTitle({ children, ...props }) {
2
+ return <div trait="typo.h6" mb="5" {...props}>{children}</div>;
3
+ }
@@ -1,3 +1,2 @@
1
- /// <reference types="react" />
2
1
  import { ParentComponent, SoperioComponent } from "@soperio/react";
3
2
  export declare function PageSidebar({ children, ...props }: SoperioComponent & ParentComponent): JSX.Element;
@@ -0,0 +1,3 @@
1
+ export function PageSidebar({ children, ...props }) {
2
+ return <div w="112" minW="112" minH="100%" gap="8" dflex flexCol {...props}>{children}</div>;
3
+ }
@@ -1,4 +1,3 @@
1
- /// <reference types="react" />
2
1
  import { ParentComponent, SoperioComponent } from "@soperio/react";
3
2
  export declare function PageSidebarSection({ title, children, ...props }: {
4
3
  title?: string;
@@ -0,0 +1,7 @@
1
+ import { PageSectionTitle } from "./PageSectionTitle";
2
+ export function PageSidebarSection({ title, children, ...props }) {
3
+ return (<div w="full" {...props}>
4
+ {title && <PageSectionTitle>{title}</PageSectionTitle>}
5
+ {children}
6
+ </div>);
7
+ }
@@ -0,0 +1,9 @@
1
+ import { QueryLoadingState } from "@compill/components";
2
+ import { Container } from "@valerya/ui";
3
+ import React from "react";
4
+ export const PageStateContainer = React.forwardRef(({ loading = false, children, ...props }, ref) => {
5
+ return (<>
6
+ {loading && <QueryLoadingState w="full" h="100%"/>}
7
+ {!loading && <Container ref={ref} center size="x2" dflex flexCol gap="8" {...props}>{children}</Container>}
8
+ </>);
9
+ });
@@ -1,3 +1,2 @@
1
- /// <reference types="react" />
2
1
  import { ParentComponent, SoperioComponent } from "@soperio/react";
3
2
  export declare function PageSubSectionTitle({ children, ...props }: SoperioComponent & ParentComponent): JSX.Element;
@@ -0,0 +1,3 @@
1
+ export function PageSubSectionTitle({ children, ...props }) {
2
+ return <div trait="typo.h6" mb="3" {...props}>{children}</div>;
3
+ }
@@ -1,3 +1,2 @@
1
- /// <reference types="react" />
2
1
  import { ParentComponent, SoperioComponent } from "@soperio/react";
3
2
  export declare function PageTitle({ children, ...props }: SoperioComponent & ParentComponent): JSX.Element;
@@ -0,0 +1,3 @@
1
+ export function PageTitle({ children, ...props }) {
2
+ return <div trait="typo.h5" {...props}>{children}</div>;
3
+ }