From 2cea9c21f0251dff3abb30c86323ce3898decc4b Mon Sep 17 00:00:00 2001 From: EATSTEAK Date: Mon, 12 Sep 2022 00:06:48 +0900 Subject: [PATCH 01/10] feat(config): add `alert` field to `ServiceConfig` and `ServiceConfigSchema` --- packages/client/src/lib/api/config.ts | 3 ++- packages/types/index.d.ts | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/client/src/lib/api/config.ts b/packages/client/src/lib/api/config.ts index 9a9f87a7..8722b5a3 100644 --- a/packages/client/src/lib/api/config.ts +++ b/packages/client/src/lib/api/config.ts @@ -39,7 +39,8 @@ const DepartmentConfigSchema = ConfigSchema.extend({ }); const ServiceConfigSchema = ConfigSchema.extend({ - buildings: BuildingSchema.default({}) + buildings: BuildingSchema.default({}), + alert: z.string().optional() }); const ConfigUpdateRequestSchema = z.object({ diff --git a/packages/types/index.d.ts b/packages/types/index.d.ts index e9a851e9..56ba336a 100644 --- a/packages/types/index.d.ts +++ b/packages/types/index.d.ts @@ -115,6 +115,7 @@ type ServiceConfig = Config & { buildings: { [buildingId: string]: Building; }; + alert?: string; }; type ServiceConfigResponse = ConfigResponse & { From 966f9b2df323bd1dc1c9fb258a3ce9bfd0b89eb8 Mon Sep 17 00:00:00 2001 From: EATSTEAK Date: Mon, 12 Sep 2022 00:07:42 +0900 Subject: [PATCH 02/10] refactor(client/config): check schema in `getServiceConfig`, `getDepartmentConfig`, `getDepartmentConfigs` --- packages/client/src/lib/api/config.ts | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/packages/client/src/lib/api/config.ts b/packages/client/src/lib/api/config.ts index 8722b5a3..d612a3af 100644 --- a/packages/client/src/lib/api/config.ts +++ b/packages/client/src/lib/api/config.ts @@ -71,21 +71,28 @@ export async function apiGetConfig(): Promise< } export function getServiceConfig(configs: Config[]): ServiceConfig { - return ( - (configs.find((c: Config) => c.id === 'SERVICE') as ServiceConfig) ?? { - id: 'SERVICE', - name: null, - buildings: {} - } - ); + const foundConfig = configs.find((c: Config) => c.id === 'SERVICE') as ServiceConfig; + const parsed = ServiceConfigSchema.safeParse(foundConfig); + if (parsed.success) return parsed.data as ServiceConfig; + return { + id: 'SERVICE', + name: null, + buildings: {} + }; } export function getDepartmentConfig(configs: Config[], departmentId: string): DepartmentConfig { - return configs.find((c: Config) => c.id === departmentId) as DepartmentConfig; + const foundConfig = configs.find((c: Config) => c.id === departmentId); + const parsed = DepartmentConfigSchema.safeParse(foundConfig); + if (parsed.success) return parsed.data as DepartmentConfig; + return null; } export function getDepartmentConfigs(configs: Config[]): DepartmentConfig[] { - return configs.filter((c: Config) => c.id !== 'SERVICE') as DepartmentConfig[]; + const foundConfigs = configs.filter((c: Config) => c.id !== 'SERVICE') as DepartmentConfig[]; + const parsed = z.array(DepartmentConfigSchema).safeParse(foundConfigs); + if (parsed.success) return parsed.data as DepartmentConfig[]; + return null; } export async function apiUpdateConfig( From 05337c9c028d0e2d12bc3a87b345f0a3d6f8b5c7 Mon Sep 17 00:00:00 2001 From: EATSTEAK Date: Mon, 12 Sep 2022 00:09:11 +0900 Subject: [PATCH 03/10] feat(config): add `alert`(shorthand `a`) in `ServiceConfigResponse`, `ServiceConfigDao` --- packages/types/index.d.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/types/index.d.ts b/packages/types/index.d.ts index 56ba336a..a95eac5d 100644 --- a/packages/types/index.d.ts +++ b/packages/types/index.d.ts @@ -122,11 +122,13 @@ type ServiceConfigResponse = ConfigResponse & { buildings: { [buildingId: string]: Building; }; + alert?: string; }; type ServiceConfigDao = DaoData & ConfigDao & { b: { M: { [buildingId: string]: { M: BuildingData } } }; + a?: { S: string }; }; type Building = { From cf94836ba1087bef5a2e212480436d7a0931967f Mon Sep 17 00:00:00 2001 From: EATSTEAK Date: Mon, 12 Sep 2022 00:12:06 +0900 Subject: [PATCH 04/10] feat(config/data): add `alert` in dao conversion functions --- packages/server/src/config/data.ts | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/packages/server/src/config/data.ts b/packages/server/src/config/data.ts index d7c27f23..3f351323 100644 --- a/packages/server/src/config/data.ts +++ b/packages/server/src/config/data.ts @@ -116,7 +116,8 @@ function toServiceConfigDao(data: ServiceConfig): ServiceConfigDao { M: Object.fromEntries( Object.entries(data.buildings).map(([s, b]) => [s, { M: toBuildingData(b) }]) ) - } + }, + ...(data.alert && { a: { S: data.alert } }) }; } @@ -125,7 +126,8 @@ function fromServiceConfigDao(dao: ServiceConfigDao): ServiceConfig { ...fromConfigDao(dao), buildings: Object.fromEntries( Object.entries(dao.b?.M ?? {}).map(([s, bd]) => [s, fromBuildingData(bd.M)]) - ) + ), + ...(dao.a?.S && { alert: dao.a.S }) }; } @@ -236,6 +238,11 @@ export const updateConfig = async function (config: ConfigUpdateRequest) { attributeNames['#aT'] = 'aT'; updateExp += `${updateExp ? ',' : 'SET'} #aT = :activateTo`; } + if (config.alert) { + attributes[':alert'] = { S: config.alert }; + attributeNames['#a'] = 'a'; + updateExp += `${updateExp ? ',' : 'SET'} #a = :alert`; + } if (config.activateFrom === null) { removeExp += `${removeExp ? ',' : 'REMOVE'} aF`; } @@ -243,6 +250,10 @@ export const updateConfig = async function (config: ConfigUpdateRequest) { attributeNames['#aT'] = 'aT'; removeExp += `${removeExp ? ',' : 'REMOVE'} #aT`; } + if (config.alert === null) { + attributeNames['#a'] = 'a'; + removeExp += `${removeExp ? ',' : 'REMOVE'} #a';`; + } if ((config as ServiceConfigUpdateRequest).buildings) { const buildings = (config as ServiceConfigUpdateRequest).buildings; attributes[':buildings'] = { From ac48816ef530e978919b1a54518ad690492e6478 Mon Sep 17 00:00:00 2001 From: EATSTEAK Date: Mon, 12 Sep 2022 00:14:32 +0900 Subject: [PATCH 05/10] feat(type): add `alert` in `ConfigUpdateRequest` --- packages/types/index.d.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/types/index.d.ts b/packages/types/index.d.ts index a95eac5d..c116cca5 100644 --- a/packages/types/index.d.ts +++ b/packages/types/index.d.ts @@ -182,6 +182,7 @@ type ConfigUpdateRequest = { name?: string; activateFrom?: string | null; activateTo?: string | null; + alert?: string | null; }; type DepartmentConfigUpdateRequest = ConfigUpdateRequest & { From f10b6fd1e55946d1cc719496fea9f88d25f34683 Mon Sep 17 00:00:00 2001 From: EATSTEAK Date: Mon, 12 Sep 2022 00:41:55 +0900 Subject: [PATCH 06/10] fix(client/config): ServiceConfigSchema --- packages/client/src/lib/api/config.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/client/src/lib/api/config.ts b/packages/client/src/lib/api/config.ts index d612a3af..8be3aa09 100644 --- a/packages/client/src/lib/api/config.ts +++ b/packages/client/src/lib/api/config.ts @@ -39,7 +39,7 @@ const DepartmentConfigSchema = ConfigSchema.extend({ }); const ServiceConfigSchema = ConfigSchema.extend({ - buildings: BuildingSchema.default({}), + buildings: z.record(BuildingSchema).default({}).optional(), alert: z.string().optional() }); @@ -49,7 +49,7 @@ const ConfigUpdateRequestSchema = z.object({ activateFrom: z.string().optional(), activateTo: z.string().optional(), contact: z.string().optional(), - buildings: BuildingSchema.optional() + buildings: z.record(BuildingSchema).optional() }); export async function apiGetConfig(): Promise< @@ -74,6 +74,7 @@ export function getServiceConfig(configs: Config[]): ServiceConfig { const foundConfig = configs.find((c: Config) => c.id === 'SERVICE') as ServiceConfig; const parsed = ServiceConfigSchema.safeParse(foundConfig); if (parsed.success) return parsed.data as ServiceConfig; + console.error(parsed, foundConfig); return { id: 'SERVICE', name: null, From 9e2e172247c856d91aaf83a0009b9fd54ce7b275 Mon Sep 17 00:00:00 2001 From: EATSTEAK Date: Mon, 12 Sep 2022 00:42:08 +0900 Subject: [PATCH 07/10] feat(icons): add `Info` icon --- packages/client/src/icons/Info.svelte | 41 +++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 packages/client/src/icons/Info.svelte diff --git a/packages/client/src/icons/Info.svelte b/packages/client/src/icons/Info.svelte new file mode 100644 index 00000000..462c3532 --- /dev/null +++ b/packages/client/src/icons/Info.svelte @@ -0,0 +1,41 @@ + + + + \ No newline at end of file From 4a67026eb488503cffe872c1b4f225fd14a2a4bf Mon Sep 17 00:00:00 2001 From: EATSTEAK Date: Mon, 12 Sep 2022 00:43:23 +0900 Subject: [PATCH 08/10] feat(admin): add `alert` field to ServiceSettings --- .../molecule/admin/service/ServiceSettings.svelte | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/packages/client/src/components/molecule/admin/service/ServiceSettings.svelte b/packages/client/src/components/molecule/admin/service/ServiceSettings.svelte index 591ab843..71434ff1 100644 --- a/packages/client/src/components/molecule/admin/service/ServiceSettings.svelte +++ b/packages/client/src/components/molecule/admin/service/ServiceSettings.svelte @@ -21,6 +21,7 @@ let name; let activateFrom; let activateTo; + let alert; let buildings; $: if (serviceConfig) { @@ -31,8 +32,9 @@ $: newConfig = { id: 'SERVICE', name, - ...(activateFrom && { activateFrom: activateFrom.toISOString() }), - ...(activateTo && { activateTo: activateTo.toISOString() }), + ...(activateFrom ? { activateFrom: activateFrom.toISOString() } : (serviceConfig?.activateFrom && { activateFrom: null })), + ...(activateTo ? { activateTo: activateTo.toISOString() } : (serviceConfig?.activateTo && { activateTo: null })), + ...(alert ? { alert } : (serviceConfig.alert && { alert: null })), buildings }; $: isModified = !!serviceConfig && !isEqual(serviceConfig, newConfig); @@ -48,6 +50,7 @@ activateFrom = serviceConfig?.activateFrom ?? null; activateTo = serviceConfig?.activateTo ?? null; buildings = structuredClone(serviceConfig?.buildings ?? {}); + alert = serviceConfig?.alert ?? null; } function updateConfig() { @@ -107,6 +110,8 @@ bind:value={activateFrom} invalidClass='text-red-800' /> + {:else}
@@ -120,6 +125,10 @@
+
+ + +
{/if} From 0f5033c573bf066c65863767c14af1080ba594c3 Mon Sep 17 00:00:00 2001 From: EATSTEAK Date: Mon, 12 Sep 2022 00:43:40 +0900 Subject: [PATCH 09/10] feat(shell): add `alert` area --- packages/client/src/components/molecule/Shell.svelte | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/packages/client/src/components/molecule/Shell.svelte b/packages/client/src/components/molecule/Shell.svelte index aab0b85d..c6b48d57 100644 --- a/packages/client/src/components/molecule/Shell.svelte +++ b/packages/client/src/components/molecule/Shell.svelte @@ -13,12 +13,15 @@ import { config, user } from '$lib/store'; import { getDepartmentConfig, getServiceConfig } from '$lib/api/config'; import { isActivated } from '$lib/utils'; + import Info from '../../icons/Info.svelte'; let clazz = ''; export { clazz as class }; let currentTime = new Date(); + $: serviceConfig = $config && $config.success ? getServiceConfig($config.result) : undefined; + onMount(() => { if (!disableBlock) { const interval = setInterval(() => { @@ -39,7 +42,6 @@ function isReservable(config: Config[], user: User, time: Date): boolean { if (!user || user.isAdmin) return true; - const serviceConfig: ServiceConfig = getServiceConfig(config) as ServiceConfig; const userDeptConfig: DepartmentConfig = getDepartmentConfig(config, user.department) as DepartmentConfig; if (serviceConfig) { return isActivated(serviceConfig.activateFrom as Date, serviceConfig.activateTo as Date); @@ -80,6 +82,14 @@
+ {#if serviceConfig && serviceConfig.alert} +
+ +
+ 안내: {serviceConfig.alert} +
+
+ {/if}
From ae811f690dd4b79e8c46dc6af1435925169d3bd3 Mon Sep 17 00:00:00 2001 From: EATSTEAK Date: Mon, 12 Sep 2022 01:10:17 +0900 Subject: [PATCH 10/10] design: uniform margin and padding to constant look --- .../src/components/molecule/Shell.svelte | 2 +- .../admin/service/ServiceSettings.svelte | 4 +-- .../molecule/reserve/LockerReserveInfo.svelte | 28 +++++++++---------- .../reserve/LockerSectionSelector.svelte | 4 +-- 4 files changed, 18 insertions(+), 20 deletions(-) diff --git a/packages/client/src/components/molecule/Shell.svelte b/packages/client/src/components/molecule/Shell.svelte index c6b48d57..0179940d 100644 --- a/packages/client/src/components/molecule/Shell.svelte +++ b/packages/client/src/components/molecule/Shell.svelte @@ -83,7 +83,7 @@
{#if serviceConfig && serviceConfig.alert} -
+
안내: {serviceConfig.alert} diff --git a/packages/client/src/components/molecule/admin/service/ServiceSettings.svelte b/packages/client/src/components/molecule/admin/service/ServiceSettings.svelte index 71434ff1..7c47d589 100644 --- a/packages/client/src/components/molecule/admin/service/ServiceSettings.svelte +++ b/packages/client/src/components/molecule/admin/service/ServiceSettings.svelte @@ -72,8 +72,8 @@ -
-
+
+

서비스 설정