@kaspernj/api-maker 1.0.461 → 1.0.463
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/build/bootstrap/attribute-row.js +3 -2
- package/build/bootstrap/sort-link.js +5 -5
- package/build/cable-subscription-pool.js +3 -3
- package/build/channels-consumer.js +7 -2
- package/build/collection.js +2 -1
- package/build/config.js +8 -2
- package/build/devise.js +9 -6
- package/build/history-expo.js +24 -0
- package/build/history-react-native.js +20 -0
- package/build/inputs/checkbox.js +1 -8
- package/build/link.js +6 -2
- package/build/router.js +2 -2
- package/build/session-status-updater.js +11 -3
- package/build/super-admin/edit-page.js +2 -2
- package/build/super-admin/index.js +2 -2
- package/build/super-admin/layout/header/index.js +23 -14
- package/build/super-admin/layout/index.js +69 -14
- package/build/super-admin/layout/menu/index.js +131 -20
- package/build/super-admin/show-nav.js +2 -2
- package/build/super-admin/show-reflection-page.js +2 -2
- package/build/table/filters/filter.js +3 -3
- package/build/table/filters/index.js +2 -2
- package/build/table/header-column.js +3 -3
- package/build/table/model-row.js +5 -5
- package/build/table/settings/download-action.js +3 -3
- package/build/table/table.js +5 -5
- package/build/table/use-sorting.js +2 -2
- package/build/translated-collections.js +2 -2
- package/build/use-breakpoint.js +20 -2
- package/build/use-collection.js +2 -2
- package/build/use-current-user.js +6 -2
- package/build/use-model.js +2 -2
- package/build/utils/icon.js +23 -0
- package/build/utils/modal.js +3 -3
- package/build/with-api-maker.js +29 -0
- package/package.json +4 -2
- package/src/bootstrap/attribute-row.jsx +2 -1
- package/src/bootstrap/sort-link.jsx +4 -4
- package/src/cable-subscription-pool.js +2 -2
- package/src/channels-consumer.js +7 -1
- package/src/collection.js +1 -0
- package/src/config.js +3 -1
- package/src/devise.js +7 -7
- package/src/history-expo.js +25 -0
- package/src/history-react-native.js +25 -0
- package/src/inputs/checkbox.jsx +0 -4
- package/src/link.jsx +6 -1
- package/src/router.jsx +1 -1
- package/src/session-status-updater.js +12 -2
- package/src/super-admin/edit-page.jsx +1 -1
- package/src/super-admin/index.jsx +1 -1
- package/src/super-admin/layout/header/index.jsx +27 -16
- package/src/super-admin/layout/header/style.scss +0 -11
- package/src/super-admin/layout/index.jsx +61 -15
- package/src/super-admin/layout/menu/index.jsx +124 -40
- package/src/super-admin/layout/menu/style.scss +0 -94
- package/src/super-admin/show-nav.jsx +1 -1
- package/src/super-admin/show-reflection-page.jsx +1 -1
- package/src/table/filters/filter.jsx +2 -2
- package/src/table/filters/index.jsx +1 -1
- package/src/table/header-column.jsx +2 -2
- package/src/table/model-row.jsx +4 -4
- package/src/table/settings/download-action.jsx +2 -2
- package/src/table/table.jsx +4 -4
- package/src/table/use-sorting.js +1 -1
- package/src/translated-collections.js +1 -1
- package/src/use-breakpoint.js +25 -1
- package/src/use-collection.js +1 -1
- package/src/use-current-user.js +5 -2
- package/src/use-model.js +1 -1
- package/src/utils/icon.jsx +21 -0
- package/src/utils/modal.jsx +2 -2
- package/src/with-api-maker.jsx +31 -0
- package/build/history.native.js +0 -10
- package/src/history.native.js +0 -9
- package/src/super-admin/layout/style.scss +0 -25
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import React, {useMemo} from "react"
|
|
2
2
|
import BaseComponent from "../base-component"
|
|
3
3
|
import classNames from "classnames"
|
|
4
|
-
import FontAwesomeIcon from "react-native-vector-icons/FontAwesome"
|
|
5
4
|
import Header from "./components/header"
|
|
6
5
|
import HeaderColumnContent from "./header-column-content"
|
|
6
|
+
import Icon from "../utils/icon"
|
|
7
7
|
import memo from "set-state-compare/src/memo"
|
|
8
8
|
import {Animated, PanResponder} from "react-native"
|
|
9
9
|
import PropTypes from "prop-types"
|
|
@@ -100,7 +100,7 @@ export default memo(shapeComponent(class ApiMakerTableHeaderColumn extends BaseC
|
|
|
100
100
|
{...restColumnProps}
|
|
101
101
|
>
|
|
102
102
|
{mdUp &&
|
|
103
|
-
<
|
|
103
|
+
<Icon name="bars" style={{marginRight: 3, fontSize: 12}} {...touchProps} />
|
|
104
104
|
}
|
|
105
105
|
<HeaderColumnContent column={column} table={table} tableSettingColumn={tableSettingColumn} />
|
|
106
106
|
{mdUp &&
|
package/src/table/model-row.jsx
CHANGED
|
@@ -4,7 +4,7 @@ import Column from "./components/column"
|
|
|
4
4
|
import columnIdentifier from "./column-identifier"
|
|
5
5
|
import EventEmitter from "events"
|
|
6
6
|
import FlashMessage from "../flash-message"
|
|
7
|
-
import
|
|
7
|
+
import Icon from "../utils/icon"
|
|
8
8
|
import * as inflection from "inflection"
|
|
9
9
|
import modelCallbackArgs from "./model-callback-args"
|
|
10
10
|
import Link from "../link"
|
|
@@ -76,17 +76,17 @@ export default memo(shapeComponent(class ApiMakerBootStrapLiveTableModelRow exte
|
|
|
76
76
|
{actionsContent && actionsContent(this.tt.modelCallbackArgs)}
|
|
77
77
|
{viewPath &&
|
|
78
78
|
<Link dataSet={{class: "view-button"}} style={{marginLeft: 2, marginRight: 2}} to={viewPath}>
|
|
79
|
-
<
|
|
79
|
+
<Icon name="search" size={18} />
|
|
80
80
|
</Link>
|
|
81
81
|
}
|
|
82
82
|
{editPath &&
|
|
83
83
|
<Link dataSet={{class: "edit-button"}} style={{marginLeft: 2, marginRight: 2}} to={editPath}>
|
|
84
|
-
<
|
|
84
|
+
<Icon name="pencil" size={20} />
|
|
85
85
|
</Link>
|
|
86
86
|
}
|
|
87
87
|
{destroyEnabled && model.can("destroy") &&
|
|
88
88
|
<Pressable dataSet={{class: "destroy-button"}} style={{marginLeft: 2, marginRight: 2}} onPress={this.tt.onDestroyClicked}>
|
|
89
|
-
<
|
|
89
|
+
<Icon name="remove" size={22} />
|
|
90
90
|
</Pressable>
|
|
91
91
|
}
|
|
92
92
|
</Column>
|
|
@@ -3,7 +3,7 @@ import ColumnContent from "../column-content"
|
|
|
3
3
|
import columnIdentifier from "../column-identifier"
|
|
4
4
|
import columnVisible from "../column-visible"
|
|
5
5
|
import {saveAs} from "file-saver"
|
|
6
|
-
import
|
|
6
|
+
import Icon from "../../utils/icon"
|
|
7
7
|
import memo from "set-state-compare/src/memo"
|
|
8
8
|
import PropTypes from "prop-types"
|
|
9
9
|
import propTypesExact from "prop-types-exact"
|
|
@@ -21,7 +21,7 @@ export default memo(shapeComponent(class ApiMakerTableSettingsDownloadAction ext
|
|
|
21
21
|
render() {
|
|
22
22
|
return (
|
|
23
23
|
<Pressable onPress={this.tt.onDownloadPress} style={{flexDirection: "row", alignItems: "center"}}>
|
|
24
|
-
<
|
|
24
|
+
<Icon name="download" size={20} />
|
|
25
25
|
<Text style={{marginLeft: 5}}>
|
|
26
26
|
Download
|
|
27
27
|
</Text>
|
package/src/table/table.jsx
CHANGED
|
@@ -11,11 +11,11 @@ import DraggableSort from "../draggable-sort/index"
|
|
|
11
11
|
import EventEmitter from "events"
|
|
12
12
|
import Filters from "./filters"
|
|
13
13
|
import FlatList from "./components/flat-list"
|
|
14
|
-
import FontAwesomeIcon from "react-native-vector-icons/FontAwesome"
|
|
15
14
|
import {Form} from "../form"
|
|
16
15
|
import Header from "./components/header"
|
|
17
16
|
import HeaderColumn from "./header-column"
|
|
18
17
|
import HeaderSelect from "./header-select"
|
|
18
|
+
import Icon from "../utils/icon"
|
|
19
19
|
import * as inflection from "inflection"
|
|
20
20
|
import memo from "set-state-compare/src/memo"
|
|
21
21
|
import modelClassRequire from "../model-class-require"
|
|
@@ -36,7 +36,7 @@ import useCollection from "../use-collection"
|
|
|
36
36
|
import useI18n from "i18n-on-steroids/src/use-i18n"
|
|
37
37
|
import useEventEmitter from "../use-event-emitter"
|
|
38
38
|
import useModelEvent from "../use-model-event"
|
|
39
|
-
import useQueryParams from "on-location-changed/
|
|
39
|
+
import useQueryParams from "on-location-changed/build/use-query-params"
|
|
40
40
|
import Widths from "./widths"
|
|
41
41
|
|
|
42
42
|
const paginationOptions = [30, 60, 90, ["All", "all"]]
|
|
@@ -732,14 +732,14 @@ export default memo(shapeComponent(class ApiMakerTable extends BaseComponent {
|
|
|
732
732
|
<View style={{flexDirection: "row"}}>
|
|
733
733
|
{controls && controls({models, qParams, query, result})}
|
|
734
734
|
<Pressable dataSet={{class: "filter-button"}} onPress={this.tt.onFilterClicked}>
|
|
735
|
-
<
|
|
735
|
+
<Icon name="search" size={20} />
|
|
736
736
|
</Pressable>
|
|
737
737
|
<View style={{position: "relative"}}>
|
|
738
738
|
{showSettings &&
|
|
739
739
|
<Settings onRequestClose={this.tt.onRequestCloseSettings} table={this} />
|
|
740
740
|
}
|
|
741
741
|
<Pressable dataSet={{class: "settings-button"}} onPress={this.tt.onSettingsClicked}>
|
|
742
|
-
<
|
|
742
|
+
<Icon name="gear" size={20} />
|
|
743
743
|
</Pressable>
|
|
744
744
|
</View>
|
|
745
745
|
</View>
|
package/src/table/use-sorting.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {camelize} from "inflection"
|
|
2
|
-
import useQueryParams from "on-location-changed/
|
|
2
|
+
import useQueryParams from "on-location-changed/build/use-query-params"
|
|
3
3
|
|
|
4
4
|
const calculateQParams = (defaultParams, queryParams, searchKey) => {
|
|
5
5
|
if (searchKey in queryParams) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {digg} from "diggerize"
|
|
2
2
|
import I18nOnSteroids from "i18n-on-steroids"
|
|
3
|
-
import translatedCollectionsData from "
|
|
3
|
+
import translatedCollectionsData from "translated-collections-data.json"
|
|
4
4
|
|
|
5
5
|
export default class ApiMakerTranslatedCollections {
|
|
6
6
|
static get (modelClass, collectionName) {
|
package/src/use-breakpoint.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {useCallback, useLayoutEffect} from "react"
|
|
2
2
|
import apiMakerConfig from "@kaspernj/api-maker/build/config"
|
|
3
3
|
import {Dimensions} from "react-native"
|
|
4
|
+
import * as inflection from "inflection"
|
|
4
5
|
import useShape from "set-state-compare/src/use-shape"
|
|
5
6
|
|
|
6
7
|
const calculateBreakPoint = (window) => {
|
|
@@ -26,6 +27,8 @@ const calculateBreakPoint = (window) => {
|
|
|
26
27
|
throw new Error(`Couldn't not find breakpoint from window width: ${windowWidth}`)
|
|
27
28
|
}
|
|
28
29
|
|
|
30
|
+
const sizeTypes = ["down", "up"]
|
|
31
|
+
|
|
29
32
|
const useBreakpoint = () => {
|
|
30
33
|
const s = useShape()
|
|
31
34
|
const onCalled = useCallback(({window}) => {
|
|
@@ -40,13 +43,34 @@ const useBreakpoint = () => {
|
|
|
40
43
|
breakpoint: () => calculateBreakPoint(Dimensions.get("window"))
|
|
41
44
|
})
|
|
42
45
|
|
|
46
|
+
const styling = useCallback((args) => {
|
|
47
|
+
const style = Object.assign({}, args.base)
|
|
48
|
+
|
|
49
|
+
for (const breakpointData of apiMakerConfig.getBreakPoints()) {
|
|
50
|
+
const breakpoint = breakpointData[0]
|
|
51
|
+
|
|
52
|
+
for (const sizeType of sizeTypes) {
|
|
53
|
+
const breakpointWithSizeType = `${breakpoint}${inflection.camelize(sizeType)}`
|
|
54
|
+
|
|
55
|
+
if (args[breakpointWithSizeType] && s.s.breakpoint[breakpointWithSizeType]) {
|
|
56
|
+
Object.assign(style, args[breakpointWithSizeType])
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return style
|
|
62
|
+
}, [])
|
|
63
|
+
|
|
43
64
|
useLayoutEffect(() => {
|
|
44
65
|
const subscription = Dimensions.addEventListener("change", onCalled)
|
|
45
66
|
|
|
46
67
|
return () => subscription?.remove()
|
|
47
68
|
})
|
|
48
69
|
|
|
49
|
-
return
|
|
70
|
+
return {
|
|
71
|
+
styling,
|
|
72
|
+
...s.s.breakpoint
|
|
73
|
+
}
|
|
50
74
|
}
|
|
51
75
|
|
|
52
76
|
export default useBreakpoint
|
package/src/use-collection.js
CHANGED
|
@@ -5,7 +5,7 @@ import ModelEvents from "./model-events"
|
|
|
5
5
|
import {useCallback, useLayoutEffect, useMemo} from "react"
|
|
6
6
|
import useCreatedEvent from "./use-created-event"
|
|
7
7
|
import useShape from "set-state-compare/src/use-shape"
|
|
8
|
-
import useQueryParams from "on-location-changed/
|
|
8
|
+
import useQueryParams from "on-location-changed/build/use-query-params"
|
|
9
9
|
|
|
10
10
|
const useCollection = (props, cacheKeys = []) => {
|
|
11
11
|
const {
|
package/src/use-current-user.js
CHANGED
|
@@ -2,6 +2,7 @@ import {useCallback, useMemo} from "react"
|
|
|
2
2
|
import {camelize} from "inflection"
|
|
3
3
|
import Devise from "./devise"
|
|
4
4
|
import {digg} from "diggerize"
|
|
5
|
+
import * as inflection from "inflection"
|
|
5
6
|
import Logger from "./logger"
|
|
6
7
|
import Services from "./services"
|
|
7
8
|
import useEventEmitter from "./use-event-emitter"
|
|
@@ -21,11 +22,13 @@ const useCurrentUser = (args) => {
|
|
|
21
22
|
|
|
22
23
|
const loadCurrentUserFromRequest = useCallback(async () => {
|
|
23
24
|
const {scope, scopeName} = s.m
|
|
25
|
+
const getArgsMethodName = `get${inflection.camelize(scope)}Args`
|
|
26
|
+
const args = Devise[getArgsMethodName]()
|
|
24
27
|
|
|
25
28
|
logger.debug(() => `Loading ${scope} with request`)
|
|
26
29
|
|
|
27
|
-
const result = await Services.current().sendRequest("Devise::Current", {scope})
|
|
28
|
-
const current = digg(result, "current")
|
|
30
|
+
const result = await Services.current().sendRequest("Devise::Current", {query: args.query, scope})
|
|
31
|
+
const current = digg(result, "current")[0]
|
|
29
32
|
|
|
30
33
|
if (!(scopeName in s.setStates)) throw new Error(`'${scopeName}' not found in setStates`)
|
|
31
34
|
if (current) Devise.updateSession(current)
|
package/src/use-model.js
CHANGED
|
@@ -2,7 +2,7 @@ import {useCallback, useLayoutEffect, useMemo} from "react"
|
|
|
2
2
|
import Devise from "./devise"
|
|
3
3
|
import * as inflection from "inflection"
|
|
4
4
|
import ModelEvents from "./model-events"
|
|
5
|
-
import useQueryParams from "on-location-changed/
|
|
5
|
+
import useQueryParams from "on-location-changed/build/use-query-params"
|
|
6
6
|
import useShape from "set-state-compare/src/use-shape"
|
|
7
7
|
|
|
8
8
|
const useModel = (modelClassArg, argsArg = {}) => {
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import BaseComponent from "../base-component"
|
|
2
|
+
import FontAwesomeIcon from "react-native-vector-icons/FontAwesome"
|
|
3
|
+
import memo from "set-state-compare/src/memo"
|
|
4
|
+
import React from "react"
|
|
5
|
+
import {shapeComponent} from "set-state-compare/src/shape-component"
|
|
6
|
+
import {useDefaultStyle} from "./default-style"
|
|
7
|
+
|
|
8
|
+
export default memo(shapeComponent(class ApiMakerUtilsIcon extends BaseComponent {
|
|
9
|
+
render() {
|
|
10
|
+
const defaultStyle = useDefaultStyle()
|
|
11
|
+
const {style, ...restProps} = this.props
|
|
12
|
+
const actualStyle = Object.assign(
|
|
13
|
+
{color: defaultStyle.Text.color},
|
|
14
|
+
style
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
return (
|
|
18
|
+
<FontAwesomeIcon style={actualStyle} {...restProps} />
|
|
19
|
+
)
|
|
20
|
+
}
|
|
21
|
+
}))
|
package/src/utils/modal.jsx
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {Modal, Pressable, View} from "react-native"
|
|
2
2
|
import BaseComponent from "../base-component"
|
|
3
3
|
import Card from "./card"
|
|
4
|
-
import
|
|
4
|
+
import Icon from "../utils/icon"
|
|
5
5
|
import memo from "set-state-compare/src/memo"
|
|
6
6
|
import {shapeComponent} from "set-state-compare/src/shape-component"
|
|
7
7
|
import useBreakpoint from "../use-breakpoint"
|
|
@@ -50,7 +50,7 @@ export default memo(shapeComponent(class ApiMakerUtilsComponent extends BaseComp
|
|
|
50
50
|
cardHeaderControls() {
|
|
51
51
|
return (
|
|
52
52
|
<Pressable onPress={this.tt.onModalClosePress} style={{marginLeft: "auto", padding: 5}}>
|
|
53
|
-
<
|
|
53
|
+
<Icon name="remove" />
|
|
54
54
|
</Pressable>
|
|
55
55
|
)
|
|
56
56
|
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import React, {createContext, useContext, useMemo} from "react"
|
|
2
|
+
import ApiMakerConfig from "./config"
|
|
3
|
+
import memo from "set-state-compare/src/memo"
|
|
4
|
+
|
|
5
|
+
const ApiMakerContext = createContext()
|
|
6
|
+
const useApiMaker = () => {
|
|
7
|
+
const apiMakerContext = useContext(ApiMakerContext)
|
|
8
|
+
|
|
9
|
+
if (apiMakerContext) {
|
|
10
|
+
return apiMakerContext
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
return {
|
|
14
|
+
config: ApiMakerConfig
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const WithApiMaker = memo(({children, config, ...restProps}) => {
|
|
19
|
+
const restPropsKeys = Object.keys(restProps)
|
|
20
|
+
const value = useMemo(() => ({config}), [config])
|
|
21
|
+
|
|
22
|
+
if (restPropsKeys.length > 0) throw new Error(`Unhandled props: ${restPropsKeys.join(", ")}`)
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<ApiMakerContext.Provider value={value}>
|
|
26
|
+
{children}
|
|
27
|
+
</ApiMakerContext.Provider>
|
|
28
|
+
)
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
export {useApiMaker, WithApiMaker}
|
package/build/history.native.js
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
class HistoryNative {
|
|
2
|
-
push(...args) {
|
|
3
|
-
throw new Error("Stub: Push from history.nativejs", {
|
|
4
|
-
args
|
|
5
|
-
});
|
|
6
|
-
}
|
|
7
|
-
}
|
|
8
|
-
const historyNative = new HistoryNative();
|
|
9
|
-
export default historyNative;
|
|
10
|
-
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJIaXN0b3J5TmF0aXZlIiwicHVzaCIsImFyZ3MiLCJFcnJvciIsImhpc3RvcnlOYXRpdmUiXSwic291cmNlcyI6WyIuLi9zcmMvaGlzdG9yeS5uYXRpdmUuanMiXSwic291cmNlc0NvbnRlbnQiOlsiY2xhc3MgSGlzdG9yeU5hdGl2ZSB7XG4gIHB1c2goLi4uYXJncykge1xuICAgIHRocm93IG5ldyBFcnJvcihcIlN0dWI6IFB1c2ggZnJvbSBoaXN0b3J5Lm5hdGl2ZWpzXCIsIHthcmdzfSlcbiAgfVxufVxuXG5jb25zdCBoaXN0b3J5TmF0aXZlID0gbmV3IEhpc3RvcnlOYXRpdmUoKVxuXG5leHBvcnQgZGVmYXVsdCBoaXN0b3J5TmF0aXZlXG4iXSwibWFwcGluZ3MiOiJBQUFBLE1BQU1BLGFBQWEsQ0FBQztFQUNsQkMsSUFBSUEsQ0FBQyxHQUFHQyxJQUFJLEVBQUU7SUFDWixNQUFNLElBQUlDLEtBQUssQ0FBQyxrQ0FBa0MsRUFBRTtNQUFDRDtJQUFJLENBQUMsQ0FBQztFQUM3RDtBQUNGO0FBRUEsTUFBTUUsYUFBYSxHQUFHLElBQUlKLGFBQWEsQ0FBQyxDQUFDO0FBRXpDLGVBQWVJLGFBQWEiLCJpZ25vcmVMaXN0IjpbXX0=
|
package/src/history.native.js
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
@use "@kaspernj/api-maker/src/super-admin/stylesheets/variables" as *;
|
|
2
|
-
|
|
3
|
-
[data-component="super-admin--layout"] {
|
|
4
|
-
width: 100%;
|
|
5
|
-
min-height: 100vh;
|
|
6
|
-
background: #fff;
|
|
7
|
-
color: #000;
|
|
8
|
-
|
|
9
|
-
[data-class="app-layout-content-container"] {
|
|
10
|
-
min-height: 100vh;
|
|
11
|
-
background: #f7f7f7;
|
|
12
|
-
|
|
13
|
-
@media (max-width: $sm-to) {
|
|
14
|
-
padding: 130px 30px 30px;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
@media (min-width: $md-from) {
|
|
18
|
-
padding: 130px 30px 30px 280px;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
@media (min-width: $lg-from) {
|
|
22
|
-
padding: 130px 30px 30px 320px;
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
}
|