Fix strict null errors in utils (#3007)
* Fix strict null in utils/errors * Fix auth-related src/utils strict null errors * Fix data, maps and tables utils * Fix utils/urls * Fix filters * Fix strict null errors in utils/handlers * Fix strict nulls in utils/menu * Fix strict nulls in utils/sort * Fix strict nulls in utils/richText * Fix search handler * Fix siteSettings leftover type mismatch * Fix page map error for attribute case * Fix type error for sdk error codes * Fix Choice type in page maps * Fix error types mismatch * Remove addressType from type union in auth error message
This commit is contained in:
parent
221adf25d6
commit
abbe76442d
39 changed files with 121 additions and 90 deletions
|
@ -6,7 +6,7 @@ import makeQuery, { UseQueryResult } from "./makeQuery";
|
|||
import useDebounce from "./useDebounce";
|
||||
|
||||
export interface SearchVariables {
|
||||
after?: string;
|
||||
after?: string | null;
|
||||
first: number;
|
||||
query: string;
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ import SiteSettingsPage, { SiteSettingsPageProps } from "./SiteSettingsPage";
|
|||
const props: Omit<SiteSettingsPageProps, "classes"> = {
|
||||
disabled: false,
|
||||
errors: [],
|
||||
onSubmit: () => undefined,
|
||||
onSubmit: async () => undefined,
|
||||
saveButtonBarState: "default",
|
||||
shop,
|
||||
};
|
||||
|
|
|
@ -7,6 +7,6 @@ export enum GqlErrors {
|
|||
|
||||
export function hasError(err: ApolloError, ...errorCodes: string[]): boolean {
|
||||
return err.graphQLErrors.some(gqlError =>
|
||||
errorCodes.includes(gqlError.extensions.exception.code),
|
||||
errorCodes.includes(gqlError.extensions?.exception.code),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,31 +1,30 @@
|
|||
import { LoginData } from "@saleor/sdk";
|
||||
import { UserFragment } from "@dashboard/graphql";
|
||||
import { UserDetailsFragment } from "@saleor/sdk/dist/apollo/types";
|
||||
|
||||
export const isSupported = !!(
|
||||
navigator?.credentials?.preventSilentAccess && window.PasswordCredential
|
||||
);
|
||||
export const isSupported = !!window.PasswordCredential;
|
||||
|
||||
export async function login<T>(
|
||||
loginFn: (id: string, password: string) => Promise<T>,
|
||||
): Promise<T | null> {
|
||||
let result: T;
|
||||
let result: T | null;
|
||||
|
||||
try {
|
||||
const credential = await navigator.credentials.get({ password: true });
|
||||
if (credential instanceof PasswordCredential) {
|
||||
result = await loginFn(credential.id, credential.password);
|
||||
result = await loginFn(credential.id, credential.password ?? "");
|
||||
}
|
||||
} catch {
|
||||
result = null;
|
||||
}
|
||||
|
||||
return result;
|
||||
return result!;
|
||||
}
|
||||
|
||||
export function saveCredentials(
|
||||
user: LoginData["user"],
|
||||
user: UserFragment | UserDetailsFragment,
|
||||
password: string,
|
||||
): Promise<CredentialType | null> {
|
||||
let result: Promise<CredentialType | null>;
|
||||
): Promise<CredentialType> | null {
|
||||
let result: Promise<CredentialType> | null;
|
||||
|
||||
if (isSupported) {
|
||||
const cred = new PasswordCredential({
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
interface PublicationData {
|
||||
publicationDate: string;
|
||||
publicationDate: string | null;
|
||||
isPublished: boolean;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
import { AccountErrorCode } from "@dashboard/graphql";
|
||||
import { SetPasswordData } from "@saleor/sdk";
|
||||
import {
|
||||
AccountError,
|
||||
AccountErrorCode as SdkAccountErrorCode,
|
||||
} from "@saleor/sdk/dist/apollo/types";
|
||||
import { defineMessages, IntlShape } from "react-intl";
|
||||
|
||||
import { getCommonFormFieldErrorMessage } from "./common";
|
||||
|
@ -48,11 +51,14 @@ const messages = defineMessages({
|
|||
});
|
||||
|
||||
interface ErrorFragment {
|
||||
code: AccountErrorCode | SetPasswordData["errors"][number]["code"];
|
||||
code: AccountErrorCode;
|
||||
field: string | null;
|
||||
}
|
||||
|
||||
function getAccountErrorMessage(err: ErrorFragment, intl: IntlShape): string {
|
||||
function getAccountErrorMessage(
|
||||
err: ErrorFragment | Omit<AccountError, "addressType">,
|
||||
intl: IntlShape,
|
||||
): string | undefined {
|
||||
if (err) {
|
||||
switch (err.code) {
|
||||
case AccountErrorCode.INVALID_PASSWORD:
|
||||
|
@ -78,7 +84,10 @@ function getAccountErrorMessage(err: ErrorFragment, intl: IntlShape): string {
|
|||
}
|
||||
}
|
||||
|
||||
return getCommonFormFieldErrorMessage(err, intl);
|
||||
return getCommonFormFieldErrorMessage<AccountErrorCode | SdkAccountErrorCode>(
|
||||
err,
|
||||
intl,
|
||||
);
|
||||
}
|
||||
|
||||
export default getAccountErrorMessage;
|
||||
|
|
|
@ -38,7 +38,10 @@ const messages = defineMessages({
|
|||
},
|
||||
});
|
||||
|
||||
function getAppErrorMessage(err: AppErrorFragment, intl: IntlShape): string {
|
||||
function getAppErrorMessage(
|
||||
err: AppErrorFragment,
|
||||
intl: IntlShape,
|
||||
): string | undefined {
|
||||
if (err) {
|
||||
switch (err.code) {
|
||||
case AppErrorCode.INVALID_MANIFEST_FORMAT:
|
||||
|
|
|
@ -21,7 +21,7 @@ const messages = defineMessages({
|
|||
function getAttributeErrorMessage(
|
||||
err: Omit<AttributeErrorFragment, "__typename"> | undefined,
|
||||
intl: IntlShape,
|
||||
): string {
|
||||
): string | undefined {
|
||||
if (err) {
|
||||
switch (err.code) {
|
||||
case AttributeErrorCode.ALREADY_EXISTS:
|
||||
|
|
|
@ -21,7 +21,7 @@ const messages = defineMessages({
|
|||
function getChannelsErrorMessage(
|
||||
err: Omit<ChannelErrorFragment, "__typename"> | undefined,
|
||||
intl: IntlShape,
|
||||
): string {
|
||||
): string | undefined {
|
||||
if (err) {
|
||||
switch (err.code) {
|
||||
case ChannelErrorCode.ALREADY_EXISTS:
|
||||
|
|
|
@ -33,7 +33,7 @@ export interface CommonError<ErrorCode> {
|
|||
export function getCommonFormFieldErrorMessage<ErrorCode>(
|
||||
error: CommonError<ErrorCode> | undefined,
|
||||
intl: IntlShape,
|
||||
): string {
|
||||
): string | undefined {
|
||||
if (error) {
|
||||
switch (error.code) {
|
||||
case "GRAPHQL_ERROR":
|
||||
|
|
|
@ -14,7 +14,7 @@ const messages = defineMessages({
|
|||
function getDiscountErrorMessage(
|
||||
err: Omit<DiscountErrorFragment, "__typename"> | undefined,
|
||||
intl: IntlShape,
|
||||
): string {
|
||||
): string | undefined {
|
||||
if (err) {
|
||||
switch (err.code) {
|
||||
case DiscountErrorCode.ALREADY_EXISTS:
|
||||
|
|
|
@ -6,7 +6,7 @@ import { getCommonFormFieldErrorMessage } from "./common";
|
|||
function getExportErrorMessage(
|
||||
err: Omit<ExportErrorFragment, "__typename"> | undefined,
|
||||
intl: IntlShape,
|
||||
): string {
|
||||
): string | undefined {
|
||||
return getCommonFormFieldErrorMessage(err, intl);
|
||||
}
|
||||
|
||||
|
|
|
@ -3,20 +3,14 @@ import { UserError } from "@dashboard/types";
|
|||
export function getFieldError<T extends UserError>(
|
||||
errors: T[],
|
||||
field: string,
|
||||
): T {
|
||||
): T | undefined {
|
||||
return errors.find(err => err.field === field);
|
||||
}
|
||||
|
||||
export function getErrors(errors: UserError[]): string[] {
|
||||
return errors
|
||||
.filter(err => ["", null].includes(err.field))
|
||||
.map(err => err.message);
|
||||
}
|
||||
|
||||
export type FormErrors<
|
||||
TField extends string,
|
||||
TError extends UserError
|
||||
> = Record<TField, TError>;
|
||||
> = Record<TField, TError | undefined>;
|
||||
|
||||
export function getFormErrors<TField extends string, TError extends UserError>(
|
||||
fields: TField[],
|
||||
|
@ -25,7 +19,7 @@ export function getFormErrors<TField extends string, TError extends UserError>(
|
|||
return fields.reduce((errs, field) => {
|
||||
errs[field] = getFieldError(errors, field);
|
||||
return errs;
|
||||
}, ({} as unknown) as Record<TField, TError>);
|
||||
}, ({} as unknown) as Record<TField, TError | undefined>);
|
||||
}
|
||||
|
||||
export interface ChannelError {
|
||||
|
|
|
@ -40,7 +40,7 @@ const messages = defineMessages({
|
|||
function getInvoiceErrorMessage(
|
||||
err: InvoiceErrorFragment,
|
||||
intl: IntlShape,
|
||||
): string {
|
||||
): string | undefined {
|
||||
if (err) {
|
||||
switch (err.code) {
|
||||
case InvoiceErrorCode.EMAIL_NOT_SET:
|
||||
|
|
|
@ -6,7 +6,7 @@ import { getCommonFormFieldErrorMessage } from "./common";
|
|||
function getMenuErrorMessage(
|
||||
err: Omit<MenuErrorFragment, "__typename"> | undefined,
|
||||
intl: IntlShape,
|
||||
): string {
|
||||
): string | undefined {
|
||||
return getCommonFormFieldErrorMessage(err, intl);
|
||||
}
|
||||
|
||||
|
|
|
@ -75,7 +75,7 @@ const messages = defineMessages({
|
|||
function getOrderErrorMessage(
|
||||
err: OrderErrorFragment,
|
||||
intl: IntlShape,
|
||||
): string {
|
||||
): string | undefined {
|
||||
if (err) {
|
||||
switch (err.code) {
|
||||
case OrderErrorCode.BILLING_ADDRESS_NOT_SET:
|
||||
|
|
|
@ -29,7 +29,7 @@ const messages = defineMessages({
|
|||
function getPageErrorMessage(
|
||||
err: Omit<PageErrorFragment, "__typename"> | undefined,
|
||||
intl: IntlShape,
|
||||
): string {
|
||||
): string | undefined {
|
||||
if (err) {
|
||||
switch (err.code) {
|
||||
case PageErrorCode.UNIQUE:
|
||||
|
|
|
@ -32,7 +32,7 @@ const messages = defineMessages({
|
|||
function getPermissionGroupErrorMessage(
|
||||
err: PermissionGroupErrorFragment,
|
||||
intl: IntlShape,
|
||||
): string {
|
||||
): string | undefined {
|
||||
if (err) {
|
||||
switch (err.code) {
|
||||
case PermissionGroupErrorCode.ASSIGN_NON_STAFF_MEMBER:
|
||||
|
|
|
@ -17,7 +17,7 @@ const messages = defineMessages({
|
|||
function getPluginErrorMessage(
|
||||
err: PluginErrorFragment,
|
||||
intl: IntlShape,
|
||||
): string {
|
||||
): string | undefined {
|
||||
if (err) {
|
||||
switch (err.code) {
|
||||
case PluginErrorCode.PLUGIN_MISCONFIGURED:
|
||||
|
|
|
@ -83,7 +83,7 @@ function getProductErrorMessage(
|
|||
>
|
||||
| undefined,
|
||||
intl: IntlShape,
|
||||
): string {
|
||||
): string | undefined {
|
||||
if (err) {
|
||||
switch (err.code) {
|
||||
case ProductErrorCode.ATTRIBUTE_ALREADY_ASSIGNED:
|
||||
|
@ -119,7 +119,7 @@ function getProductErrorMessage(
|
|||
export function getProductVariantAttributeErrorMessage(
|
||||
err: Omit<ProductErrorFragment, "__typename"> | undefined,
|
||||
intl: IntlShape,
|
||||
): string {
|
||||
): string | undefined {
|
||||
if (err) {
|
||||
switch (err.code) {
|
||||
case ProductErrorCode.UNIQUE:
|
||||
|
@ -135,7 +135,7 @@ export function getProductVariantAttributeErrorMessage(
|
|||
export function getBulkProductErrorMessage(
|
||||
err: BulkProductErrorFragment | undefined,
|
||||
intl: IntlShape,
|
||||
): string {
|
||||
): string | undefined {
|
||||
if (err?.code === ProductErrorCode.UNIQUE && err.field === "sku") {
|
||||
return intl.formatMessage(messages.skuUnique);
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ const messages = defineMessages({
|
|||
function getShippingErrorMessage(
|
||||
err: Omit<ShippingErrorFragment, "__typename"> | undefined,
|
||||
intl: IntlShape,
|
||||
): string {
|
||||
): string | undefined {
|
||||
if (err) {
|
||||
switch (err.code) {
|
||||
case ShippingErrorCode.ALREADY_EXISTS:
|
||||
|
|
|
@ -14,7 +14,7 @@ const messages = defineMessages({
|
|||
function getShopErrorMessage(
|
||||
err: Omit<ShopErrorFragment, "__typename"> | undefined,
|
||||
intl: IntlShape,
|
||||
): string {
|
||||
): string | undefined {
|
||||
if (err) {
|
||||
switch (err.code) {
|
||||
case ShopErrorCode.ALREADY_EXISTS:
|
||||
|
|
|
@ -6,7 +6,7 @@ import getAccountErrorMessage from "./account";
|
|||
function getStaffErrorMessage(
|
||||
err: StaffErrorFragment,
|
||||
intl: IntlShape,
|
||||
): string {
|
||||
): string | undefined {
|
||||
return getAccountErrorMessage(err, intl);
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ const messages = defineMessages({
|
|||
function getStockErrorMessage(
|
||||
err: Omit<StockErrorFragment, "__typename"> | undefined,
|
||||
intl: IntlShape,
|
||||
): string {
|
||||
): string | undefined {
|
||||
if (err) {
|
||||
switch (err.code) {
|
||||
case StockErrorCode.UNIQUE:
|
||||
|
@ -34,7 +34,7 @@ function getStockErrorMessage(
|
|||
export function getBulkStockErrorMessage(
|
||||
err: Omit<BulkStockErrorFragment, "__typename"> | undefined,
|
||||
intl: IntlShape,
|
||||
): string {
|
||||
): string | undefined {
|
||||
return getProductErrorMessage(err, intl);
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ export type TaxClassError =
|
|||
function getTaxesErrorMessage(
|
||||
err: Omit<TaxClassError, "__typename"> | undefined,
|
||||
intl: IntlShape,
|
||||
): string {
|
||||
): string | undefined {
|
||||
return getCommonFormFieldErrorMessage(err, intl);
|
||||
}
|
||||
|
||||
|
|
|
@ -14,14 +14,14 @@ const messages = defineMessages({
|
|||
function getWarehouseErrorMessage(
|
||||
err: Omit<WarehouseErrorFragment, "__typename"> | undefined,
|
||||
intl: IntlShape,
|
||||
): string {
|
||||
): string | undefined {
|
||||
return getCommonFormFieldErrorMessage(err, intl);
|
||||
}
|
||||
|
||||
export function getWarehouseSlugErrorMessage(
|
||||
err: Omit<WarehouseErrorFragment, "__typename"> | undefined,
|
||||
intl: IntlShape,
|
||||
): string {
|
||||
): string | undefined {
|
||||
if (err) {
|
||||
switch (err.code) {
|
||||
case WarehouseErrorCode.UNIQUE:
|
||||
|
|
|
@ -6,7 +6,7 @@ import { getCommonFormFieldErrorMessage } from "./common";
|
|||
function getWebhookErrorMessage(
|
||||
err: Omit<WebhookErrorFragment, "__typename"> | undefined,
|
||||
intl: IntlShape,
|
||||
): string {
|
||||
): string | undefined {
|
||||
return getCommonFormFieldErrorMessage(err, intl);
|
||||
}
|
||||
|
||||
|
|
|
@ -161,6 +161,6 @@ export function createBooleanField<K extends string>(
|
|||
},
|
||||
],
|
||||
type: FieldType.boolean,
|
||||
value: [defaultValue?.toString()],
|
||||
value: [defaultValue?.toString() ?? ""],
|
||||
};
|
||||
}
|
||||
|
|
|
@ -91,7 +91,7 @@ export function getSingleValueQueryParam<
|
|||
>(param: FilterElement<TKey>, key: TUrlKey) {
|
||||
const { active, value } = param;
|
||||
|
||||
if (!active) {
|
||||
if (!active || !value) {
|
||||
return {
|
||||
[key]: undefined,
|
||||
};
|
||||
|
@ -161,7 +161,7 @@ export function getMinMaxQueryParam<
|
|||
>(param: FilterElement<TKey>, keyFrom: TUrlKey, keyTo: TUrlKey) {
|
||||
const { active, multiple, value } = param;
|
||||
|
||||
if (!active) {
|
||||
if (!active || !value) {
|
||||
return {
|
||||
[keyFrom]: undefined,
|
||||
[keyTo]: undefined,
|
||||
|
|
|
@ -8,7 +8,8 @@ export type GetFilterTabsOutput<TUrlFilters> = Array<UserFilter<TUrlFilters>>;
|
|||
function getFilterTabs<TUrlFilters>(
|
||||
key: string,
|
||||
): GetFilterTabsOutput<TUrlFilters> {
|
||||
return JSON.parse(localStorage.getItem(key)) || [];
|
||||
const filterTabs = localStorage.getItem(key);
|
||||
return filterTabs ? JSON.parse(filterTabs) : [];
|
||||
}
|
||||
|
||||
function saveFilterTab<TUrlFilters>(
|
||||
|
|
|
@ -20,7 +20,7 @@ function createMetadataCreateHandler<T extends MetadataFormData, TError>(
|
|||
return async (data: T) => {
|
||||
const { id, errors } = await create(data);
|
||||
|
||||
if (id === null || !!errors?.length) {
|
||||
if (!id || !!errors?.length) {
|
||||
return errors;
|
||||
}
|
||||
|
||||
|
@ -33,8 +33,8 @@ function createMetadataCreateHandler<T extends MetadataFormData, TError>(
|
|||
},
|
||||
});
|
||||
const updateMetaErrors = [
|
||||
...(updateMetaResult.data.deleteMetadata.errors || []),
|
||||
...(updateMetaResult.data.updateMetadata.errors || []),
|
||||
...(updateMetaResult.data?.deleteMetadata?.errors || []),
|
||||
...(updateMetaResult.data?.updateMetadata?.errors || []),
|
||||
];
|
||||
|
||||
if (updateMetaErrors.length > 0) {
|
||||
|
@ -52,8 +52,8 @@ function createMetadataCreateHandler<T extends MetadataFormData, TError>(
|
|||
});
|
||||
|
||||
const updatePrivateMetaErrors = [
|
||||
...(updatePrivateMetaResult.data.deletePrivateMetadata.errors || []),
|
||||
...(updatePrivateMetaResult.data.updatePrivateMetadata.errors || []),
|
||||
...(updatePrivateMetaResult.data?.deletePrivateMetadata?.errors || []),
|
||||
...(updatePrivateMetaResult.data?.updatePrivateMetadata?.errors || []),
|
||||
];
|
||||
|
||||
if (updatePrivateMetaErrors.length > 0) {
|
||||
|
|
|
@ -62,8 +62,8 @@ function createMetadataUpdateHandler<TData extends MetadataFormData, TError>(
|
|||
});
|
||||
|
||||
const updateMetaErrors = [
|
||||
...(updateMetaResult.data.deleteMetadata.errors || []),
|
||||
...(updateMetaResult.data.updateMetadata.errors || []),
|
||||
...(updateMetaResult.data?.deleteMetadata?.errors || []),
|
||||
...(updateMetaResult.data?.updateMetadata?.errors || []),
|
||||
];
|
||||
|
||||
if (updateMetaErrors.length > 0) {
|
||||
|
@ -84,8 +84,10 @@ function createMetadataUpdateHandler<TData extends MetadataFormData, TError>(
|
|||
});
|
||||
|
||||
const updatePrivateMetaErrors = [
|
||||
...(updatePrivateMetaResult.data.deletePrivateMetadata.errors || []),
|
||||
...(updatePrivateMetaResult.data.updatePrivateMetadata.errors || []),
|
||||
...(updatePrivateMetaResult.data?.deletePrivateMetadata?.errors ||
|
||||
[]),
|
||||
...(updatePrivateMetaResult.data?.updatePrivateMetadata?.errors ||
|
||||
[]),
|
||||
];
|
||||
|
||||
if (updatePrivateMetaErrors.length > 0) {
|
||||
|
|
|
@ -20,6 +20,10 @@ function createMultiAutocompleteSelectHandler(
|
|||
const id = event.target.value;
|
||||
const choice = combinedChoices.find(choice => choice.value === id);
|
||||
|
||||
if (!choice) {
|
||||
return;
|
||||
}
|
||||
|
||||
setSelected(toggle(choice, selected, (a, b) => a.value === b.value));
|
||||
};
|
||||
}
|
||||
|
|
|
@ -8,10 +8,11 @@ import {
|
|||
CountryWithCodeFragment,
|
||||
MetadataInput,
|
||||
MetadataItemFragment,
|
||||
SearchPagesQuery,
|
||||
PageFragment,
|
||||
} from "@dashboard/graphql";
|
||||
import { getFullName } from "@dashboard/misc";
|
||||
import { Node, RelayToFlat, SlugNode, TagNode } from "@dashboard/types";
|
||||
import { Node, SlugNode, TagNode } from "@dashboard/types";
|
||||
import { Choice } from "@saleor/macaw-ui";
|
||||
|
||||
interface Edge<T> {
|
||||
node: T;
|
||||
|
@ -40,8 +41,8 @@ export function mapCountriesToChoices(countries: CountryWithCodeFragment[]) {
|
|||
}
|
||||
|
||||
export function mapPagesToChoices(
|
||||
pages: RelayToFlat<SearchPagesQuery["search"]>,
|
||||
) {
|
||||
pages: Array<Pick<PageFragment, "title" | "id">>,
|
||||
): Choice[] {
|
||||
return pages.map(page => ({
|
||||
label: page.title,
|
||||
value: page.id,
|
||||
|
@ -105,6 +106,10 @@ export function mapMultiValueNodeToChoice<T extends Record<string, any>>(
|
|||
return (nodes as string[]).map(node => ({ label: node, value: node }));
|
||||
}
|
||||
|
||||
if (!key) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return (nodes as T[]).map(node => ({ label: node[key], value: node[key] }));
|
||||
}
|
||||
|
||||
|
@ -120,6 +125,10 @@ export function mapSingleValueNodeToChoice<T extends Record<string, any>>(
|
|||
return (nodes as string[]).map(node => ({ label: node, value: node }));
|
||||
}
|
||||
|
||||
if (!key) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return (nodes as T[]).map(node => ({ label: node[key], value: node[key] }));
|
||||
}
|
||||
|
||||
|
|
|
@ -27,9 +27,11 @@ export type IFlatMenu<TMenuData = {}, TValue = string> = Array<
|
|||
export function validateMenuOptions<TMenuData = {}, TValue = string>(
|
||||
menu: IMenu<TMenuData, TValue>,
|
||||
): boolean {
|
||||
const isValue = (val: TValue | undefined): val is TValue => val !== undefined;
|
||||
|
||||
const values: TValue[] = toFlat(menu)
|
||||
.map(menuItem => menuItem.value)
|
||||
.filter(value => value !== undefined);
|
||||
.filter(isValue);
|
||||
const uniqueValues = Array.from(new Set(values));
|
||||
return uniqueValues.length === values.length;
|
||||
}
|
||||
|
@ -56,9 +58,9 @@ export function getMenuItemByValue<TMenuData = {}, TValue = string>(
|
|||
value: TValue,
|
||||
): IMenuItem<TMenuData, TValue> {
|
||||
const flatMenu = toFlat(menu);
|
||||
const flatMenuItem: IFlatMenuItem<TMenuData, TValue> = flatMenu.find(
|
||||
menuItem => menuItem.value === value,
|
||||
);
|
||||
const flatMenuItem:
|
||||
| IFlatMenuItem<TMenuData, TValue>
|
||||
| undefined = flatMenu.find(menuItem => menuItem.value === value);
|
||||
|
||||
if (flatMenuItem === undefined) {
|
||||
throw new Error(`Value ${value} does not exist in menu`);
|
||||
|
@ -94,6 +96,10 @@ function _walkToRoot<TMenuData = {}, TValue = string>(
|
|||
): IFlatMenu<TMenuData, TValue> {
|
||||
const menuItem = flatMenu.find(menuItem => menuItem.id === parent);
|
||||
|
||||
if (menuItem === undefined) {
|
||||
throw new Error(`Value ${parent} does not exist in menu`);
|
||||
}
|
||||
|
||||
if (menuItem.parent === null) {
|
||||
return [menuItem];
|
||||
}
|
||||
|
@ -107,6 +113,10 @@ export function walkToRoot<TMenuData = {}, TValue = string>(
|
|||
const flatMenu = toFlat(menu);
|
||||
const menuItem = flatMenu.find(menuItem => menuItem.value === value);
|
||||
|
||||
if (menuItem === undefined) {
|
||||
throw new Error(`Value ${value} does not exist in menu`);
|
||||
}
|
||||
|
||||
return (menuItem.parent === null
|
||||
? [menuItem]
|
||||
: [menuItem, ..._walkToRoot(flatMenu, menuItem.parent)]
|
||||
|
@ -116,7 +126,7 @@ export function walkToRoot<TMenuData = {}, TValue = string>(
|
|||
function _toFlat<TMenuData = {}, TValue = string>(
|
||||
menuItem: IMenuItem<TMenuData, TValue>,
|
||||
sort: number,
|
||||
parent: string,
|
||||
parent: string | null,
|
||||
): IFlatMenu<TMenuData, TValue> {
|
||||
const id = parent ? [parent, sort].join(":") : sort.toString();
|
||||
const flatMenuItem: IFlatMenuItem<TMenuData, TValue> = {
|
||||
|
|
|
@ -1,19 +1,27 @@
|
|||
import { EditorCore } from "@dashboard/components/RichTextEditor";
|
||||
import { OutputData } from "@editorjs/editorjs";
|
||||
import { useMemo, useRef, useState } from "react";
|
||||
import { MutableRefObject, useMemo, useRef, useState } from "react";
|
||||
|
||||
interface UseRichTextOptions {
|
||||
initial: string | null;
|
||||
initial: string | null | undefined;
|
||||
loading?: boolean;
|
||||
triggerChange: () => void;
|
||||
}
|
||||
|
||||
interface UseRichTextResult {
|
||||
editorRef: MutableRefObject<EditorCore | null>;
|
||||
handleChange: () => void;
|
||||
getValue: () => Promise<OutputData>;
|
||||
defaultValue: OutputData | undefined;
|
||||
isReadyForMount: boolean;
|
||||
}
|
||||
|
||||
export function useRichText({
|
||||
initial,
|
||||
loading,
|
||||
triggerChange,
|
||||
}: UseRichTextOptions) {
|
||||
const editorRef = useRef<EditorCore>(null);
|
||||
}: UseRichTextOptions): UseRichTextResult {
|
||||
const editorRef = useRef<EditorCore | null>(null);
|
||||
const [isReadyForMount, setIsReadyForMount] = useState(false);
|
||||
|
||||
const handleChange = () => {
|
||||
|
@ -33,7 +41,7 @@ export function useRichText({
|
|||
return;
|
||||
}
|
||||
|
||||
if (initial === undefined) {
|
||||
if (!initial) {
|
||||
setIsReadyForMount(true);
|
||||
return "";
|
||||
}
|
||||
|
|
|
@ -72,7 +72,7 @@ type GetSortQueryField<TUrlField extends string, TSortField extends string> = (
|
|||
type GetSortQueryVariables<
|
||||
TSortField extends string,
|
||||
TParams extends Record<any, any>
|
||||
> = (params: TParams) => SortingInput<TSortField>;
|
||||
> = (params: TParams) => SortingInput<TSortField> | undefined;
|
||||
export function createGetSortQueryVariables<
|
||||
TUrlField extends string,
|
||||
TSortField extends string,
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
export function getFooterColSpanWithBulkActions(
|
||||
arr: any[],
|
||||
numberOfColumns: number,
|
||||
): number {
|
||||
if (arr === undefined || arr.length > 0) {
|
||||
return numberOfColumns + 1;
|
||||
}
|
||||
|
||||
return numberOfColumns;
|
||||
}
|
|
@ -8,7 +8,9 @@ export function stringifyQs(params: unknown, arrayFormat?: string): string {
|
|||
});
|
||||
}
|
||||
|
||||
export function getArrayQueryParam(param: string | string[]): string[] {
|
||||
export function getArrayQueryParam(
|
||||
param: string | string[],
|
||||
): string[] | undefined {
|
||||
if (!param) {
|
||||
return undefined;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue