@things-factory/shell 4.0.37 → 4.0.41
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/client/app/app.js +6 -6
- package/client/app/pages/page-404.js +35 -36
- package/client/index.js +2 -8
- package/config/config.development.js +42 -0
- package/config/config.production.js +43 -0
- package/db.test.sqlite +0 -0
- package/dist-server/pubsub.js +35 -1
- package/dist-server/pubsub.js.map +1 -1
- package/dist-server/server-dev.js +11 -4
- package/dist-server/server-dev.js.map +1 -1
- package/dist-server/server.js +11 -4
- package/dist-server/server.js.map +1 -1
- package/dist-server/utils/condition-builder.js +1 -0
- package/dist-server/utils/condition-builder.js.map +1 -1
- package/dist-server/utils/list-params-converter.js +21 -55
- package/dist-server/utils/list-params-converter.js.map +1 -1
- package/dist-server/utils/list-query-builder.js +15 -3
- package/dist-server/utils/list-query-builder.js.map +1 -1
- package/package.json +13 -11
- package/server/pubsub.ts +43 -1
- package/server/server-dev.ts +14 -4
- package/server/server.ts +12 -4
- package/server/utils/condition-builder.ts +1 -0
- package/server/utils/list-params-converter.ts +28 -57
- package/server/utils/list-query-builder.ts +19 -3
- package/client/actions/app.js +0 -12
- package/client/actions/index.js +0 -2
- package/client/actions/route.js +0 -101
- package/client/app/pages/page-view.js +0 -144
- package/client/reducers/app.js +0 -40
- package/client/reducers/route.js +0 -66
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"list-query-builder.js","sourceRoot":"","sources":["../../server/utils/list-query-builder.ts"],"names":[],"mappings":";;;AAAA,2DAAoD;AAE7C,MAAM,UAAU,GAAG,UAAU,YAAiB,EAAE,MAAW,EAAE,OAAY,EAAE,YAAqB,IAAI
|
1
|
+
{"version":3,"file":"list-query-builder.js","sourceRoot":"","sources":["../../server/utils/list-query-builder.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@things-factory/shell",
|
3
|
-
"version": "4.0.
|
3
|
+
"version": "4.0.41",
|
4
4
|
"description": "Core module for framework",
|
5
5
|
"bin": {
|
6
6
|
"things-factory": "bin/things-factory",
|
@@ -36,7 +36,7 @@
|
|
36
36
|
"@graphql-tools/schema": "^8.2.0",
|
37
37
|
"@graphql-tools/utils": "^8.3.0",
|
38
38
|
"@hatiolab/koa-webpack": "^6.0.0",
|
39
|
-
"@hatiolab/things-scene": "^2.7.
|
39
|
+
"@hatiolab/things-scene": "^2.7.33",
|
40
40
|
"@koa/cors": "^3.1.0",
|
41
41
|
"@material/mwc-button": "^0.25.3",
|
42
42
|
"@material/mwc-fab": "^0.25.3",
|
@@ -44,13 +44,14 @@
|
|
44
44
|
"@material/mwc-icon-button": "^0.25.3",
|
45
45
|
"@material/mwc-slider": "^0.25.3",
|
46
46
|
"@material/mwc-textfield": "^0.25.3",
|
47
|
-
"@operato/board": "^0.3.
|
48
|
-
"@operato/graphql": "^0.3.
|
49
|
-
"@operato/
|
50
|
-
"@
|
51
|
-
"@things-factory/
|
52
|
-
"@things-factory/
|
53
|
-
"@things-factory/
|
47
|
+
"@operato/board": "^0.3.21",
|
48
|
+
"@operato/graphql": "^0.3.21",
|
49
|
+
"@operato/shell": "^0.3.21",
|
50
|
+
"@operato/utils": "^0.3.21",
|
51
|
+
"@things-factory/ejs-remote": "^4.0.41",
|
52
|
+
"@things-factory/env": "^4.0.41",
|
53
|
+
"@things-factory/styles": "^4.0.41",
|
54
|
+
"@things-factory/utils": "^4.0.41",
|
54
55
|
"@webcomponents/webcomponentsjs": "^2.6.0",
|
55
56
|
"@webpack-contrib/schema-utils": "^1.0.0-beta.0",
|
56
57
|
"apollo-server-core": "^3.5.0",
|
@@ -68,6 +69,7 @@
|
|
68
69
|
"fs-extra": "^9.0.1",
|
69
70
|
"glob": "^7.1.6",
|
70
71
|
"graphql": "^15.7.2",
|
72
|
+
"graphql-kafka-subscriptions": "^0.4.0",
|
71
73
|
"graphql-mqtt-subscriptions": "^1.2.0",
|
72
74
|
"graphql-redis-subscriptions": "^2.4.2",
|
73
75
|
"graphql-subscriptions": "^2.0.0",
|
@@ -93,7 +95,7 @@
|
|
93
95
|
"loader-utils": "^2.0.0",
|
94
96
|
"lodash": "^4.17.15",
|
95
97
|
"mkdirp": "^1.0.3",
|
96
|
-
"mqtt": "^4.
|
98
|
+
"mqtt": "^4.3.4",
|
97
99
|
"node-fetch": "^2.6.0",
|
98
100
|
"node-sass": "^6.0.1",
|
99
101
|
"nodemon": "^2.0.2",
|
@@ -124,5 +126,5 @@
|
|
124
126
|
"resolutions": {
|
125
127
|
"core-js": "^3.16.0"
|
126
128
|
},
|
127
|
-
"gitHead": "
|
129
|
+
"gitHead": "1dd445b5b5e5b9e37291dc274886131199d7bf6a"
|
128
130
|
}
|
package/server/pubsub.ts
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
import { KafkaPubSub } from 'graphql-kafka-subscriptions'
|
1
2
|
import { MQTTPubSub } from 'graphql-mqtt-subscriptions'
|
2
3
|
import { RedisPubSub } from 'graphql-redis-subscriptions'
|
3
4
|
import { PubSub } from 'graphql-subscriptions'
|
@@ -6,7 +7,7 @@ import { connect } from 'mqtt'
|
|
6
7
|
|
7
8
|
import { config } from '@things-factory/env'
|
8
9
|
|
9
|
-
const { middleware, host, port, nodes, options } = config.get('pubsub', {})
|
10
|
+
const { middleware, host, port, nodes, topic, options } = config.get('pubsub', {})
|
10
11
|
|
11
12
|
const debug = require('debug')('things-factory:shell')
|
12
13
|
|
@@ -43,9 +44,50 @@ switch (middleware) {
|
|
43
44
|
subscriber: cluster
|
44
45
|
})
|
45
46
|
break
|
47
|
+
case 'kafka':
|
48
|
+
// globalConfig: {} // options passed directly to the consumer and producer
|
49
|
+
pubsub = new KafkaPubSub({
|
50
|
+
topic,
|
51
|
+
host,
|
52
|
+
port,
|
53
|
+
...options
|
54
|
+
})
|
55
|
+
break
|
46
56
|
default:
|
47
57
|
pubsub = new PubSub()
|
48
58
|
break
|
49
59
|
}
|
50
60
|
|
61
|
+
debug(middleware || 'default', 'pubsub initialized.')
|
62
|
+
|
63
|
+
// kafka pubsub keeps connection and app port with 'ctrl+c' termination.
|
64
|
+
const exitHandler = async (evt) => {
|
65
|
+
if (pubsub.close) {
|
66
|
+
try {
|
67
|
+
await pubsub.close()
|
68
|
+
} catch (err) {
|
69
|
+
console.error(err)
|
70
|
+
}
|
71
|
+
}
|
72
|
+
debug('exit on', evt.name)
|
73
|
+
if (evt.exit) process.exit()
|
74
|
+
}
|
75
|
+
|
76
|
+
/*
|
77
|
+
* exit events hint from https://stackoverflow.com/a/14032965/14539284
|
78
|
+
*/
|
79
|
+
|
80
|
+
//do something when app is closing
|
81
|
+
process.on('exit', exitHandler.bind(null, { name: 'exit', exit: true } ))
|
82
|
+
|
83
|
+
//catches ctrl+c event
|
84
|
+
process.on('SIGINT', exitHandler.bind(null, { name: 'SIGINT', exit: true } ))
|
85
|
+
|
86
|
+
// catches "kill pid" (for example: nodemon restart)
|
87
|
+
process.on('SIGUSR1', exitHandler.bind(null, { name: 'SIGUSR1', exit: true } ))
|
88
|
+
process.on('SIGUSR2', exitHandler.bind(null, { name: 'SIGUSR2', exit: true } ))
|
89
|
+
|
90
|
+
//catches uncaught exceptions
|
91
|
+
process.on('uncaughtException', exitHandler.bind(null, { name: 'uncaughtException', exit: true } ))
|
92
|
+
|
51
93
|
export { pubsub }
|
package/server/server-dev.ts
CHANGED
@@ -24,6 +24,7 @@ import koaBodyParser from 'koa-bodyparser'
|
|
24
24
|
import koaStatic from 'koa-static'
|
25
25
|
import koaWebpack from '@hatiolab/koa-webpack'
|
26
26
|
import { schema } from './schema'
|
27
|
+
import bytesFormat from 'bytes'
|
27
28
|
|
28
29
|
const debug = require('debug')('things-factory:shell:server-dev')
|
29
30
|
|
@@ -47,12 +48,21 @@ const compiler = webpack(webpackConfig)
|
|
47
48
|
|
48
49
|
const PORT = (process.env.PORT = flags.port)
|
49
50
|
|
51
|
+
const requestBody = config.get('requestBody')||{}
|
52
|
+
|
50
53
|
const bodyParserOption = {
|
51
|
-
formLimit: '10mb',
|
52
|
-
jsonLimit: '10mb',
|
53
|
-
textLimit: '10mb'
|
54
|
+
formLimit: requestBody.formLimit||'10mb',
|
55
|
+
jsonLimit: requestBody.jsonLimit||'10mb',
|
56
|
+
textLimit: requestBody.textLimit||'10mb'
|
57
|
+
}
|
58
|
+
|
59
|
+
const fileUpload = config.get('fileUpload')||{}
|
60
|
+
const fileUploadOption = {
|
61
|
+
maxFileSize: bytesFormat.parse(fileUpload.maxFileSize)||bytesFormat.parse('10mb'),
|
62
|
+
maxFiles: fileUpload.maxFiles||10
|
54
63
|
}
|
55
64
|
|
65
|
+
|
56
66
|
/* bootstrap */
|
57
67
|
const bootstrap = async () => {
|
58
68
|
await databaseInitializer()
|
@@ -199,7 +209,7 @@ const bootstrap = async () => {
|
|
199
209
|
})
|
200
210
|
|
201
211
|
app.use(koaBodyParser(bodyParserOption))
|
202
|
-
app.use(graphqlUploadKoa(
|
212
|
+
app.use(graphqlUploadKoa(fileUploadOption))
|
203
213
|
|
204
214
|
app.use(
|
205
215
|
server.getMiddleware({
|
package/server/server.ts
CHANGED
@@ -20,6 +20,7 @@ import ip from 'koa-ip'
|
|
20
20
|
import koaBodyParser from 'koa-bodyparser'
|
21
21
|
import koaStatic from 'koa-static'
|
22
22
|
import { schema } from './schema'
|
23
|
+
import bytesFormat from 'bytes'
|
23
24
|
|
24
25
|
const args = require('args')
|
25
26
|
|
@@ -31,12 +32,19 @@ const path = require('path')
|
|
31
32
|
|
32
33
|
const PORT = (process.env.PORT = flags.port)
|
33
34
|
|
35
|
+
const requestBody = config.get('requestBody')||{}
|
36
|
+
|
34
37
|
const bodyParserOption = {
|
35
|
-
formLimit: '10mb',
|
36
|
-
jsonLimit: '10mb',
|
37
|
-
textLimit: '10mb'
|
38
|
+
formLimit: requestBody.formLimit||'10mb',
|
39
|
+
jsonLimit: requestBody.jsonLimit||'10mb',
|
40
|
+
textLimit: requestBody.textLimit||'10mb'
|
38
41
|
}
|
39
42
|
|
43
|
+
const fileUpload = config.get('fileUpload')||{}
|
44
|
+
const fileUploadOption = {
|
45
|
+
maxFileSize: bytesFormat.parse(fileUpload.maxFileSize)||bytesFormat.parse('10mb'),
|
46
|
+
maxFiles: fileUpload.maxFiles||10
|
47
|
+
}
|
40
48
|
/* bootstrap */
|
41
49
|
const bootstrap = async () => {
|
42
50
|
await databaseInitializer()
|
@@ -165,7 +173,7 @@ const bootstrap = async () => {
|
|
165
173
|
})
|
166
174
|
|
167
175
|
app.use(koaBodyParser(bodyParserOption))
|
168
|
-
app.use(graphqlUploadKoa(
|
176
|
+
app.use(graphqlUploadKoa(fileUploadOption))
|
169
177
|
|
170
178
|
app.use(
|
171
179
|
server.getMiddleware({
|
@@ -1,13 +1,15 @@
|
|
1
|
-
import { Equal,
|
1
|
+
import { Between, Equal, ILike, In, IsNull, Like, Not, Raw } from 'typeorm'
|
2
|
+
|
2
3
|
import { ListParam } from '../service/common-types'
|
3
4
|
|
4
5
|
const OPERATION_FUNCTION_MAP = {
|
6
|
+
search: value => ILike(value),
|
5
7
|
eq: value => Equal(value),
|
6
8
|
noteq: value => Not(Equal(value)),
|
7
9
|
like: value => Like(value),
|
8
|
-
i_like: value =>
|
10
|
+
i_like: value => ILike(value),
|
9
11
|
nlike: value => Not(Like(value)),
|
10
|
-
i_nlike: value =>
|
12
|
+
i_nlike: value => Not(ILike(value)),
|
11
13
|
lt: value => Raw(alias => `${alias} < ${typeof value === 'string' ? "'" + value + "'" : value}`),
|
12
14
|
gt: value => Raw(alias => `${alias} > ${typeof value === 'string' ? "'" + value + "'" : value}`),
|
13
15
|
lte: value => Raw(alias => `${alias} <= ${typeof value === 'string' ? "'" + value + "'" : value}`),
|
@@ -25,51 +27,6 @@ const OPERATION_FUNCTION_MAP = {
|
|
25
27
|
between: value => Between(value[0], value[1])
|
26
28
|
}
|
27
29
|
|
28
|
-
// function getOperatorFunction({ operator, name, value, dataType }) {
|
29
|
-
// switch (operator) {
|
30
|
-
// case 'eq':
|
31
|
-
// return Equal(value)
|
32
|
-
// case 'noteq':
|
33
|
-
// return Not(Equal(value))
|
34
|
-
// case 'like':
|
35
|
-
// return Like(value)
|
36
|
-
// case 'nlike':
|
37
|
-
// return Not(Like(value))
|
38
|
-
// case 'lt':
|
39
|
-
// return Raw(alias => `${alias} < ${value}`)
|
40
|
-
// case 'gt':
|
41
|
-
// return Raw(alias => `${alias} > ${value}`)
|
42
|
-
// case 'lte':
|
43
|
-
// return Raw(alias => `${alias} <= ${value}`)
|
44
|
-
// case 'gte':
|
45
|
-
// return Raw(alias => `${alias} >= ${value}`)
|
46
|
-
// case 'in':
|
47
|
-
// return In(value)
|
48
|
-
// case 'notin':
|
49
|
-
// return Not(In(value))
|
50
|
-
// case 'is_null':
|
51
|
-
// return IsNull()
|
52
|
-
// case 'is_not_null':
|
53
|
-
// return Not(IsNull())
|
54
|
-
// case 'is_false':
|
55
|
-
// return Raw(alias => `${alias} IS FALSE`)
|
56
|
-
// case 'is_true':
|
57
|
-
// return Raw(alias => `${alias} IS TRUE`)
|
58
|
-
// case 'is_not_false':
|
59
|
-
// return Raw(alias => `${alias} IS NOT FALSE`)
|
60
|
-
// case 'is_not_true':
|
61
|
-
// return Raw(alias => `${alias} IS NOT TRUE`)
|
62
|
-
// case 'is_present':
|
63
|
-
// return Raw(alias => `${alias} IS PRESENT`)
|
64
|
-
// case 'is_blank':
|
65
|
-
// return Raw(alias => `${alias} IS BLANK`)
|
66
|
-
// case 'is_empty_num_id':
|
67
|
-
// return Raw(alias => `${alias} IS EMPTY NUMERIC ID`)
|
68
|
-
// case 'between':
|
69
|
-
// return Between(value[0], value[1])
|
70
|
-
// }
|
71
|
-
// }
|
72
|
-
|
73
30
|
function getOperatorFunction({ operator, name, value, dataType }) {
|
74
31
|
return OPERATION_FUNCTION_MAP[operator](value)
|
75
32
|
}
|
@@ -111,17 +68,31 @@ function makeSortingParams(sortings) {
|
|
111
68
|
}
|
112
69
|
|
113
70
|
function makeFilterParams(filters) {
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
71
|
+
/* for where AND clauses */
|
72
|
+
const columnFilters = filters.filter(filter => filter.operator !== 'search')
|
73
|
+
const columnWhere = columnFilters.reduce((where, f) => {
|
74
|
+
where[f.name] = getOperatorFunction(f)
|
75
|
+
return where
|
76
|
+
}, {})
|
77
|
+
|
78
|
+
const searchFilters = filters.filter(filter => filter.operator === 'search')
|
79
|
+
if (searchFilters.length === 0) {
|
80
|
+
return {
|
81
|
+
where: columnWhere
|
82
|
+
}
|
122
83
|
}
|
123
84
|
|
124
|
-
|
85
|
+
/* for fulltext searching ... OR-AND composition */
|
86
|
+
const searchWheres = searchFilters.map(f => {
|
87
|
+
return {
|
88
|
+
[f.name]: getOperatorFunction(f),
|
89
|
+
...columnWhere
|
90
|
+
}
|
91
|
+
})
|
92
|
+
|
93
|
+
return {
|
94
|
+
where: searchWheres
|
95
|
+
}
|
125
96
|
}
|
126
97
|
|
127
98
|
export function convertListParams(params: typeof ListParam, domain?: String) {
|
@@ -1,13 +1,16 @@
|
|
1
|
+
import { Brackets } from 'typeorm'
|
2
|
+
|
1
3
|
import { buildCondition } from './condition-builder'
|
2
4
|
|
3
5
|
export const buildQuery = function (queryBuilder: any, params: any, context: any, domainRef: Boolean = true) {
|
4
|
-
const
|
6
|
+
const columnFilters = params.filters?.filter(filter => filter.operator !== 'search') || []
|
7
|
+
const searchFilters = params.filters?.filter(filter => filter.operator === 'search') || []
|
5
8
|
const pagination = params.pagination
|
6
9
|
const sortings = params.sortings
|
7
10
|
const domainId = context && context.state.domain && context.state.domain.id
|
8
11
|
|
9
|
-
if (
|
10
|
-
|
12
|
+
if (columnFilters && columnFilters.length > 0) {
|
13
|
+
columnFilters.forEach(filter => {
|
11
14
|
const condition = buildCondition(
|
12
15
|
queryBuilder.alias,
|
13
16
|
filter.name,
|
@@ -22,6 +25,19 @@ export const buildQuery = function (queryBuilder: any, params: any, context: any
|
|
22
25
|
})
|
23
26
|
}
|
24
27
|
|
28
|
+
if (searchFilters.length > 0) {
|
29
|
+
queryBuilder.andWhere(
|
30
|
+
new Brackets(qb => {
|
31
|
+
searchFilters.forEach((filter, index) => {
|
32
|
+
const clause = `${queryBuilder.alias}.${filter.name} LIKE :${filter.name}`
|
33
|
+
const parameters = { [filter.name]: filter.value }
|
34
|
+
|
35
|
+
index === 0 ? qb.where(clause, parameters) : qb.orWhere(clause, parameters)
|
36
|
+
})
|
37
|
+
})
|
38
|
+
)
|
39
|
+
}
|
40
|
+
|
25
41
|
if (domainRef) {
|
26
42
|
queryBuilder.andWhere(`${queryBuilder.alias}.domain = :domainId`, { domainId })
|
27
43
|
}
|
package/client/actions/app.js
DELETED
@@ -1,12 +0,0 @@
|
|
1
|
-
export const UPDATE_MODULES = 'UPDATE_MODULES'
|
2
|
-
export const UPDATE_BASE_URL = 'UPDATE_BASE_URL'
|
3
|
-
export const UPDATE_CONTEXT_PATH = 'UPDATE_CONTEXT_PATH'
|
4
|
-
export const SET_DOMAINS = 'SET-DOMAINS'
|
5
|
-
|
6
|
-
export const updateDomains = (domains, domain) => (dispatch, getState) => {
|
7
|
-
dispatch({
|
8
|
-
type: SET_DOMAINS,
|
9
|
-
domains,
|
10
|
-
domain
|
11
|
-
})
|
12
|
-
}
|
package/client/actions/index.js
DELETED
package/client/actions/route.js
DELETED
@@ -1,101 +0,0 @@
|
|
1
|
-
import { store } from '../store'
|
2
|
-
import { getPathInfo } from '@things-factory/utils'
|
3
|
-
|
4
|
-
export const UPDATE_PAGE = 'UPDATE_PAGE'
|
5
|
-
export const UPDATE_CONTEXT = 'UPDATE_CONTEXT'
|
6
|
-
export const UPDATE_ACTIVE_PAGE = 'UPDATE_ACTIVE_PAGE'
|
7
|
-
|
8
|
-
export const REGISTER_NAVIGATION_CALLBACK = 'REGISTER_NAVIGATION_CALLBACK'
|
9
|
-
export const UNREGISTER_NAVIGATION_CALLBACK = 'UNREGISTER_NAVIGATION_CALLBACK'
|
10
|
-
|
11
|
-
export const HOMEPAGE = ''
|
12
|
-
|
13
|
-
/**
|
14
|
-
* 페이지를 이동하는 방법으로는 다음 두가지가 있다.
|
15
|
-
* 1. page link를 사용하는 방법 <a href='page'>goto page</a>
|
16
|
-
* 이 방법은 route(page)와 동일하다.
|
17
|
-
* 2. navigate('page')를 사용하는 방법
|
18
|
-
*
|
19
|
-
* @param string page
|
20
|
-
*/
|
21
|
-
export const navigate = (location, replace) => {
|
22
|
-
if (replace) history.replaceState(history.state, '', location)
|
23
|
-
else history.pushState({}, '', location)
|
24
|
-
|
25
|
-
window.dispatchEvent(new Event('popstate'))
|
26
|
-
}
|
27
|
-
|
28
|
-
export const navigateWithSilence = ({ pathname: path, search }) => dispatch => {
|
29
|
-
const { path: pathname } = getPathInfo(path)
|
30
|
-
|
31
|
-
const reg = /\/([^\/]+)\/*([^\/]*)/
|
32
|
-
const decodePath = decodeURIComponent(pathname)
|
33
|
-
const matchReturn = decodePath.match(reg) || []
|
34
|
-
const page = matchReturn[1] || HOMEPAGE
|
35
|
-
const id = matchReturn[2]
|
36
|
-
const searchParams = new URLSearchParams(search)
|
37
|
-
|
38
|
-
var params = {}
|
39
|
-
searchParams.forEach((value, key) => {
|
40
|
-
params[key] = value
|
41
|
-
})
|
42
|
-
|
43
|
-
// Any other info you might want to extract from the path (like page type),
|
44
|
-
// you can do here
|
45
|
-
dispatch(loadPage(page, id, params))
|
46
|
-
}
|
47
|
-
|
48
|
-
const _preLoadPage = page => {
|
49
|
-
/*
|
50
|
-
* _preLoadPage 에서는 page를 load하기 전처리를 수행한다.
|
51
|
-
* 예를 들면, page dynamic import 또는 page re-routing
|
52
|
-
*/
|
53
|
-
var state = store.getState()
|
54
|
-
|
55
|
-
/* override 기능을 위해서 dependency 관계의 역순으로 route를 실행한다. */
|
56
|
-
var modules = state.app.modules
|
57
|
-
if (modules) {
|
58
|
-
for (let i = modules.length - 1; i >= 0; i--) {
|
59
|
-
let factoryModule = modules[i]
|
60
|
-
let _page = factoryModule.route && factoryModule.route(page)
|
61
|
-
if (_page) {
|
62
|
-
return _page
|
63
|
-
}
|
64
|
-
}
|
65
|
-
}
|
66
|
-
}
|
67
|
-
|
68
|
-
export const loadPage = (page, id, params) => dispatch => {
|
69
|
-
var newPage = _preLoadPage(page)
|
70
|
-
|
71
|
-
if (page !== newPage && (newPage.indexOf('/') == 0)) {
|
72
|
-
dispatch(
|
73
|
-
navigateWithSilence({
|
74
|
-
pathname: newPage,
|
75
|
-
params
|
76
|
-
})
|
77
|
-
)
|
78
|
-
return
|
79
|
-
}
|
80
|
-
|
81
|
-
dispatch({
|
82
|
-
type: UPDATE_PAGE,
|
83
|
-
page: newPage,
|
84
|
-
resourceId: id,
|
85
|
-
params
|
86
|
-
})
|
87
|
-
}
|
88
|
-
|
89
|
-
export const route = url => {
|
90
|
-
/*
|
91
|
-
* Caution : This function works normally in a desktop environment,
|
92
|
-
* but it is not guaranteed in a mobile environment, so be sure to check it.
|
93
|
-
*/
|
94
|
-
const link = document.createElement('a')
|
95
|
-
|
96
|
-
link.setAttribute('href', url)
|
97
|
-
|
98
|
-
document.body.appendChild(link)
|
99
|
-
link.click()
|
100
|
-
document.body.removeChild(link)
|
101
|
-
}
|
@@ -1,144 +0,0 @@
|
|
1
|
-
import { LitElement, html } from 'lit-element'
|
2
|
-
|
3
|
-
import { store } from '../../store'
|
4
|
-
import { UPDATE_CONTEXT } from '../../actions/route'
|
5
|
-
|
6
|
-
import isEqual from 'lodash/isEqual'
|
7
|
-
|
8
|
-
function diff(after, before) {
|
9
|
-
var changed = false
|
10
|
-
var changes = {}
|
11
|
-
|
12
|
-
Object.getOwnPropertyNames(after).forEach(function(key) {
|
13
|
-
let before_val = before[key]
|
14
|
-
let after_val = after[key]
|
15
|
-
|
16
|
-
if (!isEqual(before_val, after_val)) {
|
17
|
-
changes[key] = after_val
|
18
|
-
changed = true
|
19
|
-
}
|
20
|
-
})
|
21
|
-
|
22
|
-
return changed && changes
|
23
|
-
}
|
24
|
-
|
25
|
-
export class PageView extends LitElement {
|
26
|
-
// Only render this page if it's actually visible.
|
27
|
-
shouldUpdate(changes) {
|
28
|
-
var active = String(this.active) == 'true'
|
29
|
-
var { active: oldActive = false } = this._oldLifecycleInfo$ || {}
|
30
|
-
|
31
|
-
/*
|
32
|
-
* page lifecycle
|
33
|
-
* case 1. page가 새로 activate 되었다.
|
34
|
-
* case 2. page가 active 상태에서 lifecycle 정보가 바뀌었다.
|
35
|
-
**/
|
36
|
-
if (active) {
|
37
|
-
this.pageUpdate({
|
38
|
-
active
|
39
|
-
})
|
40
|
-
} else if (oldActive) {
|
41
|
-
this.pageUpdate({
|
42
|
-
active
|
43
|
-
})
|
44
|
-
}
|
45
|
-
|
46
|
-
return active
|
47
|
-
}
|
48
|
-
|
49
|
-
static get properties() {
|
50
|
-
return {
|
51
|
-
active: Boolean,
|
52
|
-
lifecycle: Object,
|
53
|
-
contextPath: { attribute: 'context-path' }
|
54
|
-
}
|
55
|
-
}
|
56
|
-
|
57
|
-
/* lifecycle */
|
58
|
-
async pageUpdate(changes = {}, force = false) {
|
59
|
-
var before = this._oldLifecycleInfo$ || {}
|
60
|
-
|
61
|
-
var after = {
|
62
|
-
...before,
|
63
|
-
...this.lifecycle,
|
64
|
-
contextPath: this.contextPath,
|
65
|
-
...changes
|
66
|
-
}
|
67
|
-
|
68
|
-
if (!('initialized' in changes) && after.active && !before.initialized) {
|
69
|
-
after.initialized = true
|
70
|
-
}
|
71
|
-
|
72
|
-
if (force) {
|
73
|
-
after.updated = Date.now()
|
74
|
-
}
|
75
|
-
|
76
|
-
var changed = diff(after, before)
|
77
|
-
if (!changed) {
|
78
|
-
return
|
79
|
-
}
|
80
|
-
|
81
|
-
this._oldLifecycleInfo$ = after
|
82
|
-
|
83
|
-
/* page의 이미 초기화된 상태에서 contextPath가 바뀐다면, 무조건 page가 리셋되어야 한다. */
|
84
|
-
if (before.initialized && changed.contextPath) {
|
85
|
-
await this.pageReset()
|
86
|
-
return
|
87
|
-
}
|
88
|
-
|
89
|
-
if (changed.initialized) {
|
90
|
-
await this.pageInitialized(after)
|
91
|
-
}
|
92
|
-
|
93
|
-
if ('initialized' in changed) {
|
94
|
-
if (changed.initialized) {
|
95
|
-
/*
|
96
|
-
* 방금 초기화된 경우라면, 엘리먼트들이 만들어지지 않았을 가능성이 있으므로,
|
97
|
-
* 다음 animationFrame에서 pageUpdated 콜백을 호출한다.
|
98
|
-
*/
|
99
|
-
requestAnimationFrame(async () => {
|
100
|
-
await this.pageUpdated(changed, after, before)
|
101
|
-
/* active page인 경우에는, page Context 갱신도 필요할 것이다. */
|
102
|
-
after.active && this.updateContext()
|
103
|
-
})
|
104
|
-
} else {
|
105
|
-
await this.pageDisposed(after)
|
106
|
-
}
|
107
|
-
} else {
|
108
|
-
await this.pageUpdated(changed, after, before)
|
109
|
-
/* active page인 경우에는, page Context 갱신도 필요할 것이다. */
|
110
|
-
after.active && this.updateContext()
|
111
|
-
}
|
112
|
-
}
|
113
|
-
|
114
|
-
async pageReset() {
|
115
|
-
var { initialized } = this._oldLifecycleInfo$ || {}
|
116
|
-
|
117
|
-
if (initialized) {
|
118
|
-
await this.pageDispose()
|
119
|
-
await this.pageUpdate({}, true)
|
120
|
-
}
|
121
|
-
}
|
122
|
-
|
123
|
-
async pageDispose() {
|
124
|
-
await this.pageUpdate({
|
125
|
-
initialized: false
|
126
|
-
})
|
127
|
-
}
|
128
|
-
|
129
|
-
pageInitialized(pageInfo) {}
|
130
|
-
pageUpdated(changes, after, before) {}
|
131
|
-
pageDisposed(pageInfo) {}
|
132
|
-
|
133
|
-
/* context */
|
134
|
-
updateContext(override) {
|
135
|
-
store.dispatch({
|
136
|
-
type: UPDATE_CONTEXT,
|
137
|
-
context: override ? { ...this.context, ...override } : this.context
|
138
|
-
})
|
139
|
-
}
|
140
|
-
|
141
|
-
get context() {
|
142
|
-
return {}
|
143
|
-
}
|
144
|
-
}
|
package/client/reducers/app.js
DELETED
@@ -1,40 +0,0 @@
|
|
1
|
-
import { UPDATE_MODULES, UPDATE_BASE_URL, UPDATE_CONTEXT_PATH, SET_DOMAINS } from '../actions/app.js'
|
2
|
-
import { getPathInfo } from '@things-factory/utils'
|
3
|
-
|
4
|
-
const INITIAL_STATE = {
|
5
|
-
baseUrl: location.origin,
|
6
|
-
contextPath: getPathInfo(location.pathname).contextPath,
|
7
|
-
domains: []
|
8
|
-
}
|
9
|
-
|
10
|
-
const app = (state = INITIAL_STATE, action) => {
|
11
|
-
switch (action.type) {
|
12
|
-
case UPDATE_MODULES:
|
13
|
-
return {
|
14
|
-
...state,
|
15
|
-
modules: action.modules
|
16
|
-
}
|
17
|
-
case UPDATE_BASE_URL:
|
18
|
-
return {
|
19
|
-
...state,
|
20
|
-
baseUrl: action.baseUrl
|
21
|
-
}
|
22
|
-
case UPDATE_CONTEXT_PATH:
|
23
|
-
return {
|
24
|
-
...state,
|
25
|
-
contextPath: action.contextPath
|
26
|
-
}
|
27
|
-
|
28
|
-
case SET_DOMAINS:
|
29
|
-
return {
|
30
|
-
...state,
|
31
|
-
domains: action.domains,
|
32
|
-
domain: action.domain
|
33
|
-
}
|
34
|
-
|
35
|
-
default:
|
36
|
-
return state
|
37
|
-
}
|
38
|
-
}
|
39
|
-
|
40
|
-
export default app
|