@kaspernj/api-maker 1.0.318 → 1.0.320

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/package.json CHANGED
@@ -16,7 +16,7 @@
16
16
  ]
17
17
  },
18
18
  "name": "@kaspernj/api-maker",
19
- "version": "1.0.318",
19
+ "version": "1.0.320",
20
20
  "type": "module",
21
21
  "description": "",
22
22
  "main": "index.js",
@@ -52,7 +52,7 @@
52
52
  "on-location-changed": ">= 1.0.8",
53
53
  "qs": ">= 6.9.3",
54
54
  "replaceall": ">= 0.1.6",
55
- "set-state-compare": ">= 1.0.26",
55
+ "set-state-compare": ">= 1.0.28",
56
56
  "spark-md5": "^3.0.2",
57
57
  "strftime": ">= 0.10.0",
58
58
  "uniqunize": "^1.0.1",
package/src/can-can.mjs CHANGED
@@ -81,6 +81,9 @@ export default class ApiMakerCanCan {
81
81
  for (const abilityData of abilities) {
82
82
  const subject = abilityData[0]
83
83
 
84
+ if (!subject) throw new Error(`Invalid subject given in abilities: ${subject} - ${JSON.stringify(abilities)}`)
85
+ if (!Array.isArray(abilityData[1])) throw new Error(`Expected an array of abilities but got: ${typeof abilityData[1]}: ${abilityData[1]}`)
86
+
84
87
  for (const ability of abilityData[1]) {
85
88
  const promise = this.loadAbility(ability, subject)
86
89
 
@@ -119,7 +122,7 @@ export default class ApiMakerCanCan {
119
122
  clearTimeout(this.queueAbilitiesRequestTimeout)
120
123
  }
121
124
 
122
- this.queueAbilitiesRequestTimeout = setTimeout(() => this.sendAbilitiesRequest(), 0)
125
+ this.queueAbilitiesRequestTimeout = setTimeout(this.sendAbilitiesRequest, 0)
123
126
  }
124
127
 
125
128
  async resetAbilities () {
@@ -129,7 +132,7 @@ export default class ApiMakerCanCan {
129
132
  this.events.emit("onResetAbilities")
130
133
  }
131
134
 
132
- async sendAbilitiesRequest () {
135
+ sendAbilitiesRequest = async () => {
133
136
  const abilitiesToLoad = this.abilitiesToLoad
134
137
  const abilitiesToLoadData = this.abilitiesToLoadData
135
138
 
@@ -20,7 +20,13 @@ const ApiMakerSuperAdmin = () => {
20
20
  const modelId = queryParams.model_id
21
21
  const modelName = modelClass?.modelClassData()?.name
22
22
  const [model, setModel] = useState()
23
- const canCan = useCanCan(() => [[modelClass, ["new"]]])
23
+ const canCan = useCanCan(() => {
24
+ const abilities = []
25
+
26
+ if (modelClass) abilities.push([modelClass, ["new"]])
27
+
28
+ return abilities
29
+ })
24
30
 
25
31
  const loadModel = useCallback(async () => {
26
32
  if (modelId && modelClass) {
@@ -2,21 +2,21 @@ import "./style"
2
2
  import EventListener from "../../../event-listener"
3
3
  import PropTypes from "prop-types"
4
4
  import PropTypesExact from "prop-types-exact"
5
- import {memo, useCallback, useRef, useState} from "react"
6
- import useShape from "set-state-compare/src/use-shape.js"
5
+ import {memo, useCallback, useRef} from "react"
6
+ import useShape from "set-state-compare/src/use-s.js"
7
7
 
8
8
  const ApiMakerSuperAdminLayoutHeader = ({actions, onTriggerMenu, title}) => {
9
- const shape = useShape()
9
+ const s = useShape()
10
10
  const headerActionsRef = useRef()
11
- const setHeaderActionsActive = shape.useState("headerActionsActive", false)
11
+ const setHeaderActionsActive = s.useState("headerActionsActive", false)
12
12
  const onGearsClicked = useCallback((e) => {
13
13
  e.preventDefault()
14
- setHeaderActionsActive(!shape.state.headerActionsActive)
14
+ setHeaderActionsActive(!s.state.headerActionsActive)
15
15
  }, [])
16
16
 
17
17
  const onWindowMouseUp = useCallback((e) => {
18
18
  // Close the header actions menu if clicked happened outside
19
- if (shape.state.headerActionsActive && headerActionsRef.current && !headerActionsRef.current.contains(e.target)) setHeaderActionsActive(false)
19
+ if (s.state.headerActionsActive && headerActionsRef.current && !headerActionsRef.current.contains(e.target)) setHeaderActionsActive(false)
20
20
  }, [])
21
21
 
22
22
  return (
@@ -26,7 +26,7 @@ const ApiMakerSuperAdminLayoutHeader = ({actions, onTriggerMenu, title}) => {
26
26
  {title}
27
27
  </div>
28
28
  {actions &&
29
- <div className="header-actions-container" data-active={shape.state.headerActionsActive}>
29
+ <div className="header-actions-container" data-active={s.state.headerActionsActive}>
30
30
  <div className="header-actions" ref={headerActionsRef}>
31
31
  {actions}
32
32
  </div>
@@ -6,9 +6,9 @@ import Header from "./header"
6
6
  import Menu from "./menu"
7
7
  import PropTypes from "prop-types"
8
8
  import PropTypesExact from "prop-types-exact"
9
- import {memo, useCallback, useEffect, useState} from "react"
9
+ import {memo, useCallback, useEffect} from "react"
10
10
  import useCurrentUser from "../../use-current-user"
11
- import useShape from "set-state-compare/src/use-shape.js"
11
+ import useShape from "set-state-compare/src/use-s.js"
12
12
 
13
13
  const NoAccess = React.lazy(() => import("./no-access"))
14
14
 
@@ -23,13 +23,13 @@ const ApiMakerSuperAdminLayout = ({
23
23
  menu,
24
24
  ...restProps
25
25
  }) => {
26
- const shape = useShape()
26
+ const s = useShape()
27
27
  const currentUser = useCurrentUser()
28
28
 
29
29
  useEffect(() => {
30
30
  CommandsPool.current().globalRequestData.layout = "admin"
31
31
  CommandsPool.current().globalRequestData.locale = I18n.locale
32
- }, [])
32
+ }, [I18n.locale])
33
33
 
34
34
  const headTitle = headTitle || headerTitle
35
35
 
@@ -39,21 +39,21 @@ const ApiMakerSuperAdminLayout = ({
39
39
  document.title = "Wooftech"
40
40
  }
41
41
 
42
- const setMenuTriggered = shape.useState("menuTriggered", false)
42
+ const setMenuTriggered = s.useState("menuTriggered", false)
43
43
  const noAccess = !currentUser
44
44
  const onRequestMenuClose = useCallback(() => setMenuTriggered(false), [])
45
45
  const onTriggerMenu = useCallback((e) => {
46
46
  e.preventDefault()
47
- setMenuTriggered(!shape.state.menuTriggered)
47
+ setMenuTriggered(!s.state.menuTriggered)
48
48
  }, [])
49
49
 
50
50
  return (
51
- <div className={classNames("components--admin--layout", className)} data-menu-triggered={shape.state.menuTriggered} {...restProps}>
51
+ <div className={classNames("components--admin--layout", className)} data-menu-triggered={s.state.menuTriggered} {...restProps}>
52
52
  <Menu
53
53
  active={active}
54
54
  noAccess={noAccess}
55
55
  onRequestMenuClose={onRequestMenuClose}
56
- triggered={shape.state.menuTriggered}
56
+ triggered={s.state.menuTriggered}
57
57
  />
58
58
  <Header actions={actions} onTriggerMenu={onTriggerMenu} title={headerTitle} />
59
59
  <div className="app-layout-content-container">
@@ -63,7 +63,6 @@ const ComponentsAdminLayoutMenu = ({active, noAccess, triggered}) => {
63
63
 
64
64
  ComponentsAdminLayoutMenu.propTypes = PropTypesExact({
65
65
  active: PropTypes.string,
66
- currentUser: PropTypes.instanceOf(User),
67
66
  noAccess: PropTypes.bool.isRequired,
68
67
  onRequestMenuClose: PropTypes.func.isRequired,
69
68
  triggered: PropTypes.bool.isRequired
@@ -1,4 +1,3 @@
1
- import CanCan from "../../../can-can"
2
1
  import {digg} from "diggerize"
3
2
  import {memo, useMemo} from "react"
4
3
  import MenuItem from "./menu-item"
@@ -6,20 +5,13 @@ import models from "../../models"
6
5
  import Params from "../../../params"
7
6
  import PropTypes from "prop-types"
8
7
  import PropTypesExact from "prop-types-exact"
9
- import withCanCan from "@kaspernj/api-maker/src/with-can-can"
8
+ import useCanCan from "../../../use-can-can"
10
9
 
11
- const abilities = []
12
-
13
- for (const model of models) {
14
- abilities.push(
15
- [model, ["index"]]
16
- )
17
- }
18
-
19
- const ComponentsAdminLayoutMenuContent = ({active, canCan}) => {
10
+ const ComponentsAdminLayoutMenuContent = ({active}) => {
11
+ const canCan = useCanCan(() => models.map((model) => [model, ["index"]]))
20
12
  const sortedModels = useMemo(
21
13
  () => models.sort((a, b) => a.modelName().human({count: 2}).toLowerCase().localeCompare(b.modelName().human({count: 2}).toLowerCase())),
22
- []
14
+ [I18n.locale]
23
15
  )
24
16
 
25
17
  return (
@@ -39,8 +31,7 @@ const ComponentsAdminLayoutMenuContent = ({active, canCan}) => {
39
31
  }
40
32
 
41
33
  ComponentsAdminLayoutMenuContent.propTypes = PropTypesExact({
42
- active: PropTypes.string,
43
- canCan: PropTypes.instanceOf(CanCan)
34
+ active: PropTypes.string
44
35
  })
45
36
 
46
- export default withCanCan(memo(ComponentsAdminLayoutMenuContent), abilities)
37
+ export default memo(ComponentsAdminLayoutMenuContent)
@@ -1,14 +1,16 @@
1
1
  import CanCan from "./can-can.mjs"
2
2
  import {useCallback, useEffect, useState} from "react"
3
+ import useCurrentUser from "./use-current-user.mjs"
3
4
  import useShape from "set-state-compare/src/use-shape.js"
4
5
 
5
6
  const useCanCan = (abilitiesCallback, dependencies) => {
7
+ const currentUser = useCurrentUser()
6
8
  const s = useShape({abilitiesCallback})
7
9
  const [canCan, setCanCan] = useState()
8
10
 
9
- useEffect(() => {
10
- loadAbilities()
11
- }, dependencies)
11
+ if (!dependencies) {
12
+ dependencies = [currentUser?.id()]
13
+ }
12
14
 
13
15
  const loadAbilities = useCallback(async () => {
14
16
  const canCan = CanCan.current()
@@ -24,6 +26,10 @@ const useCanCan = (abilitiesCallback, dependencies) => {
24
26
  loadAbilities()
25
27
  }, [])
26
28
 
29
+ useEffect(() => {
30
+ loadAbilities()
31
+ }, dependencies)
32
+
27
33
  useEffect(() => {
28
34
  CanCan.current().events.addListener("onResetAbilities", onResetAbilities)
29
35