@things-factory/organization 10.1.227 → 10.1.228
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.
|
@@ -73,6 +73,7 @@ let EmployeeProfileListPage = class EmployeeProfileListPage extends localize(i18
|
|
|
73
73
|
const shown = this.languages.find(one => one.code === this.language)?.display ?? this.language;
|
|
74
74
|
return html `<ox-grist
|
|
75
75
|
class="page-fill"
|
|
76
|
+
search-mode="term"
|
|
76
77
|
.mode=${isMobileDevice() ? 'CARD' : 'GRID'}
|
|
77
78
|
.config=${this.gristConfig}
|
|
78
79
|
.fetchHandler=${this.fetchHandler.bind(this)}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"employee-profile-list-page.js","sourceRoot":"","sources":["../../../client/pages/employee-profile/employee-profile-list-page.ts"],"names":[],"mappings":"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","sourcesContent":["import '@operato/data-grist/ox-grist.js'\nimport '@operato/input/ox-select.js'\nimport '@operato/popup/ox-popup-list.js'\n\nimport gql from 'graphql-tag'\nimport { css, html } from 'lit'\nimport { customElement, query, state } from 'lit/decorators.js'\n\nimport { DataGrist, FetchOption } from '@operato/data-grist'\nimport { client } from '@operato/graphql'\nimport { i18next, localize } from '@operato/i18n'\nimport { notify } from '@operato/layout'\nimport { PageView } from '@operato/shell'\nimport { CommonGristStyles, CommonHeaderStyles, ScrollbarStyles, WorkSurfacePageStyles } from '@operato/styles'\nimport { isMobileDevice } from '@operato/utils'\nimport { getLanguages } from '@things-factory/auth-base/dist-client'\n\nimport { profileFile, readerLanguageOf, saveProfileFile, type Language, type ProfileFormat } from './employee-profile-files'\nimport { openProfilePreview } from './employee-profile-preview'\n\nconst dayOf = (value?: string | null) => {\n if (!value) return ''\n const day = new Date(value)\n const pad = (n: number) => String(n).padStart(2, '0')\n return `${day.getFullYear()}-${pad(day.getMonth() + 1)}-${pad(day.getDate())}`\n}\n\n/**\n * 인력 프로필 — every active employee and when their profile was last written; the rows picked are downloaded as one\n * document to attach to a quotation - Excel or PDF, laid out once on the server (ADR-0169 decision 5). Read under\n * `employee-profile`: the basics and the profile, nothing else of the employee record.\n */\n@customElement('employee-profile-list-page')\nexport class EmployeeProfileListPage extends localize(i18next)(PageView) {\n static styles = [\n WorkSurfacePageStyles,\n CommonGristStyles,\n CommonHeaderStyles,\n ScrollbarStyles,\n css`\n .filters {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--spacing-medium, 8px);\n font-size: var(--ui-t-small, 11.5px);\n color: var(--ui-muted, var(--md-sys-color-on-surface-variant));\n }\n ox-select {\n min-width: 140px;\n }\n `\n ]\n\n @state() gristConfig: any\n /** The languages the application runs, and the one the document's own words are printed in - the reader's at first. */\n @state() languages: Language[] = []\n @state() language = ''\n @query('ox-grist') private grist!: DataGrist\n\n get context() {\n return {\n title: i18next.t('title.employee-profile-list'),\n search: {\n handler: (search: string) => {\n this.grist.searchText = search\n },\n value: this.grist?.searchText || ''\n },\n actions: [\n { title: i18next.t('button.employee-profile-preview'), icon: 'preview', action: () => this.preview() },\n { title: i18next.t('button.employee-profile-download-pdf'), icon: 'picture_as_pdf', action: () => this.download('PDF') },\n { title: i18next.t('button.employee-profile-download'), icon: 'download', emphasis: { raised: true }, action: () => this.download('XLSX') }\n ]\n }\n }\n\n render() {\n const shown = this.languages.find(one => one.code === this.language)?.display ?? this.language\n return html`<ox-grist\n class=\"page-fill\"\n .mode=${isMobileDevice() ? 'CARD' : 'GRID'}\n .config=${this.gristConfig}\n .fetchHandler=${this.fetchHandler.bind(this)}\n >\n ${this.languages.length > 1\n ? html`<div slot=\"headroom\" class=\"header\">\n <div class=\"filters\">\n <span>${i18next.t('label.employee-profile-document-language')}</span>\n <ox-select\n .value=${this.language}\n aria-label=${i18next.t('label.employee-profile-document-language')}\n @change=${(e: CustomEvent) => (this.language = String(e.detail || this.language))}\n >\n <span slot=\"label\">${shown}</span>\n <ox-popup-list align-left nowrap with-search>${this.languages.map(one => html`<div option value=${one.code}>${one.display}</div>`)}</ox-popup-list>\n </ox-select>\n </div>\n </div>`\n : ''}\n </ox-grist>`\n }\n\n async pageInitialized() {\n /* The reader's language first - matched to a code the application runs, by its language part when the region differs. */\n this.languages = ((await getLanguages()) ?? []) as Language[]\n this.language = readerLanguageOf(this.languages)\n\n const text = (name: string, header: string, width: number, extra: any = {}) => ({\n type: 'string',\n name,\n header,\n width,\n sortable: true,\n ...extra,\n record: { editable: false, ...extra.record }\n })\n this.gristConfig = {\n rows: { appendable: false, selectable: { multiple: true } },\n pagination: { infinite: true },\n emptyNote: { title: i18next.t('text.employee-profile-empty') },\n list: { fields: ['name', 'departmentName'], details: ['jobPosition', 'profileUpdatedAt'] },\n columns: [\n { type: 'gutter', gutterName: 'sequence' },\n { type: 'gutter', gutterName: 'row-selector', multiple: true },\n text('name', i18next.t('field.name'), 120),\n text('departmentName', i18next.t('label.department'), 160),\n text('jobPosition', i18next.t('label.job-position'), 100),\n text('jobResponsibility', i18next.t('label.job-responsibility'), 100),\n text('profileUpdatedAt', i18next.t('label.employee-profile-updated-at'), 120)\n ]\n }\n }\n\n /** Every active employee at once - a company's people, not a ledger - narrowed here by the search words. */\n async fetchHandler({ search }: FetchOption) {\n const response = await client.query({\n query: gql`\n query {\n employeeProfiles {\n employeeId\n controlNo\n name\n departmentName\n jobPosition\n jobResponsibility\n hiredOn\n profile {\n summary\n skills\n educations { school major degree startedOn endedOn }\n certificates { name issuer acquiredOn }\n careers { company department position startedOn endedOn duties }\n projects { name client startedOn endedOn role duties technologies }\n updatedAt\n }\n }\n }\n `,\n fetchPolicy: 'network-only'\n })\n if (response.errors?.length) throw response\n\n const words = (search ?? '').trim().toLowerCase()\n const records = (response.data.employeeProfiles as any[])\n .map(one => ({ ...one, id: one.employeeId, profileUpdatedAt: dayOf(one.profile?.updatedAt) }))\n .filter(one => !words || [one.name, one.departmentName, one.jobPosition, one.jobResponsibility].some(value => value?.toLowerCase().includes(words)))\n return { total: records.length, records }\n }\n\n /** The ids of the rows picked - or nothing, having said so. */\n private picked(): string[] | null {\n const picked = this.grist?.selected ?? []\n if (picked.length) return picked.map((one: any) => one.employeeId)\n notify({ level: 'warn', message: i18next.t('text.employee-profile-select-rows-first') })\n return null\n }\n\n private preview() {\n const employeeIds = this.picked()\n if (employeeIds) openProfilePreview({ employeeIds }, this.languages, this.language)\n }\n\n private async download(format: ProfileFormat) {\n const employeeIds = this.picked()\n if (!employeeIds) return\n try {\n saveProfileFile(await profileFile({ employeeIds }, format, this.language))\n } catch (error: any) {\n notify({ level: 'error', message: error?.message ?? String(error) })\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"employee-profile-list-page.js","sourceRoot":"","sources":["../../../client/pages/employee-profile/employee-profile-list-page.ts"],"names":[],"mappings":"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","sourcesContent":["import '@operato/data-grist/ox-grist.js'\nimport '@operato/input/ox-select.js'\nimport '@operato/popup/ox-popup-list.js'\n\nimport gql from 'graphql-tag'\nimport { css, html } from 'lit'\nimport { customElement, query, state } from 'lit/decorators.js'\n\nimport { DataGrist, FetchOption } from '@operato/data-grist'\nimport { client } from '@operato/graphql'\nimport { i18next, localize } from '@operato/i18n'\nimport { notify } from '@operato/layout'\nimport { PageView } from '@operato/shell'\nimport { CommonGristStyles, CommonHeaderStyles, ScrollbarStyles, WorkSurfacePageStyles } from '@operato/styles'\nimport { isMobileDevice } from '@operato/utils'\nimport { getLanguages } from '@things-factory/auth-base/dist-client'\n\nimport { profileFile, readerLanguageOf, saveProfileFile, type Language, type ProfileFormat } from './employee-profile-files'\nimport { openProfilePreview } from './employee-profile-preview'\n\nconst dayOf = (value?: string | null) => {\n if (!value) return ''\n const day = new Date(value)\n const pad = (n: number) => String(n).padStart(2, '0')\n return `${day.getFullYear()}-${pad(day.getMonth() + 1)}-${pad(day.getDate())}`\n}\n\n/**\n * 인력 프로필 — every active employee and when their profile was last written; the rows picked are downloaded as one\n * document to attach to a quotation - Excel or PDF, laid out once on the server (ADR-0169 decision 5). Read under\n * `employee-profile`: the basics and the profile, nothing else of the employee record.\n */\n@customElement('employee-profile-list-page')\nexport class EmployeeProfileListPage extends localize(i18next)(PageView) {\n static styles = [\n WorkSurfacePageStyles,\n CommonGristStyles,\n CommonHeaderStyles,\n ScrollbarStyles,\n css`\n .filters {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--spacing-medium, 8px);\n font-size: var(--ui-t-small, 11.5px);\n color: var(--ui-muted, var(--md-sys-color-on-surface-variant));\n }\n ox-select {\n min-width: 140px;\n }\n `\n ]\n\n @state() gristConfig: any\n /** The languages the application runs, and the one the document's own words are printed in - the reader's at first. */\n @state() languages: Language[] = []\n @state() language = ''\n @query('ox-grist') private grist!: DataGrist\n\n get context() {\n return {\n title: i18next.t('title.employee-profile-list'),\n search: {\n handler: (search: string) => {\n this.grist.searchText = search\n },\n value: this.grist?.searchText || ''\n },\n actions: [\n { title: i18next.t('button.employee-profile-preview'), icon: 'preview', action: () => this.preview() },\n { title: i18next.t('button.employee-profile-download-pdf'), icon: 'picture_as_pdf', action: () => this.download('PDF') },\n { title: i18next.t('button.employee-profile-download'), icon: 'download', emphasis: { raised: true }, action: () => this.download('XLSX') }\n ]\n }\n }\n\n render() {\n const shown = this.languages.find(one => one.code === this.language)?.display ?? this.language\n return html`<ox-grist\n class=\"page-fill\"\n search-mode=\"term\"\n .mode=${isMobileDevice() ? 'CARD' : 'GRID'}\n .config=${this.gristConfig}\n .fetchHandler=${this.fetchHandler.bind(this)}\n >\n ${this.languages.length > 1\n ? html`<div slot=\"headroom\" class=\"header\">\n <div class=\"filters\">\n <span>${i18next.t('label.employee-profile-document-language')}</span>\n <ox-select\n .value=${this.language}\n aria-label=${i18next.t('label.employee-profile-document-language')}\n @change=${(e: CustomEvent) => (this.language = String(e.detail || this.language))}\n >\n <span slot=\"label\">${shown}</span>\n <ox-popup-list align-left nowrap with-search>${this.languages.map(one => html`<div option value=${one.code}>${one.display}</div>`)}</ox-popup-list>\n </ox-select>\n </div>\n </div>`\n : ''}\n </ox-grist>`\n }\n\n async pageInitialized() {\n /* The reader's language first - matched to a code the application runs, by its language part when the region differs. */\n this.languages = ((await getLanguages()) ?? []) as Language[]\n this.language = readerLanguageOf(this.languages)\n\n const text = (name: string, header: string, width: number, extra: any = {}) => ({\n type: 'string',\n name,\n header,\n width,\n sortable: true,\n ...extra,\n record: { editable: false, ...extra.record }\n })\n this.gristConfig = {\n rows: { appendable: false, selectable: { multiple: true } },\n pagination: { infinite: true },\n emptyNote: { title: i18next.t('text.employee-profile-empty') },\n list: { fields: ['name', 'departmentName'], details: ['jobPosition', 'profileUpdatedAt'] },\n columns: [\n { type: 'gutter', gutterName: 'sequence' },\n { type: 'gutter', gutterName: 'row-selector', multiple: true },\n text('name', i18next.t('field.name'), 120),\n text('departmentName', i18next.t('label.department'), 160),\n text('jobPosition', i18next.t('label.job-position'), 100),\n text('jobResponsibility', i18next.t('label.job-responsibility'), 100),\n text('profileUpdatedAt', i18next.t('label.employee-profile-updated-at'), 120)\n ]\n }\n }\n\n /** Every active employee at once - a company's people, not a ledger - narrowed here by the search words. */\n async fetchHandler({ search }: FetchOption) {\n const response = await client.query({\n query: gql`\n query {\n employeeProfiles {\n employeeId\n controlNo\n name\n departmentName\n jobPosition\n jobResponsibility\n hiredOn\n profile {\n summary\n skills\n educations { school major degree startedOn endedOn }\n certificates { name issuer acquiredOn }\n careers { company department position startedOn endedOn duties }\n projects { name client startedOn endedOn role duties technologies }\n updatedAt\n }\n }\n }\n `,\n fetchPolicy: 'network-only'\n })\n if (response.errors?.length) throw response\n\n const words = (search ?? '').trim().toLowerCase()\n const records = (response.data.employeeProfiles as any[])\n .map(one => ({ ...one, id: one.employeeId, profileUpdatedAt: dayOf(one.profile?.updatedAt) }))\n .filter(one => !words || [one.name, one.departmentName, one.jobPosition, one.jobResponsibility].some(value => value?.toLowerCase().includes(words)))\n return { total: records.length, records }\n }\n\n /** The ids of the rows picked - or nothing, having said so. */\n private picked(): string[] | null {\n const picked = this.grist?.selected ?? []\n if (picked.length) return picked.map((one: any) => one.employeeId)\n notify({ level: 'warn', message: i18next.t('text.employee-profile-select-rows-first') })\n return null\n }\n\n private preview() {\n const employeeIds = this.picked()\n if (employeeIds) openProfilePreview({ employeeIds }, this.languages, this.language)\n }\n\n private async download(format: ProfileFormat) {\n const employeeIds = this.picked()\n if (!employeeIds) return\n try {\n saveProfileFile(await profileFile({ employeeIds }, format, this.language))\n } catch (error: any) {\n notify({ level: 'error', message: error?.message ?? String(error) })\n }\n }\n}\n"]}
|