@things-factory/organization 10.1.223 → 10.1.227

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.
Files changed (69) hide show
  1. package/dist-client/pages/employee-profile/employee-profile-files.d.ts +23 -0
  2. package/dist-client/pages/employee-profile/employee-profile-files.js +50 -0
  3. package/dist-client/pages/employee-profile/employee-profile-files.js.map +1 -0
  4. package/dist-client/pages/employee-profile/employee-profile-form.d.ts +63 -0
  5. package/dist-client/pages/employee-profile/employee-profile-form.js +132 -0
  6. package/dist-client/pages/employee-profile/employee-profile-form.js.map +1 -0
  7. package/dist-client/pages/employee-profile/employee-profile-list-page.d.ts +52 -0
  8. package/dist-client/pages/employee-profile/employee-profile-list-page.js +206 -0
  9. package/dist-client/pages/employee-profile/employee-profile-list-page.js.map +1 -0
  10. package/dist-client/pages/employee-profile/employee-profile-preview.d.ts +28 -0
  11. package/dist-client/pages/employee-profile/employee-profile-preview.js +179 -0
  12. package/dist-client/pages/employee-profile/employee-profile-preview.js.map +1 -0
  13. package/dist-client/pages/employee-profile/my-employee-profile-page.d.ts +56 -0
  14. package/dist-client/pages/employee-profile/my-employee-profile-page.js +656 -0
  15. package/dist-client/pages/employee-profile/my-employee-profile-page.js.map +1 -0
  16. package/dist-client/route.d.ts +1 -1
  17. package/dist-client/route.js +7 -0
  18. package/dist-client/route.js.map +1 -1
  19. package/dist-client/tsconfig.tsbuildinfo +1 -1
  20. package/dist-server/ai-entry/employee-profile-entry.d.ts +10 -0
  21. package/dist-server/ai-entry/employee-profile-entry.js +88 -0
  22. package/dist-server/ai-entry/employee-profile-entry.js.map +1 -0
  23. package/dist-server/ai-entry/entry-target-shape.d.ts +11 -1
  24. package/dist-server/ai-entry/entry-target-shape.js.map +1 -1
  25. package/dist-server/ai-entry/organization-entry-targets.d.ts +8 -0
  26. package/dist-server/ai-entry/organization-entry-targets.js +26 -1
  27. package/dist-server/ai-entry/organization-entry-targets.js.map +1 -1
  28. package/dist-server/role-tasks.js +4 -1
  29. package/dist-server/role-tasks.js.map +1 -1
  30. package/dist-server/service/employee-profile/employee-profile-document.d.ts +122 -0
  31. package/dist-server/service/employee-profile/employee-profile-document.js +439 -0
  32. package/dist-server/service/employee-profile/employee-profile-document.js.map +1 -0
  33. package/dist-server/service/employee-profile/employee-profile-mutation.d.ts +6 -0
  34. package/dist-server/service/employee-profile/employee-profile-mutation.js +74 -0
  35. package/dist-server/service/employee-profile/employee-profile-mutation.js.map +1 -0
  36. package/dist-server/service/employee-profile/employee-profile-query.d.ts +14 -0
  37. package/dist-server/service/employee-profile/employee-profile-query.js +137 -0
  38. package/dist-server/service/employee-profile/employee-profile-query.js.map +1 -0
  39. package/dist-server/service/employee-profile/employee-profile-rows.d.ts +29 -0
  40. package/dist-server/service/employee-profile/employee-profile-rows.js +122 -0
  41. package/dist-server/service/employee-profile/employee-profile-rows.js.map +1 -0
  42. package/dist-server/service/employee-profile/employee-profile-rules.d.ts +61 -0
  43. package/dist-server/service/employee-profile/employee-profile-rules.js +104 -0
  44. package/dist-server/service/employee-profile/employee-profile-rules.js.map +1 -0
  45. package/dist-server/service/employee-profile/employee-profile-type.d.ts +35 -0
  46. package/dist-server/service/employee-profile/employee-profile-type.js +110 -0
  47. package/dist-server/service/employee-profile/employee-profile-type.js.map +1 -0
  48. package/dist-server/service/employee-profile/employee-profile.d.ts +24 -0
  49. package/dist-server/service/employee-profile/employee-profile.js +112 -0
  50. package/dist-server/service/employee-profile/employee-profile.js.map +1 -0
  51. package/dist-server/service/employee-profile/index.d.ts +5 -0
  52. package/dist-server/service/employee-profile/index.js +9 -0
  53. package/dist-server/service/employee-profile/index.js.map +1 -0
  54. package/dist-server/service/index.d.ts +3 -2
  55. package/dist-server/service/index.js +6 -2
  56. package/dist-server/service/index.js.map +1 -1
  57. package/dist-server/tsconfig.tsbuildinfo +1 -1
  58. package/package.json +8 -6
  59. package/tests/employee-profile-db.test.ts +247 -0
  60. package/tests/employee-profile-document.test.ts +219 -0
  61. package/tests/employee-profile-entry.test.ts +72 -0
  62. package/tests/employee-profile-rules.test.ts +103 -0
  63. package/things-factory.config.js +3 -0
  64. package/translations/en.json +78 -1
  65. package/translations/es.json +78 -1
  66. package/translations/ja.json +78 -1
  67. package/translations/ko.json +78 -1
  68. package/translations/ms.json +78 -1
  69. package/translations/zh.json +78 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"my-employee-profile-page.js","sourceRoot":"","sources":["../../../client/pages/employee-profile/my-employee-profile-page.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/icon/icon.js'\nimport '@operato/list-state/ox-empty-note.js'\nimport '@operato/list-state/ox-page-state.js'\n\nimport gql from 'graphql-tag'\nimport { css, html, nothing } from 'lit'\nimport { customElement, state } from 'lit/decorators.js'\n\nimport { client } from '@operato/graphql'\nimport { i18next, localize } from '@operato/i18n'\nimport { notify } from '@operato/layout'\nimport { PageView } from '@operato/shell'\nimport { ButtonStyles, DocumentPageStyles, FormFieldStyles } from '@operato/styles'\nimport { getLanguages } from '@things-factory/auth-base/dist-client'\n\nimport {\n addSkills,\n blankRow,\n completenessOf,\n headlineOf,\n periodLabelOf,\n PROFILE_SECTIONS,\n profileFormOf,\n profileInputOf,\n type ProfileField,\n type ProfileForm,\n type ProfileRow,\n type ProfileSection\n} from './employee-profile-form'\nimport { readerLanguageOf, type Language } from './employee-profile-files'\nimport { openProfilePreview } from './employee-profile-preview'\n\nconst PROFILE_FIELDS = `\n id\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\nconst SUMMARY_LIMIT = 500\n\n/**\n * 내 프로필 — the employee writes their own career profile: a summary, skills, and the rows of education,\n * certificates, past jobs and projects; sales attaches it to quotations (ADR-0169 decisions 2 · 5). Saved whole.\n *\n * The page is built to be filled in: who it is about and how complete it is stand at the top, each missing essential a\n * click away; each row is a card whose headline reads like the document's line; a section with nothing yet says what\n * it is for; and the document itself is one click away (PDF), as sales will hand it in. An account not linked to an\n * employee record has no profile to write, and is told so before anything is typed.\n */\n@customElement('my-employee-profile-page')\nexport class MyEmployeeProfilePage extends localize(i18next)(PageView) {\n static styles = [\n FormFieldStyles,\n ButtonStyles,\n DocumentPageStyles,\n css`\n label {\n display: flex;\n flex-direction: column;\n gap: var(--spacing-small, 4px);\n min-width: 0;\n font-size: var(--ui-t-small, 11.5px);\n color: var(--ui-muted, var(--md-sys-color-on-surface-variant));\n }\n label > :is(input, textarea) {\n font-size: var(--ui-t-body, 13px);\n color: var(--ui-ink, var(--md-sys-color-on-surface));\n }\n input,\n textarea {\n box-sizing: border-box;\n width: 100%;\n font-family: inherit;\n }\n input:not([type='checkbox']) {\n height: var(--form-element-height-medium, 32px);\n }\n textarea {\n min-height: 72px;\n resize: vertical;\n line-height: 1.5;\n }\n .muted {\n color: var(--ui-muted, var(--md-sys-color-on-surface-variant));\n }\n\n /* ── Who it is about, and how far along ─────────────────────────────── */\n .hero {\n display: grid;\n grid-template-columns: minmax(0, 1fr) minmax(240px, 340px);\n gap: var(--spacing-huge, 24px);\n align-items: center;\n }\n .who {\n display: flex;\n align-items: center;\n gap: var(--spacing-large, 12px);\n min-width: 0;\n }\n .avatar {\n flex: none;\n display: grid;\n place-items: center;\n width: 56px;\n height: 56px;\n border-radius: 50%;\n background: var(--md-sys-color-primary-container);\n color: var(--md-sys-color-on-primary-container);\n font-size: 22px;\n font-weight: 700;\n }\n .who h2 {\n margin: 0;\n font-size: var(--ui-t-headline, 20px);\n font-weight: 700;\n color: var(--ui-ink, var(--md-sys-color-on-surface));\n }\n .who p {\n margin: 2px 0 0;\n font-size: var(--ui-t-body, 13px);\n }\n .progress {\n display: flex;\n flex-direction: column;\n gap: var(--spacing-small, 4px);\n }\n .progress-head {\n display: flex;\n align-items: baseline;\n justify-content: space-between;\n font-size: var(--ui-t-small, 11.5px);\n }\n .progress-head strong {\n font-size: var(--ui-t-title, 15px);\n color: var(--ui-ink, var(--md-sys-color-on-surface));\n }\n .bar {\n height: 8px;\n border-radius: 4px;\n background: var(--md-sys-color-surface-container-high);\n overflow: hidden;\n }\n .bar > span {\n display: block;\n height: 100%;\n border-radius: 4px;\n background: var(--md-sys-color-primary);\n transition: width 0.3s ease;\n }\n .missing {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--spacing-small, 4px);\n margin-top: var(--spacing-small, 4px);\n font-size: var(--ui-t-small, 11.5px);\n }\n .hero-foot {\n grid-column: 1 / -1;\n display: flex;\n align-items: center;\n gap: var(--spacing-medium, 8px);\n padding-top: var(--spacing-large, 12px);\n border-top: 1px solid var(--ui-line, var(--md-sys-color-outline-variant));\n font-size: var(--ui-t-small, 11.5px);\n }\n .hero-foot .unsaved {\n color: var(--md-sys-color-tertiary, var(--md-sys-color-primary));\n font-weight: 600;\n }\n .hero-foot button {\n margin-left: auto;\n }\n\n /* ── A section ─────────────────────────────────────────────────────── */\n .page-section-header h3 {\n display: flex;\n align-items: center;\n gap: var(--spacing-medium, 8px);\n }\n .page-section-header h3 md-icon {\n --md-icon-size: 20px;\n color: var(--md-sys-color-primary);\n }\n .count {\n min-width: 20px;\n padding: 1px 7px;\n border-radius: 10px;\n background: var(--md-sys-color-surface-container-high);\n font-size: var(--ui-t-small, 11.5px);\n font-weight: 600;\n text-align: center;\n color: var(--ui-muted, var(--md-sys-color-on-surface-variant));\n }\n .counter {\n margin-left: auto;\n font-size: var(--ui-t-small, 11.5px);\n }\n .summary textarea {\n min-height: 132px;\n }\n\n /* Skills as chips, the field to add more inside the same box. */\n .chips {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--spacing-small, 4px);\n min-height: 88px;\n align-content: flex-start;\n box-sizing: border-box;\n padding: var(--spacing-medium, 8px);\n border: 1px solid var(--md-sys-color-outline);\n border-radius: var(--input-field-border-radius, var(--md-sys-shape-corner-small, 4px));\n background: var(--md-sys-color-surface-container-highest);\n }\n .chips:focus-within {\n border-color: var(--md-sys-color-primary);\n }\n .chip {\n display: inline-flex;\n align-items: center;\n gap: 2px;\n height: 26px;\n padding: 0 4px 0 10px;\n border-radius: 13px;\n background: var(--md-sys-color-secondary-container);\n color: var(--md-sys-color-on-secondary-container);\n font-size: var(--ui-t-body, 13px);\n }\n .chip button {\n height: 20px;\n width: 20px;\n padding: 0;\n border: 0;\n background: transparent;\n }\n .chip button md-icon {\n --md-icon-size: 14px;\n color: inherit;\n }\n .chips input {\n flex: 1 1 140px;\n width: auto;\n height: 26px;\n border: 0;\n padding: 0 4px;\n background: transparent;\n outline: none;\n }\n\n /* A row of a section is a card: its line as the document reads it, then its fields. */\n .entries {\n display: flex;\n flex-direction: column;\n gap: var(--spacing-medium, 8px);\n }\n .entry {\n display: flex;\n flex-direction: column;\n gap: var(--spacing-large, 12px);\n }\n .entry-head {\n display: flex;\n align-items: center;\n gap: var(--spacing-medium, 8px);\n min-width: 0;\n }\n .entry-head strong {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-size: var(--ui-t-body, 13px);\n color: var(--ui-ink, var(--md-sys-color-on-surface));\n }\n .entry-head strong.untitled {\n font-weight: 400;\n color: var(--ui-muted, var(--md-sys-color-on-surface-variant));\n }\n .entry-head .period {\n flex: none;\n font-size: var(--ui-t-small, 11.5px);\n }\n .entry-head button {\n margin-left: auto;\n }\n .fields {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));\n gap: var(--spacing-medium, 8px) var(--spacing-large, 12px);\n }\n .fields .wide {\n grid-column: 1 / -1;\n }\n .fields .start {\n grid-column-start: 1;\n }\n .end {\n display: grid;\n grid-template-columns: minmax(0, 1fr) auto;\n gap: var(--spacing-medium, 8px);\n align-items: end;\n min-width: 0;\n }\n .ongoing {\n flex-direction: row;\n align-items: center;\n gap: var(--spacing-small, 4px);\n height: var(--form-element-height-medium, 32px);\n font-size: var(--ui-t-body, 13px);\n white-space: nowrap;\n color: var(--ui-ink, var(--md-sys-color-on-surface));\n }\n .ongoing input {\n width: auto;\n }\n\n /* A section with nothing yet: what it is for, and the way to begin. */\n .empty-slot {\n display: flex;\n align-items: center;\n gap: var(--spacing-large, 12px);\n padding: var(--spacing-large, 12px) 16px;\n border: 1px dashed var(--md-sys-color-outline-variant);\n border-radius: var(--ui-r, 10px);\n font-size: var(--ui-t-body, 13px);\n }\n .empty-slot button {\n margin-left: auto;\n }\n\n @media (max-width: 720px) {\n .hero {\n grid-template-columns: 1fr;\n }\n .empty-slot {\n flex-direction: column;\n align-items: flex-start;\n }\n .empty-slot button {\n margin-left: 0;\n }\n }\n @media (pointer: coarse) {\n input,\n textarea {\n font-size: 16px;\n }\n }\n `\n ]\n\n @state() form: ProfileForm = profileFormOf(null)\n /** Who the profile is about - the employee record's basics. */\n @state() me: any = null\n /** Whether the account is linked to an employee record - unknown until read. */\n @state() linked: boolean | null = null\n @state() loading = false\n @state() error: unknown = null\n @state() busy = false\n @state() updatedAt: string | null = null\n /** The form as last read or saved - what is written differs from it until saved. */\n private saved = JSON.stringify(profileInputOf(profileFormOf(null)))\n\n private get dirty() {\n return JSON.stringify(profileInputOf(this.form)) !== this.saved\n }\n\n get context() {\n return {\n title: i18next.t('title.my-employee-profile'),\n frame: 'document',\n actions: this.linked ? [{ title: i18next.t('button.save'), icon: 'save', emphasis: { raised: true }, action: () => this.save() }] : []\n }\n }\n\n async pageUpdated(changes: any) {\n if ((this as any).active && changes.active) this.load()\n }\n\n private async load() {\n this.loading = true\n this.error = null\n try {\n const response = await client.query({\n query: gql`\n query {\n myEmployees { id name jobPosition jobResponsibility hiredOn department { name } }\n myEmployeeProfile { ${PROFILE_FIELDS} }\n }\n `,\n fetchPolicy: 'no-cache'\n })\n if (response.errors?.length) throw response.errors[0]\n this.me = response.data?.myEmployees?.[0] ?? null\n this.linked = !!this.me\n this.hold(response.data?.myEmployeeProfile)\n } catch (error) {\n this.error = error\n } finally {\n this.loading = false\n this.updateContext()\n }\n }\n\n private hold(profile: any) {\n this.form = profileFormOf(profile)\n this.saved = JSON.stringify(profileInputOf(this.form))\n this.updatedAt = profile?.updatedAt ?? null\n }\n\n private async save(): Promise<boolean> {\n if (this.busy) return false\n this.busy = true\n try {\n const response = await client.mutate({\n mutation: gql`\n mutation ($profile: EmployeeProfileInput!) {\n saveMyEmployeeProfile(profile: $profile) { ${PROFILE_FIELDS} }\n }\n `,\n variables: { profile: profileInputOf(this.form) }\n })\n if (response.errors?.length) throw response.errors[0]\n this.hold(response.data.saveMyEmployeeProfile)\n notify({ message: i18next.t('text.saved') })\n return true\n } catch (error: any) {\n notify({ level: 'error', message: error?.message ?? String(error) })\n return false\n } finally {\n this.busy = false\n }\n }\n\n /** The document as sales will hand it in - what is written is saved first, so the preview shows it. */\n private async preview() {\n if (this.dirty && !(await this.save())) return\n const languages = ((await getLanguages()) ?? []) as Language[]\n openProfilePreview({ own: true }, languages, readerLanguageOf(languages))\n }\n\n private goTo(key: string) {\n const section = this.renderRoot.querySelector<HTMLElement>(`#${key}`)\n section?.scrollIntoView({ behavior: 'smooth', block: 'start' })\n section?.querySelector<HTMLElement>('textarea, input:not([type=\"checkbox\"])')?.focus({ preventScroll: true })\n }\n\n render() {\n return html`<ox-page-state .loading=${this.loading && this.linked === null} .error=${this.linked === null ? this.error : null} @retry=${() => this.load()}>\n ${this.linked === false\n ? html`<ox-empty-note\n icon=\"badge\"\n title=${i18next.t('text.employee-profile-not-linked-title')}\n description=${i18next.t('text.employee-profile-not-linked-description')}\n ></ox-empty-note>`\n : this.linked\n ? html`<div class=\"page\">\n ${this.renderHero()}\n <div class=\"page-section-grid\">${this.renderSummary()} ${this.renderSkills()}</div>\n ${PROFILE_SECTIONS.map(section => this.renderSection(section))}\n </div>`\n : nothing}\n </ox-page-state>`\n }\n\n private renderHero() {\n const me = this.me ?? {}\n const { percent, missing } = completenessOf(this.form)\n const role = [me.jobPosition, me.jobResponsibility].filter(Boolean).join(' / ')\n const day = (value?: string | null) => (value ? String(value).slice(0, 10).replace(/-/g, '.') : '')\n\n return html`<section class=\"hero page-card\">\n <div class=\"who\">\n <div class=\"avatar\" aria-hidden=\"true\">${(me.name ?? '?').trim().slice(0, 1)}</div>\n <div>\n <h2>${me.name ?? ''}</h2>\n <p class=\"muted\">${[me.department?.name, role].filter(Boolean).join(' · ')}</p>\n ${me.hiredOn ? html`<p class=\"muted\">${i18next.t('label.hired-on')} ${day(me.hiredOn)}</p>` : nothing}\n </div>\n </div>\n\n <div class=\"progress\">\n <div class=\"progress-head\">\n <span class=\"muted\">${i18next.t('text.employee-profile-completeness')}</span>\n <strong>${percent}%</strong>\n </div>\n <div class=\"bar\" role=\"progressbar\" aria-valuemin=\"0\" aria-valuemax=\"100\" aria-valuenow=${percent}><span style=\"width:${percent}%\"></span></div>\n ${missing.length\n ? html`<div class=\"missing\">\n <span class=\"muted\">${i18next.t('text.employee-profile-to-fill')}</span>\n ${missing.map(key => html`<button small quiet @click=${() => this.goTo(key)}>${i18next.t(`label.employee-profile-${key}`)}</button>`)}\n </div>`\n : html`<div class=\"missing muted\">${i18next.t('text.employee-profile-ready')}</div>`}\n </div>\n\n <div class=\"hero-foot\">\n ${this.dirty\n ? html`<span class=\"unsaved\">${i18next.t('text.employee-profile-unsaved')}</span>`\n : this.updatedAt\n ? html`<span class=\"muted\">${i18next.t('label.employee-profile-updated-at')} ${day(this.updatedAt)}</span>`\n : nothing}\n <button ?disabled=${this.busy} @click=${() => this.preview()}><md-icon>preview</md-icon>${i18next.t('button.employee-profile-preview')}</button>\n </div>\n </section>`\n }\n\n private renderSummary() {\n const summary = this.form.summary\n return html`<section id=\"summary\" class=\"page-section summary\">\n <header class=\"page-section-header\">\n <h3><md-icon>person</md-icon>${i18next.t('label.employee-profile-summary')}</h3>\n <span class=\"counter muted\">${summary.length} / ${SUMMARY_LIMIT}</span>\n </header>\n <textarea\n aria-label=${i18next.t('label.employee-profile-summary')}\n maxlength=${SUMMARY_LIMIT}\n placeholder=${i18next.t('text.employee-profile-summary-example')}\n .value=${summary}\n @input=${(e: any) => (this.form = { ...this.form, summary: e.target.value })}\n ></textarea>\n </section>`\n }\n\n private renderSkills() {\n const skills = this.form.skills\n const add = (input: HTMLInputElement) => {\n this.form = { ...this.form, skills: addSkills(skills, input.value) }\n input.value = ''\n }\n\n return html`<section id=\"skills\" class=\"page-section\">\n <header class=\"page-section-header\">\n <h3><md-icon>construction</md-icon>${i18next.t('label.employee-profile-skills')}</h3>\n ${skills.length ? html`<span class=\"count\">${skills.length}</span>` : nothing}\n </header>\n <div class=\"chips\" @click=${(e: Event) => (e.currentTarget as HTMLElement).querySelector('input')?.focus()}>\n ${skills.map(\n skill => html`<span class=\"chip\"\n >${skill}\n <button\n unstyled\n title=${i18next.t('button.delete')}\n aria-label=${`${i18next.t('button.delete')} ${skill}`}\n @click=${() => (this.form = { ...this.form, skills: skills.filter(one => one !== skill) })}\n >\n <md-icon>close</md-icon>\n </button></span\n >`\n )}\n <input\n aria-label=${i18next.t('label.employee-profile-skills')}\n placeholder=${i18next.t('text.employee-profile-skill-placeholder')}\n @keydown=${(e: KeyboardEvent) => {\n const input = e.target as HTMLInputElement\n if ((e.key === 'Enter' || e.key === ',') && !e.isComposing) {\n e.preventDefault()\n add(input)\n } else if (e.key === 'Backspace' && !input.value && skills.length) {\n this.form = { ...this.form, skills: skills.slice(0, -1) }\n }\n }}\n @blur=${(e: Event) => add(e.target as HTMLInputElement)}\n />\n </div>\n </section>`\n }\n\n private renderSection(section: ProfileSection) {\n const rows = this.form[section.key]\n /* Each change reads the rows as they are now - two inputs before a render must not undo each other. */\n const current = () => this.form[section.key]\n const setRows = (next: ProfileRow[]) => (this.form = { ...this.form, [section.key]: next })\n const change = (index: number, patch: ProfileRow) => setRows(current().map((row, at) => (at === index ? { ...row, ...patch } : row)))\n const remove = (index: number) => setRows(current().filter((_, at) => at !== index))\n /* The newest first, as the document is read; its first field takes the cursor. */\n const add = async () => {\n setRows([blankRow(section), ...current()])\n await this.updateComplete\n this.renderRoot.querySelector<HTMLInputElement>(`#${section.key} .entry input`)?.focus()\n }\n\n return html`<section id=${section.key} class=\"page-section\">\n <header class=\"page-section-header\">\n <h3><md-icon>${section.icon}</md-icon>${i18next.t(section.title)}</h3>\n ${rows.length ? html`<span class=\"count\">${rows.length}</span>` : nothing}\n ${rows.length\n ? html`<div class=\"page-section-actions\">\n <button @click=${add}><md-icon>add</md-icon>${i18next.t('button.add')}</button>\n </div>`\n : nothing}\n </header>\n ${rows.length\n ? html`<div class=\"entries\">${rows.map((row, index) => this.renderEntry(section, row, index, change, () => remove(index)))}</div>`\n : html`<div class=\"empty-slot\">\n <span class=\"muted\">${i18next.t(`text.employee-profile-why-${section.key}`)}</span>\n <button @click=${add}><md-icon>add</md-icon>${i18next.t('button.add')}</button>\n </div>`}\n </section>`\n }\n\n private renderEntry(section: ProfileSection, row: ProfileRow, index: number, change: (index: number, patch: ProfileRow) => void, remove: () => void) {\n const headline = headlineOf(section, row)\n const period = periodLabelOf(row, i18next.t('text.employee-profile-doc-ongoing'))\n const field = (one: ProfileField) => {\n const label = i18next.t(one.label)\n if (one.input === 'textarea') {\n return html`<label class=\"wide\"\n >${label}<textarea .value=${row[one.name] ?? ''} @input=${(e: any) => change(index, { [one.name]: e.target.value })}></textarea\n ></label>`\n }\n const ended = one.name === 'endedOn' && section.ongoing\n const input = html`<input\n type=${one.input ?? 'text'}\n .value=${ended && row.ongoing ? '' : (row[one.name] ?? '')}\n ?disabled=${ended && !!row.ongoing}\n @input=${(e: any) => change(index, { [one.name]: e.target.value })}\n />`\n /* A period begins a line of its own, its end beside it. */\n if (!ended) return html`<label class=${one.name === 'startedOn' ? 'start' : ''}>${label}${input}</label>`\n /* The end and 「going on」 share one cell - the period stays on one line. */\n return html`<div class=\"end\">\n <label>${label}${input}</label>\n <label class=\"ongoing\"\n ><input\n type=\"checkbox\"\n .checked=${!!row.ongoing}\n @change=${(e: any) => change(index, { ongoing: e.target.checked ? 'true' : '', ...(e.target.checked ? { endedOn: '' } : {}) })}\n />${i18next.t('label.employee-profile-ongoing')}</label\n >\n </div>`\n }\n\n return html`<div class=\"entry page-card\">\n <div class=\"entry-head\">\n <strong class=${headline ? '' : 'untitled'}>${headline || i18next.t('text.employee-profile-new-entry')}</strong>\n ${period ? html`<span class=\"period muted\">${period}</span>` : nothing}\n <button quiet icon-only title=${i18next.t('button.delete')} aria-label=${i18next.t('button.delete')} @click=${remove}><md-icon>delete</md-icon></button>\n </div>\n <div class=\"fields\">${section.fields.map(field)}</div>\n </div>`\n }\n}\n"]}
@@ -1 +1 @@
1
- export default function route(page: string): "approval-line-list" | "common-approval-line-templates-page" | "my-approval-line-templates-page" | "employee-list" | "department-list" | undefined;
1
+ export default function route(page: string): "approval-line-list" | "common-approval-line-templates-page" | "my-approval-line-templates-page" | "employee-list" | "department-list" | "my-employee-profile" | "employee-profile-list" | undefined;
@@ -6,6 +6,13 @@ export default function route(page) {
6
6
  case 'department-list':
7
7
  import('./pages/department/department-list-page');
8
8
  return page;
9
+ /* The employee writes their own profile; sales downloads the chosen ones for a quotation (ADR-0169). */
10
+ case 'my-employee-profile':
11
+ import('./pages/employee-profile/my-employee-profile-page');
12
+ return page;
13
+ case 'employee-profile-list':
14
+ import('./pages/employee-profile/employee-profile-list-page');
15
+ return page;
9
16
  /* 공용과 내 것을 한 목록에 — 아래 둘을 대신한다. */
10
17
  case 'approval-line-list':
11
18
  import('./pages/approval-line/approval-line-list-page');
@@ -1 +1 @@
1
- {"version":3,"file":"route.js","sourceRoot":"","sources":["../client/route.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,OAAO,UAAU,KAAK,CAAC,IAAY;IACxC,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,eAAe;YAClB,MAAM,CAAC,qCAAqC,CAAC,CAAA;YAC7C,OAAO,IAAI,CAAA;QAEb,KAAK,iBAAiB;YACpB,MAAM,CAAC,yCAAyC,CAAC,CAAA;YACjD,OAAO,IAAI,CAAA;QAEb,kCAAkC;QAClC,KAAK,oBAAoB;YACvB,MAAM,CAAC,+CAA+C,CAAC,CAAA;YACvD,OAAO,IAAI,CAAA;QAEb;;;;WAIG;QACH,KAAK,qCAAqC;YACxC,MAAM,CAAC,2DAA2D,CAAC,CAAA;YACnE,OAAO,IAAI,CAAA;QAEb,KAAK,iCAAiC;YACpC,MAAM,CAAC,uDAAuD,CAAC,CAAA;YAC/D,OAAO,IAAI,CAAA;IACf,CAAC;AACH,CAAC","sourcesContent":["export default function route(page: string) {\n switch (page) {\n case 'employee-list':\n import('./pages/employee/employee-list-page')\n return page\n\n case 'department-list':\n import('./pages/department/department-list-page')\n return page\n\n /* 공용과 내 것을 한 목록에 — 아래 둘을 대신한다. */\n case 'approval-line-list':\n import('./pages/approval-line/approval-line-list-page')\n return page\n\n /*\n * 아래 두 화면은 아직 살아 있다. operato-dataset · operato-gangsters · operato-twin 의 메뉴가 이 두\n * 주소를 가리킨다. 지금 지우면 그 세 앱의 메뉴가 아무 데도 안 닿는다. operato-plant 만 새 화면으로\n * 돌렸고, 나머지가 옮겨 온 뒤에 지운다.\n */\n case 'common-approval-line-templates-page':\n import('./pages/approval-line/common-approval-line-templates-page')\n return page\n\n case 'my-approval-line-templates-page':\n import('./pages/approval-line/my-approval-line-templates-page')\n return page\n }\n}\n"]}
1
+ {"version":3,"file":"route.js","sourceRoot":"","sources":["../client/route.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,OAAO,UAAU,KAAK,CAAC,IAAY;IACxC,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,eAAe;YAClB,MAAM,CAAC,qCAAqC,CAAC,CAAA;YAC7C,OAAO,IAAI,CAAA;QAEb,KAAK,iBAAiB;YACpB,MAAM,CAAC,yCAAyC,CAAC,CAAA;YACjD,OAAO,IAAI,CAAA;QAEb,wGAAwG;QACxG,KAAK,qBAAqB;YACxB,MAAM,CAAC,mDAAmD,CAAC,CAAA;YAC3D,OAAO,IAAI,CAAA;QAEb,KAAK,uBAAuB;YAC1B,MAAM,CAAC,qDAAqD,CAAC,CAAA;YAC7D,OAAO,IAAI,CAAA;QAEb,kCAAkC;QAClC,KAAK,oBAAoB;YACvB,MAAM,CAAC,+CAA+C,CAAC,CAAA;YACvD,OAAO,IAAI,CAAA;QAEb;;;;WAIG;QACH,KAAK,qCAAqC;YACxC,MAAM,CAAC,2DAA2D,CAAC,CAAA;YACnE,OAAO,IAAI,CAAA;QAEb,KAAK,iCAAiC;YACpC,MAAM,CAAC,uDAAuD,CAAC,CAAA;YAC/D,OAAO,IAAI,CAAA;IACf,CAAC;AACH,CAAC","sourcesContent":["export default function route(page: string) {\n switch (page) {\n case 'employee-list':\n import('./pages/employee/employee-list-page')\n return page\n\n case 'department-list':\n import('./pages/department/department-list-page')\n return page\n\n /* The employee writes their own profile; sales downloads the chosen ones for a quotation (ADR-0169). */\n case 'my-employee-profile':\n import('./pages/employee-profile/my-employee-profile-page')\n return page\n\n case 'employee-profile-list':\n import('./pages/employee-profile/employee-profile-list-page')\n return page\n\n /* 공용과 내 것을 한 목록에 — 아래 둘을 대신한다. */\n case 'approval-line-list':\n import('./pages/approval-line/approval-line-list-page')\n return page\n\n /*\n * 아래 두 화면은 아직 살아 있다. operato-dataset · operato-gangsters · operato-twin 의 메뉴가 이 두\n * 주소를 가리킨다. 지금 지우면 그 세 앱의 메뉴가 아무 데도 안 닿는다. operato-plant 만 새 화면으로\n * 돌렸고, 나머지가 옮겨 온 뒤에 지운다.\n */\n case 'common-approval-line-templates-page':\n import('./pages/approval-line/common-approval-line-templates-page')\n return page\n\n case 'my-approval-line-templates-page':\n import('./pages/approval-line/my-approval-line-templates-page')\n return page\n }\n}\n"]}