@things-factory/kpi 9.0.15 → 9.0.16

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.
@@ -4,6 +4,7 @@ import '@material/web/button/elevated-button.js';
4
4
  import '@operato/data-grist/ox-grist.js';
5
5
  import '@operato/data-grist/ox-filters-form.js';
6
6
  import '@operato/data-grist/ox-record-creator.js';
7
+ import './kpi-viz-editor.js';
7
8
  import { CommonButtonStyles, CommonHeaderStyles, CommonGristStyles, ScrollbarStyles } from '@operato/styles';
8
9
  import { PageView, store } from '@operato/shell';
9
10
  import { css, html } from 'lit';
@@ -19,6 +20,7 @@ import { connect } from 'pwa-helpers/connect-mixin';
19
20
  import gql from 'graphql-tag';
20
21
  import { KpiImporter } from './kpi-importer';
21
22
  import { KpiGradeEditor } from './kpi-grade-editor';
23
+ import { KpiVizEditor } from './kpi-viz-editor';
22
24
  let KpiListPage = class KpiListPage extends connect(store)(localize(i18next)(ScopedElementsMixin(PageView))) {
23
25
  constructor() {
24
26
  super(...arguments);
@@ -51,7 +53,8 @@ let KpiListPage = class KpiListPage extends connect(store)(localize(i18next)(Sco
51
53
  static get scopedElements() {
52
54
  return {
53
55
  'kpi-importer': KpiImporter,
54
- 'kpi-grade-editor': KpiGradeEditor
56
+ 'kpi-grade-editor': KpiGradeEditor,
57
+ 'kpi-viz-editor': KpiVizEditor
55
58
  };
56
59
  }
57
60
  get context() {
@@ -228,7 +231,29 @@ let KpiListPage = class KpiListPage extends connect(store)(localize(i18next)(Sco
228
231
  width: 60
229
232
  },
230
233
  { type: 'string', name: 'state', header: '상태', record: { editable: false }, width: 100 },
231
- { type: 'string', name: 'vizType', header: '시각화유형', record: { editable: true }, width: 120 },
234
+ {
235
+ type: 'string',
236
+ name: 'vizType',
237
+ header: '시각화 설정',
238
+ record: {
239
+ editable: false,
240
+ renderer: (v, c, r) => {
241
+ const vizType = r.vizType || 'CARD';
242
+ const vizMeta = r.vizMeta || {};
243
+ const color = vizMeta.color || '#2196f3';
244
+ const icon = vizMeta.icon || 'dashboard';
245
+ return html `
246
+ <div style="display:flex;align-items:center;gap:8px;">
247
+ <span style="color:${color};cursor:pointer;" @click=${() => this._editViz(r)}> ${vizType} </span>
248
+ <md-icon style="color:${color};font-size:16px;cursor:pointer;" @click=${() => this._editViz(r)}>
249
+ ${icon}
250
+ </md-icon>
251
+ </div>
252
+ `;
253
+ }
254
+ },
255
+ width: 150
256
+ },
232
257
  { type: 'string', name: 'schedule', header: '스케줄', record: { editable: true }, width: 120 },
233
258
  { type: 'string', name: 'scheduleId', header: '스케줄ID', record: { editable: false }, width: 120 },
234
259
  { type: 'string', name: 'timezone', header: '타임존', record: { editable: true }, width: 100 },
@@ -284,6 +309,8 @@ let KpiListPage = class KpiListPage extends connect(store)(localize(i18next)(Sco
284
309
  description
285
310
  active
286
311
  grades
312
+ vizType
313
+ vizMeta
287
314
  category {
288
315
  id
289
316
  name
@@ -478,6 +505,49 @@ let KpiListPage = class KpiListPage extends connect(store)(localize(i18next)(Sco
478
505
  });
479
506
  }
480
507
  }
508
+ async _editViz(kpi) {
509
+ const popup = await openPopup(html `
510
+ <kpi-viz-editor
511
+ .kpi=${kpi}
512
+ .onSave=${(vizType, vizMeta) => this._onVizUpdated(kpi.id, vizType, vizMeta)}
513
+ .onCancel=${() => popup.close()}
514
+ ></kpi-viz-editor>
515
+ `, {
516
+ title: `${kpi.name} - 시각화 설정`,
517
+ size: 'large'
518
+ });
519
+ }
520
+ async _onVizUpdated(kpiId, vizType, vizMeta) {
521
+ try {
522
+ const response = await client.mutate({
523
+ mutation: gql `
524
+ mutation ($id: String!, $patch: KpiPatch!) {
525
+ updateKpi(id: $id, patch: $patch) {
526
+ id
527
+ name
528
+ vizType
529
+ vizMeta
530
+ }
531
+ }
532
+ `,
533
+ variables: {
534
+ id: kpiId,
535
+ patch: { vizType, vizMeta }
536
+ }
537
+ });
538
+ if (!response.errors) {
539
+ this.grist.fetch();
540
+ notify({
541
+ message: '시각화 설정이 성공적으로 업데이트되었습니다.'
542
+ });
543
+ }
544
+ }
545
+ catch (error) {
546
+ notify({
547
+ message: '시각화 설정 업데이트 중 오류가 발생했습니다.'
548
+ });
549
+ }
550
+ }
481
551
  };
482
552
  __decorate([
483
553
  property({ type: Object }),
@@ -1 +1 @@
1
- {"version":3,"file":"kpi-list-page.js","sourceRoot":"","sources":["../../../client/pages/kpi/kpi-list-page.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/icon/icon.js'\nimport '@material/web/button/elevated-button.js'\nimport '@operato/data-grist/ox-grist.js'\nimport '@operato/data-grist/ox-filters-form.js'\nimport '@operato/data-grist/ox-record-creator.js'\n\nimport { CommonButtonStyles, CommonHeaderStyles, CommonGristStyles, ScrollbarStyles } from '@operato/styles'\nimport { PageView, store } from '@operato/shell'\nimport { css, html } from 'lit'\nimport { customElement, property, query } from 'lit/decorators.js'\nimport { ScopedElementsMixin } from '@open-wc/scoped-elements'\nimport { ColumnConfig, DataGrist, FetchOption } from '@operato/data-grist'\nimport { client } from '@operato/graphql'\nimport { i18next, localize } from '@operato/i18n'\nimport { notify, openPopup } from '@operato/layout'\nimport { OxPopup, OxPrompt } from '@operato/popup'\nimport { isMobileDevice } from '@operato/utils'\n\nimport { connect } from 'pwa-helpers/connect-mixin'\nimport gql from 'graphql-tag'\n\nimport { KpiImporter } from './kpi-importer'\nimport { KpiGradeEditor } from './kpi-grade-editor'\n\n@customElement('kpi-list-page')\nexport class KpiListPage extends connect(store)(localize(i18next)(ScopedElementsMixin(PageView))) {\n static styles = [\n ScrollbarStyles,\n CommonGristStyles,\n CommonHeaderStyles,\n css`\n :host {\n display: flex;\n\n width: 100%;\n\n --grid-record-emphasized-background-color: #8b0000;\n --grid-record-emphasized-color: #ff6b6b;\n }\n\n ox-grist {\n overflow-y: auto;\n flex: 1;\n }\n\n ox-filters-form {\n flex: 1;\n }\n `\n ]\n\n static get scopedElements() {\n return {\n 'kpi-importer': KpiImporter,\n 'kpi-grade-editor': KpiGradeEditor\n }\n }\n\n @property({ type: Object }) gristConfig: any\n @property({ type: String }) mode: 'CARD' | 'GRID' | 'LIST' = isMobileDevice() ? 'CARD' : 'GRID'\n\n @query('ox-grist') private grist!: DataGrist\n\n get context() {\n return {\n title: i18next.t('title.kpi list'),\n search: {\n handler: (search: string) => {\n this.grist.searchText = search\n },\n value: this.grist.searchText\n },\n filter: {\n handler: () => {\n this.grist.toggleHeadroom()\n }\n },\n help: 'kpi/kpi',\n actions: [\n {\n title: i18next.t('button.save'),\n action: this._updateKpi.bind(this),\n ...CommonButtonStyles.save\n },\n {\n title: i18next.t('button.delete'),\n action: this._deleteKpi.bind(this),\n ...CommonButtonStyles.delete\n }\n ],\n exportable: {\n name: i18next.t('title.kpi list'),\n data: this.exportHandler.bind(this)\n },\n importable: {\n handler: this.importHandler.bind(this)\n }\n }\n }\n\n render() {\n const mode = this.mode || (isMobileDevice() ? 'CARD' : 'GRID')\n\n return html`\n <ox-grist .mode=${mode} .config=${this.gristConfig} .fetchHandler=${this.fetchHandler.bind(this)}>\n <div slot=\"headroom\" class=\"header\">\n <div class=\"filters\">\n <ox-filters-form autofocus without-search></ox-filters-form>\n\n <div id=\"modes\">\n <md-icon @click=${() => (this.mode = 'GRID')} ?active=${mode == 'GRID'}>grid_on</md-icon>\n <md-icon @click=${() => (this.mode = 'LIST')} ?active=${mode == 'LIST'}>format_list_bulleted</md-icon>\n <md-icon @click=${() => (this.mode = 'CARD')} ?active=${mode == 'CARD'}>apps</md-icon>\n </div>\n\n <ox-record-creator id=\"add\" .callback=${this.creationCallback.bind(this)}>\n <button>\n <md-icon>add</md-icon>\n </button>\n </ox-record-creator>\n </div>\n </div>\n </ox-grist>\n `\n }\n\n async pageInitialized(lifecycle: any) {\n this.gristConfig = {\n list: {\n fields: [\n 'name',\n 'description',\n 'category',\n 'formula',\n 'active',\n 'state',\n 'vizType',\n 'schedule',\n 'scheduleId',\n 'timezone',\n 'version',\n 'createdAt',\n 'updatedAt',\n 'creator',\n 'updater',\n 'thumbnail'\n ],\n details: [\n 'name',\n 'description',\n 'category',\n 'formula',\n 'active',\n 'state',\n 'vizType',\n 'schedule',\n 'scheduleId',\n 'timezone',\n 'version',\n 'createdAt',\n 'updatedAt',\n 'creator',\n 'updater',\n 'thumbnail'\n ]\n },\n columns: [\n { type: 'gutter', gutterName: 'sequence' },\n { type: 'gutter', gutterName: 'row-selector', multiple: true },\n {\n type: 'string',\n name: 'name',\n header: '이름',\n record: { editable: true },\n filter: 'search',\n sortable: true,\n width: 120\n },\n {\n type: 'string',\n name: 'description',\n header: i18next.t('field.description'),\n record: { editable: true },\n filter: 'search',\n width: 200\n },\n // {\n // type: 'string',\n // name: 'category',\n // header: '카테고리',\n // record: { editable: false, renderer: (v, c, r) => r.category?.name },\n // width: 120\n // },\n {\n type: 'resource-object',\n name: 'category',\n label: true,\n header: '카테고리',\n record: {\n editable: true,\n options: {\n title: i18next.t('title.lookup category'),\n queryName: 'kpiCategories'\n }\n },\n width: 200\n },\n { type: 'string', name: 'formula', header: '산식', record: { editable: true }, width: 200 },\n {\n type: 'string',\n name: 'grades',\n header: '등급 설정',\n record: {\n editable: false,\n renderer: (v, c, r) => {\n if (r.grades && r.grades.length > 0) {\n return html`<span style=\"color: #4caf50; cursor: pointer;\" @click=${() => this._editGrades(r)}>\n ${r.grades.length}개 등급 설정됨\n </span>`\n } else {\n return html`<span style=\"color: #999; cursor: pointer;\" @click=${() => this._editGrades(r)}>\n 등급 설정 없음\n </span>`\n }\n }\n },\n width: 150\n },\n {\n type: 'checkbox',\n name: 'active',\n label: true,\n header: i18next.t('field.active'),\n record: { editable: true },\n filter: true,\n sortable: true,\n width: 60\n },\n { type: 'string', name: 'state', header: '상태', record: { editable: false }, width: 100 },\n { type: 'string', name: 'vizType', header: '시각화유형', record: { editable: true }, width: 120 },\n { type: 'string', name: 'schedule', header: '스케줄', record: { editable: true }, width: 120 },\n { type: 'string', name: 'scheduleId', header: '스케줄ID', record: { editable: false }, width: 120 },\n { type: 'string', name: 'timezone', header: '타임존', record: { editable: true }, width: 100 },\n { type: 'number', name: 'version', header: '버전', record: { editable: false }, width: 80 },\n { type: 'datetime', name: 'createdAt', header: '생성일', record: { editable: false }, width: 180 },\n {\n type: 'datetime',\n name: 'updatedAt',\n header: i18next.t('field.updated_at'),\n record: { editable: false },\n sortable: true,\n width: 180\n },\n {\n type: 'resource-object',\n name: 'creator',\n header: '생성자',\n record: { editable: false, renderer: (v, c, r) => r.creator?.name },\n width: 120\n },\n {\n type: 'resource-object',\n name: 'updater',\n header: i18next.t('field.updater'),\n record: { editable: false, renderer: (v, c, r) => r.updater?.name },\n sortable: true,\n width: 120\n },\n { type: 'string', name: 'thumbnail', header: '썸네일', record: { editable: false }, width: 120 }\n ],\n rows: {\n appendable: false,\n selectable: {\n multiple: true\n }\n },\n sorters: [{ name: 'name' }]\n }\n }\n\n async pageUpdated(changes: any, lifecycle: any) {\n if (this.active) {\n // do something here when this page just became as active\n }\n }\n\n async fetchHandler({ page = 1, limit = 100, sortings = [], filters = [] }: FetchOption) {\n const response = await client.query({\n query: gql`\n query ($filters: [Filter!], $pagination: Pagination, $sortings: [Sorting!]) {\n responses: kpis(filters: $filters, pagination: $pagination, sortings: $sortings) {\n items {\n id\n name\n description\n active\n grades\n category {\n id\n name\n description\n }\n updater {\n id\n name\n }\n updatedAt\n creator {\n id\n name\n }\n createdAt\n }\n total\n }\n }\n `,\n variables: {\n filters,\n pagination: { page, limit },\n sortings\n }\n })\n\n return {\n total: response.data.responses.total || 0,\n records: response.data.responses.items || []\n }\n }\n\n async _deleteKpi() {\n if (\n await OxPrompt.open({\n title: i18next.t('text.are_you_sure'),\n text: i18next.t('text.sure_to_x', { x: i18next.t('text.delete') }),\n confirmButton: { text: i18next.t('button.confirm') },\n cancelButton: { text: i18next.t('button.cancel') }\n })\n ) {\n const ids = this.grist.selected.map(record => record.id)\n if (ids && ids.length > 0) {\n const response = await client.mutate({\n mutation: gql`\n mutation ($ids: [String!]!) {\n deleteKpis(ids: $ids)\n }\n `,\n variables: {\n ids\n }\n })\n\n if (!response.errors) {\n this.grist.fetch()\n notify({\n message: i18next.t('text.info_x_successfully', { x: i18next.t('text.delete') })\n })\n }\n }\n }\n }\n\n async _updateKpi() {\n let patches = this.grist.dirtyRecords\n if (patches && patches.length) {\n patches = patches.map(patch => {\n let patchField: any = patch.id ? { id: patch.id } : {}\n const dirtyFields = patch.__dirtyfields__\n for (let key in dirtyFields) {\n patchField[key] = dirtyFields[key].after\n }\n patchField.cuFlag = patch.__dirty__\n\n return patchField\n })\n\n const response = await client.mutate({\n mutation: gql`\n mutation ($patches: [KpiPatch!]!) {\n updateMultipleKpi(patches: $patches) {\n name\n }\n }\n `,\n variables: {\n patches\n }\n })\n\n if (!response.errors) {\n this.grist.fetch()\n }\n }\n }\n\n async creationCallback(kpi) {\n try {\n const response = await client.query({\n query: gql`\n mutation ($kpi: NewKpi!) {\n createKpi(kpi: $kpi) {\n id\n }\n }\n `,\n variables: {\n kpi\n },\n context: {\n hasUpload: true\n }\n })\n\n if (!response.errors) {\n this.grist.fetch()\n document.dispatchEvent(\n new CustomEvent('notify', {\n detail: {\n message: i18next.t('text.data_created_successfully')\n }\n })\n )\n }\n\n return true\n } catch (ex) {\n console.error(ex)\n document.dispatchEvent(\n new CustomEvent('notify', {\n detail: {\n type: 'error',\n message: i18next.t('text.error')\n }\n })\n )\n return false\n }\n }\n\n async exportHandler() {\n const exportTargets = this.grist.selected.length ? this.grist.selected : this.grist.dirtyData.records\n const targetFieldSet = new Set(['id', 'name', 'description', 'active'])\n\n return exportTargets.map(kpi => {\n let tempObj = {}\n for (const field of targetFieldSet) {\n tempObj[field] = kpi[field]\n }\n\n return tempObj\n })\n }\n\n async importHandler(records) {\n const popup = openPopup(\n html`\n <kpi-importer\n .kpis=${records}\n @imported=${() => {\n history.back()\n this.grist.fetch()\n }}\n ></kpi-importer>\n `,\n {\n backdrop: true,\n size: 'large',\n title: i18next.t('title.import kpi')\n }\n )\n\n popup.onclosed = () => {\n this.grist.fetch()\n }\n }\n\n async _editGrades(kpi: any) {\n const popup = await openPopup(\n html`\n <kpi-grade-editor .kpi=${kpi} @grades-updated=${(e: any) => this._onGradesUpdated(e.detail)}></kpi-grade-editor>\n `,\n {\n title: `${kpi.name} - 등급 설정`,\n size: 'large'\n }\n )\n }\n\n async _onGradesUpdated(detail: any) {\n const { kpiId, grades } = detail\n\n try {\n const response = await client.mutate({\n mutation: gql`\n mutation ($id: String!, $patch: KpiPatch!) {\n updateKpi(id: $id, patch: $patch) {\n id\n name\n grades\n }\n }\n `,\n variables: {\n id: kpiId,\n patch: { grades }\n }\n })\n\n if (!response.errors) {\n this.grist.fetch()\n notify({\n message: '등급 설정이 성공적으로 업데이트되었습니다.'\n })\n }\n } catch (error) {\n notify({\n message: '등급 설정 업데이트 중 오류가 발생했습니다.'\n })\n }\n }\n}\n"]}
1
+ {"version":3,"file":"kpi-list-page.js","sourceRoot":"","sources":["../../../client/pages/kpi/kpi-list-page.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/icon/icon.js'\nimport '@material/web/button/elevated-button.js'\nimport '@operato/data-grist/ox-grist.js'\nimport '@operato/data-grist/ox-filters-form.js'\nimport '@operato/data-grist/ox-record-creator.js'\nimport './kpi-viz-editor.js'\n\nimport { CommonButtonStyles, CommonHeaderStyles, CommonGristStyles, ScrollbarStyles } from '@operato/styles'\nimport { PageView, store } from '@operato/shell'\nimport { css, html } from 'lit'\nimport { customElement, property, query } from 'lit/decorators.js'\nimport { ScopedElementsMixin } from '@open-wc/scoped-elements'\nimport { ColumnConfig, DataGrist, FetchOption } from '@operato/data-grist'\nimport { client } from '@operato/graphql'\nimport { i18next, localize } from '@operato/i18n'\nimport { notify, openPopup } from '@operato/layout'\nimport { OxPopup, OxPrompt } from '@operato/popup'\nimport { isMobileDevice } from '@operato/utils'\n\nimport { connect } from 'pwa-helpers/connect-mixin'\nimport gql from 'graphql-tag'\n\nimport { KpiImporter } from './kpi-importer'\nimport { KpiGradeEditor } from './kpi-grade-editor'\nimport { KpiVizEditor } from './kpi-viz-editor'\n\n@customElement('kpi-list-page')\nexport class KpiListPage extends connect(store)(localize(i18next)(ScopedElementsMixin(PageView))) {\n static styles = [\n ScrollbarStyles,\n CommonGristStyles,\n CommonHeaderStyles,\n css`\n :host {\n display: flex;\n\n width: 100%;\n\n --grid-record-emphasized-background-color: #8b0000;\n --grid-record-emphasized-color: #ff6b6b;\n }\n\n ox-grist {\n overflow-y: auto;\n flex: 1;\n }\n\n ox-filters-form {\n flex: 1;\n }\n `\n ]\n\n static get scopedElements() {\n return {\n 'kpi-importer': KpiImporter,\n 'kpi-grade-editor': KpiGradeEditor,\n 'kpi-viz-editor': KpiVizEditor\n }\n }\n\n @property({ type: Object }) gristConfig: any\n @property({ type: String }) mode: 'CARD' | 'GRID' | 'LIST' = isMobileDevice() ? 'CARD' : 'GRID'\n\n @query('ox-grist') private grist!: DataGrist\n\n get context() {\n return {\n title: i18next.t('title.kpi list'),\n search: {\n handler: (search: string) => {\n this.grist.searchText = search\n },\n value: this.grist.searchText\n },\n filter: {\n handler: () => {\n this.grist.toggleHeadroom()\n }\n },\n help: 'kpi/kpi',\n actions: [\n {\n title: i18next.t('button.save'),\n action: this._updateKpi.bind(this),\n ...CommonButtonStyles.save\n },\n {\n title: i18next.t('button.delete'),\n action: this._deleteKpi.bind(this),\n ...CommonButtonStyles.delete\n }\n ],\n exportable: {\n name: i18next.t('title.kpi list'),\n data: this.exportHandler.bind(this)\n },\n importable: {\n handler: this.importHandler.bind(this)\n }\n }\n }\n\n render() {\n const mode = this.mode || (isMobileDevice() ? 'CARD' : 'GRID')\n\n return html`\n <ox-grist .mode=${mode} .config=${this.gristConfig} .fetchHandler=${this.fetchHandler.bind(this)}>\n <div slot=\"headroom\" class=\"header\">\n <div class=\"filters\">\n <ox-filters-form autofocus without-search></ox-filters-form>\n\n <div id=\"modes\">\n <md-icon @click=${() => (this.mode = 'GRID')} ?active=${mode == 'GRID'}>grid_on</md-icon>\n <md-icon @click=${() => (this.mode = 'LIST')} ?active=${mode == 'LIST'}>format_list_bulleted</md-icon>\n <md-icon @click=${() => (this.mode = 'CARD')} ?active=${mode == 'CARD'}>apps</md-icon>\n </div>\n\n <ox-record-creator id=\"add\" .callback=${this.creationCallback.bind(this)}>\n <button>\n <md-icon>add</md-icon>\n </button>\n </ox-record-creator>\n </div>\n </div>\n </ox-grist>\n `\n }\n\n async pageInitialized(lifecycle: any) {\n this.gristConfig = {\n list: {\n fields: [\n 'name',\n 'description',\n 'category',\n 'formula',\n 'active',\n 'state',\n 'vizType',\n 'schedule',\n 'scheduleId',\n 'timezone',\n 'version',\n 'createdAt',\n 'updatedAt',\n 'creator',\n 'updater',\n 'thumbnail'\n ],\n details: [\n 'name',\n 'description',\n 'category',\n 'formula',\n 'active',\n 'state',\n 'vizType',\n 'schedule',\n 'scheduleId',\n 'timezone',\n 'version',\n 'createdAt',\n 'updatedAt',\n 'creator',\n 'updater',\n 'thumbnail'\n ]\n },\n columns: [\n { type: 'gutter', gutterName: 'sequence' },\n { type: 'gutter', gutterName: 'row-selector', multiple: true },\n {\n type: 'string',\n name: 'name',\n header: '이름',\n record: { editable: true },\n filter: 'search',\n sortable: true,\n width: 120\n },\n {\n type: 'string',\n name: 'description',\n header: i18next.t('field.description'),\n record: { editable: true },\n filter: 'search',\n width: 200\n },\n // {\n // type: 'string',\n // name: 'category',\n // header: '카테고리',\n // record: { editable: false, renderer: (v, c, r) => r.category?.name },\n // width: 120\n // },\n {\n type: 'resource-object',\n name: 'category',\n label: true,\n header: '카테고리',\n record: {\n editable: true,\n options: {\n title: i18next.t('title.lookup category'),\n queryName: 'kpiCategories'\n }\n },\n width: 200\n },\n { type: 'string', name: 'formula', header: '산식', record: { editable: true }, width: 200 },\n {\n type: 'string',\n name: 'grades',\n header: '등급 설정',\n record: {\n editable: false,\n renderer: (v, c, r) => {\n if (r.grades && r.grades.length > 0) {\n return html`<span style=\"color: #4caf50; cursor: pointer;\" @click=${() => this._editGrades(r)}>\n ${r.grades.length}개 등급 설정됨\n </span>`\n } else {\n return html`<span style=\"color: #999; cursor: pointer;\" @click=${() => this._editGrades(r)}>\n 등급 설정 없음\n </span>`\n }\n }\n },\n width: 150\n },\n {\n type: 'checkbox',\n name: 'active',\n label: true,\n header: i18next.t('field.active'),\n record: { editable: true },\n filter: true,\n sortable: true,\n width: 60\n },\n { type: 'string', name: 'state', header: '상태', record: { editable: false }, width: 100 },\n {\n type: 'string',\n name: 'vizType',\n header: '시각화 설정',\n record: {\n editable: false,\n renderer: (v, c, r) => {\n const vizType = r.vizType || 'CARD'\n const vizMeta = r.vizMeta || {}\n const color = vizMeta.color || '#2196f3'\n const icon = vizMeta.icon || 'dashboard'\n\n return html`\n <div style=\"display:flex;align-items:center;gap:8px;\">\n <span style=\"color:${color};cursor:pointer;\" @click=${() => this._editViz(r)}> ${vizType} </span>\n <md-icon style=\"color:${color};font-size:16px;cursor:pointer;\" @click=${() => this._editViz(r)}>\n ${icon}\n </md-icon>\n </div>\n `\n }\n },\n width: 150\n },\n { type: 'string', name: 'schedule', header: '스케줄', record: { editable: true }, width: 120 },\n { type: 'string', name: 'scheduleId', header: '스케줄ID', record: { editable: false }, width: 120 },\n { type: 'string', name: 'timezone', header: '타임존', record: { editable: true }, width: 100 },\n { type: 'number', name: 'version', header: '버전', record: { editable: false }, width: 80 },\n { type: 'datetime', name: 'createdAt', header: '생성일', record: { editable: false }, width: 180 },\n {\n type: 'datetime',\n name: 'updatedAt',\n header: i18next.t('field.updated_at'),\n record: { editable: false },\n sortable: true,\n width: 180\n },\n {\n type: 'resource-object',\n name: 'creator',\n header: '생성자',\n record: { editable: false, renderer: (v, c, r) => r.creator?.name },\n width: 120\n },\n {\n type: 'resource-object',\n name: 'updater',\n header: i18next.t('field.updater'),\n record: { editable: false, renderer: (v, c, r) => r.updater?.name },\n sortable: true,\n width: 120\n },\n { type: 'string', name: 'thumbnail', header: '썸네일', record: { editable: false }, width: 120 }\n ],\n rows: {\n appendable: false,\n selectable: {\n multiple: true\n }\n },\n sorters: [{ name: 'name' }]\n }\n }\n\n async pageUpdated(changes: any, lifecycle: any) {\n if (this.active) {\n // do something here when this page just became as active\n }\n }\n\n async fetchHandler({ page = 1, limit = 100, sortings = [], filters = [] }: FetchOption) {\n const response = await client.query({\n query: gql`\n query ($filters: [Filter!], $pagination: Pagination, $sortings: [Sorting!]) {\n responses: kpis(filters: $filters, pagination: $pagination, sortings: $sortings) {\n items {\n id\n name\n description\n active\n grades\n vizType\n vizMeta\n category {\n id\n name\n description\n }\n updater {\n id\n name\n }\n updatedAt\n creator {\n id\n name\n }\n createdAt\n }\n total\n }\n }\n `,\n variables: {\n filters,\n pagination: { page, limit },\n sortings\n }\n })\n\n return {\n total: response.data.responses.total || 0,\n records: response.data.responses.items || []\n }\n }\n\n async _deleteKpi() {\n if (\n await OxPrompt.open({\n title: i18next.t('text.are_you_sure'),\n text: i18next.t('text.sure_to_x', { x: i18next.t('text.delete') }),\n confirmButton: { text: i18next.t('button.confirm') },\n cancelButton: { text: i18next.t('button.cancel') }\n })\n ) {\n const ids = this.grist.selected.map(record => record.id)\n if (ids && ids.length > 0) {\n const response = await client.mutate({\n mutation: gql`\n mutation ($ids: [String!]!) {\n deleteKpis(ids: $ids)\n }\n `,\n variables: {\n ids\n }\n })\n\n if (!response.errors) {\n this.grist.fetch()\n notify({\n message: i18next.t('text.info_x_successfully', { x: i18next.t('text.delete') })\n })\n }\n }\n }\n }\n\n async _updateKpi() {\n let patches = this.grist.dirtyRecords\n if (patches && patches.length) {\n patches = patches.map(patch => {\n let patchField: any = patch.id ? { id: patch.id } : {}\n const dirtyFields = patch.__dirtyfields__\n for (let key in dirtyFields) {\n patchField[key] = dirtyFields[key].after\n }\n patchField.cuFlag = patch.__dirty__\n\n return patchField\n })\n\n const response = await client.mutate({\n mutation: gql`\n mutation ($patches: [KpiPatch!]!) {\n updateMultipleKpi(patches: $patches) {\n name\n }\n }\n `,\n variables: {\n patches\n }\n })\n\n if (!response.errors) {\n this.grist.fetch()\n }\n }\n }\n\n async creationCallback(kpi) {\n try {\n const response = await client.query({\n query: gql`\n mutation ($kpi: NewKpi!) {\n createKpi(kpi: $kpi) {\n id\n }\n }\n `,\n variables: {\n kpi\n },\n context: {\n hasUpload: true\n }\n })\n\n if (!response.errors) {\n this.grist.fetch()\n document.dispatchEvent(\n new CustomEvent('notify', {\n detail: {\n message: i18next.t('text.data_created_successfully')\n }\n })\n )\n }\n\n return true\n } catch (ex) {\n console.error(ex)\n document.dispatchEvent(\n new CustomEvent('notify', {\n detail: {\n type: 'error',\n message: i18next.t('text.error')\n }\n })\n )\n return false\n }\n }\n\n async exportHandler() {\n const exportTargets = this.grist.selected.length ? this.grist.selected : this.grist.dirtyData.records\n const targetFieldSet = new Set(['id', 'name', 'description', 'active'])\n\n return exportTargets.map(kpi => {\n let tempObj = {}\n for (const field of targetFieldSet) {\n tempObj[field] = kpi[field]\n }\n\n return tempObj\n })\n }\n\n async importHandler(records) {\n const popup = openPopup(\n html`\n <kpi-importer\n .kpis=${records}\n @imported=${() => {\n history.back()\n this.grist.fetch()\n }}\n ></kpi-importer>\n `,\n {\n backdrop: true,\n size: 'large',\n title: i18next.t('title.import kpi')\n }\n )\n\n popup.onclosed = () => {\n this.grist.fetch()\n }\n }\n\n async _editGrades(kpi: any) {\n const popup = await openPopup(\n html`\n <kpi-grade-editor .kpi=${kpi} @grades-updated=${(e: any) => this._onGradesUpdated(e.detail)}></kpi-grade-editor>\n `,\n {\n title: `${kpi.name} - 등급 설정`,\n size: 'large'\n }\n )\n }\n\n async _onGradesUpdated(detail: any) {\n const { kpiId, grades } = detail\n\n try {\n const response = await client.mutate({\n mutation: gql`\n mutation ($id: String!, $patch: KpiPatch!) {\n updateKpi(id: $id, patch: $patch) {\n id\n name\n grades\n }\n }\n `,\n variables: {\n id: kpiId,\n patch: { grades }\n }\n })\n\n if (!response.errors) {\n this.grist.fetch()\n notify({\n message: '등급 설정이 성공적으로 업데이트되었습니다.'\n })\n }\n } catch (error) {\n notify({\n message: '등급 설정 업데이트 중 오류가 발생했습니다.'\n })\n }\n }\n\n async _editViz(kpi: any) {\n const popup = await openPopup(\n html`\n <kpi-viz-editor\n .kpi=${kpi}\n .onSave=${(vizType: string, vizMeta: any) => this._onVizUpdated(kpi.id, vizType, vizMeta)}\n .onCancel=${() => popup.close()}\n ></kpi-viz-editor>\n `,\n {\n title: `${kpi.name} - 시각화 설정`,\n size: 'large'\n }\n )\n }\n\n async _onVizUpdated(kpiId: string, vizType: string, vizMeta: any) {\n try {\n const response = await client.mutate({\n mutation: gql`\n mutation ($id: String!, $patch: KpiPatch!) {\n updateKpi(id: $id, patch: $patch) {\n id\n name\n vizType\n vizMeta\n }\n }\n `,\n variables: {\n id: kpiId,\n patch: { vizType, vizMeta }\n }\n })\n\n if (!response.errors) {\n this.grist.fetch()\n notify({\n message: '시각화 설정이 성공적으로 업데이트되었습니다.'\n })\n }\n } catch (error) {\n notify({\n message: '시각화 설정 업데이트 중 오류가 발생했습니다.'\n })\n }\n }\n}\n"]}
@@ -0,0 +1,20 @@
1
+ import '@material/web/button/elevated-button.js';
2
+ import '@material/web/select/outlined-select.js';
3
+ import '@material/web/textfield/outlined-text-field.js';
4
+ import '@material/web/icon/icon.js';
5
+ import { LitElement } from 'lit';
6
+ declare const KpiVizEditor_base: (new (...args: any[]) => LitElement) & typeof LitElement;
7
+ export declare class KpiVizEditor extends KpiVizEditor_base {
8
+ static styles: import("lit").CSSResult[];
9
+ kpi: any;
10
+ selectedVizType: string;
11
+ vizMeta: any;
12
+ onSave: Function;
13
+ onCancel: Function;
14
+ connectedCallback(): void;
15
+ _selectVizType(type: string): void;
16
+ _updateVizMeta(key: string, value: any): void;
17
+ _renderPreview(): import("lit-html").TemplateResult<1>;
18
+ render(): import("lit-html").TemplateResult<1>;
19
+ }
20
+ export {};
@@ -0,0 +1,364 @@
1
+ import { __decorate, __metadata } from "tslib";
2
+ import '@material/web/button/elevated-button.js';
3
+ import '@material/web/select/outlined-select.js';
4
+ import '@material/web/textfield/outlined-text-field.js';
5
+ import '@material/web/icon/icon.js';
6
+ import { css, html, LitElement } from 'lit';
7
+ import { customElement, property } from 'lit/decorators.js';
8
+ import { i18next, localize } from '@operato/i18n';
9
+ import { CommonHeaderStyles, ScrollbarStyles } from '@operato/styles';
10
+ const VIZ_TYPES = [
11
+ { value: 'CARD', label: '카드', icon: 'dashboard' },
12
+ { value: 'GAUGE', label: '게이지', icon: 'speed' },
13
+ { value: 'PROGRESS', label: '진행률', icon: 'linear_scale' },
14
+ { value: 'BAR', label: '막대 차트', icon: 'bar_chart' },
15
+ { value: 'LINE', label: '선 차트', icon: 'show_chart' },
16
+ { value: 'PIE', label: '파이 차트', icon: 'pie_chart' },
17
+ { value: 'DONUT', label: '도넛 차트', icon: 'donut_large' },
18
+ { value: 'RADAR', label: '레이더 차트', icon: 'radar' },
19
+ { value: 'BULLET', label: '불릿 차트', icon: 'track_changes' },
20
+ { value: 'THERMOMETER', label: '온도계', icon: 'thermostat' },
21
+ { value: 'SPEEDOMETER', label: '속도계', icon: 'speed' },
22
+ { value: 'ICON', label: '아이콘', icon: 'emoji_events' },
23
+ { value: 'BADGE', label: '배지', icon: 'badge' },
24
+ { value: 'TEXT', label: '텍스트', icon: 'text_fields' },
25
+ { value: 'TABLE', label: '테이블', icon: 'table_chart' }
26
+ ];
27
+ let KpiVizEditor = class KpiVizEditor extends localize(i18next)(LitElement) {
28
+ constructor() {
29
+ super(...arguments);
30
+ this.kpi = null;
31
+ this.selectedVizType = 'CARD';
32
+ this.vizMeta = {};
33
+ this.onSave = () => { };
34
+ this.onCancel = () => { };
35
+ }
36
+ static { this.styles = [
37
+ CommonHeaderStyles,
38
+ ScrollbarStyles,
39
+ css `
40
+ :host {
41
+ display: flex;
42
+ flex-direction: column;
43
+ background-color: var(--md-sys-color-surface, #f4f6fa);
44
+ }
45
+
46
+ .viz-editor {
47
+ flex: 1;
48
+ display: flex;
49
+ flex-direction: column;
50
+ overflow-y: auto;
51
+
52
+ background: white;
53
+ padding: 24px;
54
+ }
55
+
56
+ .form-group {
57
+ margin-bottom: 20px;
58
+ }
59
+
60
+ .form-group label {
61
+ display: block;
62
+ margin-bottom: 8px;
63
+ font-weight: 500;
64
+ color: #555;
65
+ }
66
+
67
+ .form-options {
68
+ flex: 1;
69
+ display: flex;
70
+ flex-direction: row;
71
+ }
72
+
73
+ .viz-type-grid {
74
+ display: grid;
75
+ grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
76
+ gap: 12px;
77
+ margin-bottom: 20px;
78
+ }
79
+
80
+ .viz-type-option {
81
+ display: flex;
82
+ flex-direction: column;
83
+ align-items: center;
84
+ padding: 16px 12px;
85
+ border: 2px solid #e0e0e0;
86
+ border-radius: 8px;
87
+ cursor: pointer;
88
+ transition: all 0.2s;
89
+ text-align: center;
90
+ }
91
+
92
+ .viz-type-option:hover {
93
+ border-color: #2196f3;
94
+ background: #f5f9ff;
95
+ }
96
+
97
+ .viz-type-option.selected {
98
+ border-color: #2196f3;
99
+ background: #e3f2fd;
100
+ }
101
+
102
+ .viz-type-option md-icon {
103
+ font-size: 24px;
104
+ margin-bottom: 8px;
105
+ color: #666;
106
+ }
107
+
108
+ .viz-type-option.selected md-icon {
109
+ color: #2196f3;
110
+ }
111
+
112
+ .viz-type-option .label {
113
+ font-size: 0.9rem;
114
+ font-weight: 500;
115
+ color: #333;
116
+ }
117
+
118
+ .viz-meta-section {
119
+ margin-top: 24px;
120
+ padding-top: 20px;
121
+ border-top: 1px solid #eee;
122
+ }
123
+
124
+ .color-picker {
125
+ display: flex;
126
+ gap: 12px;
127
+ align-items: center;
128
+ margin-bottom: 16px;
129
+ }
130
+
131
+ .color-input {
132
+ width: 60px;
133
+ height: 40px;
134
+ border: none;
135
+ border-radius: 6px;
136
+ cursor: pointer;
137
+ }
138
+
139
+ .buttons {
140
+ display: flex;
141
+ gap: 12px;
142
+ justify-content: flex-end;
143
+ margin-top: 24px;
144
+ padding-top: 20px;
145
+ border-top: 1px solid #eee;
146
+ }
147
+
148
+ .preview {
149
+ flex: 1;
150
+ margin: 30px 16px 16px 16px;
151
+ padding: 16px;
152
+ background: #f8f9fa;
153
+ border-radius: 8px;
154
+ border: 1px solid #e9ecef;
155
+ }
156
+
157
+ .preview h4 {
158
+ margin: 0 0 12px 0;
159
+ color: #495057;
160
+ font-size: 0.95rem;
161
+ }
162
+
163
+ .footer span {
164
+ font-size: 0.8em;
165
+ color: var(--md-sys-color-on-surface);
166
+ line-height: 1.5;
167
+ padding: 10px;
168
+ }
169
+ `
170
+ ]; }
171
+ connectedCallback() {
172
+ super.connectedCallback();
173
+ if (this.kpi) {
174
+ this.selectedVizType = this.kpi.vizType || 'CARD';
175
+ this.vizMeta = this.kpi.vizMeta || {};
176
+ }
177
+ }
178
+ _selectVizType(type) {
179
+ this.selectedVizType = type;
180
+ this.requestUpdate();
181
+ }
182
+ _updateVizMeta(key, value) {
183
+ this.vizMeta = { ...this.vizMeta, [key]: value };
184
+ this.requestUpdate();
185
+ }
186
+ _renderPreview() {
187
+ const kpiValue = this.kpi?.value?.value || 75;
188
+ const targetValue = this.kpi?.targetValue || 100;
189
+ const unit = this.kpi?.unit || '';
190
+ const color = this.vizMeta.color || '#2196f3';
191
+ const icon = this.vizMeta.icon || 'trending_up';
192
+ switch (this.selectedVizType) {
193
+ case 'CARD':
194
+ return html `
195
+ <div
196
+ style="display:flex;align-items:center;gap:12px;padding:16px;background:white;border-radius:8px;border:1px solid #e0e0e0;"
197
+ >
198
+ <md-icon style="color:${color};font-size:32px;">${icon}</md-icon>
199
+ <div>
200
+ <div style="font-size:1.5rem;font-weight:bold;color:${color};">${kpiValue}${unit}</div>
201
+ <div style="font-size:0.9rem;color:#666;">목표: ${targetValue}${unit}</div>
202
+ </div>
203
+ </div>
204
+ `;
205
+ case 'GAUGE':
206
+ const percentage = Math.min((kpiValue / targetValue) * 100, 100);
207
+ return html `
208
+ <div style="text-align:center;padding:16px;">
209
+ <div
210
+ style="width:120px;height:60px;border-radius:60px 60px 0 0;background:conic-gradient(${color} 0deg ${percentage *
211
+ 3.6}deg, #e0e0e0 ${percentage * 3.6}deg 360deg);margin:0 auto;position:relative;"
212
+ >
213
+ <div
214
+ style="position:absolute;bottom:0;left:50%;transform:translateX(-50%);font-size:1.2rem;font-weight:bold;color:${color};"
215
+ >
216
+ ${kpiValue}${unit}
217
+ </div>
218
+ </div>
219
+ </div>
220
+ `;
221
+ case 'PROGRESS':
222
+ const progressPercentage = Math.min((kpiValue / targetValue) * 100, 100);
223
+ return html `
224
+ <div style="padding:16px;">
225
+ <div style="background:#e0e0e0;height:20px;border-radius:10px;overflow:hidden;">
226
+ <div style="background:${color};height:100%;width:${progressPercentage}%;transition:width 0.3s;"></div>
227
+ </div>
228
+ <div style="text-align:center;margin-top:8px;font-weight:bold;color:${color};">
229
+ ${kpiValue}${unit} / ${targetValue}${unit}
230
+ </div>
231
+ </div>
232
+ `;
233
+ case 'ICON':
234
+ return html `
235
+ <div style="text-align:center;padding:16px;">
236
+ <md-icon style="color:${color};font-size:48px;">${icon}</md-icon>
237
+ <div style="font-size:1.2rem;font-weight:bold;color:${color};margin-top:8px;">${kpiValue}${unit}</div>
238
+ </div>
239
+ `;
240
+ default:
241
+ return html ` <div style="padding:16px;text-align:center;color:#666;">${this.selectedVizType} 미리보기</div> `;
242
+ }
243
+ }
244
+ render() {
245
+ return html `
246
+ <div class="viz-editor">
247
+ <div class="form-group">
248
+ <label>시각화 타입 선택</label>
249
+ <div class="viz-type-grid">
250
+ ${VIZ_TYPES.map(type => html `
251
+ <div
252
+ class="viz-type-option ${this.selectedVizType === type.value ? 'selected' : ''}"
253
+ @click=${() => this._selectVizType(type.value)}
254
+ >
255
+ <md-icon>${type.icon}</md-icon>
256
+ <div class="label">${type.label}</div>
257
+ </div>
258
+ `)}
259
+ </div>
260
+ </div>
261
+
262
+ <div class="form-options">
263
+ <div class="viz-meta-section">
264
+ <label>시각화 옵션</label>
265
+
266
+ <div class="form-group">
267
+ <label>색상</label>
268
+ <div class="color-picker">
269
+ <input
270
+ type="color"
271
+ class="color-input"
272
+ .value=${this.vizMeta.color || '#2196f3'}
273
+ @change=${(e) => this._updateVizMeta('color', e.target.value)}
274
+ />
275
+ <md-outlined-text-field
276
+ label="색상 코드"
277
+ .value=${this.vizMeta.color || '#2196f3'}
278
+ @change=${(e) => this._updateVizMeta('color', e.target.value)}
279
+ ></md-outlined-text-field>
280
+ </div>
281
+ </div>
282
+
283
+ <div class="form-group">
284
+ <label>아이콘</label>
285
+ <md-outlined-text-field
286
+ label="Material Icons 이름"
287
+ .value=${this.vizMeta.icon || 'trending_up'}
288
+ @change=${(e) => this._updateVizMeta('icon', e.target.value)}
289
+ ></md-outlined-text-field>
290
+ </div>
291
+
292
+ <div class="form-group">
293
+ <label>최소값</label>
294
+ <md-outlined-text-field
295
+ type="number"
296
+ label="최소값"
297
+ .value=${this.vizMeta.minValue || 0}
298
+ @change=${(e) => this._updateVizMeta('minValue', parseFloat(e.target.value))}
299
+ ></md-outlined-text-field>
300
+ </div>
301
+
302
+ <div class="form-group">
303
+ <label>최대값</label>
304
+ <md-outlined-text-field
305
+ type="number"
306
+ label="최대값"
307
+ .value=${this.vizMeta.maxValue || 100}
308
+ @change=${(e) => this._updateVizMeta('maxValue', parseFloat(e.target.value))}
309
+ ></md-outlined-text-field>
310
+ </div>
311
+
312
+ <div class="form-group">
313
+ <label>소수점 자릿수</label>
314
+ <md-outlined-text-field
315
+ type="number"
316
+ label="소수점 자릿수"
317
+ .value=${this.vizMeta.decimalPlaces || 0}
318
+ @change=${(e) => this._updateVizMeta('decimalPlaces', parseInt(e.target.value))}
319
+ ></md-outlined-text-field>
320
+ </div>
321
+ </div>
322
+
323
+ <div class="preview">
324
+ <h4>미리보기</h4>
325
+ ${this._renderPreview()}
326
+ </div>
327
+ </div>
328
+ </div>
329
+
330
+ <div class="footer">
331
+ <div filler></div>
332
+ <button type="button" @click=${this.onCancel}><md-icon>cancel</md-icon>취소</button>
333
+ <button type="button" @click=${() => this.onSave(this.selectedVizType, this.vizMeta)} done>
334
+ <md-icon>save</md-icon>저장
335
+ </button>
336
+ </div>
337
+ `;
338
+ }
339
+ };
340
+ __decorate([
341
+ property({ type: Object }),
342
+ __metadata("design:type", Object)
343
+ ], KpiVizEditor.prototype, "kpi", void 0);
344
+ __decorate([
345
+ property({ type: String }),
346
+ __metadata("design:type", String)
347
+ ], KpiVizEditor.prototype, "selectedVizType", void 0);
348
+ __decorate([
349
+ property({ type: Object }),
350
+ __metadata("design:type", Object)
351
+ ], KpiVizEditor.prototype, "vizMeta", void 0);
352
+ __decorate([
353
+ property({ type: Object }),
354
+ __metadata("design:type", Function)
355
+ ], KpiVizEditor.prototype, "onSave", void 0);
356
+ __decorate([
357
+ property({ type: Object }),
358
+ __metadata("design:type", Function)
359
+ ], KpiVizEditor.prototype, "onCancel", void 0);
360
+ KpiVizEditor = __decorate([
361
+ customElement('kpi-viz-editor')
362
+ ], KpiVizEditor);
363
+ export { KpiVizEditor };
364
+ //# sourceMappingURL=kpi-viz-editor.js.map