Changes
6 changed files (+134/-107)
-
-
@@ -11,9 +11,9 @@ import * as IllegalMessageError from "./errors/IllegalMessageError.tsx";import * as GenericError from "./errors/GenericError.tsx"; import * as UnhandledMessageError from "./errors/UnhandledMessageError.tsx"; import * as NonErrorThrownError from "./errors/NonErrorThrownError.tsx"; import * as NotFoundError from "./errors/NotFoundError.tsx"; import * as NoStorageSpaceError from "./errors/NoStorageSpaceError.tsx"; import * as MissingFieldError from "./errors/MissingFieldError.tsx"; import * as WorkspaceAccessError from "./errors/WorkspaceAccessError.tsx"; export interface ManagedProps extends ErrorCalloutProps { error: unknown;
-
@@ -36,8 +36,8 @@ if (MissingFieldError.is(error)) {return <MissingFieldError.Callout error={error} {...rest} />; } if (WorkspaceAccessError.is(error)) { return <WorkspaceAccessError.Callout error={error} {...rest} />; if (NotFoundError.is(error)) { return <NotFoundError.Callout error={error} {...rest} />; } if (UnhandledMessageError.is(error)) {
-
-
-
@@ -0,0 +1,44 @@// SPDX-FileCopyrightText: 2024 Shota FUJI <pockawoooh@gmail.com> // SPDX-License-Identifier: AGPL-3.0-only import { create } from "@bufbuild/protobuf"; import { NotFoundSchema } from "@yamori/proto/yamori/error/v1/not_found_pb.js"; import type { Meta, StoryObj } from "@storybook/react"; import { Callout } from "./NotFoundError.tsx"; export default { component: Callout, args: { title: "エラー", error: create(NotFoundSchema, { typeName: "Foo", }), }, } satisfies Meta<typeof Callout>; type Story = StoryObj<typeof Callout>; export const Defaults: Story = {}; export const Workspace: Story = { args: { error: create(NotFoundSchema, { typeName: "yamori.workspace.v1.Workspace", }), }, }; export const Worker: Story = { args: { error: create(NotFoundSchema, { typeName: "yamori.worker.v1.Worker", }), }, }; export const EmptyTypeName: Story = { args: { error: create(NotFoundSchema, {}), }, };
-
-
-
@@ -0,0 +1,84 @@// SPDX-FileCopyrightText: 2024 Shota FUJI <pockawoooh@gmail.com> // SPDX-License-Identifier: AGPL-3.0-only import { isMessage } from "@bufbuild/protobuf"; import { Button, Code, DataList, Dialog, Flex, Text } from "@radix-ui/themes"; import { NotFoundSchema, type NotFound, } from "@yamori/proto/yamori/error/v1/not_found_pb.js"; import { type FC } from "react"; import { ErrorCallout, type ErrorCalloutProps } from "../ErrorCallout.tsx"; export function is(x: unknown): x is NotFound { return isMessage(x, NotFoundSchema); } function message(typeName: string): string { switch (typeName) { case "yamori.workspace.v1.Workspace": return "対象のワークスペースが見つかりません。"; case "yamori.worker.v1.Worker": return "対象の労働者が見つかりません。"; default: return "対象のデータが見つかりません。"; } } export interface CalloutProps extends ErrorCalloutProps { error: NotFound; } export const Callout: FC<CalloutProps> = ({ error, actions, children, ...rest }) => { return ( <Dialog.Root> <ErrorCallout {...rest} actions={ <> {actions} <Dialog.Trigger> <Button size="1" variant="outline"> 詳細 </Button> </Dialog.Trigger> </> } > {children || message(error.typeName)} </ErrorCallout> <Dialog.Content> <Dialog.Title>該当データなしエラー</Dialog.Title> <Dialog.Description size="2"> 処理を行う直接・間接の対象となるデータが存在せず処理が中断された際のエラーです。 </Dialog.Description> <Text as="p" size="2" mt="2"> 対象のデータが削除されていないか確認してください。 データが存在するにも関わらずこのエラーが発生する場合はアプリケーション不具合の可能性があります。 </Text> <DataList.Root mt="5" orientation={{ initial: "vertical", sm: "horizontal" }}> <DataList.Item> <DataList.Label>データ種別</DataList.Label> <DataList.Value> {error.typeName ? <Code>{error.typeName}</Code> : "---"} </DataList.Value> </DataList.Item> </DataList.Root> <Text as="p" color="gray" size="1" mt="5"> 上記は問い合わせの際に必要な情報となります。 </Text> <Flex justify="end" mt="5"> <Dialog.Close> <Button>閉じる</Button> </Dialog.Close> </Flex> </Dialog.Content> </Dialog.Root> ); };
-
-
-
@@ -1,28 +0,0 @@// SPDX-FileCopyrightText: 2024 Shota FUJI <pockawoooh@gmail.com> // SPDX-License-Identifier: AGPL-3.0-only import { create } from "@bufbuild/protobuf"; import { AccessErrorSchema } from "@yamori/proto/yamori/workspace/v1/access_error_pb.js"; import type { Meta, StoryObj } from "@storybook/react"; import { Callout } from "./WorkspaceAccessError.tsx"; export default { component: Callout, args: { title: "エラー", error: create(AccessErrorSchema, { workspaceId: { value: "ws-foo" }, }), }, } satisfies Meta<typeof Callout>; type Story = StoryObj<typeof Callout>; export const Defaults: Story = {}; export const NoWorkspaceId: Story = { args: { error: create(AccessErrorSchema, {}), }, };
-
-
-
@@ -1,73 +0,0 @@// SPDX-FileCopyrightText: 2024 Shota FUJI <pockawoooh@gmail.com> // SPDX-License-Identifier: AGPL-3.0-only import { isMessage } from "@bufbuild/protobuf"; import { Button, Code, DataList, Dialog, Flex, Text } from "@radix-ui/themes"; import { AccessErrorSchema, type AccessError, } from "@yamori/proto/yamori/workspace/v1/access_error_pb.js"; import { type FC } from "react"; import { ErrorCallout, type ErrorCalloutProps } from "../ErrorCallout.tsx"; export function is(x: unknown): x is AccessError { return isMessage(x, AccessErrorSchema); } export interface CalloutProps extends ErrorCalloutProps { error: AccessError; } export const Callout: FC<CalloutProps> = ({ error, actions, children, ...rest }) => { return ( <Dialog.Root> <ErrorCallout {...rest} actions={ <> {actions} <Dialog.Trigger> <Button size="1" variant="outline"> 詳細 </Button> </Dialog.Trigger> </> } > {children || "ワークスペースにアクセスできません"} </ErrorCallout> <Dialog.Content> <Dialog.Title>ワークスペースアクセスエラー</Dialog.Title> <Dialog.Description size="2"> ワークスペースに紐づく処理をしようとしたものの、対象のワークスペースにアクセスできなかった際のエラーです。 </Dialog.Description> <Text as="p" size="2" mt="2"> ワークスペースが既に削除されている可能性があります。 ワークスペースが存在するにも関わらずこのエラーが発生する場合は、ワークスペースのデータが破損しているかアプリケーションの不具合となります。 </Text> <DataList.Root mt="5" orientation={{ initial: "vertical", sm: "horizontal" }}> <DataList.Item> <DataList.Label>ワークスペースID</DataList.Label> <DataList.Value> {error.workspaceId?.value ? <Code>{error.workspaceId.value}</Code> : "---"} </DataList.Value> </DataList.Item> </DataList.Root> <Text as="p" color="gray" size="1" mt="5"> 上記は問い合わせの際に必要な情報となります。 </Text> <Flex justify="end" mt="5"> <Dialog.Close> <Button>閉じる</Button> </Dialog.Close> </Flex> </Dialog.Content> </Dialog.Root> ); };
-
-
-
@@ -69,15 +69,15 @@ ]),], }; export const WorkspaceAccessError: Story = { export const NotFoundError: Story = { decorators: [ withMockedBackend([ Create({ failureRate: 1, error: { case: "workspaceAccessError", case: "notFound", value: { workspaceId: { value: "ws-foo" }, typeName: "yamori.workspace.v1.Workspace", }, }, }),
-