@hrbolek/uoisfrontend-template 0.6.2 → 0.6.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.js +17 -17
- package/dist/es/index.js +38 -31
- package/dist/umd/index.js +31 -31
- package/package.json +1 -1
- package/src/Base/Components/Link.jsx +13 -8
- package/src/Base/Mutations/General.jsx +3 -1
- package/src/Base/Mutations/Update.jsx +5 -0
- package/src/EventGQLModel/Components/A4Plan/A4Plan.jsx +363 -0
- package/src/EventGQLModel/Components/A4Plan/index.js +1 -0
- package/src/EventGQLModel/Components/CardCapsule.jsx +43 -0
- package/src/EventGQLModel/Components/Children.jsx +31 -0
- package/src/EventGQLModel/Components/ConfirmEdit.jsx +61 -0
- package/src/EventGQLModel/Components/Filter.jsx +14 -0
- package/src/EventGQLModel/Components/LargeCard.jsx +54 -0
- package/src/EventGQLModel/Components/Link.jsx +55 -0
- package/src/EventGQLModel/Components/LiveEdit.jsx +111 -0
- package/src/EventGQLModel/Components/MediumCard.jsx +39 -0
- package/src/EventGQLModel/Components/MediumContent.jsx +96 -0
- package/src/EventGQLModel/Components/MediumEditableContent.jsx +35 -0
- package/src/EventGQLModel/Components/Plan/PlanRow.jsx +470 -0
- package/src/EventGQLModel/Components/Plan/_utils.js +971 -0
- package/src/EventGQLModel/Components/Plan/calendarReducer.js +535 -0
- package/src/EventGQLModel/Components/Plan/index.js +3 -0
- package/src/EventGQLModel/Components/Table.jsx +7 -0
- package/src/EventGQLModel/Components/index.js +15 -0
- package/src/EventGQLModel/Mutations/Create.jsx +202 -0
- package/src/EventGQLModel/Mutations/Delete.jsx +173 -0
- package/src/EventGQLModel/Mutations/InteractiveMutations.jsx +30 -0
- package/src/EventGQLModel/Mutations/Update.jsx +147 -0
- package/src/EventGQLModel/Mutations/helpers.jsx +7 -0
- package/src/EventGQLModel/Pages/PageBase.jsx +56 -0
- package/src/EventGQLModel/Pages/PageCreateItem.jsx +28 -0
- package/src/EventGQLModel/Pages/PageDeleteItem.jsx +16 -0
- package/src/EventGQLModel/Pages/PageNavbar.jsx +160 -0
- package/src/EventGQLModel/Pages/PagePlan.jsx +42 -0
- package/src/EventGQLModel/Pages/PageReadItem.jsx +11 -0
- package/src/EventGQLModel/Pages/PageReadItemEx.jsx +42 -0
- package/src/EventGQLModel/Pages/PageSubevents.jsx +43 -0
- package/src/EventGQLModel/Pages/PageUpdateItem.jsx +14 -0
- package/src/EventGQLModel/Pages/PageVector.jsx +80 -0
- package/src/EventGQLModel/Pages/RouterSegment.jsx +82 -0
- package/src/EventGQLModel/Pages/index.js +2 -0
- package/src/EventGQLModel/Queries/DeleteAsyncAction.jsx +32 -0
- package/src/EventGQLModel/Queries/Fragments.jsx +123 -0
- package/src/EventGQLModel/Queries/InsertAsyncAction.jsx +40 -0
- package/src/EventGQLModel/Queries/ReadAsyncAction.jsx +44 -0
- package/src/EventGQLModel/Queries/ReadPageAsyncAction.jsx +13 -0
- package/src/EventGQLModel/Queries/ReadSubEventsAsyncAction.jsx +44 -0
- package/src/EventGQLModel/Queries/SearchAsyncAction.jsx +16 -0
- package/src/EventGQLModel/Queries/UpdateAsyncAction.jsx +40 -0
- package/src/EventGQLModel/Queries/index.js +6 -0
- package/src/EventGQLModel/Scalars/ScalarAttribute.jsx +54 -0
- package/src/EventGQLModel/Scalars/TemplateScalarAttribute.jsx +88 -0
- package/src/EventGQLModel/Scalars/index.js +1 -0
- package/src/EventGQLModel/Vectors/TemplateVectorsAttribute.jsx +326 -0
- package/src/EventGQLModel/Vectors/VectorAttribute.jsx +56 -0
- package/src/EventGQLModel/Vectors/index.js +1 -0
- package/src/EventGQLModel/WhatToDo.md +44 -0
- package/src/EventGQLModel/index.js +71 -0
- package/src/GroupGQLModel/Mutations/Create.jsx +8 -2
- package/src/GroupGQLModel/Mutations/Delete.jsx +8 -2
- package/src/GroupGQLModel/Mutations/Update.jsx +8 -8
- package/src/GroupGQLModel/Queries/Fragments.jsx +17 -1
- package/src/GroupGQLModel/Scalars/RBACObject.jsx +17 -5
- package/src/GroupGQLModel/Vectors/GroupMemberships.jsx +1 -1
- package/src/UserGQLModel/Components/MediumContent.jsx +9 -3
- package/src/UserGQLModel/Queries/Fragments.jsx +6 -0
- package/src/_Template/WhatToDo.md +1 -1
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import Nav from 'react-bootstrap/Nav'
|
|
2
|
+
import { Link, LinkURI } from '../Components'
|
|
3
|
+
import { ProxyLink } from '../../../../_template/src/Base/Components/ProxyLink';
|
|
4
|
+
import { NavDropdown } from 'react-bootstrap';
|
|
5
|
+
import { UpdateLink } from '../Mutations/Update';
|
|
6
|
+
import { CreateButton } from '../Mutations/Create';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Allow to use HashContainer for determination which component at page will be rendered.
|
|
10
|
+
* That must be manually inserted at TemplatePageContent, usually this should be done
|
|
11
|
+
* as children of TemplateLargeCard.
|
|
12
|
+
* <TemplateLargeCard>
|
|
13
|
+
* <HashContainer>
|
|
14
|
+
* <VectorA id="history"/>
|
|
15
|
+
* <VectorB id="roles"/>
|
|
16
|
+
* <VectorC id="graph"/>
|
|
17
|
+
* </HashContainer>
|
|
18
|
+
* </TemplateLargeCard>
|
|
19
|
+
* it is usefull to define globally active "areas" like science, administration, teaching, ...
|
|
20
|
+
*/
|
|
21
|
+
// const TemplatePageSegments = [
|
|
22
|
+
// { segment: 'education', label: 'Výuka' },
|
|
23
|
+
// { segment: 'reaserach', label: 'Tvůrčí činnost' },
|
|
24
|
+
// { segment: 'administration', label: 'Organizační činnost' },
|
|
25
|
+
// { segment: 'development', label: 'Rozvoj' },
|
|
26
|
+
// ]
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* A navigation button component that generates a URL based on the template's ID and a specific segment.
|
|
30
|
+
* The button uses a `ProxyLink` to navigate while preserving hash and query parameters.
|
|
31
|
+
*
|
|
32
|
+
* ### Features:
|
|
33
|
+
* - Dynamically constructs the URL with a hash fragment pointing to the specified segment.
|
|
34
|
+
* - Displays a label for the navigation link.
|
|
35
|
+
* - Integrates seamlessly with `ProxyLink` for enhanced navigation.
|
|
36
|
+
*
|
|
37
|
+
* @component
|
|
38
|
+
* @param {Object} props - The properties for the TitleNavButton component.
|
|
39
|
+
* @param {Object} props.template - The template object containing details about the template.
|
|
40
|
+
* @param {string|number} props.template.id - The unique identifier for the template.
|
|
41
|
+
* @param {string} props.segment - The segment to append as a hash fragment in the URL.
|
|
42
|
+
* @param {string} props.label - The text to display as the label for the navigation button.
|
|
43
|
+
*
|
|
44
|
+
* @returns {JSX.Element} A styled navigation button linking to the constructed URL.
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* // Example 1: Basic usage with a template and segment
|
|
48
|
+
* const template = { id: 123 };
|
|
49
|
+
* const segment = "details";
|
|
50
|
+
* const label = "View Details";
|
|
51
|
+
*
|
|
52
|
+
* <TitleNavButton template={template} segment={segment} label={label} />
|
|
53
|
+
* // Resulting URL: `/ug/template/view/123#details`
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* // Example 2: Different segment and label
|
|
57
|
+
* <TitleNavButton template={{ id: 456 }} segment="settings" label="Template Settings" />
|
|
58
|
+
* // Resulting URL: `/ug/template/view/456#settings`
|
|
59
|
+
*/
|
|
60
|
+
// const TitleNavButton = ({ item, segment, label, ...props }) => {
|
|
61
|
+
// // const urlbase = (segment) => `/templates/template/${segment}/${template?.id}`;
|
|
62
|
+
// const urlbase = (segment) => `${LinkURI}${item?.id}#${segment}`;
|
|
63
|
+
// return (
|
|
64
|
+
// <Nav.Link as={"span"} {...props}>
|
|
65
|
+
// {/* <ProxyLink to={urlbase(segment)}>{label}</ProxyLink> */}
|
|
66
|
+
// </Nav.Link>
|
|
67
|
+
// );
|
|
68
|
+
// };
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Renders the navigation bar for an Template page.
|
|
72
|
+
*
|
|
73
|
+
* This component uses a custom hook, `useHash()`, to determine the current hash
|
|
74
|
+
* and highlights the active segment. It displays a navigation bar (using MyNavbar)
|
|
75
|
+
* with several segments (e.g. "history", "roles", "graph"), each rendered as a
|
|
76
|
+
* TitleNavButton. The segments are hardcoded in this component and only rendered
|
|
77
|
+
* if an `template` object is provided.
|
|
78
|
+
*
|
|
79
|
+
* @component
|
|
80
|
+
* @param {Object} props - The component properties.
|
|
81
|
+
* @param {Object} props.template - The template entity object that provides context for the page.
|
|
82
|
+
* @param {string|number} props.template.id - The unique identifier for the template.
|
|
83
|
+
* @param {Function} props.onSearchChange - Callback function to handle changes in the search input.
|
|
84
|
+
*
|
|
85
|
+
* @returns {JSX.Element} The rendered TemplatePageNavbar component.
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* // Example usage:
|
|
89
|
+
* const template = { id: 123, ... };
|
|
90
|
+
* <TemplatePageNavbar template={template} onSearchChange={handleSearchChange} />
|
|
91
|
+
*/
|
|
92
|
+
// export const PageNavbar = ({ item, children, onSearchChange }) => {
|
|
93
|
+
// // const [currentHash, setHash] = useHash(); // Use the custom hook to manage hash
|
|
94
|
+
// const currentHash = "da"
|
|
95
|
+
// return (
|
|
96
|
+
// <div className='screen-only'>
|
|
97
|
+
// <MyNavbar onSearchChange={onSearchChange} >
|
|
98
|
+
// {item && TemplatePageSegments.map(({ segment, label }) => (
|
|
99
|
+
// <Nav.Item key={segment} >
|
|
100
|
+
// <TitleNavButton
|
|
101
|
+
// template={item}
|
|
102
|
+
// segment={segment}
|
|
103
|
+
// label={label}
|
|
104
|
+
// className={segment === currentHash ? "active" : ""} aria-current={segment === currentHash ? "page" : undefined}
|
|
105
|
+
// />
|
|
106
|
+
// </Nav.Item>
|
|
107
|
+
// ))}
|
|
108
|
+
// {children}
|
|
109
|
+
// </MyNavbar>
|
|
110
|
+
// </div>
|
|
111
|
+
// );
|
|
112
|
+
// };
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
export const MyNavDropdown = ({ item }) => {
|
|
116
|
+
const { __typename } = item || {}
|
|
117
|
+
const hasProperType = __typename === "TemplateGQLModel"
|
|
118
|
+
return (
|
|
119
|
+
<NavDropdown title="Skupiny">
|
|
120
|
+
<NavDropdown.Item as={ProxyLink} to={VectorItemsURI}>
|
|
121
|
+
Seznam všech
|
|
122
|
+
</NavDropdown.Item>
|
|
123
|
+
|
|
124
|
+
<NavDropdown.Item as={Link} item={item} action="roles" disabled={!hasProperType}>
|
|
125
|
+
Role<br/><Link item={item} />
|
|
126
|
+
</NavDropdown.Item>
|
|
127
|
+
<NavDropdown.Item as={Link} item={item} action="subgroups" disabled={!hasProperType}>
|
|
128
|
+
Podskupiny<br/><Link item={item} />
|
|
129
|
+
</NavDropdown.Item>
|
|
130
|
+
<NavDropdown.Item as={Link} item={item} action="memberships" disabled={!hasProperType}>
|
|
131
|
+
Členové<br/><Link item={item} />
|
|
132
|
+
</NavDropdown.Item>
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
<NavDropdown.Divider />
|
|
136
|
+
|
|
137
|
+
<NavDropdown.Item
|
|
138
|
+
as={UpdateLink}
|
|
139
|
+
item={item}
|
|
140
|
+
disabled={!hasProperType}
|
|
141
|
+
>
|
|
142
|
+
Upravit<br/><Link item={item} />
|
|
143
|
+
</NavDropdown.Item>
|
|
144
|
+
<NavDropdown.Item
|
|
145
|
+
as={CreateButton}
|
|
146
|
+
item={item}
|
|
147
|
+
disabled={!hasProperType}
|
|
148
|
+
item={{
|
|
149
|
+
group: item,
|
|
150
|
+
groupId: item?.groupId
|
|
151
|
+
}}
|
|
152
|
+
>
|
|
153
|
+
Nové<br/><Link item={item} />
|
|
154
|
+
</NavDropdown.Item>
|
|
155
|
+
|
|
156
|
+
<NavDropdown.Divider />
|
|
157
|
+
<NavDropdown.Item as={ProxyLink} to={`/generic/${item?.__typename}/__def/${item?.id}`} reloadDocument={false}>Definice</NavDropdown.Item >
|
|
158
|
+
</NavDropdown>
|
|
159
|
+
)
|
|
160
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { GeneratedContentBase } from "../../Base/Pages/Page"
|
|
2
|
+
import { ReadItemURI } from "../Components"
|
|
3
|
+
import { ReadAsyncAction } from "../Queries"
|
|
4
|
+
import { PageReadItem } from "./PageReadItem"
|
|
5
|
+
|
|
6
|
+
export const RolesOnURI = ReadItemURI.replace("view", "roleson")
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Základní obálka pro „read“ stránku entity podle `:id` z routy.
|
|
11
|
+
*
|
|
12
|
+
* Využívá `PageItemBase`, který zajistí:
|
|
13
|
+
* - získání `id` z URL (`useParams`)
|
|
14
|
+
* - načtení entity přes `AsyncActionProvider` pomocí `queryAsyncAction`
|
|
15
|
+
* - vložení navigace (`PageNavbar`)
|
|
16
|
+
*
|
|
17
|
+
* Uvnitř provideru vykreslí `ReadWithComponent`, který si vezme načtený `item`
|
|
18
|
+
* z `useGQLEntityContext()` a zobrazí ho v zadané komponentě (defaultně `LargeCard`).
|
|
19
|
+
*
|
|
20
|
+
* @component
|
|
21
|
+
* @param {object} props
|
|
22
|
+
* @param {Function} [props.queryAsyncAction=ReadAsyncAction]
|
|
23
|
+
* Async action (např. thunk) pro načtení entity z backendu/GraphQL dle `id`.
|
|
24
|
+
* @param {Object<string, any>} [props]
|
|
25
|
+
* Další props předané do `ReadWithComponent` (např. `Component`, layout props).
|
|
26
|
+
*
|
|
27
|
+
* @returns {import("react").JSX.Element}
|
|
28
|
+
*/
|
|
29
|
+
export const PagePlan = ({
|
|
30
|
+
queryAsyncAction=ReadAsyncAction,
|
|
31
|
+
children,
|
|
32
|
+
...props
|
|
33
|
+
}) => {
|
|
34
|
+
return (
|
|
35
|
+
<PageReadItem
|
|
36
|
+
queryAsyncAction={queryAsyncAction}
|
|
37
|
+
SubPage={GeneratedContentBase}
|
|
38
|
+
{...props}
|
|
39
|
+
/>
|
|
40
|
+
)
|
|
41
|
+
}
|
|
42
|
+
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { GeneratedContentBase } from "../../../../_template/src/Base/Pages/Page"
|
|
2
|
+
import { PageItemBase } from "./PageBase"
|
|
3
|
+
|
|
4
|
+
export const PageReadItem = ({
|
|
5
|
+
SubPage=GeneratedContentBase,
|
|
6
|
+
...props
|
|
7
|
+
}) => {
|
|
8
|
+
return (
|
|
9
|
+
<PageItemBase SubPage={SubPage} {...props}/>
|
|
10
|
+
)
|
|
11
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { GeneratedContentBase } from "../../../../_template/src/Base/Pages/Page"
|
|
2
|
+
import { ReadItemURI } from "../Components"
|
|
3
|
+
import { ReadAsyncAction } from "../Queries"
|
|
4
|
+
import { PageReadItem } from "./PageReadItem"
|
|
5
|
+
|
|
6
|
+
export const RolesOnURI = ReadItemURI.replace("view", "roleson")
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Základní obálka pro „read“ stránku entity podle `:id` z routy.
|
|
11
|
+
*
|
|
12
|
+
* Využívá `PageItemBase`, který zajistí:
|
|
13
|
+
* - získání `id` z URL (`useParams`)
|
|
14
|
+
* - načtení entity přes `AsyncActionProvider` pomocí `queryAsyncAction`
|
|
15
|
+
* - vložení navigace (`PageNavbar`)
|
|
16
|
+
*
|
|
17
|
+
* Uvnitř provideru vykreslí `ReadWithComponent`, který si vezme načtený `item`
|
|
18
|
+
* z `useGQLEntityContext()` a zobrazí ho v zadané komponentě (defaultně `LargeCard`).
|
|
19
|
+
*
|
|
20
|
+
* @component
|
|
21
|
+
* @param {object} props
|
|
22
|
+
* @param {Function} [props.queryAsyncAction=ReadAsyncAction]
|
|
23
|
+
* Async action (např. thunk) pro načtení entity z backendu/GraphQL dle `id`.
|
|
24
|
+
* @param {Object<string, any>} [props]
|
|
25
|
+
* Další props předané do `ReadWithComponent` (např. `Component`, layout props).
|
|
26
|
+
*
|
|
27
|
+
* @returns {import("react").JSX.Element}
|
|
28
|
+
*/
|
|
29
|
+
export const PageReadItemRolesOn = ({
|
|
30
|
+
queryAsyncAction=ReadAsyncAction,
|
|
31
|
+
children,
|
|
32
|
+
...props
|
|
33
|
+
}) => {
|
|
34
|
+
return (
|
|
35
|
+
<PageReadItem
|
|
36
|
+
queryAsyncAction={queryAsyncAction}
|
|
37
|
+
SubPage={GeneratedContentBase}
|
|
38
|
+
{...props}
|
|
39
|
+
/>
|
|
40
|
+
)
|
|
41
|
+
}
|
|
42
|
+
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { GeneratedContentBase } from "../../Base/Pages/Page"
|
|
2
|
+
import { ReadItemURI } from "../Components"
|
|
3
|
+
import { ReadAsyncAction } from "../Queries"
|
|
4
|
+
import { ReadSubEventsAsyncAction } from "../Queries/ReadSubEventsAsyncAction"
|
|
5
|
+
import { PageReadItem } from "./PageReadItem"
|
|
6
|
+
|
|
7
|
+
export const SubEventsURI = ReadItemURI.replace("view", "subevents")
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Základní obálka pro „read“ stránku entity podle `:id` z routy.
|
|
12
|
+
*
|
|
13
|
+
* Využívá `PageItemBase`, který zajistí:
|
|
14
|
+
* - získání `id` z URL (`useParams`)
|
|
15
|
+
* - načtení entity přes `AsyncActionProvider` pomocí `queryAsyncAction`
|
|
16
|
+
* - vložení navigace (`PageNavbar`)
|
|
17
|
+
*
|
|
18
|
+
* Uvnitř provideru vykreslí `ReadWithComponent`, který si vezme načtený `item`
|
|
19
|
+
* z `useGQLEntityContext()` a zobrazí ho v zadané komponentě (defaultně `LargeCard`).
|
|
20
|
+
*
|
|
21
|
+
* @component
|
|
22
|
+
* @param {object} props
|
|
23
|
+
* @param {Function} [props.queryAsyncAction=ReadAsyncAction]
|
|
24
|
+
* Async action (např. thunk) pro načtení entity z backendu/GraphQL dle `id`.
|
|
25
|
+
* @param {Object<string, any>} [props]
|
|
26
|
+
* Další props předané do `ReadWithComponent` (např. `Component`, layout props).
|
|
27
|
+
*
|
|
28
|
+
* @returns {import("react").JSX.Element}
|
|
29
|
+
*/
|
|
30
|
+
export const PageSubevents = ({
|
|
31
|
+
queryAsyncAction=ReadSubEventsAsyncAction,
|
|
32
|
+
children,
|
|
33
|
+
...props
|
|
34
|
+
}) => {
|
|
35
|
+
return (
|
|
36
|
+
<PageReadItem
|
|
37
|
+
queryAsyncAction={queryAsyncAction}
|
|
38
|
+
SubPage={GeneratedContentBase}
|
|
39
|
+
{...props}
|
|
40
|
+
/>
|
|
41
|
+
)
|
|
42
|
+
}
|
|
43
|
+
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
|
|
2
|
+
import { ReadPageAsyncAction } from "../Queries"
|
|
3
|
+
import { useInfiniteScroll } from "../../../../dynamic/src/Hooks/useInfiniteScroll"
|
|
4
|
+
import { PageBase } from "./PageBase"
|
|
5
|
+
import { Table } from "../Components/Table"
|
|
6
|
+
import { Filter } from "../Components/Filter"
|
|
7
|
+
import { FilterButton, ResetFilterButton } from "../../../../_template/src/Base/FormControls/Filter"
|
|
8
|
+
import { useSearchParams } from "react-router"
|
|
9
|
+
import { useEffect } from "react"
|
|
10
|
+
import { useMemo } from "react"
|
|
11
|
+
import { AsyncStateIndicator } from "../../../../_template/src/Base/Helpers/AsyncStateIndicator"
|
|
12
|
+
import { Collapsible } from "../../../../_template/src/Base/FormControls/Collapsible"
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
function safeParseWhere(sp, paramName = "where") {
|
|
16
|
+
const raw = sp.get(paramName);
|
|
17
|
+
if (!raw) return null;
|
|
18
|
+
try {
|
|
19
|
+
const obj = JSON.parse(raw);
|
|
20
|
+
return obj && typeof obj === "object" ? obj : null;
|
|
21
|
+
} catch {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
//
|
|
27
|
+
const filterParameterName = "gr_where"
|
|
28
|
+
export const PageVector = ({ children, queryAsyncAction = ReadPageAsyncAction }) => {
|
|
29
|
+
|
|
30
|
+
const [sp] = useSearchParams();
|
|
31
|
+
|
|
32
|
+
const whereFromUrl = useMemo(() => safeParseWhere(sp, filterParameterName), [sp.toString()]);
|
|
33
|
+
|
|
34
|
+
const { items, loading, error, hasMore, sentinelRef, loadMore, restart } = useInfiniteScroll(
|
|
35
|
+
{
|
|
36
|
+
asyncAction: queryAsyncAction,
|
|
37
|
+
actionParams: { skip: 0, limit: 25, where: whereFromUrl },
|
|
38
|
+
// reset: whereFromUrl
|
|
39
|
+
}
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
useEffect(() => {
|
|
43
|
+
const params = {skip: 0, limit: 25, where: whereFromUrl}
|
|
44
|
+
restart(params)
|
|
45
|
+
}, [whereFromUrl]);
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
return (
|
|
49
|
+
<PageBase>
|
|
50
|
+
<Collapsible
|
|
51
|
+
className="form-control btn btn-outline-primary"
|
|
52
|
+
buttonLabelCollapsed="Zobrazit filtr"
|
|
53
|
+
buttonLabelExpanded="Skrýt filtr"
|
|
54
|
+
>
|
|
55
|
+
<Filter>
|
|
56
|
+
<FilterButton
|
|
57
|
+
className="form-control btn btn-outline-success"
|
|
58
|
+
paramName={filterParameterName}
|
|
59
|
+
>
|
|
60
|
+
Filtrovat
|
|
61
|
+
</FilterButton>
|
|
62
|
+
<ResetFilterButton
|
|
63
|
+
className="form-control btn btn-warning"
|
|
64
|
+
paramName={filterParameterName}
|
|
65
|
+
>
|
|
66
|
+
Vymazat filtr
|
|
67
|
+
</ResetFilterButton>
|
|
68
|
+
</Filter>
|
|
69
|
+
</Collapsible>
|
|
70
|
+
|
|
71
|
+
<Table data={items} />
|
|
72
|
+
|
|
73
|
+
<AsyncStateIndicator error={error} loading={loading} text="Nahrávám další..." />
|
|
74
|
+
|
|
75
|
+
{hasMore && <div ref={sentinelRef} style={{ height: 80, backgroundColor: "lightgray" }} />}
|
|
76
|
+
{hasMore && <button className="btn btn-success form-control" onClick={() => loadMore()}>Více</button>}
|
|
77
|
+
</PageBase>
|
|
78
|
+
)
|
|
79
|
+
}
|
|
80
|
+
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { PageVector } from "./PageVector"
|
|
2
|
+
import { PageUpdateItem } from "./PageUpdateItem"
|
|
3
|
+
import { PageCreateItem } from "./PageCreateItem"
|
|
4
|
+
import { PageReadItem } from "./PageReadItem"
|
|
5
|
+
import { PageDeleteItem } from "./PageDeleteItem"
|
|
6
|
+
import { PagePlan } from "./PagePlan"
|
|
7
|
+
|
|
8
|
+
import { DeleteItemURI, UpdateItemURI } from "../Components"
|
|
9
|
+
import { CreateURI, ReadItemURI, VectorItemsURI, PlanItemURI } from "../Components"
|
|
10
|
+
import { PageSubevents, SubEventsURI } from "./PageSubevents"
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Definice segmentů rout pro Event stránky.
|
|
14
|
+
*
|
|
15
|
+
* Každý objekt v tomto poli popisuje jednu trasu (route) v aplikaci:
|
|
16
|
+
* - `path`: Stringová URL s parametrem `:id`, která identifikuje konkrétní instanci event entity.
|
|
17
|
+
* - `element`: React komponenta, která se má renderovat při shodě s cestou.
|
|
18
|
+
*
|
|
19
|
+
* Pokud komponenta stránky podporuje children jako render funkci,
|
|
20
|
+
* všechny children předané přes router budou dostávat objekt:
|
|
21
|
+
* - `event` — načtená entita podle `:id`
|
|
22
|
+
* - `onChange` — callback pro změnu hodnoty pole
|
|
23
|
+
* - `onBlur` — callback pro blur event (například při opuštění pole)
|
|
24
|
+
*
|
|
25
|
+
* @constant
|
|
26
|
+
* @type {Array<{ path: string, element: JSX.Element }>}
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* // Tato route reaguje na URL jako "/event/123"
|
|
30
|
+
* {
|
|
31
|
+
* path: "/event/:id",
|
|
32
|
+
* element: <EventPage />
|
|
33
|
+
* }
|
|
34
|
+
*
|
|
35
|
+
* // Editační route: "/event/edit/123"
|
|
36
|
+
* {
|
|
37
|
+
* path: "/event/edit/:id",
|
|
38
|
+
* element: <EventEditPage />
|
|
39
|
+
* }
|
|
40
|
+
*/
|
|
41
|
+
export const EventRouterSegments = [
|
|
42
|
+
{
|
|
43
|
+
path: CreateURI,
|
|
44
|
+
element: (<PageCreateItem />),
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
path: VectorItemsURI,
|
|
48
|
+
element: (<PageVector />),
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
path: ReadItemURI,
|
|
52
|
+
element: (<PageReadItem />),
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
path: PlanItemURI,
|
|
56
|
+
element: (<PagePlan />),
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
path: UpdateItemURI,
|
|
60
|
+
element: (<PageUpdateItem />),
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
path: DeleteItemURI,
|
|
64
|
+
element: (<PageDeleteItem />),
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
path: SubEventsURI,
|
|
68
|
+
element: (<PageSubevents />),
|
|
69
|
+
},
|
|
70
|
+
// {
|
|
71
|
+
// path: "sad",
|
|
72
|
+
// element: (<PageReadItemRolesOn />)
|
|
73
|
+
// },
|
|
74
|
+
{
|
|
75
|
+
path: VectorItemsURI.replace("list", ":any"),
|
|
76
|
+
element: (<PageVector />),
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
path: ReadItemURI.replace("view", ":any"),
|
|
80
|
+
element: (<PageReadItem />),
|
|
81
|
+
}
|
|
82
|
+
]
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { createQueryStrLazy } from "@hrbolek/uoisfrontend-gql-shared";
|
|
2
|
+
import { LargeFragment } from "./Fragments";
|
|
3
|
+
import { createAsyncGraphQLAction2 } from "../../../../dynamic/src/Core/createAsyncGraphQLAction2";
|
|
4
|
+
|
|
5
|
+
const DeleteMutationStr = `
|
|
6
|
+
mutation roleTypeDelete(
|
|
7
|
+
$id: UUID! # null,
|
|
8
|
+
$lastchange: DateTime! # null
|
|
9
|
+
) {
|
|
10
|
+
roleTypeDelete(
|
|
11
|
+
roleType: {
|
|
12
|
+
id: $id,
|
|
13
|
+
lastchange: $lastchange}
|
|
14
|
+
) {
|
|
15
|
+
...RoleTypeGQLModelDeleteError
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
fragment RoleTypeGQLModelDeleteError on RoleTypeGQLModelDeleteError {
|
|
20
|
+
__typename
|
|
21
|
+
Entity {
|
|
22
|
+
...Large
|
|
23
|
+
}
|
|
24
|
+
msg
|
|
25
|
+
code
|
|
26
|
+
failed
|
|
27
|
+
location
|
|
28
|
+
input
|
|
29
|
+
}
|
|
30
|
+
`
|
|
31
|
+
const DeleteMutation = createQueryStrLazy(`${DeleteMutationStr}`, LargeFragment)
|
|
32
|
+
export const DeleteAsyncAction = createAsyncGraphQLAction2(DeleteMutation)
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { createQueryStrLazy } from "@hrbolek/uoisfrontend-gql-shared"
|
|
2
|
+
|
|
3
|
+
const LinkFragmentStr = `
|
|
4
|
+
fragment Link on EventGQLModel {
|
|
5
|
+
__typename
|
|
6
|
+
id
|
|
7
|
+
lastchange
|
|
8
|
+
created
|
|
9
|
+
createdbyId
|
|
10
|
+
changedbyId
|
|
11
|
+
rbacobjectId
|
|
12
|
+
path
|
|
13
|
+
name
|
|
14
|
+
nameEn
|
|
15
|
+
description
|
|
16
|
+
startdate
|
|
17
|
+
enddate
|
|
18
|
+
duration_raw
|
|
19
|
+
valid
|
|
20
|
+
place
|
|
21
|
+
facilityId
|
|
22
|
+
mastereventId
|
|
23
|
+
facility {
|
|
24
|
+
__typename
|
|
25
|
+
id
|
|
26
|
+
name
|
|
27
|
+
}
|
|
28
|
+
typeId
|
|
29
|
+
type {
|
|
30
|
+
__typename
|
|
31
|
+
id
|
|
32
|
+
lastchange
|
|
33
|
+
name
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
`
|
|
37
|
+
|
|
38
|
+
const MediumFragmentStr = `
|
|
39
|
+
fragment Medium on EventGQLModel {
|
|
40
|
+
...Link
|
|
41
|
+
|
|
42
|
+
rbacobject {
|
|
43
|
+
...RBRoles
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
`
|
|
47
|
+
|
|
48
|
+
const LargeFragmentStr = `
|
|
49
|
+
fragment Large on EventGQLModel {
|
|
50
|
+
...Medium
|
|
51
|
+
subevents { ...Link }
|
|
52
|
+
}
|
|
53
|
+
`
|
|
54
|
+
|
|
55
|
+
const RoleFragmentStr = `
|
|
56
|
+
fragment Role on RoleGQLModel {
|
|
57
|
+
__typename
|
|
58
|
+
id
|
|
59
|
+
lastchange
|
|
60
|
+
created
|
|
61
|
+
createdbyId
|
|
62
|
+
changedbyId
|
|
63
|
+
rbacobjectId
|
|
64
|
+
createdby { id __typename }
|
|
65
|
+
changedby { id __typename }
|
|
66
|
+
rbacobject { id __typename }
|
|
67
|
+
valid
|
|
68
|
+
deputy
|
|
69
|
+
startdate
|
|
70
|
+
enddate
|
|
71
|
+
roletypeId
|
|
72
|
+
userId
|
|
73
|
+
groupId
|
|
74
|
+
roletype { __typename id }
|
|
75
|
+
user { __typename id fullname }
|
|
76
|
+
group { __typename id name }
|
|
77
|
+
}
|
|
78
|
+
`
|
|
79
|
+
|
|
80
|
+
const RBACFragmentStr = `
|
|
81
|
+
fragment RBRoles on RBACObjectGQLModel {
|
|
82
|
+
__typename
|
|
83
|
+
id
|
|
84
|
+
currentUserRoles {
|
|
85
|
+
__typename
|
|
86
|
+
id
|
|
87
|
+
lastchange
|
|
88
|
+
valid
|
|
89
|
+
startdate
|
|
90
|
+
enddate
|
|
91
|
+
roletype {
|
|
92
|
+
__typename
|
|
93
|
+
id
|
|
94
|
+
name
|
|
95
|
+
}
|
|
96
|
+
group {
|
|
97
|
+
__typename
|
|
98
|
+
id
|
|
99
|
+
name
|
|
100
|
+
grouptype {
|
|
101
|
+
__typename
|
|
102
|
+
id
|
|
103
|
+
name
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}`
|
|
108
|
+
|
|
109
|
+
const SubEventsFragmentStr = `
|
|
110
|
+
fragment SubEvents on EventGQLModel {
|
|
111
|
+
...Medium
|
|
112
|
+
subevents(limit: $limit, skip: $skip, where: $where, orderby: $orderby) { ...Link }
|
|
113
|
+
}
|
|
114
|
+
`
|
|
115
|
+
|
|
116
|
+
export const RoleFragment = createQueryStrLazy(`${RoleFragmentStr}`)
|
|
117
|
+
export const RBACFragment = createQueryStrLazy(`${RBACFragmentStr}`)
|
|
118
|
+
|
|
119
|
+
export const LinkFragment = createQueryStrLazy(`${LinkFragmentStr}`)
|
|
120
|
+
export const MediumFragment = createQueryStrLazy(`${MediumFragmentStr}`, LinkFragment, RBACFragment)
|
|
121
|
+
export const LargeFragment = createQueryStrLazy(`${LargeFragmentStr}`, MediumFragment)
|
|
122
|
+
export const SubEventsFragment = createQueryStrLazy(`${SubEventsFragmentStr}`, MediumFragment)
|
|
123
|
+
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { createQueryStrLazy } from "@hrbolek/uoisfrontend-gql-shared";
|
|
2
|
+
import { LargeFragment } from "./Fragments";
|
|
3
|
+
import { createAsyncGraphQLAction2 } from "../../../../dynamic/src/Core/createAsyncGraphQLAction2";
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
const InsertMutationStr = `
|
|
7
|
+
mutation roleTypeInsert(
|
|
8
|
+
$mastertypeId: UUID # null,
|
|
9
|
+
$id: UUID # null,
|
|
10
|
+
$name: String # null,
|
|
11
|
+
$nameEn: String # null,
|
|
12
|
+
$subtypes: [RoleTypeInsertGQLModel!] # null
|
|
13
|
+
) {
|
|
14
|
+
roleTypeInsert(
|
|
15
|
+
roleType: {
|
|
16
|
+
mastertypeId: $mastertypeId,
|
|
17
|
+
id: $id,
|
|
18
|
+
name: $name,
|
|
19
|
+
nameEn: $nameEn,
|
|
20
|
+
subtypes: $subtypes}
|
|
21
|
+
) {
|
|
22
|
+
... on InsertError { ...InsertError }
|
|
23
|
+
... on RoleTypeGQLModel { ...Large }
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
fragment InsertError on InsertError {
|
|
29
|
+
__typename
|
|
30
|
+
msg
|
|
31
|
+
failed
|
|
32
|
+
code
|
|
33
|
+
location
|
|
34
|
+
input
|
|
35
|
+
|
|
36
|
+
}
|
|
37
|
+
`
|
|
38
|
+
|
|
39
|
+
const InsertMutation = createQueryStrLazy(`${InsertMutationStr}`, LargeFragment)
|
|
40
|
+
export const InsertAsyncAction = createAsyncGraphQLAction2(InsertMutation)
|