@operato/shell 8.0.0-alpha.51 โ 8.0.0-beta.1
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/CHANGELOG.md +17 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +6 -6
- package/.editorconfig +0 -29
- package/.storybook/main.js +0 -3
- package/.storybook/preview.js +0 -52
- package/.storybook/server.mjs +0 -8
- package/src/actions/app.ts +0 -23
- package/src/actions/busy.ts +0 -15
- package/src/actions/const.ts +0 -8
- package/src/actions/index.ts +0 -4
- package/src/actions/route.ts +0 -126
- package/src/app/app-style.ts +0 -114
- package/src/app/app.ts +0 -274
- package/src/app/pages/page-404.ts +0 -62
- package/src/app/pages/page-view.ts +0 -215
- package/src/custom-alert.ts +0 -43
- package/src/entries/public/home.ts +0 -94
- package/src/index.ts +0 -6
- package/src/module-importer.import +0 -0
- package/src/object-store.ts +0 -173
- package/src/reducers/app.ts +0 -48
- package/src/reducers/busy.ts +0 -21
- package/src/reducers/route.ts +0 -77
- package/src/store.ts +0 -36
- package/src/types/domain.ts +0 -22
- package/src/types/index.ts +0 -5
- package/src/types/privilege.ts +0 -28
- package/src/types/role.ts +0 -33
- package/src/types/types.ts +0 -5
- package/src/types/user.ts +0 -23
- package/stories/app.stories.ts +0 -51
- package/tsconfig.json +0 -24
- package/web-dev-server.config.mjs +0 -27
- package/web-test-runner.config.mjs +0 -41
package/package.json
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
"name": "@operato/shell",
|
3
3
|
"description": "WebApplication architecturing shell following open-wc recommendations",
|
4
4
|
"author": "heartyoh",
|
5
|
-
"version": "8.0.0-
|
5
|
+
"version": "8.0.0-beta.1",
|
6
6
|
"main": "dist/src/index.js",
|
7
7
|
"module": "dist/src/index.js",
|
8
8
|
"exports": {
|
@@ -59,10 +59,10 @@
|
|
59
59
|
},
|
60
60
|
"dependencies": {
|
61
61
|
"@material/web": "^2.0.0",
|
62
|
-
"@operato/graphql": "^8.0.0-
|
63
|
-
"@operato/popup": "^8.0.0-
|
64
|
-
"@operato/styles": "^8.0.0-
|
65
|
-
"@operato/utils": "^8.0.0-
|
62
|
+
"@operato/graphql": "^8.0.0-beta.1",
|
63
|
+
"@operato/popup": "^8.0.0-beta.1",
|
64
|
+
"@operato/styles": "^8.0.0-beta.1",
|
65
|
+
"@operato/utils": "^8.0.0-beta.1",
|
66
66
|
"@webcomponents/scoped-custom-element-registry": "^0.0.9",
|
67
67
|
"lit": "^3.1.2",
|
68
68
|
"lodash-es": "^4.17.21",
|
@@ -102,5 +102,5 @@
|
|
102
102
|
"prettier --write"
|
103
103
|
]
|
104
104
|
},
|
105
|
-
"gitHead": "
|
105
|
+
"gitHead": "d5b28a2e9deb632c0dc80132f6a7196dd6fe4220"
|
106
106
|
}
|
package/.editorconfig
DELETED
@@ -1,29 +0,0 @@
|
|
1
|
-
# EditorConfig helps developers define and maintain consistent
|
2
|
-
# coding styles between different editors and IDEs
|
3
|
-
# editorconfig.org
|
4
|
-
|
5
|
-
root = true
|
6
|
-
|
7
|
-
|
8
|
-
[*]
|
9
|
-
|
10
|
-
# Change these settings to your own preference
|
11
|
-
indent_style = space
|
12
|
-
indent_size = 2
|
13
|
-
|
14
|
-
# We recommend you to keep these unchanged
|
15
|
-
end_of_line = lf
|
16
|
-
charset = utf-8
|
17
|
-
trim_trailing_whitespace = true
|
18
|
-
insert_final_newline = true
|
19
|
-
|
20
|
-
[*.md]
|
21
|
-
trim_trailing_whitespace = false
|
22
|
-
|
23
|
-
[*.json]
|
24
|
-
indent_size = 2
|
25
|
-
|
26
|
-
[*.{html,js,md}]
|
27
|
-
block_comment_start = /**
|
28
|
-
block_comment = *
|
29
|
-
block_comment_end = */
|
package/.storybook/main.js
DELETED
package/.storybook/preview.js
DELETED
@@ -1,52 +0,0 @@
|
|
1
|
-
import { i18next } from '@operato/i18n'
|
2
|
-
|
3
|
-
export const globalTypes = {
|
4
|
-
locale: {
|
5
|
-
name: 'Locale',
|
6
|
-
description: 'Internationalization locale',
|
7
|
-
toolbar: {
|
8
|
-
icon: 'globe',
|
9
|
-
items: [
|
10
|
-
{ value: 'en', right: '๐บ๐ธ', title: 'English' },
|
11
|
-
{ value: 'ko', right: '๐ฐ๐ท', title: 'ํ๊ตญ์ด' },
|
12
|
-
{ value: 'zh', right: '๐จ๐ณ', title: 'ไธญๆ' },
|
13
|
-
{ value: 'ja', right: '๐ฏ๐ต', title: 'ๆฅๆฌ่ช' },
|
14
|
-
{ value: 'ms', right: '๐ฒ๐พ', title: 'Bahasa Melayu' }
|
15
|
-
],
|
16
|
-
showName: true
|
17
|
-
}
|
18
|
-
},
|
19
|
-
theme: {
|
20
|
-
name: 'Theme',
|
21
|
-
description: 'Global theme for components',
|
22
|
-
toolbar: {
|
23
|
-
icon: 'paintbrush',
|
24
|
-
items: [
|
25
|
-
{ value: 'light', title: 'Light' },
|
26
|
-
{ value: 'dark', title: 'Dark' }
|
27
|
-
],
|
28
|
-
showName: true
|
29
|
-
}
|
30
|
-
}
|
31
|
-
}
|
32
|
-
|
33
|
-
export const decorators = [
|
34
|
-
(Story, context) => {
|
35
|
-
const { locale, theme } = context.globals
|
36
|
-
|
37
|
-
if (locale) {
|
38
|
-
i18next.changeLanguage(locale)
|
39
|
-
}
|
40
|
-
|
41
|
-
// Set the theme class for the document
|
42
|
-
if (theme === 'dark') {
|
43
|
-
document.documentElement.classList.add('dark')
|
44
|
-
document.documentElement.classList.remove('light')
|
45
|
-
} else {
|
46
|
-
document.documentElement.classList.add('light')
|
47
|
-
document.documentElement.classList.remove('dark')
|
48
|
-
}
|
49
|
-
|
50
|
-
return Story()
|
51
|
-
}
|
52
|
-
]
|
package/.storybook/server.mjs
DELETED
@@ -1,8 +0,0 @@
|
|
1
|
-
import { storybookPlugin } from '@web/dev-server-storybook';
|
2
|
-
import baseConfig from '../web-dev-server.config.mjs';
|
3
|
-
|
4
|
-
export default /** @type {import('@web/dev-server').DevServerConfig} */ ({
|
5
|
-
...baseConfig,
|
6
|
-
open: '/',
|
7
|
-
plugins: [storybookPlugin({ type: 'web-components' }), ...baseConfig.plugins],
|
8
|
-
});
|
package/src/actions/app.ts
DELETED
@@ -1,23 +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 =
|
7
|
-
(
|
8
|
-
domains: {
|
9
|
-
name: string
|
10
|
-
subdomain: string
|
11
|
-
}[],
|
12
|
-
domain: {
|
13
|
-
name: string
|
14
|
-
subdomain: string
|
15
|
-
}
|
16
|
-
) =>
|
17
|
-
(dispatch: any) => {
|
18
|
-
dispatch({
|
19
|
-
type: SET_DOMAINS,
|
20
|
-
domains,
|
21
|
-
domain
|
22
|
-
})
|
23
|
-
}
|
package/src/actions/busy.ts
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
import { setActiveRequestCounterCallback } from '@operato/graphql'
|
2
|
-
import { store } from '../store'
|
3
|
-
|
4
|
-
export const UPDATE_BUSY = 'UPDATE_BUSY'
|
5
|
-
|
6
|
-
setActiveRequestCounterCallback((count: number) => {
|
7
|
-
store.dispatch(updateBusy(count != 0) as any)
|
8
|
-
})
|
9
|
-
|
10
|
-
export const updateBusy = (busy: boolean) => (dispatch: any) => {
|
11
|
-
dispatch({
|
12
|
-
type: UPDATE_BUSY,
|
13
|
-
busy
|
14
|
-
})
|
15
|
-
}
|
package/src/actions/const.ts
DELETED
@@ -1,8 +0,0 @@
|
|
1
|
-
export const UPDATE_PAGE = 'UPDATE_PAGE'
|
2
|
-
export const UPDATE_CONTEXT = 'UPDATE_CONTEXT'
|
3
|
-
export const UPDATE_ACTIVE_PAGE = 'UPDATE_ACTIVE_PAGE'
|
4
|
-
|
5
|
-
export const REGISTER_NAVIGATION_CALLBACK = 'REGISTER_NAVIGATION_CALLBACK'
|
6
|
-
export const UNREGISTER_NAVIGATION_CALLBACK = 'UNREGISTER_NAVIGATION_CALLBACK'
|
7
|
-
|
8
|
-
export const HOMEPAGE = ''
|
package/src/actions/index.ts
DELETED
package/src/actions/route.ts
DELETED
@@ -1,126 +0,0 @@
|
|
1
|
-
import { getPathInfo } from '@operato/utils'
|
2
|
-
|
3
|
-
import { HOMEPAGE, UPDATE_PAGE } from '../actions/const'
|
4
|
-
import { store } from '../store'
|
5
|
-
|
6
|
-
/**
|
7
|
-
* Navigate to a page using one of two methods:
|
8
|
-
* 1. Using a page link: <a href='page'>goto page</a> (equivalent to route(page))
|
9
|
-
* 2. Using the navigate('page') function.
|
10
|
-
*
|
11
|
-
* ํ์ด์ง๋ฅผ ์ด๋ํ๋ ๋ฐฉ๋ฒ์ผ๋ก๋ ๋ค์ ๋๊ฐ์ง๊ฐ ์๋ค.
|
12
|
-
* 1. page link๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ <a href='page'>goto page</a>
|
13
|
-
* ์ด ๋ฐฉ๋ฒ์ route(page)์ ๋์ผํ๋ค.
|
14
|
-
* 2. navigate('page')๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ
|
15
|
-
*
|
16
|
-
* @param location - The path of the page to navigate to.
|
17
|
-
* @param replace - Optional. If true, replaces the current page in the browser's history.
|
18
|
-
*/
|
19
|
-
export const navigate = (location: string, replace?: boolean) => {
|
20
|
-
if (replace) history.replaceState(history.state, '', location)
|
21
|
-
else history.pushState({}, '', location)
|
22
|
-
|
23
|
-
window.dispatchEvent(new Event('popstate'))
|
24
|
-
}
|
25
|
-
|
26
|
-
/**
|
27
|
-
* Navigate to a page with optional query parameters, and dispatch a Redux action to load the page.
|
28
|
-
*
|
29
|
-
* @param pathInfo - Object containing pathname, search, and optional params.
|
30
|
-
* @param dispatch - Redux dispatch function.
|
31
|
-
*/
|
32
|
-
export const navigateWithSilence =
|
33
|
-
({ pathname: path, search, params }: { pathname: string; search?: string; params?: { [key: string]: any } }) =>
|
34
|
-
(dispatch: any) => {
|
35
|
-
const { path: pathname } = getPathInfo(path)
|
36
|
-
|
37
|
-
const reg = /\/([^\/]+)\/*([^\/]*)/
|
38
|
-
const decodePath = decodeURIComponent(pathname!)
|
39
|
-
const matchReturn = decodePath.match(reg) || []
|
40
|
-
const page = matchReturn[1] || HOMEPAGE
|
41
|
-
const id = matchReturn[2]
|
42
|
-
|
43
|
-
if (!params) {
|
44
|
-
params = {}
|
45
|
-
|
46
|
-
new URLSearchParams(search).forEach((value, key) => {
|
47
|
-
params![key] = value
|
48
|
-
})
|
49
|
-
}
|
50
|
-
|
51
|
-
// Any other info you might want to extract from the path (like page type),
|
52
|
-
// you can do here
|
53
|
-
dispatch(loadPage(page, id, params))
|
54
|
-
}
|
55
|
-
|
56
|
-
/**
|
57
|
-
* Preload a page by performing any necessary preprocessing before loading.
|
58
|
-
*
|
59
|
-
* @param page - The page to preload.
|
60
|
-
* @returns - The new page path or routing result after preprocessing.
|
61
|
-
*/
|
62
|
-
const _preLoadPage = async (page: any) => {
|
63
|
-
/*
|
64
|
-
* _preLoadPage ์์๋ page๋ฅผ loadํ๊ธฐ ์ ์ฒ๋ฆฌ๋ฅผ ์ํํ๋ค.
|
65
|
-
* ์๋ฅผ ๋ค๋ฉด, page dynamic import ๋๋ page re-routing
|
66
|
-
*/
|
67
|
-
var state: any = store.getState()
|
68
|
-
|
69
|
-
/* override ๊ธฐ๋ฅ์ ์ํด์ dependency ๊ด๊ณ์ ์ญ์์ผ๋ก route๋ฅผ ์คํํ๋ค. */
|
70
|
-
var modules = state.app.modules
|
71
|
-
if (modules) {
|
72
|
-
for (let i = modules.length - 1; i >= 0; i--) {
|
73
|
-
let module = modules[i]
|
74
|
-
let _page = module.route && (await module.route(page, module))
|
75
|
-
if (_page) {
|
76
|
-
return _page
|
77
|
-
}
|
78
|
-
}
|
79
|
-
}
|
80
|
-
}
|
81
|
-
|
82
|
-
/**
|
83
|
-
* Load a page by dispatching a Redux action, and handle page navigation if necessary.
|
84
|
-
*
|
85
|
-
* @param page - The page to load.
|
86
|
-
* @param id - The associated resource ID.
|
87
|
-
* @param params - Additional parameters to pass to the page.
|
88
|
-
*/
|
89
|
-
export const loadPage = (page: string, id: string, params: { [key: string]: any }) => async (dispatch: any) => {
|
90
|
-
var newPage = await _preLoadPage(page)
|
91
|
-
|
92
|
-
if (page !== newPage && newPage.indexOf('/') == 0) {
|
93
|
-
dispatch(
|
94
|
-
navigateWithSilence({
|
95
|
-
pathname: id ? `${newPage}/${id}` : newPage,
|
96
|
-
params
|
97
|
-
})
|
98
|
-
)
|
99
|
-
return
|
100
|
-
}
|
101
|
-
|
102
|
-
dispatch({
|
103
|
-
type: UPDATE_PAGE,
|
104
|
-
page: newPage,
|
105
|
-
resourceId: id,
|
106
|
-
params
|
107
|
-
})
|
108
|
-
}
|
109
|
-
|
110
|
-
/**
|
111
|
-
* Route to a given URL by creating a link element and triggering a click event.
|
112
|
-
* This approach does not work properly in a mobile environment and therefore should not be used.
|
113
|
-
*
|
114
|
-
* @deprecated
|
115
|
-
*
|
116
|
-
* @param url - The URL to route to.
|
117
|
-
*/
|
118
|
-
export const route = (url: string) => {
|
119
|
-
const link = document.createElement('a')
|
120
|
-
|
121
|
-
link.setAttribute('href', url)
|
122
|
-
|
123
|
-
document.body.appendChild(link)
|
124
|
-
link.click()
|
125
|
-
document.body.removeChild(link)
|
126
|
-
}
|
package/src/app/app-style.ts
DELETED
@@ -1,114 +0,0 @@
|
|
1
|
-
import { css } from 'lit'
|
2
|
-
|
3
|
-
export const AppStyle = css`
|
4
|
-
:host {
|
5
|
-
display: grid;
|
6
|
-
|
7
|
-
grid-template-rows: var(--app-grid-template-rows, auto 1fr auto);
|
8
|
-
grid-template-columns: var(--app-grid-template-columns, auto 1fr auto);
|
9
|
-
grid-template-areas: var(--app-grid-template-area, 'header header header' 'nav main aside' 'nav footer aside');
|
10
|
-
grid-gap: var(--app-grid-gap, 0em);
|
11
|
-
|
12
|
-
max-width: 100vw;
|
13
|
-
width: 100vw;
|
14
|
-
height: 100vh;
|
15
|
-
height: 100dvh;
|
16
|
-
}
|
17
|
-
|
18
|
-
ox-header-bar {
|
19
|
-
grid-area: header;
|
20
|
-
}
|
21
|
-
|
22
|
-
ox-nav-bar {
|
23
|
-
grid-area: nav;
|
24
|
-
}
|
25
|
-
|
26
|
-
div {
|
27
|
-
grid-area: main;
|
28
|
-
|
29
|
-
display: flex;
|
30
|
-
flex-direction: column;
|
31
|
-
overflow: hidden;
|
32
|
-
}
|
33
|
-
|
34
|
-
main {
|
35
|
-
flex: 1;
|
36
|
-
|
37
|
-
display: flex;
|
38
|
-
flex-direction: row;
|
39
|
-
overflow: hidden;
|
40
|
-
}
|
41
|
-
|
42
|
-
ox-aside-bar {
|
43
|
-
grid-area: aside;
|
44
|
-
}
|
45
|
-
|
46
|
-
ox-footer-bar {
|
47
|
-
grid-area: footer;
|
48
|
-
}
|
49
|
-
|
50
|
-
main > * {
|
51
|
-
flex: 1;
|
52
|
-
}
|
53
|
-
|
54
|
-
main > *:not([active]) {
|
55
|
-
display: none;
|
56
|
-
}
|
57
|
-
|
58
|
-
[hidden] {
|
59
|
-
display: none;
|
60
|
-
}
|
61
|
-
|
62
|
-
ox-snack-bar {
|
63
|
-
z-index: 1000;
|
64
|
-
}
|
65
|
-
|
66
|
-
@media print {
|
67
|
-
:host {
|
68
|
-
width: 100%;
|
69
|
-
height: 100%;
|
70
|
-
min-height: 100vh;
|
71
|
-
min-height: 100dvh;
|
72
|
-
|
73
|
-
max-width: unset;
|
74
|
-
width: unset;
|
75
|
-
height: unset;
|
76
|
-
height: unset;
|
77
|
-
}
|
78
|
-
|
79
|
-
main {
|
80
|
-
/* important for printing!!! */
|
81
|
-
display: block;
|
82
|
-
flex: unset;
|
83
|
-
overflow: visible;
|
84
|
-
}
|
85
|
-
|
86
|
-
ox-page-header-bar {
|
87
|
-
display: none;
|
88
|
-
}
|
89
|
-
|
90
|
-
ox-page-footer-bar {
|
91
|
-
display: none;
|
92
|
-
}
|
93
|
-
|
94
|
-
ox-header-bar {
|
95
|
-
display: none;
|
96
|
-
}
|
97
|
-
|
98
|
-
ox-nav-bar {
|
99
|
-
display: none;
|
100
|
-
}
|
101
|
-
|
102
|
-
ox-aside-bar {
|
103
|
-
display: none;
|
104
|
-
}
|
105
|
-
|
106
|
-
ox-footer-bar {
|
107
|
-
display: none;
|
108
|
-
}
|
109
|
-
|
110
|
-
ox-snack-bar {
|
111
|
-
display: none;
|
112
|
-
}
|
113
|
-
}
|
114
|
-
`
|
package/src/app/app.ts
DELETED
@@ -1,274 +0,0 @@
|
|
1
|
-
import { html, LitElement, PropertyValues } from 'lit'
|
2
|
-
import { customElement, property, query, state } from 'lit/decorators.js'
|
3
|
-
import { connect } from 'pwa-helpers/connect-mixin.js'
|
4
|
-
import { installRouter } from 'pwa-helpers/router.js'
|
5
|
-
|
6
|
-
import { ScrollbarStyles } from '@operato/styles'
|
7
|
-
import { setContextPathPrefix, getPathInfo } from '@operato/utils'
|
8
|
-
|
9
|
-
import { navigateWithSilence, UPDATE_ACTIVE_PAGE, UPDATE_CONTEXT_PATH, UPDATE_MODULES } from '../actions'
|
10
|
-
import { store } from '../store'
|
11
|
-
import { AppStyle } from './app-style'
|
12
|
-
import { PageView } from './pages/page-view'
|
13
|
-
|
14
|
-
enum MODULES_STATE {
|
15
|
-
NOT_INITIALIZED,
|
16
|
-
INITIALIZING,
|
17
|
-
INITIALIZED
|
18
|
-
}
|
19
|
-
|
20
|
-
@customElement('things-app')
|
21
|
-
export class ThingsApp extends connect(store)(LitElement) {
|
22
|
-
static styles = [ScrollbarStyles, AppStyle]
|
23
|
-
|
24
|
-
static moduleInitialized: MODULES_STATE = MODULES_STATE.NOT_INITIALIZED
|
25
|
-
static modules: Array<any> = []
|
26
|
-
|
27
|
-
/*
|
28
|
-
๋ชจ๋ ๋ชจ๋์ routes ๋ฆฌ์คํธ๊ฐ ์์ง๋ ๋๊น์ง, routeToPage(..) ๋ฅผ hold ์ํค๊ธฐ ์ํด์ ThingsApp.pages๋ฅผ Promise๋ก ์ ์ํ๋ค.
|
29
|
-
*/
|
30
|
-
static pagesResolver: (
|
31
|
-
value:
|
32
|
-
| {
|
33
|
-
[path: string]: string
|
34
|
-
}
|
35
|
-
| PromiseLike<{
|
36
|
-
[path: string]: string
|
37
|
-
}>
|
38
|
-
) => void
|
39
|
-
static pages: Promise<{ [path: string]: string }>
|
40
|
-
|
41
|
-
static callbacks: Array<any> = []
|
42
|
-
static contextPath?: string
|
43
|
-
|
44
|
-
@property({ type: String, attribute: 'context-path-prefix' }) contextPathPrefix?: string
|
45
|
-
|
46
|
-
@state() resourceId?: string
|
47
|
-
@state() page?: string
|
48
|
-
@state() params?: any
|
49
|
-
@state() activePage?: PageView
|
50
|
-
@state() context: any
|
51
|
-
@state() contextPath?: string = ThingsApp.contextPath
|
52
|
-
@state() modules: Array<any> = ThingsApp.modules
|
53
|
-
|
54
|
-
@query('main') private main!: HTMLElement
|
55
|
-
|
56
|
-
render() {
|
57
|
-
var params = this.params || {}
|
58
|
-
var fullbleed = (this.context && this.context.fullbleed) || (params.fullbleed && params.fullbleed == 'Y')
|
59
|
-
var widebleed = (this.context && this.context.widebleed) || (params.widebleed && params.widebleed == 'Y')
|
60
|
-
|
61
|
-
return html`
|
62
|
-
<div>
|
63
|
-
<ox-page-header-bar header></ox-page-header-bar>
|
64
|
-
<main></main>
|
65
|
-
<ox-page-footer-bar footer></ox-page-footer-bar>
|
66
|
-
</div>
|
67
|
-
|
68
|
-
<ox-header-bar ?fullbleed=${fullbleed}></ox-header-bar>
|
69
|
-
|
70
|
-
<ox-nav-bar ?fullbleed=${fullbleed || widebleed}></ox-nav-bar>
|
71
|
-
|
72
|
-
<ox-aside-bar ?fullbleed=${fullbleed || widebleed}></ox-aside-bar>
|
73
|
-
|
74
|
-
<ox-footer-bar ?fullbleed=${fullbleed}></ox-footer-bar>
|
75
|
-
|
76
|
-
<ox-snack-bar></ox-snack-bar>
|
77
|
-
`
|
78
|
-
}
|
79
|
-
|
80
|
-
connectedCallback() {
|
81
|
-
super.connectedCallback()
|
82
|
-
|
83
|
-
this.setBase()
|
84
|
-
|
85
|
-
if (ThingsApp.moduleInitialized != MODULES_STATE.NOT_INITIALIZED) {
|
86
|
-
/* ์ฒซ๋ฒ์งธ ์ดํ๋ก ์์ฑ๋๋ ๊ฒฝ์ฐ์๋ ๊ฐ์ ๋ก 'popstate'๋ฅผ ๋ฐ์์์ผ์, routing ๊ธฐํ๋ฅผ ์ค๋ค */
|
87
|
-
window.dispatchEvent(new CustomEvent('popstate'))
|
88
|
-
|
89
|
-
return
|
90
|
-
}
|
91
|
-
|
92
|
-
ThingsApp.moduleInitialized = MODULES_STATE.INITIALIZING
|
93
|
-
|
94
|
-
/* ๋ชจ๋ ์ํฌํธ๋ฅผ ๋์ ์ผ๋ก ์ฒ๋ฆฌํ๋ค. */
|
95
|
-
import(
|
96
|
-
/* webpackPrefetch: true */
|
97
|
-
/* webpackPreload: true */
|
98
|
-
/* webpackChunkName: "modules" */
|
99
|
-
'../module-importer.import'
|
100
|
-
).then(module => {
|
101
|
-
var modules: {
|
102
|
-
name: string
|
103
|
-
bootstrap: (m?: any /* self */) => void
|
104
|
-
}[] = module.modules
|
105
|
-
|
106
|
-
/* lifecycle - bootstrapping */
|
107
|
-
modules.forEach(async (m, idx) => {
|
108
|
-
try {
|
109
|
-
m.bootstrap && (await m.bootstrap(m))
|
110
|
-
} catch (e) {
|
111
|
-
console.error(`[${idx} BOOTSTRAP ERROR -${m.name}]`, e)
|
112
|
-
}
|
113
|
-
})
|
114
|
-
|
115
|
-
/* shouldUpdate๋ฅผ ํ์ฑํํ๋ค. */
|
116
|
-
ThingsApp.moduleInitialized = MODULES_STATE.INITIALIZED
|
117
|
-
|
118
|
-
/* modules๋ฅผ store์ dispatch ํจ์ผ๋ก์จ, update๋ฅผ invoke ์ํจ๋ค. */
|
119
|
-
store.dispatch({
|
120
|
-
type: UPDATE_MODULES,
|
121
|
-
modules
|
122
|
-
})
|
123
|
-
|
124
|
-
var lastPathName: string = ''
|
125
|
-
|
126
|
-
installRouter(async (location, e) => {
|
127
|
-
var { pathname } = location
|
128
|
-
var { contextPath } = getPathInfo(pathname)
|
129
|
-
|
130
|
-
/* ํ์ด์ง๋ฅผ ๋๊ฐ๊ธฐ ์ ์ ์ฎ๊ธฐ์ง ์๋๋ก ๊ฐ์
ํ ๊ธฐํ๋ฅผ ์ค๋ค */
|
131
|
-
if (
|
132
|
-
lastPathName &&
|
133
|
-
lastPathName != pathname &&
|
134
|
-
this.activePage &&
|
135
|
-
this.activePage.canDeactivate &&
|
136
|
-
!(await this.activePage.canDeactivate())
|
137
|
-
) {
|
138
|
-
history.pushState({}, this.activePage.title, lastPathName)
|
139
|
-
return
|
140
|
-
}
|
141
|
-
|
142
|
-
lastPathName = pathname
|
143
|
-
|
144
|
-
if (ThingsApp.contextPath !== contextPath) {
|
145
|
-
store.dispatch({
|
146
|
-
type: UPDATE_CONTEXT_PATH,
|
147
|
-
contextPath
|
148
|
-
})
|
149
|
-
}
|
150
|
-
|
151
|
-
store.dispatch(navigateWithSilence(location) as any)
|
152
|
-
|
153
|
-
ThingsApp.callbacks &&
|
154
|
-
ThingsApp.callbacks.forEach(callback => {
|
155
|
-
try {
|
156
|
-
callback.call(this, location, e)
|
157
|
-
} catch (ex) {
|
158
|
-
console.error(ex)
|
159
|
-
}
|
160
|
-
})
|
161
|
-
})
|
162
|
-
})
|
163
|
-
}
|
164
|
-
|
165
|
-
disconnectedCallback(): void {
|
166
|
-
super.disconnectedCallback()
|
167
|
-
}
|
168
|
-
|
169
|
-
async routeToPage() {
|
170
|
-
const activePages = this.renderRoot.querySelectorAll('main > .page[active]')
|
171
|
-
activePages.forEach(page => {
|
172
|
-
page.removeAttribute('active')
|
173
|
-
})
|
174
|
-
|
175
|
-
this.activePage = this.renderRoot.querySelector(`main > .page[data-page=${this.page}]`) as PageView
|
176
|
-
|
177
|
-
if (!this.activePage) {
|
178
|
-
/* ํด๋น route์ ์ฐ๊ฒฐ๋ page๊ฐ ์๋ ๊ฒฝ์ฐ์ main ์น์
์ ํด๋น element๋ฅผ ์ถ๊ฐํด์ค๋ค. */
|
179
|
-
const tagname = (await ThingsApp.pages)[this.page!]
|
180
|
-
if (tagname) {
|
181
|
-
const el = document.createElement(tagname) as PageView
|
182
|
-
el.setAttribute('class', 'page')
|
183
|
-
el.setAttribute('data-page', this.page!)
|
184
|
-
|
185
|
-
this.main.appendChild(el)
|
186
|
-
|
187
|
-
this.activePage = el
|
188
|
-
}
|
189
|
-
}
|
190
|
-
|
191
|
-
if (this.activePage) {
|
192
|
-
this.activePage.setAttribute('active', '')
|
193
|
-
this.activePage.setAttribute('context-path', this.contextPath!)
|
194
|
-
this.activePage.lifecycle = {
|
195
|
-
...(this.activePage.lifecycle || {}),
|
196
|
-
active: true,
|
197
|
-
params: this.params,
|
198
|
-
resourceId: this.resourceId,
|
199
|
-
page: this.page
|
200
|
-
}
|
201
|
-
}
|
202
|
-
|
203
|
-
store.dispatch({
|
204
|
-
type: UPDATE_ACTIVE_PAGE,
|
205
|
-
activePage: this.activePage
|
206
|
-
})
|
207
|
-
}
|
208
|
-
|
209
|
-
async updated(changes: PropertyValues<this>) {
|
210
|
-
if (changes.has('contextPathPrefix')) {
|
211
|
-
setContextPathPrefix(this.contextPathPrefix)
|
212
|
-
}
|
213
|
-
|
214
|
-
if (changes.has('modules')) {
|
215
|
-
ThingsApp.registerPages()
|
216
|
-
}
|
217
|
-
|
218
|
-
if (changes.has('page') || changes.has('resourceId') || changes.has('params')) {
|
219
|
-
this.routeToPage()
|
220
|
-
}
|
221
|
-
|
222
|
-
if (changes.has('contextPath')) {
|
223
|
-
this.setBase()
|
224
|
-
}
|
225
|
-
}
|
226
|
-
|
227
|
-
shouldUpdate() {
|
228
|
-
return ThingsApp.moduleInitialized == 2
|
229
|
-
}
|
230
|
-
|
231
|
-
stateChanged(state: any) {
|
232
|
-
this.page = state.route.page
|
233
|
-
this.params = state.route.params
|
234
|
-
this.resourceId = state.route.resourceId
|
235
|
-
this.context = state.route.context
|
236
|
-
|
237
|
-
ThingsApp.modules = this.modules = state.app.modules
|
238
|
-
ThingsApp.contextPath = this.contextPath = state.app.contextPath
|
239
|
-
ThingsApp.callbacks = state.route.callbacks
|
240
|
-
}
|
241
|
-
|
242
|
-
static async registerPages() {
|
243
|
-
ThingsApp.pages = new Promise<{ [path: string]: string }>(resolve => (ThingsApp.pagesResolver = resolve))
|
244
|
-
|
245
|
-
var reversedModules = [...ThingsApp.modules].reverse()
|
246
|
-
const pages: { [path: string]: string } = {}
|
247
|
-
|
248
|
-
/* ๋ชจ๋ ์ฐธ์กฐ ์์ ์ญ์์ผ๋ก page๋ฅผ ์ถ๊ฐํ๋ค. (for overidable) */
|
249
|
-
for (const m of reversedModules) {
|
250
|
-
if (!m.routes) {
|
251
|
-
continue
|
252
|
-
}
|
253
|
-
|
254
|
-
/*
|
255
|
-
๊ฐ ๋ชจ๋์ routes๊ฐ ๋ชจ๋ ์์ฑ๋ ๋๊น์ง ThingsApp.pages ๊ตฌ์ฑ์ ์ง์ฐํ๋ค.
|
256
|
-
๊ฐ ๋ชจ๋์ routes๋ฅผ ๋์ ์ผ๋ก๋ ๊ตฌ์ฑํ ์ ์๋๋ก ํ๊ธฐ ์ํด์์ด๋ค.
|
257
|
-
*/
|
258
|
-
const routes = await m.routes
|
259
|
-
|
260
|
-
routes.forEach((route: any) => {
|
261
|
-
if (!pages[route.page]) {
|
262
|
-
pages[route.page] = route.tagname
|
263
|
-
}
|
264
|
-
})
|
265
|
-
}
|
266
|
-
|
267
|
-
ThingsApp.pagesResolver(pages)
|
268
|
-
}
|
269
|
-
|
270
|
-
setBase() {
|
271
|
-
const base = document.querySelector('base')
|
272
|
-
base?.setAttribute('href', this.contextPath ? `${this.contextPath}/` : '/')
|
273
|
-
}
|
274
|
-
}
|