mirror of
https://github.com/docmost/docmost.git
synced 2026-08-30 02:25:01 +08:00
- default status
- type fix - error helper
This commit is contained in:
@@ -76,6 +76,24 @@
|
|||||||
"Failed to import pages": "Failed to import pages",
|
"Failed to import pages": "Failed to import pages",
|
||||||
"Failed to load page. An error occurred.": "Failed to load page. An error occurred.",
|
"Failed to load page. An error occurred.": "Failed to load page. An error occurred.",
|
||||||
"Failed to update data": "Failed to update data",
|
"Failed to update data": "Failed to update data",
|
||||||
|
"Failed to create base": "Failed to create base",
|
||||||
|
"Failed to update base": "Failed to update base",
|
||||||
|
"Failed to delete base": "Failed to delete base",
|
||||||
|
"Failed to create property": "Failed to create property",
|
||||||
|
"Failed to update property": "Failed to update property",
|
||||||
|
"Failed to delete property": "Failed to delete property",
|
||||||
|
"Failed to reorder property": "Failed to reorder property",
|
||||||
|
"Failed to create view": "Failed to create view",
|
||||||
|
"Failed to update view": "Failed to update view",
|
||||||
|
"Failed to delete view": "Failed to delete view",
|
||||||
|
"Failed to create row": "Failed to create row",
|
||||||
|
"Failed to update row": "Failed to update row",
|
||||||
|
"Failed to delete row": "Failed to delete row",
|
||||||
|
"Failed to delete rows": "Failed to delete rows",
|
||||||
|
"Failed to reorder row": "Failed to reorder row",
|
||||||
|
"Failed to move card": "Failed to move card",
|
||||||
|
"Failed to add card": "Failed to add card",
|
||||||
|
"Failed to export CSV": "Failed to export CSV",
|
||||||
"Favorite spaces": "Favorite spaces",
|
"Favorite spaces": "Favorite spaces",
|
||||||
"Favorite spaces appear here": "Favorite spaces appear here",
|
"Favorite spaces appear here": "Favorite spaces appear here",
|
||||||
"Favorites": "Favorites",
|
"Favorites": "Favorites",
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import {
|
|||||||
FilterGroup,
|
FilterGroup,
|
||||||
} from "@/ee/base/types/base.types";
|
} from "@/ee/base/types/base.types";
|
||||||
import { exportBaseToCsv } from "@/ee/base/services/base-service";
|
import { exportBaseToCsv } from "@/ee/base/services/base-service";
|
||||||
|
import { getApiErrorMessage } from "@/lib/api-error";
|
||||||
import { useBaseEditable } from "@/ee/base/context/base-editable";
|
import { useBaseEditable } from "@/ee/base/context/base-editable";
|
||||||
import { ViewTabs } from "@/ee/base/components/views/view-tabs";
|
import { ViewTabs } from "@/ee/base/components/views/view-tabs";
|
||||||
import { ViewSortConfigPopover } from "@/ee/base/components/views/view-sort-config";
|
import { ViewSortConfigPopover } from "@/ee/base/components/views/view-sort-config";
|
||||||
@@ -78,7 +79,7 @@ export function BaseToolbar({
|
|||||||
} catch (err) {
|
} catch (err) {
|
||||||
notifications.show({
|
notifications.show({
|
||||||
color: "red",
|
color: "red",
|
||||||
message: t("Failed to export CSV"),
|
message: getApiErrorMessage(err, t("Failed to export CSV")),
|
||||||
});
|
});
|
||||||
} finally {
|
} finally {
|
||||||
setExporting(false);
|
setExporting(false);
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { IconGripVertical, type IconLetterT } from "@tabler/icons-react";
|
|||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { IBase, IBaseProperty, IBaseView } from "@/ee/base/types/base.types";
|
import { IBase, IBaseProperty, IBaseView } from "@/ee/base/types/base.types";
|
||||||
import { useUpdateViewMutation } from "@/ee/base/queries/base-view-query";
|
import { useUpdateViewMutation } from "@/ee/base/queries/base-view-query";
|
||||||
import { propertyTypes } from "@/ee/base/components/property/property-type-picker";
|
import { propertyTypes } from "@/ee/base/property-types/property-type.registry";
|
||||||
import { BaseDropEdgeIndicator } from "@/ee/base/components/grid/base-drop-edge-indicator";
|
import { BaseDropEdgeIndicator } from "@/ee/base/components/grid/base-drop-edge-indicator";
|
||||||
import { combine } from "@atlaskit/pragmatic-drag-and-drop/combine";
|
import { combine } from "@atlaskit/pragmatic-drag-and-drop/combine";
|
||||||
import {
|
import {
|
||||||
|
|||||||
@@ -18,11 +18,12 @@ import {
|
|||||||
TypeOptions,
|
TypeOptions,
|
||||||
} from "@/ee/base/types/base.types";
|
} from "@/ee/base/types/base.types";
|
||||||
import { useCreatePropertyMutation } from "@/ee/base/queries/base-property-query";
|
import { useCreatePropertyMutation } from "@/ee/base/queries/base-property-query";
|
||||||
import { PropertyTypePicker, propertyTypes } from "./property-type-picker";
|
import { PropertyTypePicker } from "./property-type-picker";
|
||||||
import { PropertyOptions } from "./property-options";
|
import { PropertyOptions } from "./property-options";
|
||||||
import {
|
import {
|
||||||
getDescriptor,
|
getDescriptor,
|
||||||
defaultTypeOptionsFor,
|
defaultTypeOptionsFor,
|
||||||
|
propertyTypes,
|
||||||
} from "@/ee/base/property-types/property-type.registry";
|
} from "@/ee/base/property-types/property-type.registry";
|
||||||
import { FormulaEditor } from "../formula/formula-editor";
|
import { FormulaEditor } from "../formula/formula-editor";
|
||||||
import classes from "@/ee/base/styles/grid.module.css";
|
import classes from "@/ee/base/styles/grid.module.css";
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ import {
|
|||||||
useUpdatePropertyMutation,
|
useUpdatePropertyMutation,
|
||||||
useDeletePropertyMutation,
|
useDeletePropertyMutation,
|
||||||
} from "@/ee/base/queries/base-property-query";
|
} from "@/ee/base/queries/base-property-query";
|
||||||
import { PropertyTypePicker, propertyTypes } from "./property-type-picker";
|
import { PropertyTypePicker } from "./property-type-picker";
|
||||||
import { PropertyOptions } from "./property-options";
|
import { PropertyOptions } from "./property-options";
|
||||||
import {
|
import {
|
||||||
conversionWarning,
|
conversionWarning,
|
||||||
@@ -36,7 +36,7 @@ import {
|
|||||||
NON_USER_TARGET_TYPES,
|
NON_USER_TARGET_TYPES,
|
||||||
} from "./conversion-warning";
|
} from "./conversion-warning";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { isSystemPropertyType } from "@/ee/base/property-types/property-type.registry";
|
import { isSystemPropertyType, propertyTypes } from "@/ee/base/property-types/property-type.registry";
|
||||||
import cellClasses from "@/ee/base/styles/cells.module.css";
|
import cellClasses from "@/ee/base/styles/cells.module.css";
|
||||||
import classes from "@/ee/base/styles/property.module.css";
|
import classes from "@/ee/base/styles/property.module.css";
|
||||||
|
|
||||||
|
|||||||
@@ -1,19 +1,11 @@
|
|||||||
import { UnstyledButton, Group, Text, TextInput } from "@mantine/core";
|
import { UnstyledButton, Group, Text, TextInput } from "@mantine/core";
|
||||||
import { IconCheck, IconSearch } from "@tabler/icons-react";
|
import { IconCheck, IconSearch } from "@tabler/icons-react";
|
||||||
import { BasePropertyType } from "@/ee/base/types/base.types";
|
import { BasePropertyType } from "@/ee/base/types/base.types";
|
||||||
import {
|
import { propertyTypes } from "@/ee/base/property-types/property-type.registry";
|
||||||
PROPERTY_PICKER_ORDER,
|
|
||||||
getDescriptor,
|
|
||||||
} from "@/ee/base/property-types/property-type.registry";
|
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { useState, useRef, useEffect } from "react";
|
import { useState, useRef, useEffect } from "react";
|
||||||
import classes from "@/ee/base/styles/cells.module.css";
|
import classes from "@/ee/base/styles/cells.module.css";
|
||||||
|
|
||||||
const propertyTypes = PROPERTY_PICKER_ORDER.map((type) => {
|
|
||||||
const d = getDescriptor(type)!;
|
|
||||||
return { type, icon: d.icon, labelKey: d.labelKey };
|
|
||||||
});
|
|
||||||
|
|
||||||
type PropertyTypePickerProps = {
|
type PropertyTypePickerProps = {
|
||||||
onSelect: (type: BasePropertyType) => void;
|
onSelect: (type: BasePropertyType) => void;
|
||||||
currentType?: BasePropertyType;
|
currentType?: BasePropertyType;
|
||||||
@@ -77,5 +69,3 @@ export function PropertyTypePicker({
|
|||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export { propertyTypes };
|
|
||||||
|
|||||||
@@ -292,6 +292,7 @@ export function RowDetailModal({
|
|||||||
row={row}
|
row={row}
|
||||||
primaryProperty={primaryProperty}
|
primaryProperty={primaryProperty}
|
||||||
canEdit={canEdit}
|
canEdit={canEdit}
|
||||||
|
onClose={onClose}
|
||||||
onCommit={(value) => {
|
onCommit={(value) => {
|
||||||
if (!primaryProperty) return;
|
if (!primaryProperty) return;
|
||||||
updateRowMutation.mutate({
|
updateRowMutation.mutate({
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ type RowDetailTitleProps = {
|
|||||||
primaryProperty: IBaseProperty | undefined;
|
primaryProperty: IBaseProperty | undefined;
|
||||||
canEdit: boolean;
|
canEdit: boolean;
|
||||||
onCommit: (value: string) => void;
|
onCommit: (value: string) => void;
|
||||||
|
onClose: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function RowDetailTitle({
|
export function RowDetailTitle({
|
||||||
@@ -16,6 +17,7 @@ export function RowDetailTitle({
|
|||||||
primaryProperty,
|
primaryProperty,
|
||||||
canEdit,
|
canEdit,
|
||||||
onCommit,
|
onCommit,
|
||||||
|
onClose,
|
||||||
}: RowDetailTitleProps) {
|
}: RowDetailTitleProps) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const initial = primaryProperty
|
const initial = primaryProperty
|
||||||
@@ -57,6 +59,10 @@ export function RowDetailTitle({
|
|||||||
if (e.key === "Enter") {
|
if (e.key === "Enter") {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
(e.currentTarget as HTMLInputElement).blur();
|
(e.currentTarget as HTMLInputElement).blur();
|
||||||
|
} else if (e.key === "Escape") {
|
||||||
|
e.preventDefault();
|
||||||
|
(e.currentTarget as HTMLInputElement).blur();
|
||||||
|
onClose();
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { useMemo, useCallback } from "react";
|
|||||||
import { Popover, Switch, Stack, Text, Group, Divider, UnstyledButton } from "@mantine/core";
|
import { Popover, Switch, Stack, Text, Group, Divider, UnstyledButton } from "@mantine/core";
|
||||||
import { Table } from "@tanstack/react-table";
|
import { Table } from "@tanstack/react-table";
|
||||||
import { IBaseRow, IBaseProperty } from "@/ee/base/types/base.types";
|
import { IBaseRow, IBaseProperty } from "@/ee/base/types/base.types";
|
||||||
import { propertyTypes } from "@/ee/base/components/property/property-type-picker";
|
import { propertyTypes } from "@/ee/base/property-types/property-type.registry";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import cellClasses from "@/ee/base/styles/cells.module.css";
|
import cellClasses from "@/ee/base/styles/cells.module.css";
|
||||||
import viewClasses from "@/ee/base/styles/views.module.css";
|
import viewClasses from "@/ee/base/styles/views.module.css";
|
||||||
|
|||||||
@@ -96,7 +96,11 @@ export const PROPERTY_TYPE_REGISTRY: Record<
|
|||||||
hasOptions: true,
|
hasOptions: true,
|
||||||
defaultTypeOptions: () => {
|
defaultTypeOptions: () => {
|
||||||
const choices = defaultStatusChoices();
|
const choices = defaultStatusChoices();
|
||||||
return { choices, choiceOrder: choices.map((c) => c.id) };
|
return {
|
||||||
|
choices,
|
||||||
|
choiceOrder: choices.map((c) => c.id),
|
||||||
|
defaultValue: choices[0].id,
|
||||||
|
};
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
multiSelect: {
|
multiSelect: {
|
||||||
@@ -244,6 +248,11 @@ export const PROPERTY_PICKER_ORDER: BasePropertyType[] = [
|
|||||||
"createdAt", "lastEditedAt", "lastEditedBy",
|
"createdAt", "lastEditedAt", "lastEditedBy",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export const propertyTypes = PROPERTY_PICKER_ORDER.map((type) => {
|
||||||
|
const d = getDescriptor(type)!;
|
||||||
|
return { type, icon: d.icon, labelKey: d.labelKey };
|
||||||
|
});
|
||||||
|
|
||||||
export function systemAccessorFor(type: string) {
|
export function systemAccessorFor(type: string) {
|
||||||
return getDescriptor(type)?.systemAccessor;
|
return getDescriptor(type)?.systemAccessor;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import {
|
|||||||
import { notifications } from "@mantine/notifications";
|
import { notifications } from "@mantine/notifications";
|
||||||
import { queryClient } from "@/main";
|
import { queryClient } from "@/main";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { getApiErrorMessage } from "@/lib/api-error";
|
||||||
import { IPagination } from "@/lib/types";
|
import { IPagination } from "@/lib/types";
|
||||||
|
|
||||||
export function useCreatePropertyMutation() {
|
export function useCreatePropertyMutation() {
|
||||||
@@ -36,9 +37,9 @@ export function useCreatePropertyMutation() {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
onError: () => {
|
onError: (error) => {
|
||||||
notifications.show({
|
notifications.show({
|
||||||
message: t("Failed to create property"),
|
message: getApiErrorMessage(error, t("Failed to create property")),
|
||||||
color: "red",
|
color: "red",
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@@ -69,9 +70,9 @@ export function useUpdatePropertyMutation() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onError: () => {
|
onError: (error) => {
|
||||||
notifications.show({
|
notifications.show({
|
||||||
message: t("Failed to update property"),
|
message: getApiErrorMessage(error, t("Failed to update property")),
|
||||||
color: "red",
|
color: "red",
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@@ -114,9 +115,9 @@ export function useDeletePropertyMutation() {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
onError: () => {
|
onError: (error) => {
|
||||||
notifications.show({
|
notifications.show({
|
||||||
message: t("Failed to delete property"),
|
message: getApiErrorMessage(error, t("Failed to delete property")),
|
||||||
color: "red",
|
color: "red",
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@@ -154,7 +155,7 @@ export function useReorderPropertyMutation() {
|
|||||||
|
|
||||||
return { previous };
|
return { previous };
|
||||||
},
|
},
|
||||||
onError: (_, variables, context) => {
|
onError: (error, variables, context) => {
|
||||||
if (context?.previous) {
|
if (context?.previous) {
|
||||||
queryClient.setQueryData(
|
queryClient.setQueryData(
|
||||||
["bases", variables.pageId],
|
["bases", variables.pageId],
|
||||||
@@ -162,7 +163,7 @@ export function useReorderPropertyMutation() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
notifications.show({
|
notifications.show({
|
||||||
message: t("Failed to reorder property"),
|
message: getApiErrorMessage(error, t("Failed to reorder property")),
|
||||||
color: "red",
|
color: "red",
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import {
|
|||||||
import { notifications } from "@mantine/notifications";
|
import { notifications } from "@mantine/notifications";
|
||||||
import { queryClient } from "@/main";
|
import { queryClient } from "@/main";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { getApiErrorMessage } from "@/lib/api-error";
|
||||||
import { useAtom } from "jotai";
|
import { useAtom } from "jotai";
|
||||||
import { treeDataAtom } from "@/features/page/tree/atoms/tree-data-atom";
|
import { treeDataAtom } from "@/features/page/tree/atoms/tree-data-atom";
|
||||||
import { treeModel } from "@/features/page/tree/model/tree-model";
|
import { treeModel } from "@/features/page/tree/model/tree-model";
|
||||||
@@ -44,9 +45,9 @@ export function useCreateBaseMutation() {
|
|||||||
queryKey: ["bases", "list", data.spaceId],
|
queryKey: ["bases", "list", data.spaceId],
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
onError: () => {
|
onError: (error) => {
|
||||||
notifications.show({
|
notifications.show({
|
||||||
message: t("Failed to create base"),
|
message: getApiErrorMessage(error, t("Failed to create base")),
|
||||||
color: "red",
|
color: "red",
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@@ -77,9 +78,9 @@ export function useConvertPageToBaseMutation() {
|
|||||||
payload: { isBase: true },
|
payload: { isBase: true },
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
onError: () => {
|
onError: (error) => {
|
||||||
notifications.show({
|
notifications.show({
|
||||||
message: t("Failed to create base"),
|
message: getApiErrorMessage(error, t("Failed to create base")),
|
||||||
color: "red",
|
color: "red",
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@@ -96,9 +97,9 @@ export function useUpdateBaseMutation() {
|
|||||||
return { ...old, ...data };
|
return { ...old, ...data };
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
onError: () => {
|
onError: (error) => {
|
||||||
notifications.show({
|
notifications.show({
|
||||||
message: t("Failed to update base"),
|
message: getApiErrorMessage(error, t("Failed to update base")),
|
||||||
color: "red",
|
color: "red",
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@@ -116,9 +117,9 @@ export function useDeleteBaseMutation() {
|
|||||||
});
|
});
|
||||||
notifications.show({ message: t("Base deleted") });
|
notifications.show({ message: t("Base deleted") });
|
||||||
},
|
},
|
||||||
onError: () => {
|
onError: (error) => {
|
||||||
notifications.show({
|
notifications.show({
|
||||||
message: t("Failed to delete base"),
|
message: getApiErrorMessage(error, t("Failed to delete base")),
|
||||||
color: "red",
|
color: "red",
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ import {
|
|||||||
import { notifications } from "@mantine/notifications";
|
import { notifications } from "@mantine/notifications";
|
||||||
import { queryClient } from "@/main";
|
import { queryClient } from "@/main";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { getApiErrorMessage } from "@/lib/api-error";
|
||||||
import { useHydrateReferences } from "@/ee/base/reference/reference-store";
|
import { useHydrateReferences } from "@/ee/base/reference/reference-store";
|
||||||
import { markRequestIdOutbound } from "@/ee/base/hooks/use-base-socket";
|
import { markRequestIdOutbound } from "@/ee/base/hooks/use-base-socket";
|
||||||
import { v7 as uuid7 } from "uuid";
|
import { v7 as uuid7 } from "uuid";
|
||||||
@@ -149,9 +150,9 @@ export function useCreateRowMutation() {
|
|||||||
invalidateBaseRows(newRow.pageId);
|
invalidateBaseRows(newRow.pageId);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onError: () => {
|
onError: (error) => {
|
||||||
notifications.show({
|
notifications.show({
|
||||||
message: t("Failed to create row"),
|
message: getApiErrorMessage(error, t("Failed to create row")),
|
||||||
color: "red",
|
color: "red",
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@@ -221,7 +222,7 @@ export function useUpdateRowMutation() {
|
|||||||
|
|
||||||
return { snapshots };
|
return { snapshots };
|
||||||
},
|
},
|
||||||
onError: (_, variables, context) => {
|
onError: (error, variables, context) => {
|
||||||
if (context?.snapshots) {
|
if (context?.snapshots) {
|
||||||
for (const [key, data] of context.snapshots) {
|
for (const [key, data] of context.snapshots) {
|
||||||
queryClient.setQueryData(key, data);
|
queryClient.setQueryData(key, data);
|
||||||
@@ -231,7 +232,7 @@ export function useUpdateRowMutation() {
|
|||||||
queryKey: ["base-row", variables.pageId, variables.rowId],
|
queryKey: ["base-row", variables.pageId, variables.rowId],
|
||||||
});
|
});
|
||||||
notifications.show({
|
notifications.show({
|
||||||
message: t("Failed to update row"),
|
message: getApiErrorMessage(error, t("Failed to update row")),
|
||||||
color: "red",
|
color: "red",
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@@ -305,14 +306,14 @@ export function useDeleteRowMutation() {
|
|||||||
|
|
||||||
return { snapshots };
|
return { snapshots };
|
||||||
},
|
},
|
||||||
onError: (_, variables, context) => {
|
onError: (error, variables, context) => {
|
||||||
if (context?.snapshots) {
|
if (context?.snapshots) {
|
||||||
for (const [key, data] of context.snapshots) {
|
for (const [key, data] of context.snapshots) {
|
||||||
queryClient.setQueryData(key, data);
|
queryClient.setQueryData(key, data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
notifications.show({
|
notifications.show({
|
||||||
message: t("Failed to delete row"),
|
message: getApiErrorMessage(error, t("Failed to delete row")),
|
||||||
color: "red",
|
color: "red",
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@@ -349,14 +350,14 @@ export function useDeleteRowsMutation() {
|
|||||||
|
|
||||||
return { snapshots };
|
return { snapshots };
|
||||||
},
|
},
|
||||||
onError: (_, __, context) => {
|
onError: (error, __, context) => {
|
||||||
if (context?.snapshots) {
|
if (context?.snapshots) {
|
||||||
for (const [key, data] of context.snapshots) {
|
for (const [key, data] of context.snapshots) {
|
||||||
queryClient.setQueryData(key, data);
|
queryClient.setQueryData(key, data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
notifications.show({
|
notifications.show({
|
||||||
message: t("Failed to delete rows"),
|
message: getApiErrorMessage(error, t("Failed to delete rows")),
|
||||||
color: "red",
|
color: "red",
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@@ -399,14 +400,14 @@ export function useReorderRowMutation() {
|
|||||||
|
|
||||||
return { snapshots };
|
return { snapshots };
|
||||||
},
|
},
|
||||||
onError: (_, variables, context) => {
|
onError: (error, variables, context) => {
|
||||||
if (context?.snapshots) {
|
if (context?.snapshots) {
|
||||||
for (const [key, data] of context.snapshots) {
|
for (const [key, data] of context.snapshots) {
|
||||||
queryClient.setQueryData(key, data);
|
queryClient.setQueryData(key, data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
notifications.show({
|
notifications.show({
|
||||||
message: t("Failed to reorder row"),
|
message: getApiErrorMessage(error, t("Failed to reorder row")),
|
||||||
color: "red",
|
color: "red",
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@@ -504,14 +505,14 @@ export function useKanbanMoveCardMutation() {
|
|||||||
|
|
||||||
return { snapshots };
|
return { snapshots };
|
||||||
},
|
},
|
||||||
onError: (_, __, context) => {
|
onError: (error, __, context) => {
|
||||||
if (context?.snapshots) {
|
if (context?.snapshots) {
|
||||||
for (const [key, data] of context.snapshots) {
|
for (const [key, data] of context.snapshots) {
|
||||||
queryClient.setQueryData(key, data);
|
queryClient.setQueryData(key, data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
notifications.show({
|
notifications.show({
|
||||||
message: t("Failed to move card"),
|
message: getApiErrorMessage(error, t("Failed to move card")),
|
||||||
color: "red",
|
color: "red",
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@@ -552,9 +553,9 @@ export function useKanbanCreateCardMutation() {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
onError: () => {
|
onError: (error) => {
|
||||||
notifications.show({
|
notifications.show({
|
||||||
message: t("Failed to add card"),
|
message: getApiErrorMessage(error, t("Failed to add card")),
|
||||||
color: "red",
|
color: "red",
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ function applyConfigPatch(
|
|||||||
import { notifications } from "@mantine/notifications";
|
import { notifications } from "@mantine/notifications";
|
||||||
import { queryClient } from "@/main";
|
import { queryClient } from "@/main";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { getApiErrorMessage } from "@/lib/api-error";
|
||||||
|
|
||||||
export function useCreateViewMutation() {
|
export function useCreateViewMutation() {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@@ -45,9 +46,9 @@ export function useCreateViewMutation() {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
onError: () => {
|
onError: (error) => {
|
||||||
notifications.show({
|
notifications.show({
|
||||||
message: t("Failed to create view"),
|
message: getApiErrorMessage(error, t("Failed to create view")),
|
||||||
color: "red",
|
color: "red",
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@@ -99,7 +100,7 @@ export function useUpdateViewMutation() {
|
|||||||
|
|
||||||
return { previous };
|
return { previous };
|
||||||
},
|
},
|
||||||
onError: (_, variables, context) => {
|
onError: (error, variables, context) => {
|
||||||
if (context?.previous) {
|
if (context?.previous) {
|
||||||
queryClient.setQueryData(
|
queryClient.setQueryData(
|
||||||
["bases", variables.pageId],
|
["bases", variables.pageId],
|
||||||
@@ -107,7 +108,7 @@ export function useUpdateViewMutation() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
notifications.show({
|
notifications.show({
|
||||||
message: t("Failed to update view"),
|
message: getApiErrorMessage(error, t("Failed to update view")),
|
||||||
color: "red",
|
color: "red",
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@@ -144,9 +145,9 @@ export function useDeleteViewMutation() {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
onError: () => {
|
onError: (error) => {
|
||||||
notifications.show({
|
notifications.show({
|
||||||
message: t("Failed to delete view"),
|
message: getApiErrorMessage(error, t("Failed to delete view")),
|
||||||
color: "red",
|
color: "red",
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -447,7 +447,7 @@ const CommandGroups: SlashMenuGroupedItemsType = {
|
|||||||
{
|
{
|
||||||
title: "Kanban",
|
title: "Kanban",
|
||||||
description: "Insert a kanban board on this page",
|
description: "Insert a kanban board on this page",
|
||||||
searchTerms: ["kanban", "board", "cards", "status", "task"],
|
searchTerms: ["kanban", "board", "cards", "status", "task", "database"],
|
||||||
icon: IconLayoutKanban,
|
icon: IconLayoutKanban,
|
||||||
command: async ({ editor, range }: CommandProps) => {
|
command: async ({ editor, range }: CommandProps) => {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
import { isAxiosError } from "axios";
|
||||||
|
|
||||||
|
export function getApiErrorMessage(
|
||||||
|
error: unknown,
|
||||||
|
fallback = "An error occurred",
|
||||||
|
): string {
|
||||||
|
if (isAxiosError(error)) {
|
||||||
|
const message = error.response?.data?.message;
|
||||||
|
if (Array.isArray(message)) {
|
||||||
|
const joined = message.filter(Boolean).join(", ");
|
||||||
|
if (joined) return joined;
|
||||||
|
} else if (typeof message === "string" && message.trim()) {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fallback;
|
||||||
|
}
|
||||||
@@ -1 +1,2 @@
|
|||||||
export * from "./utils";
|
export * from "./utils";
|
||||||
|
export * from "./api-error";
|
||||||
|
|||||||
+1
-1
Submodule apps/server/src/ee updated: fa7e54ab41...aed638e895
Reference in New Issue
Block a user