@dssp/dkpi 1.0.0-alpha.40 → 1.0.0-alpha.47
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/dist-client/components/{pagenation.d.ts → sv-pagenation-control.d.ts} +1 -1
- package/dist-client/components/{pagenation.js → sv-pagenation-control.js} +10 -10
- package/dist-client/components/sv-pagenation-control.js.map +1 -0
- package/dist-client/icons/menu-icons.d.ts +6 -0
- package/dist-client/icons/menu-icons.js +42 -0
- package/dist-client/icons/menu-icons.js.map +1 -1
- package/dist-client/pages/kpi-metric-value/kpi-metric-value-editor-page.d.ts +58 -0
- package/dist-client/pages/kpi-metric-value/kpi-metric-value-editor-page.js +731 -0
- package/dist-client/pages/kpi-metric-value/kpi-metric-value-editor-page.js.map +1 -0
- package/dist-client/pages/kpi-metric-value/kpi-metric-value-importer.d.ts +23 -0
- package/dist-client/pages/kpi-metric-value/kpi-metric-value-importer.js +76 -0
- package/dist-client/pages/kpi-metric-value/kpi-metric-value-importer.js.map +1 -0
- package/dist-client/pages/kpi-metric-value/kpi-metric-value-list-page.d.ts +69 -0
- package/dist-client/pages/kpi-metric-value/kpi-metric-value-list-page.js +385 -0
- package/dist-client/pages/kpi-metric-value/kpi-metric-value-list-page.js.map +1 -0
- package/dist-client/pages/kpi-metric-value/kpi-metric-value-manual-entry-form.d.ts +12 -0
- package/dist-client/pages/kpi-metric-value/kpi-metric-value-manual-entry-form.js +174 -0
- package/dist-client/pages/kpi-metric-value/kpi-metric-value-manual-entry-form.js.map +1 -0
- package/dist-client/pages/kpi-metric-value/kpi-metric-value-manual-entry-page.d.ts +41 -0
- package/dist-client/pages/kpi-metric-value/kpi-metric-value-manual-entry-page.js +191 -0
- package/dist-client/pages/kpi-metric-value/kpi-metric-value-manual-entry-page.js.map +1 -0
- package/dist-client/pages/kpi-value/kpi-value-importer.d.ts +23 -0
- package/dist-client/pages/kpi-value/kpi-value-importer.js +93 -0
- package/dist-client/pages/kpi-value/kpi-value-importer.js.map +1 -0
- package/dist-client/pages/kpi-value/kpi-value-list-page.d.ts +72 -0
- package/dist-client/pages/kpi-value/kpi-value-list-page.js +465 -0
- package/dist-client/pages/kpi-value/kpi-value-list-page.js.map +1 -0
- package/dist-client/pages/project-complete-tabs/pc-tab1-plan.d.ts +12 -0
- package/dist-client/pages/project-complete-tabs/pc-tab1-plan.js +274 -0
- package/dist-client/pages/project-complete-tabs/pc-tab1-plan.js.map +1 -0
- package/dist-client/pages/project-complete-tabs/pc-tab2-final.d.ts +11 -0
- package/dist-client/pages/project-complete-tabs/pc-tab2-final.js +277 -0
- package/dist-client/pages/project-complete-tabs/pc-tab2-final.js.map +1 -0
- package/dist-client/pages/project-complete-tabs/pc-tab3-rating.d.ts +10 -0
- package/dist-client/pages/project-complete-tabs/pc-tab3-rating.js +230 -0
- package/dist-client/pages/project-complete-tabs/pc-tab3-rating.js.map +1 -0
- package/dist-client/pages/project-complete-tabs/pc-tab4-upload.d.ts +13 -0
- package/dist-client/pages/project-complete-tabs/pc-tab4-upload.js +217 -0
- package/dist-client/pages/project-complete-tabs/pc-tab4-upload.js.map +1 -0
- package/dist-client/pages/sv-project-complete.d.ts +26 -0
- package/dist-client/pages/sv-project-complete.js +299 -0
- package/dist-client/pages/sv-project-complete.js.map +1 -0
- package/dist-client/pages/sv-project-completed-list.d.ts +1 -1
- package/dist-client/pages/sv-project-completed-list.js +189 -168
- package/dist-client/pages/sv-project-completed-list.js.map +1 -1
- package/dist-client/pages/sv-project-detail.d.ts +13 -0
- package/dist-client/pages/sv-project-detail.js +486 -0
- package/dist-client/pages/sv-project-detail.js.map +1 -0
- package/dist-client/pages/sv-project-list.d.ts +6 -1
- package/dist-client/pages/sv-project-list.js +201 -186
- package/dist-client/pages/sv-project-list.js.map +1 -1
- package/dist-client/route.d.ts +1 -1
- package/dist-client/route.js +15 -0
- package/dist-client/route.js.map +1 -1
- package/dist-client/shared/complete-api.d.ts +3 -0
- package/dist-client/shared/complete-api.js +83 -0
- package/dist-client/shared/complete-api.js.map +1 -0
- package/dist-client/shared/func.d.ts +2 -0
- package/dist-client/shared/func.js +22 -0
- package/dist-client/shared/func.js.map +1 -0
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-client/viewparts/menu-tools.js +1 -0
- package/dist-client/viewparts/menu-tools.js.map +1 -1
- package/dist-server/index.d.ts +1 -0
- package/dist-server/index.js +1 -0
- package/dist-server/index.js.map +1 -1
- package/dist-server/scripts/propagate-parent-kpi-values.d.ts +10 -0
- package/dist-server/scripts/propagate-parent-kpi-values.js +440 -0
- package/dist-server/scripts/propagate-parent-kpi-values.js.map +1 -0
- package/dist-server/service/index.d.ts +6 -0
- package/dist-server/service/index.js +21 -0
- package/dist-server/service/index.js.map +1 -0
- package/dist-server/service/kpi-metric-value/index.d.ts +4 -0
- package/dist-server/service/kpi-metric-value/index.js +8 -0
- package/dist-server/service/kpi-metric-value/index.js.map +1 -0
- package/dist-server/service/kpi-metric-value/kpi-metric-value-mutation.d.ts +7 -0
- package/dist-server/service/kpi-metric-value/kpi-metric-value-mutation.js +104 -0
- package/dist-server/service/kpi-metric-value/kpi-metric-value-mutation.js.map +1 -0
- package/dist-server/service/kpi-metric-value/kpi-metric-value-query.d.ts +7 -0
- package/dist-server/service/kpi-metric-value/kpi-metric-value-query.js +47 -0
- package/dist-server/service/kpi-metric-value/kpi-metric-value-query.js.map +1 -0
- package/dist-server/service/kpi-value/index.d.ts +3 -0
- package/dist-server/service/kpi-value/index.js +7 -0
- package/dist-server/service/kpi-value/index.js.map +1 -0
- package/dist-server/service/kpi-value/kpi-value-query.d.ts +7 -0
- package/dist-server/service/kpi-value/kpi-value-query.js +47 -0
- package/dist-server/service/kpi-value/kpi-value-query.js.map +1 -0
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +7 -3
- package/schema.graphql +2122 -14
- package/things-factory.config.js +3 -1
- package/dist-client/components/pagenation.js.map +0 -1
|
@@ -137,6 +137,7 @@ let MenuTools = class MenuTools extends connect(store)(LitElement) {
|
|
|
137
137
|
path: 'project-setting-list',
|
|
138
138
|
icon: 'settings',
|
|
139
139
|
submenus: [
|
|
140
|
+
{ name: '프로젝트 관리', path: 'project-setting-list', icon: 'create' },
|
|
140
141
|
{ name: '사용자 관리', path: 'users', icon: 'people' },
|
|
141
142
|
{ name: '환경 설정', path: 'setting', icon: 'settings' }
|
|
142
143
|
]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"menu-tools.js","sourceRoot":"","sources":["../../client/viewparts/menu-tools.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/icon/icon.js'\n\nimport gql from 'graphql-tag'\nimport { css, html, LitElement } from 'lit'\nimport { customElement, property, query, state } from 'lit/decorators.js'\n\nimport { connect } from 'pwa-helpers'\n\nimport { store } from '@operato/shell'\nimport { client } from '@operato/graphql'\nimport { i18next } from '@operato/i18n'\n\n// import { ICONS_HOME, ICONS_KPIS, ICONS_INTEGRATION, ICONS_SETTING } from '../icons/menu-icons'\nexport async function queryDataSets(): Promise<{ id: string; name: string; description: string; active: boolean }[]> {\n const response = await client.query({\n query: gql`\n query ($filters: [Filter!], $pagination: Pagination, $sortings: [Sorting!]) {\n responses: dataSets(filters: $filters, pagination: $pagination, sortings: $sortings) {\n items {\n id\n name\n description\n active\n summaryPeriod\n }\n total\n }\n }\n `,\n variables: {\n filters: [\n {\n name: 'active',\n operator: 'eq',\n value: true\n }\n ],\n pagination: {},\n sortings: []\n }\n })\n\n return response.data.responses.items\n}\n\n@customElement('menu-tools')\nexport class MenuTools extends connect(store)(LitElement) {\n static styles = [\n css`\n :host {\n position: relative;\n display: flex;\n background-color: var(--secondary-color);\n\n /* for narrow mode */\n flex-direction: column;\n width: 100%;\n --menu-tools-color: rgba(255, 255, 255, 0.9);\n --menu-tools-active-color: rgba(107, 178, 249, 1);\n }\n\n :host([width='WIDE']) {\n /* for wide mode */\n flex-direction: row;\n width: initial;\n height: 100%;\n }\n\n ul {\n display: flex;\n flex-direction: row;\n\n margin: auto;\n padding: 0;\n list-style: none;\n height: 100%;\n overflow: none;\n }\n\n :host([width='NARROW']) ul {\n width: 100%;\n justify-content: space-around;\n }\n\n :host([width='WIDE']) ul {\n flex-direction: column;\n }\n :host([width='NARROW']) li {\n flex: 1;\n }\n\n :host([width='WIDE']) li {\n border-top: 1px solid rgba(255, 255, 255, 0.1);\n border-bottom: 1px solid rgba(0, 0, 0, 0.1);\n }\n\n a {\n display: flex;\n flex-direction: column;\n padding: 8px 8px 4px 8px;\n opacity: 0.7;\n align-items: center;\n text-align: center;\n text-decoration: none;\n text-transform: capitalize;\n color: var(--menu-tools-color);\n border-left: 2px solid transparent;\n\n --md-icon-size: 36px;\n }\n\n a[active] {\n opacity: 1;\n color: var(--menu-tools-active-color);\n font-weight: bold;\n background-color: rgba(0, 0, 0, 0.15);\n border-left: 2px solid var(--menu-tools-active-color);\n }\n\n :host([width='NARROW']) a {\n padding: 0px 0px 5px 0px;\n opacity: 0.8;\n color: var(--menu-tools-color);\n border-left: none;\n border-top: 2px solid transparent;\n }\n\n :host([width='NARROW']) a[active] {\n opacity: 1;\n color: var(--menu-tools-active-color);\n font-weight: bold;\n background-color: rgba(0, 0, 0, 0.15);\n border-left: none;\n border-top: 2px solid var(--menu-tools-active-color);\n }\n\n img {\n display: block;\n width: 35px;\n padding: 5px 10px 0px 10px;\n }\n\n :host([width='NARROW']) img {\n padding: 0;\n }\n\n div {\n font-size: 0.6em;\n }\n\n .submenu-popup {\n position: absolute;\n left: 60px; /* 탑메뉴 width */\n top: 0;\n width: 220px;\n height: 100%;\n background: linear-gradient(135deg, #1e293b 0%, #334155 100%);\n color: #fff;\n box-shadow: 2px 0 8px rgba(0, 0, 0, 0.15);\n z-index: 1000;\n display: flex;\n flex-direction: column;\n border-radius: 0 10px 10px 0;\n }\n\n .submenu-popup ul {\n list-style: none;\n margin: 0;\n padding: 0;\n }\n\n .submenu-popup li {\n font-size: 1.1em;\n }\n\n .submenu-popup li a {\n color: #fff;\n text-decoration: none;\n display: flex;\n flex-direction: row;\n align-items: center;\n gap: 12px;\n transition: background 0.2s;\n padding: 12px 16px;\n }\n\n .submenu-popup li a:hover {\n background: #333;\n }\n\n .submenu-popup li a md-icon {\n --md-icon-size: 20px;\n color: rgba(255, 255, 255, 0.8);\n }\n\n .submenu-popup li a[active] md-icon {\n color: var(--menu-tools-active-color);\n }\n .submenu-popup li {\n position: relative;\n }\n .subsubmenu {\n margin-left: 20px;\n margin-top: 8px;\n border-left: 2px solid rgba(255, 255, 255, 0.2);\n padding-left: 12px;\n }\n .subsubmenu li {\n padding: 8px 16px;\n font-size: 0.9em;\n }\n .subsubmenu li a {\n padding: 8px 12px;\n font-size: 0.85em;\n opacity: 0.8;\n }\n .subsubmenu li a:hover {\n opacity: 1;\n background: rgba(255, 255, 255, 0.1);\n }\n .subsubmenu li a[active] {\n opacity: 1;\n color: var(--menu-tools-active-color);\n background: rgba(107, 178, 249, 0.2);\n }\n .subsubmenu li a md-icon {\n --md-icon-size: 16px;\n }\n .expand-button {\n margin-left: auto;\n background: none;\n border: none;\n color: rgba(255, 255, 255, 0.6);\n cursor: pointer;\n padding: 4px;\n border-radius: 4px;\n transition: all 0.2s;\n }\n .expand-button:hover {\n color: rgba(255, 255, 255, 0.9);\n background: rgba(255, 255, 255, 0.1);\n }\n .expand-button md-icon {\n --md-icon-size: 16px;\n transition: transform 0.2s;\n }\n .expand-button.expanded md-icon {\n transform: rotate(90deg);\n }\n `\n ]\n\n @property({ type: String }) page?: string\n @property({ type: String, reflect: true }) width?: string\n\n @state() dataSets: any[] = []\n @state() menus: {\n name: string\n path: string\n icon: string\n submenus?: { name: string; path: string; icon?: string; subsubmenus?: { name: string; path: string; icon?: string }[] }[]\n }[] = this.getMenus()\n\n private getMenus(): {\n name: string\n path: string\n icon: string\n submenus?: { name: string; path: string; icon?: string; subsubmenus?: { name: string; path: string; icon?: string }[] }[]\n }[] {\n const dataSets = this.dataSets\n\n return [\n {\n name: '홈',\n path: 'project-list',\n icon: 'location_city',\n submenus: [\n { name: '프로젝트 목록', path: 'project-list', icon: 'autoplay' },\n { name: '완료 프로젝트 목록', path: 'project-completed-list', icon: 'stop_circle' }\n ]\n },\n {\n name: 'KPI',\n path: 'kpi-overview',\n icon: 'bar_chart',\n submenus: [\n { name: 'KPI 개요', path: 'kpi-overview', icon: 'widget_small' },\n { name: 'KPI 성과판', path: 'kpi-dashboard', icon: 'dashboard' },\n {\n name: i18next.t('title.kpi statistic list'),\n icon: 'candlestick_chart',\n path: 'kpi-statistic-list'\n },\n {\n name: i18next.t('title.kpi statistic editor'),\n icon: 'edit_square',\n path: 'kpi-statistic-editor'\n },\n { name: 'KPI 목록', path: 'kpi-list', icon: 'readiness_score' },\n { name: 'KPI 값 목록', path: 'kpi-value-list', icon: 'heap_snapshot_multiple' },\n { name: 'KPI 메트릭 목록', path: 'kpi-metric-list', icon: 'data_exploration' },\n { name: 'KPI 메트릭 값 목록', path: 'kpi-metric-value-list', icon: 'heap_snapshot_multiple' },\n { name: 'KPI 매트릭 값 수동 입력', path: 'kpi-metric-value-manual-entry', icon: 'edit' }\n ]\n },\n {\n name: 'Data Set',\n path: 'data-set-list',\n icon: 'dataset',\n submenus: [\n { name: 'Data Set 목록', path: 'data-set-list', icon: 'dataset' },\n { name: 'Data Key 목록', path: 'data-key-set-list', icon: 'key' },\n { name: 'Data Sample 값 수동 입력', path: 'data-entry-list', icon: 'edit' },\n {\n name: 'Data Sample 목록',\n path: 'data-sample-list',\n icon: 'rule',\n subsubmenus:\n dataSets.map(item => {\n return {\n name: item.name,\n icon: 'checklist_rtl',\n path: `data-sample-search/${item.id}`\n }\n }) || []\n },\n {\n name: 'Data Summary 목록',\n path: 'data-summary-list',\n icon: 'functions',\n subsubmenus:\n dataSets\n .filter(item => item.active && item.summaryPeriod)\n .map(item => {\n return {\n name: item.name,\n icon: 'checklist',\n path: `data-summary-period/${item.id}`\n }\n }) || []\n }\n ]\n },\n {\n name: '시스템연계',\n path: 'project-task-list',\n icon: 'hub',\n submenus: [\n { name: '연계 현황', path: 'integration-monitor', icon: 'hub' },\n { name: '연계 설정', path: 'connection', icon: 'settings' },\n { name: '연계 시나리오', path: 'scenario', icon: 'hub' }\n ]\n },\n {\n name: '셋팅',\n path: 'project-setting-list',\n icon: 'settings',\n submenus: [\n { name: '사용자 관리', path: 'users', icon: 'people' },\n { name: '환경 설정', path: 'setting', icon: 'settings' }\n ]\n }\n ]\n }\n\n @property({ type: Number }) openedMenuIndex: number | null = null\n @property({ type: Number }) openedSubmenuIndex: number | null = null\n @query('ul') menuUl!: HTMLUListElement\n @property({ type: Number }) submenuHeight: number | null = null\n\n render() {\n var page = this.page || ''\n return html`\n <ul>\n ${this.menus.map(\n (menu, i) => html`\n <li\n @click=${(e: Event) => {\n e.stopPropagation()\n this.openedMenuIndex = i\n this._setSubmenuHeight()\n }}\n >\n <a href=\"javascript:void(0)\" ?active=${this._isActiveMenu(page, menu)}>\n <md-icon>${menu.icon}</md-icon>\n <div>${menu.name}</div>\n </a>\n </li>\n `\n )}\n </ul>\n ${this.openedMenuIndex !== null\n ? html`\n <div class=\"submenu-popup\">\n <ul>\n ${this.menus[this.openedMenuIndex].submenus?.map(\n (sub, subIndex) => html`\n <li>\n <a\n href=${sub.subsubmenus ? 'javascript:void(0)' : sub.path}\n ?active=${this._isActiveSubmenu(page, sub.path)}\n @click=${sub.subsubmenus ? (e: Event) => e.preventDefault() : undefined}\n >\n ${sub.icon ? html`<md-icon>${sub.icon}</md-icon>` : ''} ${sub.name}\n ${sub.subsubmenus\n ? html`\n <button\n class=\"expand-button ${this.openedSubmenuIndex === subIndex ? 'expanded' : ''}\"\n @click=${(e: Event) => this._toggleSubsubmenu(e, subIndex)}\n >\n <md-icon>chevron_right</md-icon>\n </button>\n `\n : ''}\n </a>\n ${sub.subsubmenus && this.openedSubmenuIndex === subIndex\n ? html`\n <ul class=\"subsubmenu\">\n ${sub.subsubmenus.map(\n subsub => html`\n <li>\n <a href=${subsub.path} ?active=${this._isActiveSubsubmenu(page, subsub.path)}>\n ${subsub.icon ? html`<md-icon>${subsub.icon}</md-icon>` : ''} ${subsub.name}\n </a>\n </li>\n `\n )}\n </ul>\n `\n : ''}\n </li>\n `\n )}\n </ul>\n </div>\n `\n : ''}\n `\n }\n\n private _isActiveMenu(currentPage: string, menu: any): boolean {\n // 메인 메뉴의 active 상태 확인\n if (currentPage === menu.path) return true\n\n // 서브메뉴 중 하나라도 active인지 확인\n if (menu.submenus) {\n return menu.submenus.some((sub: any) => currentPage === sub.path || currentPage.startsWith(sub.path + '/'))\n }\n\n return false\n }\n\n private _isActiveSubmenu(currentPage: string, submenuPath: string): boolean {\n return currentPage === submenuPath || currentPage.startsWith(submenuPath + '/')\n }\n\n async firstUpdated() {\n this._setSubmenuHeight()\n\n this.dataSets = await queryDataSets()\n this.menus = this.getMenus()\n }\n\n updated(changedProps) {\n if (changedProps.has('openedMenuIndex')) {\n this._setSubmenuHeight()\n }\n }\n\n _setSubmenuHeight() {\n if (this.menuUl) {\n this.submenuHeight = this.menuUl.clientHeight\n }\n }\n\n connectedCallback() {\n super.connectedCallback()\n window.addEventListener('click', this._closeSubmenu)\n }\n\n disconnectedCallback() {\n window.removeEventListener('click', this._closeSubmenu)\n super.disconnectedCallback()\n }\n\n private _closeSubmenu = () => {\n this.openedMenuIndex = null\n }\n\n private _toggleSubsubmenu(e: Event, subIndex: number) {\n e.stopPropagation()\n if (this.openedSubmenuIndex === subIndex) {\n this.openedSubmenuIndex = null\n } else {\n this.openedSubmenuIndex = subIndex\n }\n }\n\n private _isActiveSubsubmenu(currentPage: string, subsubmenuPath: string): boolean {\n return currentPage === subsubmenuPath || currentPage.startsWith(subsubmenuPath + '/')\n }\n\n stateChanged(state) {\n this.page = state.route.page\n this.width = state.layout.width\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"menu-tools.js","sourceRoot":"","sources":["../../client/viewparts/menu-tools.ts"],"names":[],"mappings":";AAAA,OAAO,4BAA4B,CAAA;AAEnC,OAAO,GAAG,MAAM,aAAa,CAAA;AAC7B,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,KAAK,CAAA;AAC3C,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AAEzE,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AAErC,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAA;AACtC,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AAEvC,iGAAiG;AACjG,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC;QAClC,KAAK,EAAE,GAAG,CAAA;;;;;;;;;;;;;KAaT;QACD,SAAS,EAAE;YACT,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,QAAQ;oBACd,QAAQ,EAAE,IAAI;oBACd,KAAK,EAAE,IAAI;iBACZ;aACF;YACD,UAAU,EAAE,EAAE;YACd,QAAQ,EAAE,EAAE;SACb;KACF,CAAC,CAAA;IAEF,OAAO,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAA;AACtC,CAAC;AAGM,IAAM,SAAS,GAAf,MAAM,SAAU,SAAQ,OAAO,CAAC,KAAK,CAAC,CAAC,UAAU,CAAC;IAAlD;;QAiNI,aAAQ,GAAU,EAAE,CAAA;QACpB,UAAK,GAKR,IAAI,CAAC,QAAQ,EAAE,CAAA;QAyGO,oBAAe,GAAkB,IAAI,CAAA;QACrC,uBAAkB,GAAkB,IAAI,CAAA;QAExC,kBAAa,GAAkB,IAAI,CAAA;QAqHvD,kBAAa,GAAG,GAAG,EAAE;YAC3B,IAAI,CAAC,eAAe,GAAG,IAAI,CAAA;QAC7B,CAAC,CAAA;IAmBH,CAAC;IApPS,QAAQ;QAMd,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAA;QAE9B,OAAO;YACL;gBACE,IAAI,EAAE,GAAG;gBACT,IAAI,EAAE,cAAc;gBACpB,IAAI,EAAE,eAAe;gBACrB,QAAQ,EAAE;oBACR,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,UAAU,EAAE;oBAC3D,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,wBAAwB,EAAE,IAAI,EAAE,aAAa,EAAE;iBAC5E;aACF;YACD;gBACE,IAAI,EAAE,KAAK;gBACX,IAAI,EAAE,cAAc;gBACpB,IAAI,EAAE,WAAW;gBACjB,QAAQ,EAAE;oBACR,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,cAAc,EAAE;oBAC9D,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,eAAe,EAAE,IAAI,EAAE,WAAW,EAAE;oBAC7D;wBACE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,0BAA0B,CAAC;wBAC3C,IAAI,EAAE,mBAAmB;wBACzB,IAAI,EAAE,oBAAoB;qBAC3B;oBACD;wBACE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,4BAA4B,CAAC;wBAC7C,IAAI,EAAE,aAAa;wBACnB,IAAI,EAAE,sBAAsB;qBAC7B;oBACD,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,iBAAiB,EAAE;oBAC7D,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,gBAAgB,EAAE,IAAI,EAAE,wBAAwB,EAAE;oBAC5E,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,iBAAiB,EAAE,IAAI,EAAE,kBAAkB,EAAE;oBACzE,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,uBAAuB,EAAE,IAAI,EAAE,wBAAwB,EAAE;oBACvF,EAAE,IAAI,EAAE,iBAAiB,EAAE,IAAI,EAAE,+BAA+B,EAAE,IAAI,EAAE,MAAM,EAAE;iBACjF;aACF;YACD;gBACE,IAAI,EAAE,UAAU;gBAChB,IAAI,EAAE,eAAe;gBACrB,IAAI,EAAE,SAAS;gBACf,QAAQ,EAAE;oBACR,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,eAAe,EAAE,IAAI,EAAE,SAAS,EAAE;oBAC/D,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,mBAAmB,EAAE,IAAI,EAAE,KAAK,EAAE;oBAC/D,EAAE,IAAI,EAAE,qBAAqB,EAAE,IAAI,EAAE,iBAAiB,EAAE,IAAI,EAAE,MAAM,EAAE;oBACtE;wBACE,IAAI,EAAE,gBAAgB;wBACtB,IAAI,EAAE,kBAAkB;wBACxB,IAAI,EAAE,MAAM;wBACZ,WAAW,EACT,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;4BAClB,OAAO;gCACL,IAAI,EAAE,IAAI,CAAC,IAAI;gCACf,IAAI,EAAE,eAAe;gCACrB,IAAI,EAAE,sBAAsB,IAAI,CAAC,EAAE,EAAE;6BACtC,CAAA;wBACH,CAAC,CAAC,IAAI,EAAE;qBACX;oBACD;wBACE,IAAI,EAAE,iBAAiB;wBACvB,IAAI,EAAE,mBAAmB;wBACzB,IAAI,EAAE,WAAW;wBACjB,WAAW,EACT,QAAQ;6BACL,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,aAAa,CAAC;6BACjD,GAAG,CAAC,IAAI,CAAC,EAAE;4BACV,OAAO;gCACL,IAAI,EAAE,IAAI,CAAC,IAAI;gCACf,IAAI,EAAE,WAAW;gCACjB,IAAI,EAAE,uBAAuB,IAAI,CAAC,EAAE,EAAE;6BACvC,CAAA;wBACH,CAAC,CAAC,IAAI,EAAE;qBACb;iBACF;aACF;YACD;gBACE,IAAI,EAAE,OAAO;gBACb,IAAI,EAAE,mBAAmB;gBACzB,IAAI,EAAE,KAAK;gBACX,QAAQ,EAAE;oBACR,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,qBAAqB,EAAE,IAAI,EAAE,KAAK,EAAE;oBAC3D,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,UAAU,EAAE;oBACvD,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,KAAK,EAAE;iBACnD;aACF;YACD;gBACE,IAAI,EAAE,IAAI;gBACV,IAAI,EAAE,sBAAsB;gBAC5B,IAAI,EAAE,UAAU;gBAChB,QAAQ,EAAE;oBACR,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,sBAAsB,EAAE,IAAI,EAAE,QAAQ,EAAE;oBACjE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE;oBACjD,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,UAAU,EAAE;iBACrD;aACF;SACF,CAAA;IACH,CAAC;IAOD,MAAM;;QACJ,IAAI,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,EAAE,CAAA;QAC1B,OAAO,IAAI,CAAA;;UAEL,IAAI,CAAC,KAAK,CAAC,GAAG,CACd,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAA;;uBAEJ,CAAC,CAAQ,EAAE,EAAE;YACpB,CAAC,CAAC,eAAe,EAAE,CAAA;YACnB,IAAI,CAAC,eAAe,GAAG,CAAC,CAAA;YACxB,IAAI,CAAC,iBAAiB,EAAE,CAAA;QAC1B,CAAC;;qDAEsC,IAAI,CAAC,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC;2BACxD,IAAI,CAAC,IAAI;uBACb,IAAI,CAAC,IAAI;;;WAGrB,CACF;;QAED,IAAI,CAAC,eAAe,KAAK,IAAI;YAC7B,CAAC,CAAC,IAAI,CAAA;;;kBAGI,MAAA,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,QAAQ,0CAAE,GAAG,CAC9C,CAAC,GAAG,EAAE,QAAQ,EAAE,EAAE,CAAC,IAAI,CAAA;;;+BAGV,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI;kCAC9C,IAAI,CAAC,gBAAgB,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC;iCACtC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAQ,EAAE,EAAE,CAAC,CAAC,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,SAAS;;0BAErE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAA,YAAY,GAAG,CAAC,IAAI,YAAY,CAAC,CAAC,CAAC,EAAE,IAAI,GAAG,CAAC,IAAI;0BAChE,GAAG,CAAC,WAAW;gBACf,CAAC,CAAC,IAAI,CAAA;;uDAEuB,IAAI,CAAC,kBAAkB,KAAK,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE;yCACpE,CAAC,CAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,EAAE,QAAQ,CAAC;;;;6BAI7D;gBACH,CAAC,CAAC,EAAE;;wBAEN,GAAG,CAAC,WAAW,IAAI,IAAI,CAAC,kBAAkB,KAAK,QAAQ;gBACvD,CAAC,CAAC,IAAI,CAAA;;gCAEE,GAAG,CAAC,WAAW,CAAC,GAAG,CACnB,MAAM,CAAC,EAAE,CAAC,IAAI,CAAA;;8CAEA,MAAM,CAAC,IAAI,YAAY,IAAI,CAAC,mBAAmB,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC;wCACxE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAA,YAAY,MAAM,CAAC,IAAI,YAAY,CAAC,CAAC,CAAC,EAAE,IAAI,MAAM,CAAC,IAAI;;;iCAGhF,CACF;;2BAEJ;gBACH,CAAC,CAAC,EAAE;;mBAET,CACF;;;WAGN;YACH,CAAC,CAAC,EAAE;KACP,CAAA;IACH,CAAC;IAEO,aAAa,CAAC,WAAmB,EAAE,IAAS;QAClD,sBAAsB;QACtB,IAAI,WAAW,KAAK,IAAI,CAAC,IAAI;YAAE,OAAO,IAAI,CAAA;QAE1C,0BAA0B;QAC1B,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClB,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,GAAQ,EAAE,EAAE,CAAC,WAAW,KAAK,GAAG,CAAC,IAAI,IAAI,WAAW,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,CAAC,CAAA;QAC7G,CAAC;QAED,OAAO,KAAK,CAAA;IACd,CAAC;IAEO,gBAAgB,CAAC,WAAmB,EAAE,WAAmB;QAC/D,OAAO,WAAW,KAAK,WAAW,IAAI,WAAW,CAAC,UAAU,CAAC,WAAW,GAAG,GAAG,CAAC,CAAA;IACjF,CAAC;IAED,KAAK,CAAC,YAAY;QAChB,IAAI,CAAC,iBAAiB,EAAE,CAAA;QAExB,IAAI,CAAC,QAAQ,GAAG,MAAM,aAAa,EAAE,CAAA;QACrC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAA;IAC9B,CAAC;IAED,OAAO,CAAC,YAAY;QAClB,IAAI,YAAY,CAAC,GAAG,CAAC,iBAAiB,CAAC,EAAE,CAAC;YACxC,IAAI,CAAC,iBAAiB,EAAE,CAAA;QAC1B,CAAC;IACH,CAAC;IAED,iBAAiB;QACf,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,MAAM,CAAC,YAAY,CAAA;QAC/C,CAAC;IACH,CAAC;IAED,iBAAiB;QACf,KAAK,CAAC,iBAAiB,EAAE,CAAA;QACzB,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,IAAI,CAAC,aAAa,CAAC,CAAA;IACtD,CAAC;IAED,oBAAoB;QAClB,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,IAAI,CAAC,aAAa,CAAC,CAAA;QACvD,KAAK,CAAC,oBAAoB,EAAE,CAAA;IAC9B,CAAC;IAMO,iBAAiB,CAAC,CAAQ,EAAE,QAAgB;QAClD,CAAC,CAAC,eAAe,EAAE,CAAA;QACnB,IAAI,IAAI,CAAC,kBAAkB,KAAK,QAAQ,EAAE,CAAC;YACzC,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAA;QAChC,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,kBAAkB,GAAG,QAAQ,CAAA;QACpC,CAAC;IACH,CAAC;IAEO,mBAAmB,CAAC,WAAmB,EAAE,cAAsB;QACrE,OAAO,WAAW,KAAK,cAAc,IAAI,WAAW,CAAC,UAAU,CAAC,cAAc,GAAG,GAAG,CAAC,CAAA;IACvF,CAAC;IAED,YAAY,CAAC,KAAK;QAChB,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,CAAA;QAC5B,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,KAAK,CAAA;IACjC,CAAC;;AA3cM,gBAAM,GAAG;IACd,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAyMF;CACF,AA3MY,CA2MZ;AAE2B;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;uCAAc;AACE;IAA1C,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;;wCAAe;AAEhD;IAAR,KAAK,EAAE;;2CAAqB;AACpB;IAAR,KAAK,EAAE;;wCAKa;AAyGO;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;kDAAsC;AACrC;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;qDAAyC;AACvD;IAAZ,KAAK,CAAC,IAAI,CAAC;8BAAU,gBAAgB;yCAAA;AACV;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;gDAAoC;AAnUpD,SAAS;IADrB,aAAa,CAAC,YAAY,CAAC;GACf,SAAS,CA6crB","sourcesContent":["import '@material/web/icon/icon.js'\n\nimport gql from 'graphql-tag'\nimport { css, html, LitElement } from 'lit'\nimport { customElement, property, query, state } from 'lit/decorators.js'\n\nimport { connect } from 'pwa-helpers'\n\nimport { store } from '@operato/shell'\nimport { client } from '@operato/graphql'\nimport { i18next } from '@operato/i18n'\n\n// import { ICONS_HOME, ICONS_KPIS, ICONS_INTEGRATION, ICONS_SETTING } from '../icons/menu-icons'\nexport async function queryDataSets(): Promise<{ id: string; name: string; description: string; active: boolean }[]> {\n const response = await client.query({\n query: gql`\n query ($filters: [Filter!], $pagination: Pagination, $sortings: [Sorting!]) {\n responses: dataSets(filters: $filters, pagination: $pagination, sortings: $sortings) {\n items {\n id\n name\n description\n active\n summaryPeriod\n }\n total\n }\n }\n `,\n variables: {\n filters: [\n {\n name: 'active',\n operator: 'eq',\n value: true\n }\n ],\n pagination: {},\n sortings: []\n }\n })\n\n return response.data.responses.items\n}\n\n@customElement('menu-tools')\nexport class MenuTools extends connect(store)(LitElement) {\n static styles = [\n css`\n :host {\n position: relative;\n display: flex;\n background-color: var(--secondary-color);\n\n /* for narrow mode */\n flex-direction: column;\n width: 100%;\n --menu-tools-color: rgba(255, 255, 255, 0.9);\n --menu-tools-active-color: rgba(107, 178, 249, 1);\n }\n\n :host([width='WIDE']) {\n /* for wide mode */\n flex-direction: row;\n width: initial;\n height: 100%;\n }\n\n ul {\n display: flex;\n flex-direction: row;\n\n margin: auto;\n padding: 0;\n list-style: none;\n height: 100%;\n overflow: none;\n }\n\n :host([width='NARROW']) ul {\n width: 100%;\n justify-content: space-around;\n }\n\n :host([width='WIDE']) ul {\n flex-direction: column;\n }\n :host([width='NARROW']) li {\n flex: 1;\n }\n\n :host([width='WIDE']) li {\n border-top: 1px solid rgba(255, 255, 255, 0.1);\n border-bottom: 1px solid rgba(0, 0, 0, 0.1);\n }\n\n a {\n display: flex;\n flex-direction: column;\n padding: 8px 8px 4px 8px;\n opacity: 0.7;\n align-items: center;\n text-align: center;\n text-decoration: none;\n text-transform: capitalize;\n color: var(--menu-tools-color);\n border-left: 2px solid transparent;\n\n --md-icon-size: 36px;\n }\n\n a[active] {\n opacity: 1;\n color: var(--menu-tools-active-color);\n font-weight: bold;\n background-color: rgba(0, 0, 0, 0.15);\n border-left: 2px solid var(--menu-tools-active-color);\n }\n\n :host([width='NARROW']) a {\n padding: 0px 0px 5px 0px;\n opacity: 0.8;\n color: var(--menu-tools-color);\n border-left: none;\n border-top: 2px solid transparent;\n }\n\n :host([width='NARROW']) a[active] {\n opacity: 1;\n color: var(--menu-tools-active-color);\n font-weight: bold;\n background-color: rgba(0, 0, 0, 0.15);\n border-left: none;\n border-top: 2px solid var(--menu-tools-active-color);\n }\n\n img {\n display: block;\n width: 35px;\n padding: 5px 10px 0px 10px;\n }\n\n :host([width='NARROW']) img {\n padding: 0;\n }\n\n div {\n font-size: 0.6em;\n }\n\n .submenu-popup {\n position: absolute;\n left: 60px; /* 탑메뉴 width */\n top: 0;\n width: 220px;\n height: 100%;\n background: linear-gradient(135deg, #1e293b 0%, #334155 100%);\n color: #fff;\n box-shadow: 2px 0 8px rgba(0, 0, 0, 0.15);\n z-index: 1000;\n display: flex;\n flex-direction: column;\n border-radius: 0 10px 10px 0;\n }\n\n .submenu-popup ul {\n list-style: none;\n margin: 0;\n padding: 0;\n }\n\n .submenu-popup li {\n font-size: 1.1em;\n }\n\n .submenu-popup li a {\n color: #fff;\n text-decoration: none;\n display: flex;\n flex-direction: row;\n align-items: center;\n gap: 12px;\n transition: background 0.2s;\n padding: 12px 16px;\n }\n\n .submenu-popup li a:hover {\n background: #333;\n }\n\n .submenu-popup li a md-icon {\n --md-icon-size: 20px;\n color: rgba(255, 255, 255, 0.8);\n }\n\n .submenu-popup li a[active] md-icon {\n color: var(--menu-tools-active-color);\n }\n .submenu-popup li {\n position: relative;\n }\n .subsubmenu {\n margin-left: 20px;\n margin-top: 8px;\n border-left: 2px solid rgba(255, 255, 255, 0.2);\n padding-left: 12px;\n }\n .subsubmenu li {\n padding: 8px 16px;\n font-size: 0.9em;\n }\n .subsubmenu li a {\n padding: 8px 12px;\n font-size: 0.85em;\n opacity: 0.8;\n }\n .subsubmenu li a:hover {\n opacity: 1;\n background: rgba(255, 255, 255, 0.1);\n }\n .subsubmenu li a[active] {\n opacity: 1;\n color: var(--menu-tools-active-color);\n background: rgba(107, 178, 249, 0.2);\n }\n .subsubmenu li a md-icon {\n --md-icon-size: 16px;\n }\n .expand-button {\n margin-left: auto;\n background: none;\n border: none;\n color: rgba(255, 255, 255, 0.6);\n cursor: pointer;\n padding: 4px;\n border-radius: 4px;\n transition: all 0.2s;\n }\n .expand-button:hover {\n color: rgba(255, 255, 255, 0.9);\n background: rgba(255, 255, 255, 0.1);\n }\n .expand-button md-icon {\n --md-icon-size: 16px;\n transition: transform 0.2s;\n }\n .expand-button.expanded md-icon {\n transform: rotate(90deg);\n }\n `\n ]\n\n @property({ type: String }) page?: string\n @property({ type: String, reflect: true }) width?: string\n\n @state() dataSets: any[] = []\n @state() menus: {\n name: string\n path: string\n icon: string\n submenus?: { name: string; path: string; icon?: string; subsubmenus?: { name: string; path: string; icon?: string }[] }[]\n }[] = this.getMenus()\n\n private getMenus(): {\n name: string\n path: string\n icon: string\n submenus?: { name: string; path: string; icon?: string; subsubmenus?: { name: string; path: string; icon?: string }[] }[]\n }[] {\n const dataSets = this.dataSets\n\n return [\n {\n name: '홈',\n path: 'project-list',\n icon: 'location_city',\n submenus: [\n { name: '프로젝트 목록', path: 'project-list', icon: 'autoplay' },\n { name: '완료 프로젝트 목록', path: 'project-completed-list', icon: 'stop_circle' }\n ]\n },\n {\n name: 'KPI',\n path: 'kpi-overview',\n icon: 'bar_chart',\n submenus: [\n { name: 'KPI 개요', path: 'kpi-overview', icon: 'widget_small' },\n { name: 'KPI 성과판', path: 'kpi-dashboard', icon: 'dashboard' },\n {\n name: i18next.t('title.kpi statistic list'),\n icon: 'candlestick_chart',\n path: 'kpi-statistic-list'\n },\n {\n name: i18next.t('title.kpi statistic editor'),\n icon: 'edit_square',\n path: 'kpi-statistic-editor'\n },\n { name: 'KPI 목록', path: 'kpi-list', icon: 'readiness_score' },\n { name: 'KPI 값 목록', path: 'kpi-value-list', icon: 'heap_snapshot_multiple' },\n { name: 'KPI 메트릭 목록', path: 'kpi-metric-list', icon: 'data_exploration' },\n { name: 'KPI 메트릭 값 목록', path: 'kpi-metric-value-list', icon: 'heap_snapshot_multiple' },\n { name: 'KPI 매트릭 값 수동 입력', path: 'kpi-metric-value-manual-entry', icon: 'edit' }\n ]\n },\n {\n name: 'Data Set',\n path: 'data-set-list',\n icon: 'dataset',\n submenus: [\n { name: 'Data Set 목록', path: 'data-set-list', icon: 'dataset' },\n { name: 'Data Key 목록', path: 'data-key-set-list', icon: 'key' },\n { name: 'Data Sample 값 수동 입력', path: 'data-entry-list', icon: 'edit' },\n {\n name: 'Data Sample 목록',\n path: 'data-sample-list',\n icon: 'rule',\n subsubmenus:\n dataSets.map(item => {\n return {\n name: item.name,\n icon: 'checklist_rtl',\n path: `data-sample-search/${item.id}`\n }\n }) || []\n },\n {\n name: 'Data Summary 목록',\n path: 'data-summary-list',\n icon: 'functions',\n subsubmenus:\n dataSets\n .filter(item => item.active && item.summaryPeriod)\n .map(item => {\n return {\n name: item.name,\n icon: 'checklist',\n path: `data-summary-period/${item.id}`\n }\n }) || []\n }\n ]\n },\n {\n name: '시스템연계',\n path: 'project-task-list',\n icon: 'hub',\n submenus: [\n { name: '연계 현황', path: 'integration-monitor', icon: 'hub' },\n { name: '연계 설정', path: 'connection', icon: 'settings' },\n { name: '연계 시나리오', path: 'scenario', icon: 'hub' }\n ]\n },\n {\n name: '셋팅',\n path: 'project-setting-list',\n icon: 'settings',\n submenus: [\n { name: '프로젝트 관리', path: 'project-setting-list', icon: 'create' },\n { name: '사용자 관리', path: 'users', icon: 'people' },\n { name: '환경 설정', path: 'setting', icon: 'settings' }\n ]\n }\n ]\n }\n\n @property({ type: Number }) openedMenuIndex: number | null = null\n @property({ type: Number }) openedSubmenuIndex: number | null = null\n @query('ul') menuUl!: HTMLUListElement\n @property({ type: Number }) submenuHeight: number | null = null\n\n render() {\n var page = this.page || ''\n return html`\n <ul>\n ${this.menus.map(\n (menu, i) => html`\n <li\n @click=${(e: Event) => {\n e.stopPropagation()\n this.openedMenuIndex = i\n this._setSubmenuHeight()\n }}\n >\n <a href=\"javascript:void(0)\" ?active=${this._isActiveMenu(page, menu)}>\n <md-icon>${menu.icon}</md-icon>\n <div>${menu.name}</div>\n </a>\n </li>\n `\n )}\n </ul>\n ${this.openedMenuIndex !== null\n ? html`\n <div class=\"submenu-popup\">\n <ul>\n ${this.menus[this.openedMenuIndex].submenus?.map(\n (sub, subIndex) => html`\n <li>\n <a\n href=${sub.subsubmenus ? 'javascript:void(0)' : sub.path}\n ?active=${this._isActiveSubmenu(page, sub.path)}\n @click=${sub.subsubmenus ? (e: Event) => e.preventDefault() : undefined}\n >\n ${sub.icon ? html`<md-icon>${sub.icon}</md-icon>` : ''} ${sub.name}\n ${sub.subsubmenus\n ? html`\n <button\n class=\"expand-button ${this.openedSubmenuIndex === subIndex ? 'expanded' : ''}\"\n @click=${(e: Event) => this._toggleSubsubmenu(e, subIndex)}\n >\n <md-icon>chevron_right</md-icon>\n </button>\n `\n : ''}\n </a>\n ${sub.subsubmenus && this.openedSubmenuIndex === subIndex\n ? html`\n <ul class=\"subsubmenu\">\n ${sub.subsubmenus.map(\n subsub => html`\n <li>\n <a href=${subsub.path} ?active=${this._isActiveSubsubmenu(page, subsub.path)}>\n ${subsub.icon ? html`<md-icon>${subsub.icon}</md-icon>` : ''} ${subsub.name}\n </a>\n </li>\n `\n )}\n </ul>\n `\n : ''}\n </li>\n `\n )}\n </ul>\n </div>\n `\n : ''}\n `\n }\n\n private _isActiveMenu(currentPage: string, menu: any): boolean {\n // 메인 메뉴의 active 상태 확인\n if (currentPage === menu.path) return true\n\n // 서브메뉴 중 하나라도 active인지 확인\n if (menu.submenus) {\n return menu.submenus.some((sub: any) => currentPage === sub.path || currentPage.startsWith(sub.path + '/'))\n }\n\n return false\n }\n\n private _isActiveSubmenu(currentPage: string, submenuPath: string): boolean {\n return currentPage === submenuPath || currentPage.startsWith(submenuPath + '/')\n }\n\n async firstUpdated() {\n this._setSubmenuHeight()\n\n this.dataSets = await queryDataSets()\n this.menus = this.getMenus()\n }\n\n updated(changedProps) {\n if (changedProps.has('openedMenuIndex')) {\n this._setSubmenuHeight()\n }\n }\n\n _setSubmenuHeight() {\n if (this.menuUl) {\n this.submenuHeight = this.menuUl.clientHeight\n }\n }\n\n connectedCallback() {\n super.connectedCallback()\n window.addEventListener('click', this._closeSubmenu)\n }\n\n disconnectedCallback() {\n window.removeEventListener('click', this._closeSubmenu)\n super.disconnectedCallback()\n }\n\n private _closeSubmenu = () => {\n this.openedMenuIndex = null\n }\n\n private _toggleSubsubmenu(e: Event, subIndex: number) {\n e.stopPropagation()\n if (this.openedSubmenuIndex === subIndex) {\n this.openedSubmenuIndex = null\n } else {\n this.openedSubmenuIndex = subIndex\n }\n }\n\n private _isActiveSubsubmenu(currentPage: string, subsubmenuPath: string): boolean {\n return currentPage === subsubmenuPath || currentPage.startsWith(subsubmenuPath + '/')\n }\n\n stateChanged(state) {\n this.page = state.route.page\n this.width = state.layout.width\n }\n}\n"]}
|
package/dist-server/index.d.ts
CHANGED
package/dist-server/index.js
CHANGED
package/dist-server/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../server/index.ts"],"names":[],"mappings":";;;AAAA,gEAAqC","sourcesContent":["export * from './migrations/index.js'\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../server/index.ts"],"names":[],"mappings":";;;AAAA,gEAAqC;AACrC,6DAAkC","sourcesContent":["export * from './migrations/index.js'\nexport * from './service/index.js'\n"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
#!/usr/bin/env ts-node
|
|
2
|
+
/**
|
|
3
|
+
* Propagate parent KPI values based on child KPI scores and weights
|
|
4
|
+
* Processes hierarchy from leaf to root, calculating weighted averages
|
|
5
|
+
*/
|
|
6
|
+
export declare function propagateParentKpiValues(specificKpiName?: string, forceRecalculate?: boolean, targetDate?: string, orgScope?: string, version?: number): Promise<void>;
|
|
7
|
+
/**
|
|
8
|
+
* List parent KPIs and their hierarchy
|
|
9
|
+
*/
|
|
10
|
+
export declare function listParentKpiHierarchy(): Promise<void>;
|
|
@@ -0,0 +1,440 @@
|
|
|
1
|
+
#!/usr/bin/env ts-node
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.propagateParentKpiValues = propagateParentKpiValues;
|
|
5
|
+
exports.listParentKpiHierarchy = listParentKpiHierarchy;
|
|
6
|
+
const typeorm_1 = require("typeorm");
|
|
7
|
+
/**
|
|
8
|
+
* Propagate parent KPI values based on child KPI scores and weights
|
|
9
|
+
* Processes hierarchy from leaf to root, calculating weighted averages
|
|
10
|
+
*/
|
|
11
|
+
async function propagateParentKpiValues(specificKpiName, forceRecalculate = false, targetDate, orgScope, version) {
|
|
12
|
+
// Set NODE_ENV if not set
|
|
13
|
+
if (!process.env.NODE_ENV) {
|
|
14
|
+
process.env.NODE_ENV = 'development';
|
|
15
|
+
}
|
|
16
|
+
// Initialize Things-Factory environment
|
|
17
|
+
const { config } = require('@things-factory/env');
|
|
18
|
+
const ormconfig = require('@things-factory/shell/dist-server/initializers/ormconfig.js');
|
|
19
|
+
const connectionConfig = config.get('ormconfig');
|
|
20
|
+
let connection;
|
|
21
|
+
console.log('🚀 Starting Parent KPI Value Propagation...');
|
|
22
|
+
try {
|
|
23
|
+
// Create database connection using Things-Factory pattern
|
|
24
|
+
console.log('🔌 Connecting to database...');
|
|
25
|
+
connection = await (0, typeorm_1.createConnection)(Object.assign(Object.assign(Object.assign({}, ormconfig), connectionConfig), { logging: false }));
|
|
26
|
+
// Register the connection with Things-Factory shell
|
|
27
|
+
const { addDataSource } = require('@things-factory/shell');
|
|
28
|
+
addDataSource('default', connection);
|
|
29
|
+
console.log('✅ Database connected');
|
|
30
|
+
// Now we can use getRepository with the registered connection
|
|
31
|
+
const { getRepository } = require('@things-factory/shell');
|
|
32
|
+
const { Kpi } = require('@things-factory/kpi');
|
|
33
|
+
const kpiRepository = getRepository(Kpi);
|
|
34
|
+
// Get KPI-Value repository
|
|
35
|
+
let kpiValueRepository;
|
|
36
|
+
try {
|
|
37
|
+
const { KpiValue } = require('@things-factory/kpi');
|
|
38
|
+
kpiValueRepository = getRepository(KpiValue);
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
console.error('❌ KpiValue entity not found. Please ensure it exists in @things-factory/kpi');
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
// Get Domain repository and find SYSTEM domain
|
|
45
|
+
let systemDomain;
|
|
46
|
+
try {
|
|
47
|
+
const { Domain } = require('@things-factory/shell');
|
|
48
|
+
const domainRepository = getRepository(Domain);
|
|
49
|
+
systemDomain = await domainRepository.findOne({ where: { name: 'SYSTEM' } });
|
|
50
|
+
if (!systemDomain) {
|
|
51
|
+
console.error('❌ SYSTEM domain not found');
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
console.error('❌ Domain entity not found:', error.message);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
// Get all KPIs with their hierarchy
|
|
60
|
+
let kpisQuery = kpiRepository
|
|
61
|
+
.createQueryBuilder('kpi')
|
|
62
|
+
.leftJoinAndSelect('kpi.domain', 'domain')
|
|
63
|
+
.leftJoinAndSelect('kpi.parent', 'parent')
|
|
64
|
+
.leftJoinAndSelect('kpi.children', 'children')
|
|
65
|
+
.where('domain.name = :domainName', { domainName: 'SYSTEM' });
|
|
66
|
+
if (specificKpiName) {
|
|
67
|
+
kpisQuery = kpisQuery.andWhere('kpi.name = :name', { name: specificKpiName });
|
|
68
|
+
console.log(`🎯 Processing specific KPI: ${specificKpiName}`);
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
console.log('🎯 Processing all KPIs in hierarchy');
|
|
72
|
+
}
|
|
73
|
+
const allKpis = await kpisQuery.getMany();
|
|
74
|
+
if (allKpis.length === 0) {
|
|
75
|
+
console.log('⚠️ No KPIs found');
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
console.log(`📊 Found ${allKpis.length} KPIs total`);
|
|
79
|
+
// Get parent KPIs (non-leaf KPIs) ordered by level (deepest first)
|
|
80
|
+
const parentKpis = allKpis.filter(kpi => !kpi.isLeaf);
|
|
81
|
+
if (parentKpis.length === 0) {
|
|
82
|
+
console.log('⚠️ No parent KPIs found');
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
// Sort parent KPIs by hierarchy level (deepest first for bottom-up processing)
|
|
86
|
+
const sortedParentKpis = await sortKpisByLevel(parentKpis, allKpis);
|
|
87
|
+
console.log(`🔄 Processing ${sortedParentKpis.length} parent KPIs`);
|
|
88
|
+
let totalProcessed = 0;
|
|
89
|
+
let totalCreated = 0;
|
|
90
|
+
let totalUpdated = 0;
|
|
91
|
+
let errorCount = 0;
|
|
92
|
+
// Get all distinct (group, valueDate) combinations from existing KPI values
|
|
93
|
+
let groupDateCombinations = [];
|
|
94
|
+
if (orgScope && targetDate) {
|
|
95
|
+
groupDateCombinations = [{ group: orgScope, valueDate: targetDate }];
|
|
96
|
+
}
|
|
97
|
+
else if (orgScope) {
|
|
98
|
+
// Get all dates for specific group
|
|
99
|
+
const dates = await kpiValueRepository.query(`
|
|
100
|
+
SELECT DISTINCT "value_date"
|
|
101
|
+
FROM kpi_values
|
|
102
|
+
WHERE "group" = $1 AND "group" IS NOT NULL
|
|
103
|
+
ORDER BY "value_date"
|
|
104
|
+
`, [orgScope]);
|
|
105
|
+
groupDateCombinations = dates.map(row => ({ group: orgScope, valueDate: row.value_date }));
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
// Get all distinct (group, valueDate) combinations
|
|
109
|
+
const combinations = await kpiValueRepository.query(`
|
|
110
|
+
SELECT DISTINCT "group", "value_date"
|
|
111
|
+
FROM kpi_values
|
|
112
|
+
WHERE "group" IS NOT NULL AND "group" != ''
|
|
113
|
+
ORDER BY "group", "value_date"
|
|
114
|
+
`);
|
|
115
|
+
groupDateCombinations = combinations.map(row => ({ group: row.group, valueDate: row.value_date }));
|
|
116
|
+
}
|
|
117
|
+
console.log(`📍 Found ${groupDateCombinations.length} distinct (group, date) combinations`);
|
|
118
|
+
// Process each (group, date) combination
|
|
119
|
+
for (const { group: currentGroup, valueDate } of groupDateCombinations) {
|
|
120
|
+
console.log(`\\n🏢 Processing Group: ${currentGroup}, Date: ${valueDate}`);
|
|
121
|
+
// Process each parent KPI from deepest to shallowest for this group and date
|
|
122
|
+
for (const parentKpi of sortedParentKpis) {
|
|
123
|
+
try {
|
|
124
|
+
console.log(`\\n📄 Processing Parent KPI: ${parentKpi.name} (Level ${parentKpi.__level || '?'}) - Group: ${currentGroup}, Date: ${valueDate}`);
|
|
125
|
+
// Get child KPIs
|
|
126
|
+
const childKpis = allKpis.filter(kpi => { var _a; return ((_a = kpi.parent) === null || _a === void 0 ? void 0 : _a.id) === parentKpi.id; });
|
|
127
|
+
if (childKpis.length === 0) {
|
|
128
|
+
console.log(` ⚠️ No child KPIs found, skipping`);
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
console.log(` 👶 Found ${childKpis.length} child KPIs`);
|
|
132
|
+
// Get child KPI values/scores for the specific group and date
|
|
133
|
+
const childValues = await getChildKpiValues(kpiValueRepository, childKpis, valueDate, version, currentGroup);
|
|
134
|
+
if (childValues.length === 0) {
|
|
135
|
+
console.log(` ⚠️ No child KPI values found for date ${valueDate} and group ${currentGroup}, skipping`);
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
console.log(` 📊 Found values for ${childValues.length}/${childKpis.length} child KPIs`);
|
|
139
|
+
// Calculate weighted average
|
|
140
|
+
const { weightedValue, weightedScore } = calculateWeightedAverage(childValues, childKpis);
|
|
141
|
+
console.log(` 🧮 Calculated: value=${weightedValue.toFixed(4)}, score=${weightedScore.toFixed(4)}`);
|
|
142
|
+
// Check if parent KPI value already exists for this org scope
|
|
143
|
+
let existingValueQuery = kpiValueRepository
|
|
144
|
+
.createQueryBuilder('kpiValue')
|
|
145
|
+
.leftJoinAndSelect('kpiValue.kpi', 'kpi')
|
|
146
|
+
.leftJoinAndSelect('kpiValue.domain', 'domain')
|
|
147
|
+
.where('kpi.id = :kpiId', { kpiId: parentKpi.id })
|
|
148
|
+
.andWhere('kpiValue.valueDate = :valueDate', { valueDate })
|
|
149
|
+
.andWhere('domain.name = :domainName', { domainName: 'SYSTEM' });
|
|
150
|
+
if (version !== undefined) {
|
|
151
|
+
existingValueQuery = existingValueQuery.andWhere('kpiValue.version = :version', { version });
|
|
152
|
+
}
|
|
153
|
+
// Filter by group scope
|
|
154
|
+
existingValueQuery = existingValueQuery.andWhere('kpiValue.group = :groupScope', { groupScope: currentGroup });
|
|
155
|
+
const existingValue = await existingValueQuery.getOne();
|
|
156
|
+
console.log(` 🔍 Checking existing record: ${existingValue ? 'FOUND' : 'NOT FOUND'}`);
|
|
157
|
+
if (existingValue) {
|
|
158
|
+
// Update existing value
|
|
159
|
+
if (forceRecalculate || existingValue.value !== weightedValue || existingValue.score !== weightedScore) {
|
|
160
|
+
const oldValue = existingValue.value;
|
|
161
|
+
const oldScore = existingValue.score;
|
|
162
|
+
existingValue.value = weightedValue;
|
|
163
|
+
existingValue.score = weightedScore;
|
|
164
|
+
existingValue.kpiScope = currentGroup; // Set kpiScope same as group
|
|
165
|
+
existingValue.updatedAt = new Date();
|
|
166
|
+
try {
|
|
167
|
+
await kpiValueRepository.save(existingValue);
|
|
168
|
+
totalUpdated++;
|
|
169
|
+
console.log(` ✅ Updated: ${oldValue.toFixed(4)} → ${weightedValue.toFixed(4)}, score: ${oldScore.toFixed(4)} → ${weightedScore.toFixed(4)}`);
|
|
170
|
+
}
|
|
171
|
+
catch (saveError) {
|
|
172
|
+
console.log(` ❌ Update failed: ${saveError.message}`);
|
|
173
|
+
errorCount++;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
console.log(` ⏭️ No change needed`);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
// Create new value with group scope
|
|
182
|
+
const newKpiValue = {
|
|
183
|
+
kpi: parentKpi,
|
|
184
|
+
value: weightedValue,
|
|
185
|
+
score: weightedScore,
|
|
186
|
+
valueDate: valueDate,
|
|
187
|
+
version: version || parentKpi.version || 1,
|
|
188
|
+
group: currentGroup,
|
|
189
|
+
kpiScope: currentGroup, // Set kpiScope same as group
|
|
190
|
+
domain: systemDomain, // Set domain entity
|
|
191
|
+
inputType: 'AUTO', // Set inputType to AUTO
|
|
192
|
+
createdAt: new Date(),
|
|
193
|
+
updatedAt: new Date()
|
|
194
|
+
};
|
|
195
|
+
try {
|
|
196
|
+
const savedValue = await kpiValueRepository.save(newKpiValue);
|
|
197
|
+
totalCreated++;
|
|
198
|
+
console.log(` ✨ Created: value=${weightedValue.toFixed(4)}, score=${weightedScore.toFixed(4)}, id=${savedValue.id}`);
|
|
199
|
+
}
|
|
200
|
+
catch (saveError) {
|
|
201
|
+
console.log(` ❌ Save failed: ${saveError.message}`);
|
|
202
|
+
errorCount++;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
totalProcessed++;
|
|
206
|
+
}
|
|
207
|
+
catch (kpiError) {
|
|
208
|
+
console.log(` ❌ Error processing KPI ${parentKpi.name}: ${kpiError.message}`);
|
|
209
|
+
errorCount++;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
console.log(`\\n🎉 Parent KPI Value Propagation Complete!`);
|
|
214
|
+
console.log(` 📊 Parent KPIs processed: ${totalProcessed}`);
|
|
215
|
+
console.log(` ✨ Values created: ${totalCreated}`);
|
|
216
|
+
console.log(` ✅ Values updated: ${totalUpdated}`);
|
|
217
|
+
console.log(` ❌ Errors: ${errorCount}`);
|
|
218
|
+
if (errorCount > 0) {
|
|
219
|
+
console.log(`\\n⚠️ Some parent KPIs had errors. Check the logs above for details.`);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
catch (error) {
|
|
223
|
+
console.error(`❌ Fatal error during parent KPI value propagation:`, error);
|
|
224
|
+
throw error;
|
|
225
|
+
}
|
|
226
|
+
finally {
|
|
227
|
+
if (connection) {
|
|
228
|
+
await connection.close();
|
|
229
|
+
console.log('🔌 Database connection closed');
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Sort KPIs by hierarchy level (deepest first for bottom-up processing)
|
|
235
|
+
*/
|
|
236
|
+
async function sortKpisByLevel(parentKpis, allKpis) {
|
|
237
|
+
// Calculate hierarchy level for each KPI
|
|
238
|
+
const kpiLevels = new Map();
|
|
239
|
+
function calculateLevel(kpi) {
|
|
240
|
+
if (kpiLevels.has(kpi.id)) {
|
|
241
|
+
return kpiLevels.get(kpi.id);
|
|
242
|
+
}
|
|
243
|
+
if (!kpi.parent) {
|
|
244
|
+
kpiLevels.set(kpi.id, 0);
|
|
245
|
+
return 0;
|
|
246
|
+
}
|
|
247
|
+
const parentKpi = allKpis.find(k => { var _a; return k.id === ((_a = kpi.parent) === null || _a === void 0 ? void 0 : _a.id); });
|
|
248
|
+
if (!parentKpi) {
|
|
249
|
+
kpiLevels.set(kpi.id, 1);
|
|
250
|
+
return 1;
|
|
251
|
+
}
|
|
252
|
+
const level = calculateLevel(parentKpi) + 1;
|
|
253
|
+
kpiLevels.set(kpi.id, level);
|
|
254
|
+
return level;
|
|
255
|
+
}
|
|
256
|
+
// Calculate levels for all parent KPIs
|
|
257
|
+
parentKpis.forEach(kpi => {
|
|
258
|
+
const level = calculateLevel(kpi);
|
|
259
|
+
kpi.__level = level;
|
|
260
|
+
});
|
|
261
|
+
// Sort by level (deepest first)
|
|
262
|
+
return parentKpis.sort((a, b) => (b.__level || 0) - (a.__level || 0));
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Get child KPI values for a specific date
|
|
266
|
+
*/
|
|
267
|
+
async function getChildKpiValues(kpiValueRepository, childKpis, valueDate, version, orgScope) {
|
|
268
|
+
const childKpiIds = childKpis.map(kpi => kpi.id);
|
|
269
|
+
let valuesQuery = kpiValueRepository
|
|
270
|
+
.createQueryBuilder('kpiValue')
|
|
271
|
+
.leftJoinAndSelect('kpiValue.kpi', 'kpi')
|
|
272
|
+
.where('kpi.id IN (:...kpiIds)', { kpiIds: childKpiIds })
|
|
273
|
+
.andWhere('kpiValue.valueDate = :valueDate', { valueDate })
|
|
274
|
+
.andWhere('kpiValue.score IS NOT NULL');
|
|
275
|
+
if (version !== undefined) {
|
|
276
|
+
valuesQuery = valuesQuery.andWhere('kpiValue.version = :version', { version });
|
|
277
|
+
}
|
|
278
|
+
// Filter by group scope
|
|
279
|
+
if (orgScope) {
|
|
280
|
+
valuesQuery = valuesQuery.andWhere('kpiValue.group = :groupScope', { groupScope: orgScope });
|
|
281
|
+
}
|
|
282
|
+
const values = await valuesQuery.getMany();
|
|
283
|
+
return values;
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Calculate weighted average from child KPI values
|
|
287
|
+
*/
|
|
288
|
+
function calculateWeightedAverage(childValues, childKpis) {
|
|
289
|
+
let totalWeightedValue = 0;
|
|
290
|
+
let totalWeightedScore = 0;
|
|
291
|
+
let totalWeight = 0;
|
|
292
|
+
for (const value of childValues) {
|
|
293
|
+
const childKpi = childKpis.find(kpi => kpi.id === value.kpi.id);
|
|
294
|
+
const weight = (childKpi === null || childKpi === void 0 ? void 0 : childKpi.weight) || 1;
|
|
295
|
+
totalWeightedValue += value.score * weight;
|
|
296
|
+
totalWeightedScore += value.score * weight;
|
|
297
|
+
totalWeight += weight;
|
|
298
|
+
}
|
|
299
|
+
if (totalWeight === 0) {
|
|
300
|
+
return { weightedValue: 0, weightedScore: 0 };
|
|
301
|
+
}
|
|
302
|
+
return {
|
|
303
|
+
weightedValue: totalWeightedValue / totalWeight,
|
|
304
|
+
weightedScore: totalWeightedScore / totalWeight
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* List parent KPIs and their hierarchy
|
|
309
|
+
*/
|
|
310
|
+
async function listParentKpiHierarchy() {
|
|
311
|
+
// Set NODE_ENV if not set
|
|
312
|
+
if (!process.env.NODE_ENV) {
|
|
313
|
+
process.env.NODE_ENV = 'development';
|
|
314
|
+
}
|
|
315
|
+
// Initialize Things-Factory environment
|
|
316
|
+
const { config } = require('@things-factory/env');
|
|
317
|
+
const ormconfig = require('@things-factory/shell/dist-server/initializers/ormconfig.js');
|
|
318
|
+
const connectionConfig = config.get('ormconfig');
|
|
319
|
+
let connection;
|
|
320
|
+
try {
|
|
321
|
+
console.log('🔌 Connecting to database...');
|
|
322
|
+
connection = await (0, typeorm_1.createConnection)(Object.assign(Object.assign(Object.assign({}, ormconfig), connectionConfig), { logging: false }));
|
|
323
|
+
const { addDataSource } = require('@things-factory/shell');
|
|
324
|
+
addDataSource('default', connection);
|
|
325
|
+
const { getRepository } = require('@things-factory/shell');
|
|
326
|
+
const { Kpi } = require('@things-factory/kpi');
|
|
327
|
+
const kpiRepository = getRepository(Kpi);
|
|
328
|
+
// Get all KPIs with hierarchy
|
|
329
|
+
const kpis = await kpiRepository
|
|
330
|
+
.createQueryBuilder('kpi')
|
|
331
|
+
.leftJoinAndSelect('kpi.domain', 'domain')
|
|
332
|
+
.leftJoinAndSelect('kpi.parent', 'parent')
|
|
333
|
+
.leftJoinAndSelect('kpi.children', 'children')
|
|
334
|
+
.where('domain.name = :domainName', { domainName: 'SYSTEM' })
|
|
335
|
+
.getMany();
|
|
336
|
+
const parentKpis = kpis.filter(kpi => !kpi.isLeaf);
|
|
337
|
+
const sortedParentKpis = await sortKpisByLevel(parentKpis, kpis);
|
|
338
|
+
console.log(`📁 Parent KPI Hierarchy (${sortedParentKpis.length} parents):\\n`);
|
|
339
|
+
if (sortedParentKpis.length === 0) {
|
|
340
|
+
console.log(' No parent KPIs found.');
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
sortedParentKpis.forEach((kpi, index) => {
|
|
344
|
+
const level = kpi.__level || 0;
|
|
345
|
+
const indent = ' '.repeat(level);
|
|
346
|
+
const childCount = kpis.filter(k => { var _a; return ((_a = k.parent) === null || _a === void 0 ? void 0 : _a.id) === kpi.id; }).length;
|
|
347
|
+
const weight = kpi.weight || 1;
|
|
348
|
+
console.log(` ${(index + 1).toString().padStart(2)}: ${indent}${kpi.name} (L${level}, ${childCount} children, weight: ${weight})`);
|
|
349
|
+
});
|
|
350
|
+
console.log(`\\n📈 Total: ${sortedParentKpis.length} parent KPIs`);
|
|
351
|
+
}
|
|
352
|
+
catch (error) {
|
|
353
|
+
console.error('❌ Error listing parent KPIs:', error);
|
|
354
|
+
}
|
|
355
|
+
finally {
|
|
356
|
+
if (connection) {
|
|
357
|
+
await connection.close();
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
* CLI execution when called directly
|
|
363
|
+
*/
|
|
364
|
+
async function main() {
|
|
365
|
+
const args = process.argv.slice(2);
|
|
366
|
+
try {
|
|
367
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
368
|
+
console.log(`
|
|
369
|
+
🎯 Parent KPI Value Propagator
|
|
370
|
+
|
|
371
|
+
Usage:
|
|
372
|
+
ts-node server/scripts/propagate-parent-kpi-values.ts [options] [kpiName]
|
|
373
|
+
|
|
374
|
+
Options:
|
|
375
|
+
--list, -l List parent KPIs and their hierarchy
|
|
376
|
+
--force, -f Force recalculate all values (not just missing ones)
|
|
377
|
+
--date YYYY-MM-DD Target date for value calculation (default: today)
|
|
378
|
+
--org orgScope Organization scope filter (default: all orgs)
|
|
379
|
+
--version N KPI version filter (default: latest version)
|
|
380
|
+
--help, -h Show this help
|
|
381
|
+
|
|
382
|
+
Examples:
|
|
383
|
+
ts-node server/scripts/propagate-parent-kpi-values.ts # Process all parent KPIs for today
|
|
384
|
+
ts-node server/scripts/propagate-parent-kpi-values.ts --force # Recalculate ALL parent values
|
|
385
|
+
ts-node server/scripts/propagate-parent-kpi-values.ts --date 2024-01-15 # Process for specific date
|
|
386
|
+
ts-node server/scripts/propagate-parent-kpi-values.ts --org "PROJECT-123" # Process for specific org
|
|
387
|
+
ts-node server/scripts/propagate-parent-kpi-values.ts --version 2 # Process for specific version
|
|
388
|
+
ts-node server/scripts/propagate-parent-kpi-values.ts "상위 KPI명" # Process specific parent KPI
|
|
389
|
+
ts-node server/scripts/propagate-parent-kpi-values.ts --list # List parent KPI hierarchy
|
|
390
|
+
|
|
391
|
+
Note: Processes parent KPIs from deepest level to root, calculating weighted averages.
|
|
392
|
+
Child KPI scores and weights are used to calculate parent values.
|
|
393
|
+
`);
|
|
394
|
+
return;
|
|
395
|
+
}
|
|
396
|
+
if (args.includes('--list') || args.includes('-l')) {
|
|
397
|
+
await listParentKpiHierarchy();
|
|
398
|
+
return;
|
|
399
|
+
}
|
|
400
|
+
const forceRecalculate = args.includes('--force') || args.includes('-f');
|
|
401
|
+
const dateIndex = args.indexOf('--date');
|
|
402
|
+
const targetDate = dateIndex !== -1 && dateIndex + 1 < args.length ? args[dateIndex + 1] : undefined;
|
|
403
|
+
const orgIndex = args.indexOf('--org');
|
|
404
|
+
const orgScope = orgIndex !== -1 && orgIndex + 1 < args.length ? args[orgIndex + 1] : undefined;
|
|
405
|
+
const versionIndex = args.indexOf('--version');
|
|
406
|
+
const version = versionIndex !== -1 && versionIndex + 1 < args.length ? parseInt(args[versionIndex + 1]) : undefined;
|
|
407
|
+
const specificKpiName = args.find(arg => !arg.startsWith('--') && arg !== targetDate && arg !== orgScope && (version === undefined || arg !== version.toString()));
|
|
408
|
+
if (specificKpiName) {
|
|
409
|
+
console.log(`🎯 Propagating values for specific KPI: ${specificKpiName}`);
|
|
410
|
+
console.log(` Mode: ${forceRecalculate ? 'Force recalculate ALL' : 'Only missing values'}`);
|
|
411
|
+
console.log(` Date: ${targetDate || 'today'}`);
|
|
412
|
+
console.log(` Org: ${orgScope || 'all'}`);
|
|
413
|
+
console.log(` Version: ${version || 'latest'}`);
|
|
414
|
+
await propagateParentKpiValues(specificKpiName, forceRecalculate, targetDate, orgScope, version);
|
|
415
|
+
}
|
|
416
|
+
else {
|
|
417
|
+
console.log(`🎯 Propagating values for all parent KPIs`);
|
|
418
|
+
console.log(` Mode: ${forceRecalculate ? 'Force recalculate ALL' : 'Only missing values'}`);
|
|
419
|
+
console.log(` Date: ${targetDate || 'today'}`);
|
|
420
|
+
console.log(` Org: ${orgScope || 'all'}`);
|
|
421
|
+
console.log(` Version: ${version || 'latest'}`);
|
|
422
|
+
await propagateParentKpiValues(undefined, forceRecalculate, targetDate, orgScope, version);
|
|
423
|
+
}
|
|
424
|
+
console.log('\\n✨ Done!');
|
|
425
|
+
}
|
|
426
|
+
catch (error) {
|
|
427
|
+
console.error('\\n❌ Script failed:', error.message);
|
|
428
|
+
process.exit(1);
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
// Handle uncaught errors
|
|
432
|
+
process.on('unhandledRejection', (error) => {
|
|
433
|
+
console.error('❌ Unhandled error:', error.message || error);
|
|
434
|
+
process.exit(1);
|
|
435
|
+
});
|
|
436
|
+
// Run if called directly
|
|
437
|
+
if (require.main === module) {
|
|
438
|
+
main();
|
|
439
|
+
}
|
|
440
|
+
//# sourceMappingURL=propagate-parent-kpi-values.js.map
|