@kaspernj/api-maker 1.0.221 → 1.0.224
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 +1 -1
- package/src/base-model.mjs +4 -0
- package/src/bootstrap/attribute-row/index.jsx +2 -3
- package/src/model-load-wrapper.jsx +14 -3
- package/src/super-admin/config-reader.jsx +73 -0
- package/src/super-admin/index-page/index.jsx +3 -17
- package/src/super-admin/index.jsx +1 -1
- package/src/super-admin/layout/index.jsx +2 -2
- package/src/super-admin/layout/menu/menu-content.jsx +1 -9
- package/src/super-admin/layout/no-access.jsx +1 -1
- package/src/super-admin/models.js +11 -0
- package/src/super-admin/show-page.jsx +40 -2
- package/src/table/select-calculator.mjs +10 -0
package/package.json
CHANGED
package/src/base-model.mjs
CHANGED
|
@@ -94,6 +94,10 @@ class BaseModel {
|
|
|
94
94
|
return new ModelName({modelClassData: this.modelClassData()})
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
+
static primaryKey() {
|
|
98
|
+
return digg(this.modelClassData(), "primaryKey")
|
|
99
|
+
}
|
|
100
|
+
|
|
97
101
|
static ransack (query = {}) {
|
|
98
102
|
return new Collection({modelClass: this}, {ransack: query})
|
|
99
103
|
}
|
|
@@ -71,10 +71,9 @@ export default class ApiMakerBootstrapAttributeRow extends React.PureComponent {
|
|
|
71
71
|
if (value instanceof Date) {
|
|
72
72
|
return strftime("%Y-%m-%d %H:%M", value)
|
|
73
73
|
} else if (typeof value === "boolean") {
|
|
74
|
-
if (value)
|
|
75
|
-
return I18n.t("js.shared.yes")
|
|
74
|
+
if (value) return I18n.t("js.shared.yes", {defaultValue: "Yes"})
|
|
76
75
|
|
|
77
|
-
return I18n.t("js.shared.no")
|
|
76
|
+
return I18n.t("js.shared.no", {defaultValue: "No"})
|
|
78
77
|
} else if (MoneyFormatter.isMoney(value)) {
|
|
79
78
|
return MoneyFormatter.format(value)
|
|
80
79
|
} else {
|
|
@@ -1,17 +1,19 @@
|
|
|
1
|
+
import {digg, digs} from "diggerize"
|
|
1
2
|
import EventUpdated from "./event-updated"
|
|
2
3
|
import Params from "./params.mjs"
|
|
3
4
|
import PropTypes from "prop-types"
|
|
4
5
|
import React from "react"
|
|
5
6
|
import withQueryParams from "on-location-changed/src/with-query-params"
|
|
6
7
|
|
|
7
|
-
export default (WrappedComponent,
|
|
8
|
+
export default (WrappedComponent, mdelClassArg, args = {}) => {
|
|
8
9
|
class ModelLoadWrapper extends React.PureComponent {
|
|
9
10
|
static propTypes = {
|
|
10
11
|
queryParams: PropTypes.object
|
|
11
12
|
}
|
|
12
13
|
|
|
13
|
-
|
|
14
|
-
|
|
14
|
+
modelClass = this.resolveModelClass(mdelClassArg)
|
|
15
|
+
camelizedLower = this.modelClass.modelName().camelizedLower()
|
|
16
|
+
paramsVariableName = `${this.modelClass.modelName().paramKey()}_id`
|
|
15
17
|
|
|
16
18
|
state = {
|
|
17
19
|
model: undefined,
|
|
@@ -19,6 +21,14 @@ export default (WrappedComponent, ModelClass, args = {}) => {
|
|
|
19
21
|
notFound: undefined
|
|
20
22
|
}
|
|
21
23
|
|
|
24
|
+
resolveModelClass(modelClassArg) {
|
|
25
|
+
const {queryParams} = digs(this.props, "queryParams")
|
|
26
|
+
|
|
27
|
+
if (typeof modelClassArg == "object") return modelClassArg.callback({queryParams})
|
|
28
|
+
|
|
29
|
+
return modelClassArg
|
|
30
|
+
}
|
|
31
|
+
|
|
22
32
|
componentDidMount() {
|
|
23
33
|
this.loadModel()
|
|
24
34
|
}
|
|
@@ -50,6 +60,7 @@ export default (WrappedComponent, ModelClass, args = {}) => {
|
|
|
50
60
|
|
|
51
61
|
loadExistingModel = async () => {
|
|
52
62
|
const modelId = this.getModelId()
|
|
63
|
+
const ModelClass = digg(this, "modelClass")
|
|
53
64
|
const query = await ModelClass.ransack({id_eq: modelId})
|
|
54
65
|
|
|
55
66
|
if (args.abilities) query.abilities(args.abilities)
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import {digg, digs} from "diggerize"
|
|
2
|
+
import inflection from "inflection"
|
|
3
|
+
|
|
4
|
+
export default class ApiMakerSuperAdminConfigReader {
|
|
5
|
+
static forModel(modelClass) {
|
|
6
|
+
const modelNameCamelized = digg(modelClass.modelClassData(), "nameDasherized")
|
|
7
|
+
let modelConfig
|
|
8
|
+
|
|
9
|
+
try {
|
|
10
|
+
modelConfig = require(`super-admin/model-configs/${modelNameCamelized}`).default
|
|
11
|
+
} catch (error) {
|
|
12
|
+
console.log(`No model-config for ${modelClass.modelClassData().name}`)
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
return new ApiMakerSuperAdminConfigReader(modelClass, modelConfig)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
constructor(modelClass, modelConfig) {
|
|
19
|
+
this.modelClass = modelClass
|
|
20
|
+
this.modelConfig = modelConfig
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
attributesToShow() {
|
|
24
|
+
const {modelConfig} = digs(this, "modelConfig")
|
|
25
|
+
|
|
26
|
+
if (modelConfig?.show?.attributesToShow) {
|
|
27
|
+
return modelConfig.show.attributesToShow()
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return this.defaultAttributesToShow()
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
defaultAttributesToShow() {
|
|
34
|
+
const attributesToShow = []
|
|
35
|
+
|
|
36
|
+
for (const column of this.defaultTableColumns()) {
|
|
37
|
+
attributesToShow.push(digg(column, "attribute"))
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return attributesToShow
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
tableColumns() {
|
|
44
|
+
const {modelConfig} = digs(this, "modelConfig")
|
|
45
|
+
|
|
46
|
+
if (modelConfig?.table?.columns) {
|
|
47
|
+
return modelConfig.table.columns()
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return this.defaultTableColumns()
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
defaultTableColumns() {
|
|
54
|
+
const {modelClass} = digs(this, "modelClass")
|
|
55
|
+
const attributes = modelClass.attributes()
|
|
56
|
+
const columns = []
|
|
57
|
+
|
|
58
|
+
for (const attribute of attributes) {
|
|
59
|
+
if (!attribute.isSelectedByDefault()) continue
|
|
60
|
+
|
|
61
|
+
const camelizedName = inflection.camelize(attribute.name(), true)
|
|
62
|
+
const column = {
|
|
63
|
+
attribute: camelizedName
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (attribute.isColumn()) column.sortKey = camelizedName
|
|
67
|
+
|
|
68
|
+
columns.push(column)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return columns
|
|
72
|
+
}
|
|
73
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import ConfigReader from "../config-reader"
|
|
1
2
|
import {digg, digs} from "diggerize"
|
|
2
|
-
import inflection from "inflection"
|
|
3
3
|
import Params from "../../params"
|
|
4
4
|
import PropTypes from "prop-types"
|
|
5
5
|
import React from "react"
|
|
@@ -27,23 +27,9 @@ export default class ApiMakerSuperAdminIndexPage extends React.PureComponent {
|
|
|
27
27
|
|
|
28
28
|
columns = () => {
|
|
29
29
|
const {modelClass} = digs(this.props, "modelClass")
|
|
30
|
-
const
|
|
31
|
-
const columns = []
|
|
30
|
+
const configReader = ConfigReader.forModel(modelClass)
|
|
32
31
|
|
|
33
|
-
|
|
34
|
-
if (!attribute.isSelectedByDefault()) continue
|
|
35
|
-
|
|
36
|
-
const camelizedName = inflection.camelize(attribute.name(), true)
|
|
37
|
-
const column = {
|
|
38
|
-
attribute: camelizedName
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
if (attribute.isColumn()) column.sortKey = camelizedName
|
|
42
|
-
|
|
43
|
-
columns.push(column)
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
return columns
|
|
32
|
+
return configReader.tableColumns()
|
|
47
33
|
}
|
|
48
34
|
|
|
49
35
|
viewModelPath = (args) => {
|
|
@@ -20,7 +20,7 @@ class ApiMakerSuperAdmin extends React.PureComponent {
|
|
|
20
20
|
if (queryParams.model) modelClass = modelsModule[queryParams.model]
|
|
21
21
|
|
|
22
22
|
return (
|
|
23
|
-
<Layout>
|
|
23
|
+
<Layout headerTitle={modelClass?.modelName()?.human({count: 2})}>
|
|
24
24
|
{pageToShow == "index" &&
|
|
25
25
|
<IndexPage
|
|
26
26
|
currentUser={currentUser}
|
|
@@ -81,14 +81,14 @@ class ApiMakerSuperAdminLayout extends React.PureComponent {
|
|
|
81
81
|
{currentUser &&
|
|
82
82
|
<>
|
|
83
83
|
<div className="mb-4">
|
|
84
|
-
{I18n.t("js.api_maker.super_admin.layout.try_signing_out_and_in_with_a_different_user")}
|
|
84
|
+
{I18n.t("js.api_maker.super_admin.layout.try_signing_out_and_in_with_a_different_user", {defaultValue: "Try signing in with a different user."})}
|
|
85
85
|
</div>
|
|
86
86
|
</>
|
|
87
87
|
}
|
|
88
88
|
{!currentUser &&
|
|
89
89
|
<>
|
|
90
90
|
<div className="mb-4">
|
|
91
|
-
{I18n.t("js.api_maker.super_admin.layout.try_signing_in")}
|
|
91
|
+
{I18n.t("js.api_maker.super_admin.layout.try_signing_in", {defaultValue: "Try signing in."})}
|
|
92
92
|
</div>
|
|
93
93
|
</>
|
|
94
94
|
}
|
|
@@ -1,18 +1,10 @@
|
|
|
1
1
|
import CanCanLoader from "@kaspernj/api-maker/src/can-can-loader"
|
|
2
2
|
import {digg, digs} from "diggerize"
|
|
3
3
|
import MenuItem from "./menu-item"
|
|
4
|
+
import models from "../../models"
|
|
4
5
|
import Params from "../../../params"
|
|
5
6
|
import PropTypes from "prop-types"
|
|
6
7
|
import PropTypesExact from "prop-types-exact"
|
|
7
|
-
import * as modelsModule from "@kaspernj/api-maker/src/models.mjs.erb"
|
|
8
|
-
|
|
9
|
-
const models = []
|
|
10
|
-
|
|
11
|
-
for (const modelKey of Object.keys(modelsModule)) {
|
|
12
|
-
const model = modelsModule[modelKey]
|
|
13
|
-
|
|
14
|
-
models.push(model)
|
|
15
|
-
}
|
|
16
8
|
|
|
17
9
|
const abilities = []
|
|
18
10
|
|
|
@@ -7,7 +7,7 @@ class ComponentsAdminLayoutNoAccess extends React.PureComponent {
|
|
|
7
7
|
className="components--admin--layout-no-access"
|
|
8
8
|
data-user-roles={currentUser?.userRoles()?.loaded()?.map((userRole) => userRole.role()?.identifier()).join(", ")}
|
|
9
9
|
>
|
|
10
|
-
{I18n.t("js.api_maker.super_admin.layout.no_access.you_dont_have_no_access_to_this_page")}
|
|
10
|
+
{I18n.t("js.api_maker.super_admin.layout.no_access.you_dont_have_no_access_to_this_page", {defaultValue: "You don't have access to this page."})}
|
|
11
11
|
</div>
|
|
12
12
|
)
|
|
13
13
|
}
|
|
@@ -1,11 +1,49 @@
|
|
|
1
|
+
import AttributeRows from "../bootstrap/attribute-rows"
|
|
2
|
+
import ConfigReader from "./config-reader"
|
|
3
|
+
import {digg, digs} from "diggerize"
|
|
4
|
+
import modelLoadWrapper from "../model-load-wrapper"
|
|
1
5
|
import React from "react"
|
|
2
6
|
|
|
3
|
-
|
|
7
|
+
class ApiMakerSuperAdminShowPage extends React.PureComponent {
|
|
4
8
|
render() {
|
|
9
|
+
const attributes = this.attributes()
|
|
10
|
+
const model = this.model()
|
|
11
|
+
|
|
5
12
|
return (
|
|
6
13
|
<div className="super-admin--show-page">
|
|
7
|
-
|
|
14
|
+
{attributes && model &&
|
|
15
|
+
<AttributeRows attributes={attributes} model={model} />
|
|
16
|
+
}
|
|
8
17
|
</div>
|
|
9
18
|
)
|
|
10
19
|
}
|
|
20
|
+
|
|
21
|
+
attributes() {
|
|
22
|
+
const {modelClass} = digs(this.props, "modelClass")
|
|
23
|
+
const configReader = ConfigReader.forModel(modelClass)
|
|
24
|
+
|
|
25
|
+
return configReader.attributesToShow()
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
model() {
|
|
29
|
+
const {modelClass} = digs(this.props, "modelClass")
|
|
30
|
+
const camelizedLower = digg(modelClass.modelClassData(), "camelizedLower")
|
|
31
|
+
|
|
32
|
+
return digg(this, "props", camelizedLower)
|
|
33
|
+
}
|
|
11
34
|
}
|
|
35
|
+
|
|
36
|
+
const modelClassResolver = {callback: ({queryParams}) => {
|
|
37
|
+
const modelClassName = digg(queryParams, "model")
|
|
38
|
+
const modelClass = digg(require("../models.mjs.erb"), modelClassName)
|
|
39
|
+
|
|
40
|
+
return modelClass
|
|
41
|
+
}}
|
|
42
|
+
|
|
43
|
+
export default modelLoadWrapper(
|
|
44
|
+
ApiMakerSuperAdminShowPage,
|
|
45
|
+
modelClassResolver,
|
|
46
|
+
{
|
|
47
|
+
loadByQueryParam: ({props}) => props.queryParams.model_id
|
|
48
|
+
}
|
|
49
|
+
)
|
|
@@ -12,6 +12,16 @@ class SelectCalculator {
|
|
|
12
12
|
const select = this.table.props.select || {}
|
|
13
13
|
const {preparedColumns} = digs(this.table.shape, "preparedColumns")
|
|
14
14
|
|
|
15
|
+
|
|
16
|
+
// Ensure the primary key column is loader for the primary model class
|
|
17
|
+
const className = digg(modelClass.modelClassData(), "className")
|
|
18
|
+
const primaryKeyColumnName = modelClass.primaryKey()
|
|
19
|
+
|
|
20
|
+
if (!(className in select)) select[className] = []
|
|
21
|
+
if (!select[className].includes(primaryKeyColumnName)) select[className].push(primaryKeyColumnName)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
// Ensure columns used for columns are loaded
|
|
15
25
|
for (const preparedColumn of preparedColumns) {
|
|
16
26
|
const {column} = digs(preparedColumn, "column")
|
|
17
27
|
|