Support missing roles and deleted user
This commit is contained in:
@@ -9,9 +9,9 @@ export interface User {
|
||||
}
|
||||
|
||||
export interface SystemInformation {
|
||||
readonly createdBy: Option.Option<User>;
|
||||
readonly createdBy: Option.Option<User | null>;
|
||||
readonly createdAt: string;
|
||||
readonly modifiedBy: Option.Option<User>;
|
||||
readonly modifiedBy: Option.Option<User | null>;
|
||||
readonly modifiedAt: Option.Option<string>;
|
||||
}
|
||||
|
||||
@@ -113,7 +113,8 @@ const RepertoireSemaphore = Effect.unsafeMakeSemaphore(1);
|
||||
export const userLookup = (userId: UserId) => pipe(
|
||||
Effect.promise((signal) => client.user({ userId }).get({ fetch: { signal } })),
|
||||
Effect.flatMap(mapResponse),
|
||||
Effect.map((x): User => x), // safely coerce to interface
|
||||
Effect.catchAll((error) => error.status === 404 ? Effect.succeed(null) : Effect.fail(error)),
|
||||
Effect.map((x): User | null => x), // safely coerce to interface
|
||||
UserSemaphore.withPermits(1),
|
||||
);
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { client } from "@/client";
|
||||
import { useLoading } from "@/hooks/useLoading.ts";
|
||||
import { AttachmentId, PieceId } from "common";
|
||||
import { Match } from "effect";
|
||||
import JSZip from "jszip";
|
||||
import { OpenSheetMusicDisplay } from "opensheetmusicdisplay";
|
||||
import { useCallback, useEffect, useRef } from "react";
|
||||
@@ -102,7 +103,13 @@ export default function Attachment() {
|
||||
if (error !== null) {
|
||||
return (
|
||||
<div className="w-full h-full overflow-hidden flex items-center justify-center">
|
||||
<div>Wystąpił błąd: {error.status === 422 ? error.value.message : error.value}</div>
|
||||
<div>
|
||||
Wystąpił błąd: {Match.value(error).pipe(
|
||||
Match.when({ status: 422 }, ({ value }) => value.message),
|
||||
Match.when({ status: 404 }, () => "Załącznik nie istnieje"),
|
||||
Match.exhaustive,
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ export function Piece() {
|
||||
return (
|
||||
<div className="p-4 overflow-y-auto flex flex-wrap items-start gap-4">
|
||||
{error !== null ? (
|
||||
Cause.isUnknownException(error) ? "Wystąpił nieznany błąd" : `Wystąpił błąd: ${error.value}`
|
||||
Cause.isUnknownException(error) ? "Wystąpił nieznany błąd" : `Wystąpił błąd: ${JSON.stringify(error.value)}`
|
||||
) : (<>
|
||||
<div className="flex flex-col gap-4 p-4 border rounded">
|
||||
<h3 className="font-bold text-lg">Utwór</h3>
|
||||
|
||||
@@ -8,7 +8,7 @@ import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@
|
||||
import { useLoadingEffect } from "@/hooks/useLoading";
|
||||
import { authors, created, DEBOUNCE, modified } from "@/snippets";
|
||||
import { PieceId } from "common";
|
||||
import { Cause, Effect } from "effect";
|
||||
import { Cause, Effect, Match } from "effect";
|
||||
import { Loader2, Plus } from "lucide-react";
|
||||
import { FormEventHandler, useId, useRef, useState } from "react";
|
||||
import { Link, useNavigate } from "react-router-dom";
|
||||
@@ -91,7 +91,7 @@ export function Pieces() {
|
||||
) : error !== null ? (
|
||||
<TableRow>
|
||||
<TableCell colSpan={4} className="text-center">
|
||||
{Cause.isUnknownException(error) ? "Wystąpił nieznany błąd" : `Wystąpił błąd: ${error.value}`}
|
||||
{Cause.isUnknownException(error) ? "Wystąpił nieznany błąd" : `Wystąpił błąd: ${JSON.stringify(error.value)}`}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
) : (
|
||||
@@ -124,7 +124,14 @@ function PieceRow(props: PieceRow.Props) {
|
||||
if (error !== null) {
|
||||
return (
|
||||
<TableRow>
|
||||
<TableCell colSpan={4}>Wystąpił błąd: {error.status === 422 ? error.value.message : error.value}</TableCell>
|
||||
<TableCell colSpan={4}>
|
||||
Wystąpił błąd: {Match.value(error).pipe(
|
||||
Match.when({ status: 401 }, () => "Zaloguj się ponownie"),
|
||||
Match.when({ status: 422 }, ({ value }) => value.message),
|
||||
Match.when({ status: 404 }, () => "Utwór nie istnieje"),
|
||||
Match.exhaustive,
|
||||
)}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import { useLoadingEffect } from "@/hooks/useLoading";
|
||||
import { mapProp, Update, Updater } from "@/hooks/useStore";
|
||||
import { authors, DEBOUNCE, saveDelay } from "@/snippets";
|
||||
import { PieceId, RepertoireId } from "common";
|
||||
import { Array, Cause, Effect, Option, pipe } from "effect";
|
||||
import { Array, Cause, Effect, Match, Option, pipe } from "effect";
|
||||
import { ChevronDown, ChevronUp, CircleMinus, Loader2, Plus } from "lucide-react";
|
||||
import { FormEventHandler, useCallback, useId, useMemo, useRef, useState } from "react";
|
||||
import { Link, useNavigate, useParams } from "react-router-dom";
|
||||
@@ -36,7 +36,7 @@ export function Repertoire() {
|
||||
return (
|
||||
<div className="p-4 overflow-y-auto flex flex-wrap items-start gap-4">
|
||||
{error !== null ? (
|
||||
Cause.isUnknownException(error) ? "Wystąpił nieznany błąd" : `Wystąpił błąd: ${error.value}`
|
||||
Cause.isUnknownException(error) ? "Wystąpił nieznany błąd" : `Wystąpił błąd: ${JSON.stringify(error.value)}`
|
||||
) : (<>
|
||||
<div className="flex flex-col gap-4 p-4 border rounded">
|
||||
<h3 className="font-bold">Repertuar</h3>
|
||||
@@ -343,7 +343,7 @@ function AddEntryDialogContent(props: AddEntryDialogContent.Props) {
|
||||
) : error !== null ? (
|
||||
<TableRow>
|
||||
<TableCell colSpan={4} className="text-center">
|
||||
{Cause.isUnknownException(error) ? "Wystąpił nieznany błąd" : `Wystąpił błąd: ${error.value}`}
|
||||
{Cause.isUnknownException(error) ? "Wystąpił nieznany błąd" : `Wystąpił błąd: ${JSON.stringify(error.value)}`}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
) : (
|
||||
@@ -410,7 +410,14 @@ function EntryDialogPieceRow(props: EntryDialogPieceRow.Props) {
|
||||
if (error !== null) {
|
||||
return (
|
||||
<TableRow>
|
||||
<TableCell colSpan={2}>Wystąpił błąd: {error.status === 422 ? error.value.message : error.value}</TableCell>
|
||||
<TableCell colSpan={2}>
|
||||
Wystąpił błąd: {Match.value(error).pipe(
|
||||
Match.when({ status: 401 }, () => "Zaloguj się ponownie"),
|
||||
Match.when({ status: 422 }, ({ value }) => value.message),
|
||||
Match.when({ status: 404 }, () => "Utwór nie istnieje"),
|
||||
Match.exhaustive,
|
||||
)}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@
|
||||
import { useLoadingEffect } from "@/hooks/useLoading";
|
||||
import { created, DEBOUNCE, modified } from "@/snippets";
|
||||
import { RepertoireId } from "common";
|
||||
import { Cause, Effect } from "effect";
|
||||
import { Cause, Effect, Match } from "effect";
|
||||
import { Loader2, Plus } from "lucide-react";
|
||||
import { FormEventHandler, ReactNode, useId, useRef, useState } from "react";
|
||||
import { Link, useNavigate } from "react-router-dom";
|
||||
@@ -79,7 +79,7 @@ export function Repertoires() {
|
||||
) : error !== null ? (
|
||||
<TableRow>
|
||||
<TableCell colSpan={4} className="text-center">
|
||||
{Cause.isUnknownException(error) ? "Wystąpił nieznany błąd" : `Wystąpił błąd: ${error.value}`}
|
||||
{Cause.isUnknownException(error) ? "Wystąpił nieznany błąd" : `Wystąpił błąd: ${JSON.stringify(error.value)}`}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
) : (
|
||||
@@ -112,7 +112,14 @@ function RepertoireRow(props: RepertoireRow.Props) {
|
||||
if (error !== null) {
|
||||
return (
|
||||
<TableRow>
|
||||
<TableCell colSpan={4}>Wystąpił błąd: {error.status === 422 ? error.value.message : error.value}</TableCell>
|
||||
<TableCell colSpan={4}>
|
||||
Wystąpił błąd: {Match.value(error).pipe(
|
||||
Match.when({ status: 401 }, () => "Zaloguj się ponownie"),
|
||||
Match.when({ status: 422 }, ({ value }) => value.message),
|
||||
Match.when({ status: 404 }, () => "Repertuar nie istnieje"),
|
||||
Match.exhaustive,
|
||||
)}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -36,7 +36,11 @@ export function created({ createdAt, createdBy }: SystemInformation): ReactNode
|
||||
|
||||
if (Option.isSome(createdBy)) {
|
||||
nodes.push(<br />);
|
||||
nodes.push(`przez ${createdBy.value.displayName}`);
|
||||
if (createdBy.value !== null) {
|
||||
nodes.push(`przez ${createdBy.value.displayName}`);
|
||||
} else {
|
||||
nodes.push("przez nieznanego użytkownika");
|
||||
}
|
||||
}
|
||||
|
||||
return nodes;
|
||||
@@ -48,7 +52,11 @@ export function modified({ modifiedAt, modifiedBy }: SystemInformation): ReactNo
|
||||
if (Option.isNone(modifiedBy)) {
|
||||
return "\u2014";
|
||||
} else {
|
||||
return `przez ${modifiedBy.value.displayName}`;
|
||||
if (modifiedBy.value !== null) {
|
||||
return `przez ${modifiedBy.value.displayName}`;
|
||||
} else {
|
||||
return "przez nieznanego użytkownika";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,7 +64,11 @@ export function modified({ modifiedAt, modifiedBy }: SystemInformation): ReactNo
|
||||
|
||||
if (Option.isSome(modifiedBy)) {
|
||||
nodes.push(<br />);
|
||||
nodes.push(`przez ${modifiedBy.value.displayName}`);
|
||||
if (modifiedBy.value !== null) {
|
||||
nodes.push(`przez ${modifiedBy.value.displayName}`);
|
||||
} else {
|
||||
nodes.push("przez nieznanego użytkownika");
|
||||
}
|
||||
}
|
||||
|
||||
return nodes;
|
||||
|
||||
Reference in New Issue
Block a user