dinocollab-core 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (214) hide show
  1. package/README.md +54 -0
  2. package/dist/_virtual/_rollupPluginBabelHelpers.js +431 -0
  3. package/dist/_virtual/_rollupPluginBabelHelpers.js.map +1 -0
  4. package/dist/assets/vector-404265a04f4f9c8be1f.webp +0 -0
  5. package/dist/node_modules/.pnpm/@rollup_plugin-typescript@1_d0d2002d9033600b6738d939bd598bc6/node_modules/tslib/tslib.es6.js +46 -0
  6. package/dist/node_modules/.pnpm/@rollup_plugin-typescript@1_d0d2002d9033600b6738d939bd598bc6/node_modules/tslib/tslib.es6.js.map +1 -0
  7. package/dist/src/api-context/alert-global.js +151 -0
  8. package/dist/src/api-context/alert-global.js.map +1 -0
  9. package/dist/src/api-context/drawer-global.js +105 -0
  10. package/dist/src/api-context/drawer-global.js.map +1 -0
  11. package/dist/src/api-context/global-modal.js +87 -0
  12. package/dist/src/api-context/global-modal.js.map +1 -0
  13. package/dist/src/api-context/popover-global.js +102 -0
  14. package/dist/src/api-context/popover-global.js.map +1 -0
  15. package/dist/src/api-context/popover.js +86 -0
  16. package/dist/src/api-context/popover.js.map +1 -0
  17. package/dist/src/api-context/ui.units.js +21 -0
  18. package/dist/src/api-context/ui.units.js.map +1 -0
  19. package/dist/src/components/copy-to-clipboard.js +105 -0
  20. package/dist/src/components/copy-to-clipboard.js.map +1 -0
  21. package/dist/src/components/custom.breadcrumbs.js +61 -0
  22. package/dist/src/components/custom.breadcrumbs.js.map +1 -0
  23. package/dist/src/components/help-tooltip.js +91 -0
  24. package/dist/src/components/help-tooltip.js.map +1 -0
  25. package/dist/src/components/image-with-fallback.js +48 -0
  26. package/dist/src/components/image-with-fallback.js.map +1 -0
  27. package/dist/src/components/text-editor.js +117 -0
  28. package/dist/src/components/text-editor.js.map +1 -0
  29. package/dist/src/form/create.autocomplete.chips.js +218 -0
  30. package/dist/src/form/create.autocomplete.chips.js.map +1 -0
  31. package/dist/src/form/create.date-expired.js +201 -0
  32. package/dist/src/form/create.date-expired.js.map +1 -0
  33. package/dist/src/form/create.date-picker.js +125 -0
  34. package/dist/src/form/create.date-picker.js.map +1 -0
  35. package/dist/src/form/create.form-base.js +135 -0
  36. package/dist/src/form/create.form-base.js.map +1 -0
  37. package/dist/src/form/create.form-comfirm.js +119 -0
  38. package/dist/src/form/create.form-comfirm.js.map +1 -0
  39. package/dist/src/form/create.form-grid-layout.js +177 -0
  40. package/dist/src/form/create.form-grid-layout.js.map +1 -0
  41. package/dist/src/form/create.form-grid-layout.units.js +39 -0
  42. package/dist/src/form/create.form-grid-layout.units.js.map +1 -0
  43. package/dist/src/form/create.input-base.js +260 -0
  44. package/dist/src/form/create.input-base.js.map +1 -0
  45. package/dist/src/form/create.input.file.js +74 -0
  46. package/dist/src/form/create.input.file.js.map +1 -0
  47. package/dist/src/form/create.select-simple.js +104 -0
  48. package/dist/src/form/create.select-simple.js.map +1 -0
  49. package/dist/src/form/create.select-with-api.js +271 -0
  50. package/dist/src/form/create.select-with-api.js.map +1 -0
  51. package/dist/src/form/create.text-editor.js +156 -0
  52. package/dist/src/form/create.text-editor.js.map +1 -0
  53. package/dist/src/form/dino-form.js +42 -0
  54. package/dist/src/form/dino-form.js.map +1 -0
  55. package/dist/src/form/helper.js +157 -0
  56. package/dist/src/form/helper.js.map +1 -0
  57. package/dist/src/form/modal-wrapper.js +75 -0
  58. package/dist/src/form/modal-wrapper.js.map +1 -0
  59. package/dist/src/form/validator.js +186 -0
  60. package/dist/src/form/validator.js.map +1 -0
  61. package/dist/src/hooks/index.js +48 -0
  62. package/dist/src/hooks/index.js.map +1 -0
  63. package/dist/src/index.js +26 -0
  64. package/dist/src/index.js.map +1 -0
  65. package/dist/src/redux/create.hoc-lazy.js +67 -0
  66. package/dist/src/redux/create.hoc-lazy.js.map +1 -0
  67. package/dist/src/redux/dino.js +11 -0
  68. package/dist/src/redux/dino.js.map +1 -0
  69. package/dist/src/redux/types.js +9 -0
  70. package/dist/src/redux/types.js.map +1 -0
  71. package/dist/src/redux/ui.error-page.js +80 -0
  72. package/dist/src/redux/ui.error-page.js.map +1 -0
  73. package/dist/src/redux/vector-404.webp.js +4 -0
  74. package/dist/src/redux/vector-404.webp.js.map +1 -0
  75. package/dist/src/table/context.js +12 -0
  76. package/dist/src/table/context.js.map +1 -0
  77. package/dist/src/table/create.action-row.js +135 -0
  78. package/dist/src/table/create.action-row.js.map +1 -0
  79. package/dist/src/table/create.status-cell.js +49 -0
  80. package/dist/src/table/create.status-cell.js.map +1 -0
  81. package/dist/src/table/create.table.js +233 -0
  82. package/dist/src/table/create.table.js.map +1 -0
  83. package/dist/src/table/custom.filter-operators.js +89 -0
  84. package/dist/src/table/custom.filter-operators.js.map +1 -0
  85. package/dist/src/table/dino.js +129 -0
  86. package/dist/src/table/dino.js.map +1 -0
  87. package/dist/src/table/helpers.js +116 -0
  88. package/dist/src/table/helpers.js.map +1 -0
  89. package/dist/src/table/model-filter.js +23 -0
  90. package/dist/src/table/model-filter.js.map +1 -0
  91. package/dist/src/table/toolbar-pannel.js +134 -0
  92. package/dist/src/table/toolbar-pannel.js.map +1 -0
  93. package/dist/src/table/ui.buttons.js +60 -0
  94. package/dist/src/table/ui.buttons.js.map +1 -0
  95. package/dist/src/table/ui.units.js +201 -0
  96. package/dist/src/table/ui.units.js.map +1 -0
  97. package/dist/src/utils/dayjs-config.js +12 -0
  98. package/dist/src/utils/dayjs-config.js.map +1 -0
  99. package/dist/src/utils/helpers.js +197 -0
  100. package/dist/src/utils/helpers.js.map +1 -0
  101. package/dist/src/utils/json-object.js +38 -0
  102. package/dist/src/utils/json-object.js.map +1 -0
  103. package/dist/src/utils/query-param.js +172 -0
  104. package/dist/src/utils/query-param.js.map +1 -0
  105. package/package.json +52 -0
  106. package/rollup.config.js +39 -0
  107. package/src/@types/global.d.ts +5 -0
  108. package/src/api-context/alert-global.tsx +174 -0
  109. package/src/api-context/drawer-global.tsx +116 -0
  110. package/src/api-context/global-modal.tsx +109 -0
  111. package/src/api-context/index.ts +13 -0
  112. package/src/api-context/popover-global.tsx +107 -0
  113. package/src/api-context/popover.tsx +89 -0
  114. package/src/api-context/ui.units.tsx +10 -0
  115. package/src/components/copy-to-clipboard.tsx +86 -0
  116. package/src/components/custom.breadcrumbs.tsx +67 -0
  117. package/src/components/help-tooltip.tsx +75 -0
  118. package/src/components/image-with-fallback.tsx +51 -0
  119. package/src/components/index.tsx +1 -0
  120. package/src/components/input-debounce-timer.tsx +138 -0
  121. package/src/components/loading-buttons.tsx +35 -0
  122. package/src/components/text-editor.preview.tsx +30 -0
  123. package/src/components/text-editor.tsx +125 -0
  124. package/src/form/README.md +55 -0
  125. package/src/form/create.autocomplete.chips.tsx +199 -0
  126. package/src/form/create.date-expired.tsx +195 -0
  127. package/src/form/create.date-picker.tsx +122 -0
  128. package/src/form/create.form-base.tsx +102 -0
  129. package/src/form/create.form-comfirm.tsx +83 -0
  130. package/src/form/create.form-grid-layout.tsx +170 -0
  131. package/src/form/create.form-grid-layout.units.tsx +37 -0
  132. package/src/form/create.input-base.tsx +222 -0
  133. package/src/form/create.input.file.tsx +76 -0
  134. package/src/form/create.select-simple.tsx +101 -0
  135. package/src/form/create.select-with-api.tsx +213 -0
  136. package/src/form/create.text-editor.tsx +161 -0
  137. package/src/form/dino-form.tsx +40 -0
  138. package/src/form/helper.ts +132 -0
  139. package/src/form/index.ts +12 -0
  140. package/src/form/modal-wrapper.tsx +75 -0
  141. package/src/form/types.ts +16 -0
  142. package/src/form/validator.ts +202 -0
  143. package/src/hooks/index.ts +44 -0
  144. package/src/index.ts +7 -0
  145. package/src/lab/create.autocomplete.simple.tsx +57 -0
  146. package/src/lab/create.dino-store.ts +59 -0
  147. package/src/lab/create.multi-select-dropdown.tsx +189 -0
  148. package/src/lab/create.select-mul-with-api/index.tsx +271 -0
  149. package/src/lab/create.select-mul-with-api/table-custom.tsx +194 -0
  150. package/src/lab/create.select-mul-with-api/types.ts +26 -0
  151. package/src/lab/create.select-mul-with-api/ui.units.tsx +163 -0
  152. package/src/lab/filter-bar/base.tsx +162 -0
  153. package/src/lab/filter-bar/create.filter-bar.tsx +190 -0
  154. package/src/lab/filter-bar/create.filter-menu.tsx +156 -0
  155. package/src/lab/filter-bar/create.filter-panel.tsx +95 -0
  156. package/src/lab/filter-bar/create.filtered.tsx +41 -0
  157. package/src/lab/filter-bar/create.sort-menu.tsx +43 -0
  158. package/src/lab/filter-bar/demo.tsx +50 -0
  159. package/src/lab/filter-bar/index.ts +6 -0
  160. package/src/lab/filter-bar/types.ts +105 -0
  161. package/src/lab/filter-bar/ui.units.tsx +70 -0
  162. package/src/lab/grafana-dashboard/configs.ts +43 -0
  163. package/src/lab/grafana-dashboard/date-time-range/absolute-time-rage.tsx +137 -0
  164. package/src/lab/grafana-dashboard/date-time-range/helpers.ts +126 -0
  165. package/src/lab/grafana-dashboard/date-time-range/index.tsx +62 -0
  166. package/src/lab/grafana-dashboard/date-time-range/menu-wrap.tsx +101 -0
  167. package/src/lab/grafana-dashboard/date-time-range/quick-ranges.tsx +161 -0
  168. package/src/lab/grafana-dashboard/date-time-range/types.ts +9 -0
  169. package/src/lab/grafana-dashboard/date-time-range/units.tsx +18 -0
  170. package/src/lab/grafana-dashboard/helper.ts +25 -0
  171. package/src/lab/grafana-dashboard/hooks.tsx +79 -0
  172. package/src/lab/grafana-dashboard/icons.tsx +67 -0
  173. package/src/lab/grafana-dashboard/index.tsx +120 -0
  174. package/src/lab/grafana-dashboard/top-bar.tsx +62 -0
  175. package/src/lab/grafana-dashboard/top-bar.types.ts +5 -0
  176. package/src/lab/grafana-dashboard/types.ts +8 -0
  177. package/src/lab/media-player.core1.tsx +273 -0
  178. package/src/lab/media-player.muted.tsx +62 -0
  179. package/src/lab/media-player.units.ts +80 -0
  180. package/src/lab/table-grid/create.table-grid.tsx +183 -0
  181. package/src/lab/table-grid/demo.tsx +53 -0
  182. package/src/lab/table-grid/dino.tsx +8 -0
  183. package/src/lab/table-grid/helpers.tsx +11 -0
  184. package/src/lab/table-grid/index.ts +3 -0
  185. package/src/lab/table-grid/item-actions.tsx +138 -0
  186. package/src/lab/table-grid/toolbar-pannel.tsx +98 -0
  187. package/src/lab/table-grid/types.ts +68 -0
  188. package/src/redux/create.hoc-lazy.tsx +80 -0
  189. package/src/redux/dino.ts +9 -0
  190. package/src/redux/index.ts +6 -0
  191. package/src/redux/types.ts +27 -0
  192. package/src/redux/ui.error-page.tsx +62 -0
  193. package/src/redux/ui.units.tsx +41 -0
  194. package/src/redux/vector-404.webp +0 -0
  195. package/src/table/context.tsx +16 -0
  196. package/src/table/create.action-row.tsx +91 -0
  197. package/src/table/create.status-cell.tsx +51 -0
  198. package/src/table/create.table.tsx +239 -0
  199. package/src/table/custom.filter-operators.ts +94 -0
  200. package/src/table/dino.tsx +120 -0
  201. package/src/table/helpers.ts +94 -0
  202. package/src/table/index.ts +13 -0
  203. package/src/table/model-filter.ts +43 -0
  204. package/src/table/toolbar-pannel.tsx +106 -0
  205. package/src/table/types.ts +50 -0
  206. package/src/table/ui.buttons.tsx +54 -0
  207. package/src/table/ui.units.tsx +189 -0
  208. package/src/utils/dayjs-config.ts +13 -0
  209. package/src/utils/helpers.ts +171 -0
  210. package/src/utils/index.ts +7 -0
  211. package/src/utils/json-object.ts +29 -0
  212. package/src/utils/mfe-events.tsx +34 -0
  213. package/src/utils/query-param.ts +129 -0
  214. package/tsconfig.json +20 -0
@@ -0,0 +1,138 @@
1
+ import React, { Component, ComponentType, ReactNode } from 'react'
2
+ import { Box, colors, IconButton, List, ListItem, ListItemButton, ListItemIcon, ListItemProps, ListItemText, styled } from '@mui/material'
3
+ import EditIcon from '@mui/icons-material/Edit'
4
+ import MoreVertIcon from '@mui/icons-material/MoreVert'
5
+ import DeleteOutlineIcon from '@mui/icons-material/DeleteOutline'
6
+ import { ClosePopover, GlobalModalState, MapGlobalModalContext, PopoverGlobal } from '../../api-context'
7
+
8
+ export type TableGridItemActionType = 'Edit' | 'Delete'
9
+
10
+ const mapIcons: { [key in TableGridItemActionType]: ReactNode } = {
11
+ Edit: <EditIcon fontSize='small' color='primary' />,
12
+ Delete: <DeleteOutlineIcon fontSize='small' color='error' />
13
+ }
14
+
15
+ export interface TableGridItemActionsProps<T> {
16
+ value: T
17
+ }
18
+
19
+ type FormRenderFunc<T> = (value: T) => React.ReactNode
20
+
21
+ interface ListItemDef<T> {
22
+ name: string
23
+ icon?: ReactNode
24
+ /** Whether this item should trigger a close action when clicked. @default true */
25
+ closableOnClick?: boolean
26
+ /** Handler called when item is clicked */
27
+ onClick?: (event: React.MouseEvent<HTMLLIElement, MouseEvent>, value: T) => void
28
+ listItemProps?: ListItemProps
29
+ /**
30
+ * Optional custom ReactNode to override the entire ListItem UI.
31
+ * If provided, this will be rendered instead of the default ListItem structure
32
+ * (icon + text + click behavior).
33
+ */
34
+ override?: ComponentType<{ onClose?: ClosePopover }>
35
+ }
36
+
37
+ export interface TableGridItemActionsConfig<T> {
38
+ formEdit?: FormRenderFunc<T>
39
+ formDelete?: FormRenderFunc<T>
40
+ buttonEditConfig?: GlobalModalState
41
+ buttonDeleteConfig?: GlobalModalState
42
+ menuList?: {
43
+ before?: SingleOrArray<ListItemDef<T>>
44
+ after?: ListItemDef<T>
45
+ }
46
+ }
47
+
48
+ interface IProps<T> extends TableGridItemActionsProps<T>, TableGridItemActionsConfig<T> {}
49
+
50
+ export function CreateTableGridItemActions<T>() {
51
+ class TableGridItemActions extends Component<IProps<T>> {
52
+ render() {
53
+ if (!this.isVisible()) return <></>
54
+ return (
55
+ <Wrap>
56
+ <IconButton
57
+ size='small'
58
+ onClick={(e) => {
59
+ PopoverGlobal.Api.open({
60
+ anchorEl: e.currentTarget,
61
+ popoverProps: { anchorOrigin: { vertical: 'top', horizontal: 'right' }, transformOrigin: { vertical: 'top', horizontal: 'right' } },
62
+ content: (
63
+ <List>
64
+ {this.renderItems(this.props.menuList?.before)}
65
+ {this.renderItemWithForm('Edit', this.props.formEdit, this.props.buttonEditConfig)}
66
+ {this.renderItemWithForm('Delete', this.props.formDelete, this.props.buttonEditConfig ?? { backdropActivated: true })}
67
+ {this.renderItems(this.props.menuList?.after)}
68
+ </List>
69
+ )
70
+ })
71
+ }}
72
+ >
73
+ <MoreVertIcon fontSize='small' />
74
+ </IconButton>
75
+ </Wrap>
76
+ )
77
+ }
78
+
79
+ isVisible = () => {
80
+ return !!this.props.formEdit || !!this.props.formDelete
81
+ }
82
+
83
+ renderItems = (value?: SingleOrArray<ListItemDef<T>>) => {
84
+ if (!value) return <></>
85
+ const list = Array.isArray(value) ? value : [value]
86
+ return list.map((item, index) => {
87
+ const key = item.name + index
88
+ const { override: Override } = item
89
+ if (Override) return <Override key={key} onClose={PopoverGlobal.Api.close} />
90
+ return (
91
+ <ListItem
92
+ key={key}
93
+ disablePadding
94
+ sx={{ minWidth: '170px' }}
95
+ onClick={(e) => {
96
+ if (item.closableOnClick !== false) PopoverGlobal.Api.close()
97
+ item.onClick && item.onClick(e, this.props.value)
98
+ }}
99
+ {...item.listItemProps}
100
+ >
101
+ <ListItemButton>
102
+ <ListItemIcon>{item.icon}</ListItemIcon>
103
+ <ListItemText primary={item.name} />
104
+ </ListItemButton>
105
+ </ListItem>
106
+ )
107
+ })
108
+ }
109
+
110
+ renderItemWithForm = (name: TableGridItemActionType, form?: FormRenderFunc<T>, globalState?: GlobalModalState) => {
111
+ if (!form) return <></>
112
+ return MapGlobalModalContext((context) => (
113
+ <ListItem
114
+ disablePadding
115
+ sx={{ minWidth: '170px' }}
116
+ onClick={() => {
117
+ PopoverGlobal.Api.close()
118
+ context.show({ renderContent: () => form(this.props.value), ...globalState })
119
+ }}
120
+ >
121
+ <ListItemButton>
122
+ <ListItemIcon>{mapIcons[name]}</ListItemIcon>
123
+ <ListItemText primary={name} />
124
+ </ListItemButton>
125
+ </ListItem>
126
+ ))
127
+ }
128
+ }
129
+ return TableGridItemActions
130
+ }
131
+
132
+ const Wrap = styled(Box)({
133
+ background: colors.common.white,
134
+ borderRadius: '6px',
135
+ '& > .MuiButtonBase-root': {
136
+ borderRadius: '6px'
137
+ }
138
+ })
@@ -0,0 +1,98 @@
1
+ import React, { Component } from 'react'
2
+ import { Box, BoxProps, Button, ButtonProps, styled, Tooltip, Typography, TypographyProps } from '@mui/material'
3
+ import AddCircleOutlineIcon from '@mui/icons-material/AddCircleOutline'
4
+ import { MapGlobalModalContext } from '../../api-context'
5
+ import CustomBreadcrumbs, { CustomBreadcrumbConfig } from '../../components/custom.breadcrumbs'
6
+
7
+ interface SectionSlots {
8
+ before?: React.ReactNode
9
+ after?: React.ReactNode
10
+ }
11
+
12
+ export interface ToolbarPannelProps {
13
+ /** @default true */
14
+ visible?: boolean
15
+ searchInclude?: string[]
16
+ breadcrumbs?: CustomBreadcrumbConfig[]
17
+ title?: React.ReactNode
18
+ titleSlots?: SectionSlots
19
+ formCreate?: React.ReactNode
20
+ actionSlots?: SectionSlots
21
+ slots?: {
22
+ rootProps?: BoxProps
23
+ buttonCreateProps?: ButtonProps
24
+ }
25
+ }
26
+
27
+ class ToolbarPannel extends Component<ToolbarPannelProps> {
28
+ render() {
29
+ if (this.props.visible === false) return
30
+ return (
31
+ <Wrap {...this.props.slots?.rootProps}>
32
+ {this.props.titleSlots?.before}
33
+ {this.renderTitle()}
34
+ {this.props.titleSlots?.after}
35
+ <Box sx={{ flex: 1 }} />
36
+ {this.props.actionSlots?.before}
37
+ {this.renderButtonCreate()}
38
+ {this.props.actionSlots?.after}
39
+ </Wrap>
40
+ )
41
+ }
42
+
43
+ renderButtonCreate = () => {
44
+ if (!this.props.formCreate) return <></>
45
+ return MapGlobalModalContext((context) => (
46
+ <Tooltip title='Create new'>
47
+ <Button
48
+ size='small'
49
+ onClick={() => context.show({ renderContent: () => this.props.formCreate })}
50
+ startIcon={<AddCircleOutlineIcon fontSize='small' />}
51
+ sx={{ fontWeight: 600 }}
52
+ variant='contained'
53
+ {...this.props.slots?.buttonCreateProps}
54
+ >
55
+ Create
56
+ </Button>
57
+ </Tooltip>
58
+ ))
59
+ }
60
+
61
+ renderTitle = () => {
62
+ const { title, breadcrumbs } = this.props ?? {}
63
+ if (breadcrumbs) return <CustomBreadcrumbs value={breadcrumbs} />
64
+ if (typeof title === 'string') return <Title>{title}</Title>
65
+ return <>{title}</>
66
+ }
67
+ }
68
+
69
+ export default ToolbarPannel
70
+
71
+ // const SeachHelp = styled('ul')({
72
+ // margin: '0 0 0 18px',
73
+ // padding: 0,
74
+ // li: {
75
+ // position: 'relative'
76
+ // },
77
+ // 'li::after': {
78
+ // content: '"►"',
79
+ // display: 'inline-block',
80
+ // top: '50%',
81
+ // transform: 'translateY(-50%)',
82
+ // position: 'absolute',
83
+ // left: '-18px'
84
+ // }
85
+ // })
86
+
87
+ const Title = styled((props: TypographyProps) => <Typography noWrap variant='subtitle1' {...props} />)({
88
+ fontWeight: 700,
89
+ flex: 1
90
+ })
91
+
92
+ const Wrap = styled(Box)({
93
+ height: 'var(--height-toolbar, 56px)',
94
+ display: 'flex',
95
+ alignItems: 'center',
96
+ gap: '8px',
97
+ padding: '0 6px'
98
+ })
@@ -0,0 +1,68 @@
1
+ import { ComponentType, ReactNode } from 'react'
2
+ import { GridProps, RegularBreakpoints } from '@mui/material'
3
+ import { FilterBarParams, FilterState } from '../filter-bar'
4
+ import { ToolbarPannelProps } from './toolbar-pannel'
5
+ import { TableGridItemActionsConfig, TableGridItemActionsProps } from './item-actions'
6
+
7
+ export interface TableGridItemProps<T = any> {
8
+ value: T
9
+ }
10
+
11
+ export type GetSelecterIdFunc<T> = (item: T) => string
12
+
13
+ export interface PaginationModel {
14
+ page: number
15
+ pageSize: number
16
+ }
17
+
18
+ export interface TableGridFilter<T> extends FilterState<T> {
19
+ pagination: PaginationModel
20
+ loading?: boolean
21
+ }
22
+
23
+ export interface TableGridFlexibleSlots<T> {
24
+ item?: ComponentType<TableGridItemProps<T>>
25
+ }
26
+
27
+ export interface TableGridSlots<T> extends TableGridFlexibleSlots<T> {
28
+ flex?: boolean
29
+ gridContainer?: GridProps
30
+ gridItem?: GridProps
31
+ toolbar?: ComponentType
32
+ toolbarProps?: ToolbarPannelProps
33
+ action?: ComponentType<TableGridItemActionsProps<T>>
34
+ actionProps?: TableGridItemActionsConfig<T>
35
+ }
36
+
37
+ export interface TableGridInnerSlots<T> extends TableGridSlots<T> {
38
+ TableGridItem: ComponentType<TableGridItemProps<T>>
39
+ ToolbarPannel: ComponentType<ToolbarPannelProps>
40
+ }
41
+
42
+ export interface TableGridParams<T> extends TableGridFlexibleSlots<T> {
43
+ getSelecterId: GetSelecterIdFunc<T>
44
+ title?: ReactNode
45
+ filterBarConfig?: FilterBarParams<T>
46
+ size?: RegularBreakpoints
47
+ slots?: TableGridSlots<T>
48
+ }
49
+
50
+ export interface TableGridData<T> {
51
+ items?: T[]
52
+ totalItems?: number
53
+ }
54
+
55
+ export interface TableGridProps<T> {
56
+ data: TableGridData<T>
57
+ filter?: TableGridFilter<T>
58
+ onFilterChange?: (value: TableGridFilter<T>) => void
59
+ slots?: TableGridSlots<T>
60
+ }
61
+
62
+ export interface TableGridReduxState<T> {
63
+ tableData: TableGridData<T>
64
+ tableFilter: TableGridFilter<T>
65
+ tableFilterThunk: TableGridFilter<T>
66
+ }
67
+
68
+ export type TableGridStateRedux<T, K extends keyof TableGridReduxState<T> = keyof TableGridReduxState<T>> = Pick<TableGridReduxState<T>, K>
@@ -0,0 +1,80 @@
1
+ import React, { Component, PropsWithChildren } from 'react'
2
+ import { IErrorViewDefaultProps, IHocLazyWrapperProps } from './ui.units'
3
+ import { ELazyStatus, DinoReduxDispatch, DinoReduxState, ReturnDispatch } from './types'
4
+ import UIErrorPage from './ui.error-page'
5
+
6
+ interface IHocLazyBase<TModel> extends DinoReduxState, DinoReduxDispatch<TModel> {}
7
+
8
+ export interface IOptionBase {
9
+ ErrorScreen?: React.ComponentType<IErrorViewDefaultProps>
10
+ LazySpinner: React.ComponentType<PropsWithChildren<IHocLazyWrapperProps>>
11
+ }
12
+
13
+ export interface IHocLazyOtherProps<TModel> {
14
+ param?: TModel
15
+ }
16
+
17
+ export interface IHocLazyOptions<TModel> extends IHocLazyOtherProps<TModel>, Omit<IOptionBase, 'LazySpinner'> {
18
+ LazySpinner?: React.ComponentType<PropsWithChildren<IHocLazyWrapperProps>>
19
+ }
20
+
21
+ export const EmptyComponent: React.FC<React.PropsWithChildren<any>> = ({ children }) => <>{children}</>
22
+
23
+ export const OptionHocLazyDefault: IOptionBase = {
24
+ LazySpinner: EmptyComponent
25
+ }
26
+
27
+ const CreateHocLazy = function <TChildProp extends IHocLazyBase<TModel>, TModel = any>(
28
+ ChildComponent: React.ComponentType<TChildProp>,
29
+ options?: IHocLazyOptions<TModel>
30
+ ) {
31
+ type TProps = TChildProp & IHocLazyOtherProps<TModel>
32
+ class HocComponent extends Component<TProps> {
33
+ optionsMerge: IOptionBase
34
+ tokenSources?: AbortController
35
+ fetchSource?: ReturnDispatch
36
+ constructor(props: TProps) {
37
+ super(props)
38
+ this.optionsMerge = Object.assign({}, OptionHocLazyDefault, options) as IOptionBase
39
+ }
40
+
41
+ render() {
42
+ const { optionsMerge: OptionsMerge } = this
43
+ switch (this.props.status) {
44
+ case ELazyStatus.Loading:
45
+ case ELazyStatus.Loaded:
46
+ return (
47
+ <OptionsMerge.LazySpinner loading={this.props.status === ELazyStatus.Loading}>
48
+ <ChildComponent {...this.props} />
49
+ </OptionsMerge.LazySpinner>
50
+ )
51
+ case ELazyStatus.Error:
52
+ return <UIErrorPage />
53
+ default:
54
+ return <div></div>
55
+ }
56
+ }
57
+
58
+ initialParam = (): TModel => {
59
+ const oData = options?.param ?? {}
60
+ const pData = this.props?.param ?? {}
61
+ return Object.assign({}, oData, pData) as TModel
62
+ }
63
+
64
+ componentDidMount = () => {
65
+ if (this.props.fetchData) {
66
+ const param = this.initialParam()
67
+ this.tokenSources?.abort()
68
+ this.tokenSources = new AbortController()
69
+ this.fetchSource = this.props.fetchData(param, this.tokenSources.signal)
70
+ }
71
+ }
72
+
73
+ componentWillUnmount() {
74
+ this.tokenSources?.abort()
75
+ this.fetchSource?.abort && this.fetchSource.abort()
76
+ }
77
+ }
78
+ return HocComponent
79
+ }
80
+ export default CreateHocLazy
@@ -0,0 +1,9 @@
1
+ import CreateHocLazy from './create.hoc-lazy'
2
+
3
+ class DinoReduxBase {
4
+ createHocLazy = CreateHocLazy
5
+ }
6
+
7
+ const DinoRedux = new DinoReduxBase()
8
+
9
+ export default DinoRedux
@@ -0,0 +1,6 @@
1
+ export * from './types'
2
+
3
+ export { default as DinoRedux } from './dino'
4
+
5
+ export { default as CreateHocLazy } from './create.hoc-lazy'
6
+ export * from './create.hoc-lazy'
@@ -0,0 +1,27 @@
1
+ export enum ELazyStatus {
2
+ Loading = 'Loading',
3
+ Loaded = 'Loaded',
4
+ Error = 'Error'
5
+ }
6
+
7
+ export interface DinoReduxState {
8
+ status: ELazyStatus
9
+ requestedId?: string
10
+ }
11
+
12
+ export interface ReturnDispatch {
13
+ abort?: () => void
14
+ }
15
+
16
+ export interface DinoReduxDispatch<P = any> {
17
+ fetchData?: (params?: P, signal?: AbortSignal) => ReturnDispatch
18
+ setStatus: (status: ELazyStatus) => void
19
+ }
20
+
21
+ interface Actions<T, Id extends keyof T> {
22
+ create: (value: Partial<T>, signal?: AbortSignal) => Promise<void>
23
+ update: (id: T[Id], value: Partial<T>, signal?: AbortSignal) => Promise<void>
24
+ delete: (id: T[Id], value?: Partial<T>, signal?: AbortSignal) => Promise<void>
25
+ }
26
+
27
+ export type DinoReduxActions<T, Id extends keyof T, K extends keyof Actions<T, Id> = keyof Actions<T, Id>> = Pick<Actions<T, Id>, K>
@@ -0,0 +1,62 @@
1
+ import React, { FC } from 'react'
2
+ import { Box, BoxProps, Button, ButtonProps, Stack, styled, Typography } from '@mui/material'
3
+ import ArrowRightAltIcon from '@mui/icons-material/ArrowRightAlt'
4
+ import Error404Vector from './vector-404.webp'
5
+
6
+ const UIErrorPage: FC = () => (
7
+ <Stack sx={{ alignItems: 'center' }}>
8
+ <WrapImage>
9
+ <img src={Error404Vector} alt='error-404-vector' />
10
+ </WrapImage>
11
+ <Typography variant='subtitle1' component='p' sx={{ textAlign: 'center', mt: '20px' }}>
12
+ Sorry, page not found or connection to server lost. Please come back later....
13
+ </Typography>
14
+ <CustomButton href='/'>Back to home page</CustomButton>
15
+ </Stack>
16
+ )
17
+ export default UIErrorPage
18
+
19
+ const WrapImage = styled(({ children, ...props }: BoxProps) => (
20
+ <Box {...props}>
21
+ <div>{children}</div>
22
+ </Box>
23
+ ))({
24
+ width: '100%',
25
+ maxWidth: '560px',
26
+ flex: '0 0 auto',
27
+ '& > div': {
28
+ width: '100%',
29
+ paddingBottom: '100%',
30
+ position: 'relative'
31
+ },
32
+ '& img': {
33
+ position: 'absolute',
34
+ top: 0,
35
+ left: 0,
36
+ width: '100%',
37
+ height: '100%'
38
+ }
39
+ })
40
+
41
+ const CustomButton = styled((p: ButtonProps & { href: string }) => {
42
+ return <Button component='a' color='inherit' variant='contained' size='large' endIcon={<ArrowRightAltIcon fontSize='small' />} {...p} />
43
+ })({
44
+ backgroundColor: 'var(--color-black)',
45
+ color: 'var(--color-text-light)',
46
+ minWidth: '250px',
47
+ marginTop: '24px',
48
+ height: '56px',
49
+ textTransform: 'none',
50
+ fontWeight: 600,
51
+ transition: '0.3s',
52
+ '&:hover': {
53
+ backgroundColor: 'var(--color-black2)',
54
+ color: 'var(--color-text-light)'
55
+ },
56
+ '& .MuiButton-icon.MuiButton-endIcon': {
57
+ transition: '0.3s'
58
+ },
59
+ '&:hover .MuiButton-icon.MuiButton-endIcon': {
60
+ marginLeft: '16px'
61
+ }
62
+ })
@@ -0,0 +1,41 @@
1
+ import React, { FC, PropsWithChildren } from 'react'
2
+ import { Box, Button, Fade, Stack, styled, Typography } from '@mui/material'
3
+
4
+ export interface IErrorViewDefaultProps {}
5
+
6
+ export const ErrorViewDefault: FC<IErrorViewDefaultProps> = () => (
7
+ <Stack sx={{ height: '100vh', alignItems: 'center', justifyContent: 'center' }}>
8
+ <Typography variant='h1'>Errors Something</Typography>
9
+ <Typography variant='subtitle1'>Please try again :{'(('}</Typography>
10
+ <Button variant='outlined' color='inherit' LinkComponent='a' href='/'>
11
+ Try again
12
+ </Button>
13
+ </Stack>
14
+ )
15
+
16
+ export interface IHocLazyWrapperProps extends PropsWithChildren {
17
+ loading?: boolean
18
+ backdrop?: boolean
19
+ }
20
+
21
+ export const HocLazyWrapper: FC<IHocLazyWrapperProps> = (props) => (
22
+ <React.Fragment>
23
+ {props.children}
24
+ <Fade in={props.loading === true && props.backdrop !== false} unmountOnExit>
25
+ <Wrapper />
26
+ </Fade>
27
+ </React.Fragment>
28
+ )
29
+
30
+ const Wrapper = styled(Box)({
31
+ top: 0,
32
+ left: 0,
33
+ width: '100%',
34
+ height: '100%',
35
+ position: 'fixed',
36
+ background: 'rgb(0,0,0,0.15)',
37
+ display: 'flex',
38
+ justifyContent: 'center',
39
+ alignItems: 'center',
40
+ zIndex: 1150
41
+ })
Binary file
@@ -0,0 +1,16 @@
1
+ import React, { createContext } from 'react'
2
+ import { TCloseModal, TShowModal } from '../api-context'
3
+
4
+ export interface ITableBaseContext {
5
+ showModal: TShowModal
6
+ closeModal: TCloseModal
7
+ }
8
+
9
+ export const TableBaseContext = createContext<ITableBaseContext>({
10
+ showModal: () => {},
11
+ closeModal: () => {}
12
+ })
13
+
14
+ export const MapTableBaseContext = (context: (context: ITableBaseContext) => React.ReactNode) => (
15
+ <TableBaseContext.Consumer>{context}</TableBaseContext.Consumer>
16
+ )
@@ -0,0 +1,91 @@
1
+ import React, { Component } from 'react'
2
+ import { Box, BoxProps, IconButton, Tooltip } from '@mui/material'
3
+ import EditIcon from '@mui/icons-material/Edit'
4
+ import DeleteIcon from '@mui/icons-material/Delete'
5
+ import { GlobalModalState } from '../api-context'
6
+ import { ITableBaseContext, MapTableBaseContext } from './context'
7
+ import { mergeObjects } from '../utils'
8
+
9
+ export interface IActionRowProps<T> {
10
+ value: T
11
+ formEdit?: (value: T, tableContext: ITableBaseContext) => React.ReactNode
12
+ formDelete?: (value: T, tableContext: ITableBaseContext) => React.ReactNode
13
+ after?: (value: T, tableContext: ITableBaseContext) => React.ReactNode
14
+ before?: (value: T, tableContext: ITableBaseContext) => React.ReactNode
15
+ wrapProps?: BoxProps
16
+ buttonEditConfig?: GlobalModalState
17
+ buttonDeleteConfig?: GlobalModalState
18
+ }
19
+
20
+ function CreateActionRow<T>(params?: Omit<IActionRowProps<T>, 'value'>) {
21
+ class ActionRow extends Component<IActionRowProps<T>> {
22
+ get propsMerge() {
23
+ return mergeObjects<IActionRowProps<T>>(params, this.props)
24
+ }
25
+
26
+ getButtons = function* (that: ActionRow, thatProps: Omit<IActionRowProps<T>, 'value'>, tableContext: ITableBaseContext) {
27
+ const beforeFunc = that.props?.before ?? thatProps?.before
28
+ if (beforeFunc) {
29
+ yield <React.Fragment key='Before'>{beforeFunc(that.props.value, tableContext)}</React.Fragment>
30
+ }
31
+ const editFunc = that.props?.formEdit ?? thatProps?.formEdit
32
+ const editContent = editFunc ? editFunc(that.props.value, tableContext) : undefined
33
+ if (editFunc && !!editContent) {
34
+ yield (
35
+ <Tooltip title='Edit' arrow key='Edit'>
36
+ <IconButton
37
+ color='primary'
38
+ onClick={() => {
39
+ tableContext?.showModal({
40
+ renderContent: () => editContent || <React.Fragment />,
41
+ sx: { display: 'flex', justifyContent: 'center', alignItems: 'center' },
42
+ backdropActivated: true,
43
+ ...params?.buttonEditConfig
44
+ })
45
+ }}
46
+ >
47
+ <EditIcon fontSize='small' />
48
+ </IconButton>
49
+ </Tooltip>
50
+ )
51
+ }
52
+ const deleteFunc = that.props?.formDelete ?? thatProps?.formDelete
53
+ const deleteContent = deleteFunc ? deleteFunc(that.props.value, tableContext) : undefined
54
+ if (deleteFunc && !!deleteContent) {
55
+ yield (
56
+ <Tooltip title='Delete' arrow key='Delete'>
57
+ <IconButton
58
+ color='error'
59
+ onClick={() => {
60
+ tableContext?.showModal({
61
+ renderContent: () => deleteContent || <React.Fragment />,
62
+ sx: { display: 'flex', justifyContent: 'center', alignItems: 'center' },
63
+ backdropActivated: true,
64
+ ...params?.buttonDeleteConfig
65
+ })
66
+ }}
67
+ >
68
+ <DeleteIcon fontSize='small' />
69
+ </IconButton>
70
+ </Tooltip>
71
+ )
72
+ }
73
+ const afterFunc = that.props?.after ?? thatProps?.after
74
+ if (afterFunc) {
75
+ yield <React.Fragment key='After'>{afterFunc(that.props.value, tableContext)}</React.Fragment>
76
+ }
77
+ }
78
+
79
+ render() {
80
+ return MapTableBaseContext((context) => (
81
+ <Box sx={{ display: 'flex', alignItems: 'center', height: '100%' }} {...this.propsMerge.wrapProps}>
82
+ {Array.from(this.getButtons(this, this.propsMerge, context))}
83
+ </Box>
84
+ ))
85
+ }
86
+ }
87
+
88
+ return ActionRow
89
+ }
90
+
91
+ export default CreateActionRow