@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/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-alpha.51",
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-alpha.37",
63
- "@operato/popup": "^8.0.0-alpha.51",
64
- "@operato/styles": "^8.0.0-alpha.50",
65
- "@operato/utils": "^8.0.0-alpha.37",
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": "ac94e729e3647d45c921be99f96f4c2e65cef797"
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 = */
@@ -1,3 +0,0 @@
1
- module.exports = {
2
- stories: ['../dist/stories/**/*.stories.{js,md,mdx}'],
3
- };
@@ -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
- ]
@@ -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
- });
@@ -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
- }
@@ -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
- }
@@ -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 = ''
@@ -1,4 +0,0 @@
1
- export * from './app'
2
- export * from './route'
3
- export * from './busy'
4
- export * from './const'
@@ -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
- }
@@ -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
- }