Moved assert helpers into their own folder + activated some tsconfig strict options
This commit is contained in:
parent
e9950602c4
commit
0ddd46643b
|
@ -3,7 +3,7 @@ import { useSwipeable } from "react-swipeable";
|
||||||
import { layout } from "../../design.config";
|
import { layout } from "../../design.config";
|
||||||
import { Ico, Icon } from "./Ico";
|
import { Ico, Icon } from "./Ico";
|
||||||
import { MainPanel } from "./Panels/MainPanel";
|
import { MainPanel } from "./Panels/MainPanel";
|
||||||
import { isDefined, isUndefined } from "helpers/others";
|
import { isDefined, isUndefined } from "helpers/asserts";
|
||||||
import { cIf, cJoin } from "helpers/className";
|
import { cIf, cJoin } from "helpers/className";
|
||||||
import { OpenGraph, TITLE_PREFIX, TITLE_SEPARATOR } from "helpers/openGraph";
|
import { OpenGraph, TITLE_PREFIX, TITLE_SEPARATOR } from "helpers/openGraph";
|
||||||
import { Ids } from "types/ids";
|
import { Ids } from "types/ids";
|
||||||
|
@ -239,7 +239,7 @@ const ContentPlaceholder = ({ message, icon }: ContentPlaceholderProps): JSX.Ele
|
||||||
className="grid grid-flow-col place-items-center gap-9 rounded-2xl border-2 border-dotted
|
className="grid grid-flow-col place-items-center gap-9 rounded-2xl border-2 border-dotted
|
||||||
border-dark p-8 text-dark opacity-40">
|
border-dark p-8 text-dark opacity-40">
|
||||||
{isDefined(icon) && <Ico icon={icon} className="!text-[300%]" />}
|
{isDefined(icon) && <Ico icon={icon} className="!text-[300%]" />}
|
||||||
<p className={cJoin("w-64 text-2xl", cIf(!isDefined(icon), "text-center"))}>{message}</p>
|
<p className={cJoin("w-64 text-2xl", cIf(isUndefined(icon), "text-center"))}>{message}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { DatePickerFragment } from "graphql/generated";
|
||||||
import { TranslatedProps } from "types/TranslatedProps";
|
import { TranslatedProps } from "types/TranslatedProps";
|
||||||
import { useSmartLanguage } from "hooks/useSmartLanguage";
|
import { useSmartLanguage } from "hooks/useSmartLanguage";
|
||||||
import { DownPressable } from "components/Containers/DownPressable";
|
import { DownPressable } from "components/Containers/DownPressable";
|
||||||
import { isDefined } from "helpers/others";
|
import { isDefined } from "helpers/asserts";
|
||||||
import { cIf, cJoin } from "helpers/className";
|
import { cIf, cJoin } from "helpers/className";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { useCallback } from "react";
|
||||||
import { useBoolean } from "usehooks-ts";
|
import { useBoolean } from "usehooks-ts";
|
||||||
import { TranslatedChroniclePreview } from "./ChroniclePreview";
|
import { TranslatedChroniclePreview } from "./ChroniclePreview";
|
||||||
import { GetChroniclesChaptersQuery } from "graphql/generated";
|
import { GetChroniclesChaptersQuery } from "graphql/generated";
|
||||||
import { filterHasAttributes } from "helpers/others";
|
import { filterHasAttributes } from "helpers/asserts";
|
||||||
import { prettyInlineTitle, prettySlug, sJoin } from "helpers/formatters";
|
import { prettyInlineTitle, prettySlug, sJoin } from "helpers/formatters";
|
||||||
import { Ico, Icon } from "components/Ico";
|
import { Ico, Icon } from "components/Ico";
|
||||||
import { compareDate } from "helpers/date";
|
import { compareDate } from "helpers/date";
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { cJoin, cIf } from "helpers/className";
|
import { cJoin, cIf } from "helpers/className";
|
||||||
import { isDefined, isDefinedAndNotEmpty } from "helpers/others";
|
import { isDefined, isDefinedAndNotEmpty } from "helpers/asserts";
|
||||||
import { atoms } from "contexts/atoms";
|
import { atoms } from "contexts/atoms";
|
||||||
import { useAtomSetter, useAtomPair } from "helpers/atoms";
|
import { useAtomSetter, useAtomPair } from "helpers/atoms";
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { MouseEventHandler, useCallback } from "react";
|
||||||
import { Link } from "./Link";
|
import { Link } from "./Link";
|
||||||
import { Ico, Icon } from "components/Ico";
|
import { Ico, Icon } from "components/Ico";
|
||||||
import { cIf, cJoin } from "helpers/className";
|
import { cIf, cJoin } from "helpers/className";
|
||||||
import { isDefined, isDefinedAndNotEmpty } from "helpers/others";
|
import { isDefined, isDefinedAndNotEmpty } from "helpers/asserts";
|
||||||
import { TranslatedProps } from "types/TranslatedProps";
|
import { TranslatedProps } from "types/TranslatedProps";
|
||||||
import { useSmartLanguage } from "hooks/useSmartLanguage";
|
import { useSmartLanguage } from "hooks/useSmartLanguage";
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { Button } from "./Button";
|
||||||
import { ToolTip } from "components/ToolTip";
|
import { ToolTip } from "components/ToolTip";
|
||||||
import { cJoin } from "helpers/className";
|
import { cJoin } from "helpers/className";
|
||||||
import { ConditionalWrapper, Wrapper } from "helpers/component";
|
import { ConditionalWrapper, Wrapper } from "helpers/component";
|
||||||
import { isDefinedAndNotEmpty } from "helpers/others";
|
import { isDefinedAndNotEmpty } from "helpers/asserts";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ╭─────────────╮
|
* ╭─────────────╮
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import React, { MouseEventHandler } from "react";
|
import React, { MouseEventHandler } from "react";
|
||||||
import NextLink from "next/link";
|
import NextLink from "next/link";
|
||||||
import { ConditionalWrapper, Wrapper } from "helpers/component";
|
import { ConditionalWrapper, Wrapper } from "helpers/component";
|
||||||
import { isDefinedAndNotEmpty } from "helpers/others";
|
import { isDefinedAndNotEmpty } from "helpers/asserts";
|
||||||
import { cIf, cJoin } from "helpers/className";
|
import { cIf, cJoin } from "helpers/className";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { Fragment, useCallback } from "react";
|
import { Fragment, useCallback } from "react";
|
||||||
import { Ico, Icon } from "components/Ico";
|
import { Ico, Icon } from "components/Ico";
|
||||||
import { arrayMove, isDefinedAndNotEmpty } from "helpers/others";
|
import { arrayMove } from "helpers/others";
|
||||||
|
import { isDefinedAndNotEmpty } from "helpers/asserts";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ╭─────────────╮
|
* ╭─────────────╮
|
||||||
|
@ -16,6 +17,14 @@ interface Props {
|
||||||
|
|
||||||
// ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
|
// ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
|
||||||
|
|
||||||
|
interface InsertedLabelProps {
|
||||||
|
label?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const InsertedLabel = ({ label }: InsertedLabelProps) => (
|
||||||
|
<>{isDefinedAndNotEmpty(label) && <p>{label}</p>}</>
|
||||||
|
);
|
||||||
|
|
||||||
export const OrderableList = ({ onChange, items, insertLabels }: Props): JSX.Element => {
|
export const OrderableList = ({ onChange, items, insertLabels }: Props): JSX.Element => {
|
||||||
const updateOrder = useCallback(
|
const updateOrder = useCallback(
|
||||||
(sourceIndex: number, targetIndex: number) => {
|
(sourceIndex: number, targetIndex: number) => {
|
||||||
|
@ -29,9 +38,8 @@ export const OrderableList = ({ onChange, items, insertLabels }: Props): JSX.Ele
|
||||||
<div className="grid gap-2">
|
<div className="grid gap-2">
|
||||||
{items.map((item, index) => (
|
{items.map((item, index) => (
|
||||||
<Fragment key={index}>
|
<Fragment key={index}>
|
||||||
{insertLabels && isDefinedAndNotEmpty(insertLabels[index]?.name) && (
|
<InsertedLabel label={insertLabels?.[index]?.name} />
|
||||||
<p>{insertLabels[index].name}</p>
|
|
||||||
)}
|
|
||||||
<div
|
<div
|
||||||
onDragStart={(event) => {
|
onDragStart={(event) => {
|
||||||
const source = event.target as HTMLElement;
|
const source = event.target as HTMLElement;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { Ico, Icon } from "components/Ico";
|
import { Ico, Icon } from "components/Ico";
|
||||||
import { cIf, cJoin } from "helpers/className";
|
import { cIf, cJoin } from "helpers/className";
|
||||||
import { isDefinedAndNotEmpty } from "helpers/others";
|
import { isDefinedAndNotEmpty } from "helpers/asserts";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ╭─────────────╮
|
* ╭─────────────╮
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { cIf, cJoin } from "helpers/className";
|
import { cIf, cJoin } from "helpers/className";
|
||||||
import { isDefinedAndNotEmpty } from "helpers/others";
|
import { isDefinedAndNotEmpty } from "helpers/asserts";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ╭─────────────╮
|
* ╭─────────────╮
|
||||||
|
|
|
@ -9,7 +9,7 @@ import { useFullscreen } from "hooks/useFullscreen";
|
||||||
import { Ids } from "types/ids";
|
import { Ids } from "types/ids";
|
||||||
import { UploadImageFragment } from "graphql/generated";
|
import { UploadImageFragment } from "graphql/generated";
|
||||||
import { ImageQuality } from "helpers/img";
|
import { ImageQuality } from "helpers/img";
|
||||||
import { isDefined } from "helpers/others";
|
import { isDefined } from "helpers/asserts";
|
||||||
import { useAtomGetter } from "helpers/atoms";
|
import { useAtomGetter } from "helpers/atoms";
|
||||||
import { atoms } from "contexts/atoms";
|
import { atoms } from "contexts/atoms";
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { InsetBox } from "components/Containers/InsetBox";
|
||||||
import { cIf, cJoin } from "helpers/className";
|
import { cIf, cJoin } from "helpers/className";
|
||||||
import { slugify } from "helpers/formatters";
|
import { slugify } from "helpers/formatters";
|
||||||
import { getAssetURL, ImageQuality } from "helpers/img";
|
import { getAssetURL, ImageQuality } from "helpers/img";
|
||||||
import { isDefined, isDefinedAndNotEmpty, isUndefined } from "helpers/others";
|
import { isDefined, isDefinedAndNotEmpty, isUndefined } from "helpers/asserts";
|
||||||
import { AnchorShare } from "components/AnchorShare";
|
import { AnchorShare } from "components/AnchorShare";
|
||||||
import { useIntersectionList } from "hooks/useIntersectionList";
|
import { useIntersectionList } from "hooks/useIntersectionList";
|
||||||
import { Ico, Icon } from "components/Ico";
|
import { Ico, Icon } from "components/Ico";
|
||||||
|
@ -459,7 +459,7 @@ const getTocFromMarkdawn = (text: string, title?: string): TocInterface => {
|
||||||
h5 = -1;
|
h5 = -1;
|
||||||
scenebreak = 0;
|
scenebreak = 0;
|
||||||
} else if (h2 >= 0 && line.startsWith('<Header level="3"')) {
|
} else if (h2 >= 0 && line.startsWith('<Header level="3"')) {
|
||||||
toc.children[h2].children.push({
|
toc.children[h2]?.children.push({
|
||||||
title: getTitle(line),
|
title: getTitle(line),
|
||||||
slug: getSlug(line),
|
slug: getSlug(line),
|
||||||
children: [],
|
children: [],
|
||||||
|
@ -469,7 +469,7 @@ const getTocFromMarkdawn = (text: string, title?: string): TocInterface => {
|
||||||
h5 = -1;
|
h5 = -1;
|
||||||
scenebreak = 0;
|
scenebreak = 0;
|
||||||
} else if (h3 >= 0 && line.startsWith('<Header level="4"')) {
|
} else if (h3 >= 0 && line.startsWith('<Header level="4"')) {
|
||||||
toc.children[h2].children[h3].children.push({
|
toc.children[h2]?.children[h3]?.children.push({
|
||||||
title: getTitle(line),
|
title: getTitle(line),
|
||||||
slug: getSlug(line),
|
slug: getSlug(line),
|
||||||
children: [],
|
children: [],
|
||||||
|
@ -478,7 +478,7 @@ const getTocFromMarkdawn = (text: string, title?: string): TocInterface => {
|
||||||
h5 = -1;
|
h5 = -1;
|
||||||
scenebreak = 0;
|
scenebreak = 0;
|
||||||
} else if (h4 >= 0 && line.startsWith('<Header level="5"')) {
|
} else if (h4 >= 0 && line.startsWith('<Header level="5"')) {
|
||||||
toc.children[h2].children[h3].children[h4].children.push({
|
toc.children[h2]?.children[h3]?.children[h4]?.children.push({
|
||||||
title: getTitle(line),
|
title: getTitle(line),
|
||||||
slug: getSlug(line),
|
slug: getSlug(line),
|
||||||
children: [],
|
children: [],
|
||||||
|
@ -486,7 +486,7 @@ const getTocFromMarkdawn = (text: string, title?: string): TocInterface => {
|
||||||
h5++;
|
h5++;
|
||||||
scenebreak = 0;
|
scenebreak = 0;
|
||||||
} else if (h5 >= 0 && line.startsWith('<Header level="6"')) {
|
} else if (h5 >= 0 && line.startsWith('<Header level="6"')) {
|
||||||
toc.children[h2].children[h3].children[h4].children[h5].children.push({
|
toc.children[h2]?.children[h3]?.children[h4]?.children[h5]?.children.push({
|
||||||
title: getTitle(line),
|
title: getTitle(line),
|
||||||
slug: getSlug(line),
|
slug: getSlug(line),
|
||||||
children: [],
|
children: [],
|
||||||
|
@ -502,13 +502,13 @@ const getTocFromMarkdawn = (text: string, title?: string): TocInterface => {
|
||||||
};
|
};
|
||||||
|
|
||||||
if (h5 >= 0) {
|
if (h5 >= 0) {
|
||||||
toc.children[h2].children[h3].children[h4].children[h5].children.push(child);
|
toc.children[h2]?.children[h3]?.children[h4]?.children[h5]?.children.push(child);
|
||||||
} else if (h4 >= 0) {
|
} else if (h4 >= 0) {
|
||||||
toc.children[h2].children[h3].children[h4].children.push(child);
|
toc.children[h2]?.children[h3]?.children[h4]?.children.push(child);
|
||||||
} else if (h3 >= 0) {
|
} else if (h3 >= 0) {
|
||||||
toc.children[h2].children[h3].children.push(child);
|
toc.children[h2]?.children[h3]?.children.push(child);
|
||||||
} else if (h2 >= 0) {
|
} else if (h2 >= 0) {
|
||||||
toc.children[h2].children.push(child);
|
toc.children[h2]?.children.push(child);
|
||||||
} else {
|
} else {
|
||||||
toc.children.push(child);
|
toc.children.push(child);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { MouseEventHandler, useCallback } from "react";
|
||||||
import { Ico, Icon } from "components/Ico";
|
import { Ico, Icon } from "components/Ico";
|
||||||
import { ToolTip } from "components/ToolTip";
|
import { ToolTip } from "components/ToolTip";
|
||||||
import { cIf, cJoin } from "helpers/className";
|
import { cIf, cJoin } from "helpers/className";
|
||||||
import { isDefinedAndNotEmpty } from "helpers/others";
|
import { isDefinedAndNotEmpty } from "helpers/asserts";
|
||||||
import { TranslatedProps } from "types/TranslatedProps";
|
import { TranslatedProps } from "types/TranslatedProps";
|
||||||
import { useSmartLanguage } from "hooks/useSmartLanguage";
|
import { useSmartLanguage } from "hooks/useSmartLanguage";
|
||||||
import { DownPressable } from "components/Containers/DownPressable";
|
import { DownPressable } from "components/Containers/DownPressable";
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { Ico, Icon } from "components/Ico";
|
import { Ico, Icon } from "components/Ico";
|
||||||
import { isDefinedAndNotEmpty } from "helpers/others";
|
import { isDefinedAndNotEmpty } from "helpers/asserts";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ╭─────────────╮
|
* ╭─────────────╮
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { Icon } from "components/Ico";
|
||||||
import { Button } from "components/Inputs/Button";
|
import { Button } from "components/Inputs/Button";
|
||||||
import { TranslatedProps } from "types/TranslatedProps";
|
import { TranslatedProps } from "types/TranslatedProps";
|
||||||
import { useSmartLanguage } from "hooks/useSmartLanguage";
|
import { useSmartLanguage } from "hooks/useSmartLanguage";
|
||||||
import { isDefined } from "helpers/others";
|
import { isUndefined } from "helpers/asserts";
|
||||||
import { atoms } from "contexts/atoms";
|
import { atoms } from "contexts/atoms";
|
||||||
import { useAtomGetter } from "helpers/atoms";
|
import { useAtomGetter } from "helpers/atoms";
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ export const ReturnButton = ({ href, title, displayOnlyOn, className }: Props):
|
||||||
<>
|
<>
|
||||||
{((is3ColumnsLayout && displayOnlyOn === "3ColumnsLayout") ||
|
{((is3ColumnsLayout && displayOnlyOn === "3ColumnsLayout") ||
|
||||||
(!is3ColumnsLayout && displayOnlyOn === "1ColumnLayout") ||
|
(!is3ColumnsLayout && displayOnlyOn === "1ColumnLayout") ||
|
||||||
!isDefined(displayOnlyOn)) && (
|
isUndefined(displayOnlyOn)) && (
|
||||||
<div className={className}>
|
<div className={className}>
|
||||||
<Button href={href} text={`${langui.return_to} ${title}`} icon={Icon.NavigateBefore} />
|
<Button href={href} text={`${langui.return_to} ${title}`} icon={Icon.NavigateBefore} />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { NavOption } from "components/PanelComponents/NavOption";
|
||||||
import { ToolTip } from "components/ToolTip";
|
import { ToolTip } from "components/ToolTip";
|
||||||
import { Icon } from "components/Ico";
|
import { Icon } from "components/Ico";
|
||||||
import { cIf, cJoin } from "helpers/className";
|
import { cIf, cJoin } from "helpers/className";
|
||||||
import { isDefinedAndNotEmpty } from "helpers/others";
|
import { isDefinedAndNotEmpty } from "helpers/asserts";
|
||||||
import { Link } from "components/Inputs/Link";
|
import { Link } from "components/Inputs/Link";
|
||||||
import { sendAnalytics } from "helpers/analytics";
|
import { sendAnalytics } from "helpers/analytics";
|
||||||
import { ColoredSvg } from "components/ColoredSvg";
|
import { ColoredSvg } from "components/ColoredSvg";
|
||||||
|
|
|
@ -10,7 +10,7 @@ import { Popup } from "components/Containers/Popup";
|
||||||
import { sendAnalytics } from "helpers/analytics";
|
import { sendAnalytics } from "helpers/analytics";
|
||||||
import { cJoin, cIf } from "helpers/className";
|
import { cJoin, cIf } from "helpers/className";
|
||||||
import { prettyLanguage } from "helpers/formatters";
|
import { prettyLanguage } from "helpers/formatters";
|
||||||
import { filterHasAttributes, isDefined } from "helpers/others";
|
import { filterHasAttributes, isDefined } from "helpers/asserts";
|
||||||
import { atoms } from "contexts/atoms";
|
import { atoms } from "contexts/atoms";
|
||||||
import { useAtomGetter, useAtomPair } from "helpers/atoms";
|
import { useAtomGetter, useAtomPair } from "helpers/atoms";
|
||||||
import { ThemeMode } from "contexts/settings";
|
import { ThemeMode } from "contexts/settings";
|
||||||
|
@ -39,15 +39,10 @@ export const SettingsPopup = (): JSX.Element => {
|
||||||
);
|
);
|
||||||
|
|
||||||
const [currencySelect, setCurrencySelect] = useState<number>(-1);
|
const [currencySelect, setCurrencySelect] = useState<number>(-1);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isDefined(currency)) setCurrencySelect(currencyOptions.indexOf(currency));
|
if (isDefined(currency)) setCurrencySelect(currencyOptions.indexOf(currency));
|
||||||
}, [currency, currencyOptions]);
|
}, [currency, currencyOptions]);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (currencySelect >= 0) setCurrency(currencyOptions[currencySelect]);
|
|
||||||
}, [currencyOptions, currencySelect, setCurrency]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Popup
|
<Popup
|
||||||
isVisible={isSettingsOpened}
|
isVisible={isSettingsOpened}
|
||||||
|
@ -134,8 +129,11 @@ export const SettingsPopup = (): JSX.Element => {
|
||||||
options={currencyOptions}
|
options={currencyOptions}
|
||||||
value={currencySelect}
|
value={currencySelect}
|
||||||
onChange={(newCurrency) => {
|
onChange={(newCurrency) => {
|
||||||
setCurrencySelect(newCurrency);
|
const newCurrencyName = currencyOptions[newCurrency];
|
||||||
|
if (isDefined(newCurrencyName)) {
|
||||||
|
setCurrency(newCurrencyName);
|
||||||
sendAnalytics("Settings", `Change currency (${currencyOptions[newCurrency]})}`);
|
sendAnalytics("Settings", `Change currency (${currencyOptions[newCurrency]})}`);
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
className="w-28"
|
className="w-28"
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -11,7 +11,8 @@ import { ThumbnailHeader } from "./ThumbnailHeader";
|
||||||
import { ToolTip } from "./ToolTip";
|
import { ToolTip } from "./ToolTip";
|
||||||
import { useSmartLanguage } from "hooks/useSmartLanguage";
|
import { useSmartLanguage } from "hooks/useSmartLanguage";
|
||||||
import { PostWithTranslations } from "types/types";
|
import { PostWithTranslations } from "types/types";
|
||||||
import { filterHasAttributes, getStatusDescription } from "helpers/others";
|
import { getStatusDescription } from "helpers/others";
|
||||||
|
import { filterHasAttributes } from "helpers/asserts";
|
||||||
import { prettySlug } from "helpers/formatters";
|
import { prettySlug } from "helpers/formatters";
|
||||||
import { atoms } from "contexts/atoms";
|
import { atoms } from "contexts/atoms";
|
||||||
import { useAtomGetter } from "helpers/atoms";
|
import { useAtomGetter } from "helpers/atoms";
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { ImageQuality } from "helpers/img";
|
||||||
import { TranslatedProps } from "types/TranslatedProps";
|
import { TranslatedProps } from "types/TranslatedProps";
|
||||||
import { useSmartLanguage } from "hooks/useSmartLanguage";
|
import { useSmartLanguage } from "hooks/useSmartLanguage";
|
||||||
import { cIf, cJoin } from "helpers/className";
|
import { cIf, cJoin } from "helpers/className";
|
||||||
import { isDefined } from "helpers/others";
|
import { isDefined } from "helpers/asserts";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ╭─────────────╮
|
* ╭─────────────╮
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { ToolTip } from "./ToolTip";
|
||||||
import { Chip } from "components/Chip";
|
import { Chip } from "components/Chip";
|
||||||
import { RecorderChipFragment } from "graphql/generated";
|
import { RecorderChipFragment } from "graphql/generated";
|
||||||
import { ImageQuality } from "helpers/img";
|
import { ImageQuality } from "helpers/img";
|
||||||
import { filterHasAttributes } from "helpers/others";
|
import { filterHasAttributes } from "helpers/asserts";
|
||||||
import { atoms } from "contexts/atoms";
|
import { atoms } from "contexts/atoms";
|
||||||
import { useAtomGetter } from "helpers/atoms";
|
import { useAtomGetter } from "helpers/atoms";
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { Chip } from "./Chip";
|
||||||
import { PageSelector } from "./Inputs/PageSelector";
|
import { PageSelector } from "./Inputs/PageSelector";
|
||||||
import { Ico, Icon } from "./Ico";
|
import { Ico, Icon } from "./Ico";
|
||||||
import { cJoin } from "helpers/className";
|
import { cJoin } from "helpers/className";
|
||||||
import { isDefined, isDefinedAndNotEmpty } from "helpers/others";
|
import { isDefined, isDefinedAndNotEmpty } from "helpers/asserts";
|
||||||
import { useScrollTopOnChange } from "hooks/useScrollTopOnChange";
|
import { useScrollTopOnChange } from "hooks/useScrollTopOnChange";
|
||||||
import { Ids } from "types/ids";
|
import { Ids } from "types/ids";
|
||||||
import { atoms } from "contexts/atoms";
|
import { atoms } from "contexts/atoms";
|
||||||
|
@ -95,17 +95,17 @@ export const SmartList = <T,>({
|
||||||
const memo: Group<T>[] = [];
|
const memo: Group<T>[] = [];
|
||||||
|
|
||||||
sortedItem.forEach((item) => {
|
sortedItem.forEach((item) => {
|
||||||
groupingFunction(item).forEach((category) => {
|
groupingFunction(item).forEach((groupName) => {
|
||||||
const index = memo.findIndex((group) => group.name === category);
|
const group = memo.find((elem) => elem.name === groupName);
|
||||||
if (index === -1) {
|
if (isDefined(group)) {
|
||||||
|
group.items.push(item);
|
||||||
|
group.totalCount += groupCountingFunction(item);
|
||||||
|
} else {
|
||||||
memo.push({
|
memo.push({
|
||||||
name: category,
|
name: groupName,
|
||||||
items: [item],
|
items: [item],
|
||||||
totalCount: groupCountingFunction(item),
|
totalCount: groupCountingFunction(item),
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
memo[index].items.push(item);
|
|
||||||
memo[index].totalCount += groupCountingFunction(item);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -170,7 +170,7 @@ export const SmartList = <T,>({
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="mb-8">
|
<div className="mb-8">
|
||||||
{pages[page]?.length > 0 ? (
|
{(pages[page]?.length ?? 0) > 0 ? (
|
||||||
pages[page]?.map(
|
pages[page]?.map(
|
||||||
(group) =>
|
(group) =>
|
||||||
group.items.length > 0 && (
|
group.items.length > 0 && (
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { Markdawn } from "components/Markdown/Markdawn";
|
||||||
import { GetContentTextQuery, UploadImageFragment } from "graphql/generated";
|
import { GetContentTextQuery, UploadImageFragment } from "graphql/generated";
|
||||||
import { prettyInlineTitle, prettySlug, slugify } from "helpers/formatters";
|
import { prettyInlineTitle, prettySlug, slugify } from "helpers/formatters";
|
||||||
import { ImageQuality } from "helpers/img";
|
import { ImageQuality } from "helpers/img";
|
||||||
import { filterHasAttributes } from "helpers/others";
|
import { filterHasAttributes } from "helpers/asserts";
|
||||||
import { useAtomGetter } from "helpers/atoms";
|
import { useAtomGetter } from "helpers/atoms";
|
||||||
import { atoms } from "contexts/atoms";
|
import { atoms } from "contexts/atoms";
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { useEffectOnce } from "usehooks-ts";
|
||||||
import { atom } from "jotai";
|
import { atom } from "jotai";
|
||||||
import { UploadImageFragment } from "graphql/generated";
|
import { UploadImageFragment } from "graphql/generated";
|
||||||
import { LightBox } from "components/LightBox";
|
import { LightBox } from "components/LightBox";
|
||||||
import { filterDefined } from "helpers/others";
|
import { filterDefined } from "helpers/asserts";
|
||||||
import { atomPairing, useAtomSetter } from "helpers/atoms";
|
import { atomPairing, useAtomSetter } from "helpers/atoms";
|
||||||
|
|
||||||
const lightBoxAtom = atomPairing(
|
const lightBoxAtom = atomPairing(
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { atom } from "jotai";
|
||||||
import { atomWithStorage } from "jotai/utils";
|
import { atomWithStorage } from "jotai/utils";
|
||||||
import { atomPairing, useAtomGetter, useAtomPair } from "helpers/atoms";
|
import { atomPairing, useAtomGetter, useAtomPair } from "helpers/atoms";
|
||||||
import { getDefaultPreferredLanguages } from "helpers/locales";
|
import { getDefaultPreferredLanguages } from "helpers/locales";
|
||||||
import { isDefined, isDefinedAndNotEmpty } from "helpers/others";
|
import { isDefined, isDefinedAndNotEmpty } from "helpers/asserts";
|
||||||
import { usePrefersDarkMode } from "hooks/useMediaQuery";
|
import { usePrefersDarkMode } from "hooks/useMediaQuery";
|
||||||
|
|
||||||
export enum ThemeMode {
|
export enum ThemeMode {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { useLayoutEffect } from "react";
|
import { useLayoutEffect } from "react";
|
||||||
import { isDefined } from "helpers/others";
|
import { isDefined } from "helpers/asserts";
|
||||||
import { useIsWebkit } from "hooks/useIsWebkit";
|
import { useIsWebkit } from "hooks/useIsWebkit";
|
||||||
|
|
||||||
export const useWebkitFixes = (): void => {
|
export const useWebkitFixes = (): void => {
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { PostWithTranslations } from "types/types";
|
||||||
import { getOpenGraph } from "helpers/openGraph";
|
import { getOpenGraph } from "helpers/openGraph";
|
||||||
import { prettyDate, prettySlug } from "helpers/formatters";
|
import { prettyDate, prettySlug } from "helpers/formatters";
|
||||||
import { getDefaultPreferredLanguages, staticSmartLanguage } from "helpers/locales";
|
import { getDefaultPreferredLanguages, staticSmartLanguage } from "helpers/locales";
|
||||||
import { filterHasAttributes, isDefined } from "helpers/others";
|
import { filterHasAttributes, isDefined } from "helpers/asserts";
|
||||||
import { getDescription } from "helpers/description";
|
import { getDescription } from "helpers/description";
|
||||||
import { AppLayoutRequired } from "components/AppLayout";
|
import { AppLayoutRequired } from "components/AppLayout";
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ export const getPostStaticProps =
|
||||||
if (
|
if (
|
||||||
post.posts?.data &&
|
post.posts?.data &&
|
||||||
post.posts.data.length > 0 &&
|
post.posts.data.length > 0 &&
|
||||||
post.posts.data[0].attributes?.translations &&
|
post.posts.data[0]?.attributes?.translations &&
|
||||||
isDefined(context.locale) &&
|
isDefined(context.locale) &&
|
||||||
isDefined(context.locales)
|
isDefined(context.locales)
|
||||||
) {
|
) {
|
||||||
|
|
|
@ -0,0 +1,79 @@
|
||||||
|
type JoinDot<K extends string, P extends string> = `${K}${"" extends K ? "" : "."}${P}`;
|
||||||
|
|
||||||
|
type PathDot<T, Acc extends string = ""> = T extends object
|
||||||
|
? {
|
||||||
|
[K in keyof T]: K extends string ? JoinDot<Acc, K> | PathDot<T[K], JoinDot<Acc, K>> : never;
|
||||||
|
}[keyof T]
|
||||||
|
: Acc;
|
||||||
|
|
||||||
|
type PathHead<T extends unknown[]> = T extends [infer head]
|
||||||
|
? head
|
||||||
|
: // eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
T extends [infer head, ...infer rest]
|
||||||
|
? head
|
||||||
|
: "";
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
type PathRest<T extends unknown[]> = T extends [infer head, ...infer rest]
|
||||||
|
? rest extends []
|
||||||
|
? never
|
||||||
|
: rest
|
||||||
|
: never;
|
||||||
|
|
||||||
|
type PathLast<T extends unknown[]> = T["length"] extends 1 ? true : false;
|
||||||
|
|
||||||
|
type Recursive<T, Path extends unknown[]> = PathHead<Path> extends keyof T
|
||||||
|
? Omit<T, PathHead<Path>> & {
|
||||||
|
[P in PathHead<Path>]-?: PathLast<Path> extends true
|
||||||
|
? NonNullable<T[P]>
|
||||||
|
: Recursive<NonNullable<T[P]>, PathRest<Path>>;
|
||||||
|
}
|
||||||
|
: T;
|
||||||
|
|
||||||
|
type Split<Str, Acc extends string[] = []> = Str extends `${infer Head}.${infer Rest}`
|
||||||
|
? Split<Rest, [...Acc, Head]>
|
||||||
|
: Str extends `${infer Last}`
|
||||||
|
? [...Acc, Last]
|
||||||
|
: never;
|
||||||
|
|
||||||
|
export type SelectiveNonNullable<T, P extends PathDot<T>> = Recursive<NonNullable<T>, Split<P>>;
|
||||||
|
|
||||||
|
export const isDefined = <T>(t: T): t is NonNullable<T> => t !== null && t !== undefined;
|
||||||
|
|
||||||
|
export const isUndefined = <T>(t: T | null | undefined): t is null | undefined => !isDefined(t);
|
||||||
|
|
||||||
|
export const isDefinedAndNotEmpty = (string: string | null | undefined): string is string =>
|
||||||
|
isDefined(string) && string.length > 0;
|
||||||
|
|
||||||
|
export const filterDefined = <T>(t: T[] | null | undefined): NonNullable<T>[] =>
|
||||||
|
isUndefined(t) ? [] : (t.filter((item) => isDefined(item)) as NonNullable<T>[]);
|
||||||
|
|
||||||
|
export const filterHasAttributes = <T, P extends PathDot<T>>(
|
||||||
|
t: T[] | null | undefined,
|
||||||
|
paths: readonly P[]
|
||||||
|
): SelectiveNonNullable<T, typeof paths[number]>[] =>
|
||||||
|
isDefined(t)
|
||||||
|
? (t.filter((item) => hasAttributes(item, paths)) as unknown as SelectiveNonNullable<
|
||||||
|
T,
|
||||||
|
typeof paths[number]
|
||||||
|
>[])
|
||||||
|
: [];
|
||||||
|
|
||||||
|
const hasAttributes = <T>(item: T, paths: readonly PathDot<T>[]): boolean =>
|
||||||
|
isDefined(item) && paths.every((path) => hasAttribute(item, path));
|
||||||
|
|
||||||
|
const hasAttribute = <T>(item: T, path: string): boolean => {
|
||||||
|
if (isDefined(item)) {
|
||||||
|
const [head, ...rest] = path.split(".");
|
||||||
|
if (isDefined(head) && Object.keys(item).includes(head)) {
|
||||||
|
const attribute = head as keyof T;
|
||||||
|
if (isDefined(item[attribute])) {
|
||||||
|
if (rest.length > 0) {
|
||||||
|
return hasAttribute(item[attribute], rest.join("."));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
|
@ -1,4 +1,4 @@
|
||||||
import { isDefined } from "./others";
|
import { isDefined } from "./asserts";
|
||||||
|
|
||||||
export interface Wrapper {
|
export interface Wrapper {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { isUndefined } from "./others";
|
import { isUndefined } from "./asserts";
|
||||||
import { DatePickerFragment } from "graphql/generated";
|
import { DatePickerFragment } from "graphql/generated";
|
||||||
|
|
||||||
export const compareDate = (
|
export const compareDate = (
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { filterDefined, isDefined, isDefinedAndNotEmpty } from "./others";
|
import { filterDefined, isDefined, isDefinedAndNotEmpty } from "./asserts";
|
||||||
|
|
||||||
export const getDescription = (
|
export const getDescription = (
|
||||||
description: string | null | undefined,
|
description: string | null | undefined,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { convertPrice } from "./numbers";
|
import { convertPrice } from "./numbers";
|
||||||
import { isDefinedAndNotEmpty, isUndefined } from "./others";
|
import { isDefinedAndNotEmpty, isUndefined } from "./asserts";
|
||||||
import { datePickerToDate } from "./date";
|
import { datePickerToDate } from "./date";
|
||||||
import { Currencies, Languages, Langui } from "./localData";
|
import { Currencies, Languages, Langui } from "./localData";
|
||||||
import { DatePickerFragment, PricePickerFragment } from "graphql/generated";
|
import { DatePickerFragment, PricePickerFragment } from "graphql/generated";
|
||||||
|
@ -180,7 +180,7 @@ export const prettyItemSubType = (
|
||||||
case "ComponentMetadataGame":
|
case "ComponentMetadataGame":
|
||||||
return metadata.platforms?.data &&
|
return metadata.platforms?.data &&
|
||||||
metadata.platforms.data.length > 0 &&
|
metadata.platforms.data.length > 0 &&
|
||||||
metadata.platforms.data[0].attributes
|
metadata.platforms.data[0]?.attributes
|
||||||
? metadata.platforms.data[0].attributes.short
|
? metadata.platforms.data[0].attributes.short
|
||||||
: "";
|
: "";
|
||||||
case "ComponentMetadataGroup": {
|
case "ComponentMetadataGroup": {
|
||||||
|
|
|
@ -27,13 +27,11 @@ const imageQualityProperties: Record<ImageQuality, ImageProperties> = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getAssetFilename = (path: string): string => {
|
export const getAssetFilename = (path: string): string => {
|
||||||
let result = path.split("/");
|
// /uploads/329_7f41d09a98.webp -> 329_7f41d09a98.webp
|
||||||
result = result[result.length - 1].split(".");
|
let result = path.substring(path.lastIndexOf("/") + 1);
|
||||||
result = result
|
// 329_7f41d09a98.webp -> 329
|
||||||
.splice(0, result.length - 1)
|
result = result.substring(0, result.indexOf("_"));
|
||||||
.join(".")
|
return result;
|
||||||
.split("_");
|
|
||||||
return result[0];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getAssetURL = (url: string, quality: ImageQuality): string => {
|
export const getAssetURL = (url: string, quality: ImageQuality): string => {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { isDefined } from "./others";
|
import { isDefined } from "./asserts";
|
||||||
|
|
||||||
export const isUntangibleGroupItem = (
|
export const isUntangibleGroupItem = (
|
||||||
metadata:
|
metadata:
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { isDefined } from "./others";
|
import { isDefined } from "./asserts";
|
||||||
|
|
||||||
export const getDefaultPreferredLanguages = (routerLocal: string, locales: string[]): string[] => {
|
export const getDefaultPreferredLanguages = (routerLocal: string, locales: string[]): string[] => {
|
||||||
let defaultPreferredLanguages: string[] = [];
|
let defaultPreferredLanguages: string[] = [];
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { OgImage, getImgSizesByQuality, ImageQuality, getAssetURL } from "./img";
|
import { OgImage, getImgSizesByQuality, ImageQuality, getAssetURL } from "./img";
|
||||||
import { isDefinedAndNotEmpty } from "./others";
|
import { isDefinedAndNotEmpty } from "./asserts";
|
||||||
import { Langui } from "./localData";
|
import { Langui } from "./localData";
|
||||||
import { UploadImageFragment } from "graphql/generated";
|
import { UploadImageFragment } from "graphql/generated";
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { PathDot, SelectiveNonNullable } from "../types/SelectiveNonNullable";
|
|
||||||
import { Langui } from "./localData";
|
import { Langui } from "./localData";
|
||||||
|
import { isDefined } from "./asserts";
|
||||||
import {
|
import {
|
||||||
Enum_Componentsetstextset_Status,
|
Enum_Componentsetstextset_Status,
|
||||||
GetLibraryItemQuery,
|
GetLibraryItemQuery,
|
||||||
|
@ -45,47 +45,6 @@ export const getStatusDescription = (status: string, langui: Langui): string | n
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const isDefined = <T>(t: T): t is NonNullable<T> => t !== null && t !== undefined;
|
|
||||||
|
|
||||||
export const isUndefined = <T>(t: T | null | undefined): t is null | undefined =>
|
|
||||||
t === null || t === undefined;
|
|
||||||
|
|
||||||
export const isDefinedAndNotEmpty = (string: string | null | undefined): string is string =>
|
|
||||||
isDefined(string) && string.length > 0;
|
|
||||||
|
|
||||||
export const filterDefined = <T>(t: T[] | null | undefined): NonNullable<T>[] =>
|
|
||||||
isUndefined(t) ? [] : (t.filter((item) => isDefined(item)) as NonNullable<T>[]);
|
|
||||||
|
|
||||||
export const filterHasAttributes = <T, P extends PathDot<T>>(
|
|
||||||
t: T[] | null | undefined,
|
|
||||||
paths: readonly P[]
|
|
||||||
): SelectiveNonNullable<T, typeof paths[number]>[] =>
|
|
||||||
isDefined(t)
|
|
||||||
? (t.filter((item) => hasAttributes(item, paths)) as unknown as SelectiveNonNullable<
|
|
||||||
T,
|
|
||||||
typeof paths[number]
|
|
||||||
>[])
|
|
||||||
: [];
|
|
||||||
|
|
||||||
const hasAttributes = <T>(item: T, paths: readonly PathDot<T>[]): boolean =>
|
|
||||||
isDefined(item) && paths.every((path) => hasAttribute(item, path));
|
|
||||||
|
|
||||||
const hasAttribute = <T>(item: T, path: string): boolean => {
|
|
||||||
if (isDefined(item)) {
|
|
||||||
const [head, ...rest] = path.split(".");
|
|
||||||
if (Object.keys(item).includes(head)) {
|
|
||||||
const attribute = head as keyof T;
|
|
||||||
if (isDefined(item[attribute])) {
|
|
||||||
if (rest.length > 0) {
|
|
||||||
return hasAttribute(item[attribute], rest.join("."));
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const iterateMap = <K, V, U>(
|
export const iterateMap = <K, V, U>(
|
||||||
map: Map<K, V>,
|
map: Map<K, V>,
|
||||||
callbackfn: (key: K, value: V, index: number) => U,
|
callbackfn: (key: K, value: V, index: number) => U,
|
||||||
|
@ -99,7 +58,10 @@ export const iterateMap = <K, V, U>(
|
||||||
};
|
};
|
||||||
|
|
||||||
export const arrayMove = <T>(arr: T[], sourceIndex: number, targetIndex: number): T[] => {
|
export const arrayMove = <T>(arr: T[], sourceIndex: number, targetIndex: number): T[] => {
|
||||||
arr.splice(targetIndex, 0, arr.splice(sourceIndex, 1)[0]);
|
const sourceItem = arr.splice(sourceIndex, 1)[0];
|
||||||
|
if (isDefined(sourceItem)) {
|
||||||
|
arr.splice(targetIndex, 0, sourceItem);
|
||||||
|
}
|
||||||
return arr;
|
return arr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { isDefinedAndNotEmpty } from "./others";
|
import { isDefinedAndNotEmpty } from "./asserts";
|
||||||
|
|
||||||
export const prettyTerminalUnderlinedTitle = (string: string | null | undefined): string =>
|
export const prettyTerminalUnderlinedTitle = (string: string | null | undefined): string =>
|
||||||
isDefinedAndNotEmpty(string)
|
isDefinedAndNotEmpty(string)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { useCallback, useEffect, useState } from "react";
|
import { useCallback, useEffect, useState } from "react";
|
||||||
import { useIsClient } from "usehooks-ts";
|
import { useIsClient } from "usehooks-ts";
|
||||||
import { isDefined } from "helpers/others";
|
import { isDefined } from "helpers/asserts";
|
||||||
|
|
||||||
export const useFullscreen = (
|
export const useFullscreen = (
|
||||||
id: string
|
id: string
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { useCallback, useEffect, useState } from "react";
|
||||||
import { throttle } from "throttle-debounce";
|
import { throttle } from "throttle-debounce";
|
||||||
import { useIsClient } from "usehooks-ts";
|
import { useIsClient } from "usehooks-ts";
|
||||||
import { useOnScroll } from "./useOnScroll";
|
import { useOnScroll } from "./useOnScroll";
|
||||||
import { isDefined } from "helpers/others";
|
import { isDefined, isUndefined } from "helpers/asserts";
|
||||||
import { Ids } from "types/ids";
|
import { Ids } from "types/ids";
|
||||||
|
|
||||||
export const useIntersectionList = (ids: string[]): number => {
|
export const useIntersectionList = (ids: string[]): number => {
|
||||||
|
@ -16,21 +16,21 @@ export const useIntersectionList = (ids: string[]): number => {
|
||||||
(scroll: number) => {
|
(scroll: number) => {
|
||||||
console.log("useIntersectionList");
|
console.log("useIntersectionList");
|
||||||
|
|
||||||
if (!isDefined(contentPanel)) {
|
if (isUndefined(contentPanel)) {
|
||||||
setCurrentIntersection(-1);
|
setCurrentIntersection(-1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let idIndex = 0; idIndex < ids.length; idIndex++) {
|
for (const [index, id] of [...ids].reverse().entries()) {
|
||||||
const elem = document.getElementById(ids[ids.length - 1 - idIndex]);
|
const elem = document.getElementById(id);
|
||||||
const halfScreenOffset = window.screen.height / 2;
|
const halfScreenOffset = window.screen.height / 2;
|
||||||
|
|
||||||
if (isDefined(elem) && scroll > elem.offsetTop - halfScreenOffset) {
|
if (isDefined(elem) && scroll > elem.offsetTop - halfScreenOffset) {
|
||||||
setCurrentIntersection(ids.length - 1 - idIndex);
|
const unreversedIndex = ids.length - 1 - index;
|
||||||
|
setCurrentIntersection(unreversedIndex);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setCurrentIntersection(-1);
|
|
||||||
},
|
},
|
||||||
[ids, contentPanel]
|
[ids, contentPanel]
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import { useIsClient } from "usehooks-ts";
|
import { useIsClient } from "usehooks-ts";
|
||||||
import { isDefined } from "helpers/others";
|
import { isDefined } from "helpers/asserts";
|
||||||
|
|
||||||
export const useOnResize = (
|
export const useOnResize = (
|
||||||
id: string,
|
id: string,
|
||||||
|
@ -11,9 +11,12 @@ export const useOnResize = (
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log("[useOnResize]", id);
|
console.log("[useOnResize]", id);
|
||||||
const elem = isClient ? document.querySelector(`#${id}`) : null;
|
const elem = isClient ? document.querySelector(`#${id}`) : null;
|
||||||
const ro = new ResizeObserver((resizeObserverEntry) =>
|
const ro = new ResizeObserver((resizeObserverEntry) => {
|
||||||
onResize(resizeObserverEntry[0].contentRect.width, resizeObserverEntry[0].contentRect.height)
|
const entry = resizeObserverEntry[0];
|
||||||
);
|
if (isDefined(entry)) {
|
||||||
|
onResize(entry.contentRect.width, entry.contentRect.height);
|
||||||
|
}
|
||||||
|
});
|
||||||
if (isDefined(elem)) {
|
if (isDefined(elem)) {
|
||||||
ro.observe(elem);
|
ro.observe(elem);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { useCounter } from "usehooks-ts";
|
import { useCounter } from "usehooks-ts";
|
||||||
import { isDefined } from "helpers/others";
|
import { isDefined } from "helpers/asserts";
|
||||||
|
|
||||||
const NUM_RETRIES = 10;
|
const NUM_RETRIES = 10;
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { useEffect, useMemo, useState } from "react";
|
import { useEffect, useMemo, useState } from "react";
|
||||||
import { LanguageSwitcher } from "components/Inputs/LanguageSwitcher";
|
import { LanguageSwitcher } from "components/Inputs/LanguageSwitcher";
|
||||||
import { filterDefined, isDefined } from "helpers/others";
|
import { filterDefined, isDefined } from "helpers/asserts";
|
||||||
import { getPreferredLanguage } from "helpers/locales";
|
import { getPreferredLanguage } from "helpers/locales";
|
||||||
import { atoms } from "contexts/atoms";
|
import { atoms } from "contexts/atoms";
|
||||||
import { useAtomGetter } from "helpers/atoms";
|
import { useAtomGetter } from "helpers/atoms";
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import type { NextApiRequest, NextApiResponse } from "next";
|
import type { NextApiRequest, NextApiResponse } from "next";
|
||||||
import { i18n } from "../../../next.config";
|
import { i18n } from "../../../next.config";
|
||||||
import { cartesianProduct, filterHasAttributes, isDefined } from "helpers/others";
|
import { cartesianProduct } from "helpers/others";
|
||||||
|
import { filterHasAttributes, isDefined } from "helpers/asserts";
|
||||||
import { fetchLocalData } from "graphql/fetchLocalData";
|
import { fetchLocalData } from "graphql/fetchLocalData";
|
||||||
import { getReadySdk } from "graphql/sdk";
|
import { getReadySdk } from "graphql/sdk";
|
||||||
|
|
||||||
|
@ -183,7 +184,7 @@ const Revalidate = async (
|
||||||
language_code: "en",
|
language_code: "en",
|
||||||
slug: body.entry.slug,
|
slug: body.entry.slug,
|
||||||
});
|
});
|
||||||
filterHasAttributes(libraryItem.libraryItems?.data[0].attributes?.subitem_of?.data, [
|
filterHasAttributes(libraryItem.libraryItems?.data[0]?.attributes?.subitem_of?.data, [
|
||||||
"attributes.slug",
|
"attributes.slug",
|
||||||
] as const).forEach((parentItem) => paths.push(`/library/${parentItem.attributes.slug}`));
|
] as const).forEach((parentItem) => paths.push(`/library/${parentItem.attributes.slug}`));
|
||||||
}
|
}
|
||||||
|
@ -202,12 +203,12 @@ const Revalidate = async (
|
||||||
slug: body.entry.slug,
|
slug: body.entry.slug,
|
||||||
});
|
});
|
||||||
|
|
||||||
const folderSlug = content.contents?.data[0].attributes?.folder?.data?.attributes?.slug;
|
const folderSlug = content.contents?.data[0]?.attributes?.folder?.data?.attributes?.slug;
|
||||||
if (folderSlug) {
|
if (folderSlug) {
|
||||||
paths.push(`/contents/folder/${folderSlug}`);
|
paths.push(`/contents/folder/${folderSlug}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
filterHasAttributes(content.contents?.data[0].attributes?.ranged_contents?.data, [
|
filterHasAttributes(content.contents?.data[0]?.attributes?.ranged_contents?.data, [
|
||||||
"attributes.library_item.data.attributes.slug",
|
"attributes.library_item.data.attributes.slug",
|
||||||
] as const).forEach((ranged_content) => {
|
] as const).forEach((ranged_content) => {
|
||||||
const parentSlug = ranged_content.attributes.library_item.data.attributes.slug;
|
const parentSlug = ranged_content.attributes.library_item.data.attributes.slug;
|
||||||
|
@ -260,16 +261,16 @@ const Revalidate = async (
|
||||||
slug: body.entry.slug,
|
slug: body.entry.slug,
|
||||||
});
|
});
|
||||||
const parentSlug =
|
const parentSlug =
|
||||||
folder.contentsFolders?.data[0].attributes?.parent_folder?.data?.attributes?.slug;
|
folder.contentsFolders?.data[0]?.attributes?.parent_folder?.data?.attributes?.slug;
|
||||||
if (parentSlug) {
|
if (parentSlug) {
|
||||||
paths.push(`/contents/folder/${parentSlug}`);
|
paths.push(`/contents/folder/${parentSlug}`);
|
||||||
}
|
}
|
||||||
filterHasAttributes(folder.contentsFolders?.data[0].attributes?.subfolders?.data, [
|
filterHasAttributes(folder.contentsFolders?.data[0]?.attributes?.subfolders?.data, [
|
||||||
"attributes.slug",
|
"attributes.slug",
|
||||||
] as const).forEach((subfolder) =>
|
] as const).forEach((subfolder) =>
|
||||||
paths.push(`/contents/folder/${subfolder.attributes.slug}`)
|
paths.push(`/contents/folder/${subfolder.attributes.slug}`)
|
||||||
);
|
);
|
||||||
filterHasAttributes(folder.contentsFolders?.data[0].attributes?.contents?.data, [
|
filterHasAttributes(folder.contentsFolders?.data[0]?.attributes?.contents?.data, [
|
||||||
"attributes.slug",
|
"attributes.slug",
|
||||||
] as const).forEach((content) => paths.push(`/contents/${content.attributes.slug}`));
|
] as const).forEach((content) => paths.push(`/contents/${content.attributes.slug}`));
|
||||||
}
|
}
|
||||||
|
@ -308,7 +309,7 @@ const Revalidate = async (
|
||||||
paths.push(`/archives/videos`);
|
paths.push(`/archives/videos`);
|
||||||
paths.push(`/archives/videos/v/${body.entry.uid}`);
|
paths.push(`/archives/videos/v/${body.entry.uid}`);
|
||||||
const video = await sdk.getVideo({ uid: body.entry.uid });
|
const video = await sdk.getVideo({ uid: body.entry.uid });
|
||||||
const channelUid = video.videos?.data[0].attributes?.channel?.data?.attributes?.uid;
|
const channelUid = video.videos?.data[0]?.attributes?.channel?.data?.attributes?.uid;
|
||||||
if (isDefined(channelUid)) {
|
if (isDefined(channelUid)) {
|
||||||
paths.push(`/archives/videos/c/${channelUid}`);
|
paths.push(`/archives/videos/c/${channelUid}`);
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ import { getVideoThumbnailURL } from "helpers/videos";
|
||||||
import { Icon } from "components/Ico";
|
import { Icon } from "components/Ico";
|
||||||
import { useDeviceSupportsHover } from "hooks/useMediaQuery";
|
import { useDeviceSupportsHover } from "hooks/useMediaQuery";
|
||||||
import { WithLabel } from "components/Inputs/WithLabel";
|
import { WithLabel } from "components/Inputs/WithLabel";
|
||||||
import { filterHasAttributes, isDefined } from "helpers/others";
|
import { filterHasAttributes, isDefined } from "helpers/asserts";
|
||||||
import { getOpenGraph } from "helpers/openGraph";
|
import { getOpenGraph } from "helpers/openGraph";
|
||||||
import { compareDate } from "helpers/date";
|
import { compareDate } from "helpers/date";
|
||||||
import { HorizontalLine } from "components/HorizontalLine";
|
import { HorizontalLine } from "components/HorizontalLine";
|
||||||
|
@ -136,7 +136,7 @@ export const getStaticProps: GetStaticProps = async (context) => {
|
||||||
const channel = await sdk.getVideoChannel({
|
const channel = await sdk.getVideoChannel({
|
||||||
channel: context.params && isDefined(context.params.uid) ? context.params.uid.toString() : "",
|
channel: context.params && isDefined(context.params.uid) ? context.params.uid.toString() : "",
|
||||||
});
|
});
|
||||||
if (!channel.videoChannels?.data[0].attributes) return { notFound: true };
|
if (!channel.videoChannels?.data[0]?.attributes) return { notFound: true };
|
||||||
|
|
||||||
channel.videoChannels.data[0].attributes.videos?.data
|
channel.videoChannels.data[0].attributes.videos?.data
|
||||||
.sort((a, b) => compareDate(a.attributes?.published_date, b.attributes?.published_date))
|
.sort((a, b) => compareDate(a.attributes?.published_date, b.attributes?.published_date))
|
||||||
|
|
|
@ -14,7 +14,7 @@ import { SubPanel } from "components/Containers/SubPanel";
|
||||||
import { PreviewCard } from "components/PreviewCard";
|
import { PreviewCard } from "components/PreviewCard";
|
||||||
import { GetVideosPreviewQuery } from "graphql/generated";
|
import { GetVideosPreviewQuery } from "graphql/generated";
|
||||||
import { getReadySdk } from "graphql/sdk";
|
import { getReadySdk } from "graphql/sdk";
|
||||||
import { filterHasAttributes } from "helpers/others";
|
import { filterHasAttributes } from "helpers/asserts";
|
||||||
import { getVideoThumbnailURL } from "helpers/videos";
|
import { getVideoThumbnailURL } from "helpers/videos";
|
||||||
import { useDeviceSupportsHover } from "hooks/useMediaQuery";
|
import { useDeviceSupportsHover } from "hooks/useMediaQuery";
|
||||||
import { getOpenGraph } from "helpers/openGraph";
|
import { getOpenGraph } from "helpers/openGraph";
|
||||||
|
|
|
@ -12,7 +12,7 @@ import { SubPanel } from "components/Containers/SubPanel";
|
||||||
import { GetVideoQuery } from "graphql/generated";
|
import { GetVideoQuery } from "graphql/generated";
|
||||||
import { getReadySdk } from "graphql/sdk";
|
import { getReadySdk } from "graphql/sdk";
|
||||||
import { prettyDate, prettyShortenNumber } from "helpers/formatters";
|
import { prettyDate, prettyShortenNumber } from "helpers/formatters";
|
||||||
import { filterHasAttributes, isDefined } from "helpers/others";
|
import { filterHasAttributes, isDefined } from "helpers/asserts";
|
||||||
import { getVideoFile } from "helpers/videos";
|
import { getVideoFile } from "helpers/videos";
|
||||||
import { getOpenGraph } from "helpers/openGraph";
|
import { getOpenGraph } from "helpers/openGraph";
|
||||||
import { getLangui } from "graphql/fetchLocalData";
|
import { getLangui } from "graphql/fetchLocalData";
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { GetStaticProps, GetStaticPaths, GetStaticPathsResult } from "next";
|
import { GetStaticProps, GetStaticPaths, GetStaticPathsResult } from "next";
|
||||||
import { useCallback, useMemo } from "react";
|
import { useCallback } from "react";
|
||||||
import { getReadySdk } from "graphql/sdk";
|
import { getReadySdk } from "graphql/sdk";
|
||||||
import { isDefined, filterHasAttributes } from "helpers/others";
|
import { isDefined, filterHasAttributes } from "helpers/asserts";
|
||||||
import { ChronicleWithTranslations } from "types/types";
|
import { ChronicleWithTranslations } from "types/types";
|
||||||
import { AppLayout, AppLayoutRequired } from "components/AppLayout";
|
import { AppLayout, AppLayoutRequired } from "components/AppLayout";
|
||||||
import { useSmartLanguage } from "hooks/useSmartLanguage";
|
import { useSmartLanguage } from "hooks/useSmartLanguage";
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { SubPanel } from "components/Containers/SubPanel";
|
||||||
import { Icon } from "components/Ico";
|
import { Icon } from "components/Ico";
|
||||||
import { getReadySdk } from "graphql/sdk";
|
import { getReadySdk } from "graphql/sdk";
|
||||||
import { GetChroniclesChaptersQuery } from "graphql/generated";
|
import { GetChroniclesChaptersQuery } from "graphql/generated";
|
||||||
import { filterHasAttributes } from "helpers/others";
|
import { filterHasAttributes } from "helpers/asserts";
|
||||||
import { prettySlug } from "helpers/formatters";
|
import { prettySlug } from "helpers/formatters";
|
||||||
import { getOpenGraph } from "helpers/openGraph";
|
import { getOpenGraph } from "helpers/openGraph";
|
||||||
import { TranslatedChroniclesList } from "components/Chronicles/ChroniclesList";
|
import { TranslatedChroniclesList } from "components/Chronicles/ChroniclesList";
|
||||||
|
|
|
@ -21,7 +21,8 @@ import {
|
||||||
prettySlug,
|
prettySlug,
|
||||||
} from "helpers/formatters";
|
} from "helpers/formatters";
|
||||||
import { isUntangibleGroupItem } from "helpers/libraryItem";
|
import { isUntangibleGroupItem } from "helpers/libraryItem";
|
||||||
import { filterHasAttributes, getStatusDescription, isDefinedAndNotEmpty } from "helpers/others";
|
import { getStatusDescription } from "helpers/others";
|
||||||
|
import { filterHasAttributes, isDefinedAndNotEmpty } from "helpers/asserts";
|
||||||
import { ContentWithTranslations } from "types/types";
|
import { ContentWithTranslations } from "types/types";
|
||||||
import { useScrollTopOnChange } from "hooks/useScrollTopOnChange";
|
import { useScrollTopOnChange } from "hooks/useScrollTopOnChange";
|
||||||
import { useSmartLanguage } from "hooks/useSmartLanguage";
|
import { useSmartLanguage } from "hooks/useSmartLanguage";
|
||||||
|
@ -466,7 +467,7 @@ type FolderContents = NonNullable<
|
||||||
const getPreviousContent = (contents: FolderContents, currentSlug: string) => {
|
const getPreviousContent = (contents: FolderContents, currentSlug: string) => {
|
||||||
for (let index = 0; index < contents.length; index++) {
|
for (let index = 0; index < contents.length; index++) {
|
||||||
const content = contents[index];
|
const content = contents[index];
|
||||||
if (content.attributes?.slug === currentSlug && index > 0) {
|
if (content?.attributes?.slug === currentSlug && index > 0) {
|
||||||
return contents[index - 1];
|
return contents[index - 1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -478,7 +479,7 @@ const getPreviousContent = (contents: FolderContents, currentSlug: string) => {
|
||||||
const getNextContent = (contents: FolderContents, currentSlug: string) => {
|
const getNextContent = (contents: FolderContents, currentSlug: string) => {
|
||||||
for (let index = 0; index < contents.length; index++) {
|
for (let index = 0; index < contents.length; index++) {
|
||||||
const content = contents[index];
|
const content = contents[index];
|
||||||
if (content.attributes?.slug === currentSlug && index < contents.length - 1) {
|
if (content?.attributes?.slug === currentSlug && index < contents.length - 1) {
|
||||||
return contents[index + 1];
|
return contents[index + 1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,10 +15,14 @@ import { WithLabel } from "components/Inputs/WithLabel";
|
||||||
import { Button } from "components/Inputs/Button";
|
import { Button } from "components/Inputs/Button";
|
||||||
import { useDeviceSupportsHover } from "hooks/useMediaQuery";
|
import { useDeviceSupportsHover } from "hooks/useMediaQuery";
|
||||||
import { Icon } from "components/Ico";
|
import { Icon } from "components/Ico";
|
||||||
import { filterDefined, filterHasAttributes, isDefinedAndNotEmpty } from "helpers/others";
|
import {
|
||||||
|
filterDefined,
|
||||||
|
filterHasAttributes,
|
||||||
|
isDefinedAndNotEmpty,
|
||||||
|
SelectiveNonNullable,
|
||||||
|
} from "helpers/asserts";
|
||||||
import { GetContentsQuery } from "graphql/generated";
|
import { GetContentsQuery } from "graphql/generated";
|
||||||
import { SmartList } from "components/SmartList";
|
import { SmartList } from "components/SmartList";
|
||||||
import { SelectiveNonNullable } from "types/SelectiveNonNullable";
|
|
||||||
import { getOpenGraph } from "helpers/openGraph";
|
import { getOpenGraph } from "helpers/openGraph";
|
||||||
import { HorizontalLine } from "components/HorizontalLine";
|
import { HorizontalLine } from "components/HorizontalLine";
|
||||||
import { TranslatedPreviewCard } from "components/PreviewCard";
|
import { TranslatedPreviewCard } from "components/PreviewCard";
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { AppLayout, AppLayoutRequired } from "components/AppLayout";
|
||||||
import { ContentPanel, ContentPanelWidthSizes } from "components/Containers/ContentPanel";
|
import { ContentPanel, ContentPanelWidthSizes } from "components/Containers/ContentPanel";
|
||||||
import { getOpenGraph } from "helpers/openGraph";
|
import { getOpenGraph } from "helpers/openGraph";
|
||||||
import { getReadySdk } from "graphql/sdk";
|
import { getReadySdk } from "graphql/sdk";
|
||||||
import { filterHasAttributes } from "helpers/others";
|
import { filterHasAttributes } from "helpers/asserts";
|
||||||
import { GetContentsFolderQuery } from "graphql/generated";
|
import { GetContentsFolderQuery } from "graphql/generated";
|
||||||
import { getDefaultPreferredLanguages, staticSmartLanguage } from "helpers/locales";
|
import { getDefaultPreferredLanguages, staticSmartLanguage } from "helpers/locales";
|
||||||
import { prettySlug } from "helpers/formatters";
|
import { prettySlug } from "helpers/formatters";
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { ContentPanel, ContentPanelWidthSizes } from "components/Containers/Cont
|
||||||
import { ToolTip } from "components/ToolTip";
|
import { ToolTip } from "components/ToolTip";
|
||||||
import { DevGetContentsQuery } from "graphql/generated";
|
import { DevGetContentsQuery } from "graphql/generated";
|
||||||
import { getReadySdk } from "graphql/sdk";
|
import { getReadySdk } from "graphql/sdk";
|
||||||
import { filterDefined, filterHasAttributes } from "helpers/others";
|
import { filterDefined, filterHasAttributes } from "helpers/asserts";
|
||||||
import { Report, Severity } from "types/Report";
|
import { Report, Severity } from "types/Report";
|
||||||
import { getOpenGraph } from "helpers/openGraph";
|
import { getOpenGraph } from "helpers/openGraph";
|
||||||
import { getLangui } from "graphql/fetchLocalData";
|
import { getLangui } from "graphql/fetchLocalData";
|
||||||
|
@ -61,7 +61,8 @@ const CheckupContents = ({ contents, ...otherProps }: Props): JSX.Element => {
|
||||||
? "bg-[#fff344] !opacity-100"
|
? "bg-[#fff344] !opacity-100"
|
||||||
: ""
|
: ""
|
||||||
}
|
}
|
||||||
text={Severity[line.severity]}
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||||
|
text={Severity[line.severity] ?? "Unknown"}
|
||||||
/>
|
/>
|
||||||
<ToolTip content={line.recommandation} placement="left">
|
<ToolTip content={line.recommandation} placement="left">
|
||||||
<p>{line.description}</p>
|
<p>{line.description}</p>
|
||||||
|
|
|
@ -63,7 +63,8 @@ const CheckupLibraryItems = ({ libraryItems, ...otherProps }: Props): JSX.Elemen
|
||||||
? "bg-[#fff344] !opacity-100"
|
? "bg-[#fff344] !opacity-100"
|
||||||
: ""
|
: ""
|
||||||
}
|
}
|
||||||
text={Severity[line.severity]}
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||||
|
text={Severity[line.severity] ?? "Unknown"}
|
||||||
/>
|
/>
|
||||||
<ToolTip content={line.recommandation} placement="left">
|
<ToolTip content={line.recommandation} placement="left">
|
||||||
<p>{line.description}</p>
|
<p>{line.description}</p>
|
||||||
|
|
|
@ -431,12 +431,7 @@ const DesignSystem = (props: Props): JSX.Element => {
|
||||||
value={sliderState}
|
value={sliderState}
|
||||||
max={100}
|
max={100}
|
||||||
onChange={(event) => {
|
onChange={(event) => {
|
||||||
let value = 0;
|
const value = (Array.isArray(event) ? event[0] : event) ?? 0;
|
||||||
if (Array.isArray(event)) {
|
|
||||||
value = event[0];
|
|
||||||
} else {
|
|
||||||
value = event;
|
|
||||||
}
|
|
||||||
setSliderState(() => value);
|
setSliderState(() => value);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -32,7 +32,7 @@ const replaceSelection = (
|
||||||
const swapChar = (char: string, swaps: string[]): string => {
|
const swapChar = (char: string, swaps: string[]): string => {
|
||||||
for (let index = 0; index < swaps.length; index++) {
|
for (let index = 0; index < swaps.length; index++) {
|
||||||
if (char === swaps[index]) {
|
if (char === swaps[index]) {
|
||||||
return swaps[(index + 1) % swaps.length];
|
return swaps[(index + 1) % swaps.length] ?? char;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return char;
|
return char;
|
||||||
|
|
|
@ -31,13 +31,13 @@ import {
|
||||||
} from "helpers/formatters";
|
} from "helpers/formatters";
|
||||||
import { ImageQuality } from "helpers/img";
|
import { ImageQuality } from "helpers/img";
|
||||||
import { convertMmToInch } from "helpers/numbers";
|
import { convertMmToInch } from "helpers/numbers";
|
||||||
|
import { sortRangedContent } from "helpers/others";
|
||||||
import {
|
import {
|
||||||
filterDefined,
|
filterDefined,
|
||||||
filterHasAttributes,
|
filterHasAttributes,
|
||||||
isDefined,
|
isDefined,
|
||||||
isDefinedAndNotEmpty,
|
isDefinedAndNotEmpty,
|
||||||
sortRangedContent,
|
} from "helpers/asserts";
|
||||||
} from "helpers/others";
|
|
||||||
import { useScrollTopOnChange } from "hooks/useScrollTopOnChange";
|
import { useScrollTopOnChange } from "hooks/useScrollTopOnChange";
|
||||||
import { isUntangibleGroupItem } from "helpers/libraryItem";
|
import { isUntangibleGroupItem } from "helpers/libraryItem";
|
||||||
import { useDeviceSupportsHover } from "hooks/useMediaQuery";
|
import { useDeviceSupportsHover } from "hooks/useMediaQuery";
|
||||||
|
|
|
@ -11,13 +11,8 @@ import {
|
||||||
UploadImageFragment,
|
UploadImageFragment,
|
||||||
} from "graphql/generated";
|
} from "graphql/generated";
|
||||||
import { getReadySdk } from "graphql/sdk";
|
import { getReadySdk } from "graphql/sdk";
|
||||||
import {
|
import { getStatusDescription, sortRangedContent } from "helpers/others";
|
||||||
filterHasAttributes,
|
import { filterHasAttributes, isDefined, isDefinedAndNotEmpty } from "helpers/asserts";
|
||||||
getStatusDescription,
|
|
||||||
isDefined,
|
|
||||||
isDefinedAndNotEmpty,
|
|
||||||
sortRangedContent,
|
|
||||||
} from "helpers/others";
|
|
||||||
import { getOpenGraph } from "helpers/openGraph";
|
import { getOpenGraph } from "helpers/openGraph";
|
||||||
import { getLangui } from "graphql/fetchLocalData";
|
import { getLangui } from "graphql/fetchLocalData";
|
||||||
import { ContentPanel, ContentPanelWidthSizes } from "components/Containers/ContentPanel";
|
import { ContentPanel, ContentPanelWidthSizes } from "components/Containers/ContentPanel";
|
||||||
|
@ -305,12 +300,7 @@ const LibrarySlug = ({
|
||||||
max={10}
|
max={10}
|
||||||
value={filterSettings.teint * 10}
|
value={filterSettings.teint * 10}
|
||||||
onChange={(event) => {
|
onChange={(event) => {
|
||||||
let value = 0;
|
const value = (Array.isArray(event) ? event[0] : event) ?? 0;
|
||||||
if (Array.isArray(event)) {
|
|
||||||
value = event[0];
|
|
||||||
} else {
|
|
||||||
value = event;
|
|
||||||
}
|
|
||||||
setTeint(value / 10);
|
setTeint(value / 10);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
@ -390,7 +380,7 @@ const LibrarySlug = ({
|
||||||
? CUSTOM_DARK_DROPSHADOW
|
? CUSTOM_DARK_DROPSHADOW
|
||||||
: CUSTOM_LIGHT_DROPSHADOW,
|
: CUSTOM_LIGHT_DROPSHADOW,
|
||||||
}}>
|
}}>
|
||||||
{effectiveDisplayMode === "single" ? (
|
{effectiveDisplayMode === "single" && isDefined(firstPage) ? (
|
||||||
<div
|
<div
|
||||||
className={cJoin(
|
className={cJoin(
|
||||||
"relative grid grid-flow-col",
|
"relative grid grid-flow-col",
|
||||||
|
@ -412,6 +402,8 @@ const LibrarySlug = ({
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
|
isDefined(firstPage) &&
|
||||||
|
isDefined(secondPage) && (
|
||||||
<>
|
<>
|
||||||
<div
|
<div
|
||||||
className={cJoin(
|
className={cJoin(
|
||||||
|
@ -476,6 +468,7 @@ const LibrarySlug = ({
|
||||||
<PageFilters page="right" bookType={bookType} options={filterSettings} />
|
<PageFilters page="right" bookType={bookType} options={filterSettings} />
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
)
|
||||||
)}
|
)}
|
||||||
</TransformComponent>
|
</TransformComponent>
|
||||||
</TransformWrapper>
|
</TransformWrapper>
|
||||||
|
@ -498,12 +491,7 @@ const LibrarySlug = ({
|
||||||
max={pages.length - 1}
|
max={pages.length - 1}
|
||||||
value={currentPageIndex - 1}
|
value={currentPageIndex - 1}
|
||||||
onChange={(event) => {
|
onChange={(event) => {
|
||||||
let value = 0;
|
const value = (Array.isArray(event) ? event[0] : event) ?? 0;
|
||||||
if (Array.isArray(event)) {
|
|
||||||
value = event[0];
|
|
||||||
} else {
|
|
||||||
value = event;
|
|
||||||
}
|
|
||||||
changeCurrentPageIndex(() => value);
|
changeCurrentPageIndex(() => value);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
@ -657,7 +645,7 @@ export const getStaticProps: GetStaticProps = async (context) => {
|
||||||
bookType,
|
bookType,
|
||||||
pageWidth,
|
pageWidth,
|
||||||
itemSlug: item.libraryItems.data[0].attributes.slug,
|
itemSlug: item.libraryItems.data[0].attributes.slug,
|
||||||
pageRatio: `${pages[0].width ?? 21} / ${pages[0].height ?? 29.7}`,
|
pageRatio: `${pages[0]?.width ?? 21} / ${pages[0]?.height ?? 29.7}`,
|
||||||
openGraph: getOpenGraph(
|
openGraph: getOpenGraph(
|
||||||
langui,
|
langui,
|
||||||
item.libraryItems.data[0].attributes.title,
|
item.libraryItems.data[0].attributes.title,
|
||||||
|
|
|
@ -21,10 +21,15 @@ import { isUntangibleGroupItem } from "helpers/libraryItem";
|
||||||
import { PreviewCard } from "components/PreviewCard";
|
import { PreviewCard } from "components/PreviewCard";
|
||||||
import { useDeviceSupportsHover } from "hooks/useMediaQuery";
|
import { useDeviceSupportsHover } from "hooks/useMediaQuery";
|
||||||
import { ButtonGroup } from "components/Inputs/ButtonGroup";
|
import { ButtonGroup } from "components/Inputs/ButtonGroup";
|
||||||
import { filterHasAttributes, isDefined, isDefinedAndNotEmpty, isUndefined } from "helpers/others";
|
import {
|
||||||
|
filterHasAttributes,
|
||||||
|
isDefined,
|
||||||
|
isDefinedAndNotEmpty,
|
||||||
|
isUndefined,
|
||||||
|
SelectiveNonNullable,
|
||||||
|
} from "helpers/asserts";
|
||||||
import { convertPrice } from "helpers/numbers";
|
import { convertPrice } from "helpers/numbers";
|
||||||
import { SmartList } from "components/SmartList";
|
import { SmartList } from "components/SmartList";
|
||||||
import { SelectiveNonNullable } from "types/SelectiveNonNullable";
|
|
||||||
import { getOpenGraph } from "helpers/openGraph";
|
import { getOpenGraph } from "helpers/openGraph";
|
||||||
import { compareDate } from "helpers/date";
|
import { compareDate } from "helpers/date";
|
||||||
import { HorizontalLine } from "components/HorizontalLine";
|
import { HorizontalLine } from "components/HorizontalLine";
|
||||||
|
@ -142,11 +147,14 @@ const Library = ({ items, ...otherProps }: Props): JSX.Element => {
|
||||||
return naturalCompare(titleA, titleB);
|
return naturalCompare(titleA, titleB);
|
||||||
}
|
}
|
||||||
case 1: {
|
case 1: {
|
||||||
|
const commonCurrency = currencies[0];
|
||||||
|
if (isUndefined(commonCurrency)) return 0;
|
||||||
|
|
||||||
const priceA = a.attributes.price
|
const priceA = a.attributes.price
|
||||||
? convertPrice(a.attributes.price, currencies[0])
|
? convertPrice(a.attributes.price, commonCurrency)
|
||||||
: Infinity;
|
: Infinity;
|
||||||
const priceB = b.attributes.price
|
const priceB = b.attributes.price
|
||||||
? convertPrice(b.attributes.price, currencies[0])
|
? convertPrice(b.attributes.price, commonCurrency)
|
||||||
: Infinity;
|
: Infinity;
|
||||||
return priceA - priceB;
|
return priceA - priceB;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { NextRouter, useRouter } from "next/router";
|
||||||
import { PostPage } from "components/PostPage";
|
import { PostPage } from "components/PostPage";
|
||||||
import { getPostStaticProps, PostStaticProps } from "graphql/getPostStaticProps";
|
import { getPostStaticProps, PostStaticProps } from "graphql/getPostStaticProps";
|
||||||
import { getReadySdk } from "graphql/sdk";
|
import { getReadySdk } from "graphql/sdk";
|
||||||
import { filterHasAttributes, isDefined, isDefinedAndNotEmpty } from "helpers/others";
|
import { filterHasAttributes, isDefined, isDefinedAndNotEmpty } from "helpers/asserts";
|
||||||
import { Terminal } from "components/Cli/Terminal";
|
import { Terminal } from "components/Cli/Terminal";
|
||||||
import { PostWithTranslations } from "types/types";
|
import { PostWithTranslations } from "types/types";
|
||||||
import { getDefaultPreferredLanguages, staticSmartLanguage } from "helpers/locales";
|
import { getDefaultPreferredLanguages, staticSmartLanguage } from "helpers/locales";
|
||||||
|
|
|
@ -14,7 +14,7 @@ import { WithLabel } from "components/Inputs/WithLabel";
|
||||||
import { TextInput } from "components/Inputs/TextInput";
|
import { TextInput } from "components/Inputs/TextInput";
|
||||||
import { Button } from "components/Inputs/Button";
|
import { Button } from "components/Inputs/Button";
|
||||||
import { useDeviceSupportsHover } from "hooks/useMediaQuery";
|
import { useDeviceSupportsHover } from "hooks/useMediaQuery";
|
||||||
import { filterHasAttributes, isDefinedAndNotEmpty } from "helpers/others";
|
import { filterHasAttributes, isDefinedAndNotEmpty } from "helpers/asserts";
|
||||||
import { SmartList } from "components/SmartList";
|
import { SmartList } from "components/SmartList";
|
||||||
import { getOpenGraph } from "helpers/openGraph";
|
import { getOpenGraph } from "helpers/openGraph";
|
||||||
import { compareDate } from "helpers/date";
|
import { compareDate } from "helpers/date";
|
||||||
|
|
|
@ -10,7 +10,7 @@ import { ContentPanel, ContentPanelWidthSizes } from "components/Containers/Cont
|
||||||
import { SubPanel } from "components/Containers/SubPanel";
|
import { SubPanel } from "components/Containers/SubPanel";
|
||||||
import DefinitionCard from "components/Wiki/DefinitionCard";
|
import DefinitionCard from "components/Wiki/DefinitionCard";
|
||||||
import { getReadySdk } from "graphql/sdk";
|
import { getReadySdk } from "graphql/sdk";
|
||||||
import { filterHasAttributes, isDefined, isDefinedAndNotEmpty } from "helpers/others";
|
import { filterHasAttributes, isDefined, isDefinedAndNotEmpty } from "helpers/asserts";
|
||||||
import { WikiPageWithTranslations } from "types/types";
|
import { WikiPageWithTranslations } from "types/types";
|
||||||
import { useSmartLanguage } from "hooks/useSmartLanguage";
|
import { useSmartLanguage } from "hooks/useSmartLanguage";
|
||||||
import { prettySlug, sJoin } from "helpers/formatters";
|
import { prettySlug, sJoin } from "helpers/formatters";
|
||||||
|
|
|
@ -13,12 +13,8 @@ import {
|
||||||
} from "graphql/generated";
|
} from "graphql/generated";
|
||||||
import { getReadySdk } from "graphql/sdk";
|
import { getReadySdk } from "graphql/sdk";
|
||||||
import { prettySlug } from "helpers/formatters";
|
import { prettySlug } from "helpers/formatters";
|
||||||
import {
|
import { getStatusDescription } from "helpers/others";
|
||||||
filterHasAttributes,
|
import { filterHasAttributes, isDefined, isDefinedAndNotEmpty } from "helpers/asserts";
|
||||||
getStatusDescription,
|
|
||||||
isDefined,
|
|
||||||
isDefinedAndNotEmpty,
|
|
||||||
} from "helpers/others";
|
|
||||||
import { getOpenGraph } from "helpers/openGraph";
|
import { getOpenGraph } from "helpers/openGraph";
|
||||||
import { useSmartLanguage } from "hooks/useSmartLanguage";
|
import { useSmartLanguage } from "hooks/useSmartLanguage";
|
||||||
import { ToolTip } from "components/ToolTip";
|
import { ToolTip } from "components/ToolTip";
|
||||||
|
@ -156,7 +152,7 @@ const ChronologyEra = ({ id, title, description, chronologyItems }: ChronologyEr
|
||||||
let currentYear = -Infinity;
|
let currentYear = -Infinity;
|
||||||
filterHasAttributes(chronologyItems, ["attributes"] as const).forEach((item) => {
|
filterHasAttributes(chronologyItems, ["attributes"] as const).forEach((item) => {
|
||||||
if (currentYear === item.attributes.year) {
|
if (currentYear === item.attributes.year) {
|
||||||
memo[memo.length - 1].push(item);
|
memo[memo.length - 1]?.push(item);
|
||||||
} else {
|
} else {
|
||||||
currentYear = item.attributes.year;
|
currentYear = item.attributes.year;
|
||||||
memo.push([item]);
|
memo.push([item]);
|
||||||
|
@ -214,7 +210,7 @@ interface ChronologyYearProps {
|
||||||
const ChronologyYear = ({ items }: ChronologyYearProps) => (
|
const ChronologyYear = ({ items }: ChronologyYearProps) => (
|
||||||
<div
|
<div
|
||||||
className="rounded-2xl target:my-4 target:bg-mid target:py-4"
|
className="rounded-2xl target:my-4 target:bg-mid target:py-4"
|
||||||
id={generateAnchor(items[0].attributes?.year)}>
|
id={generateAnchor(items[0]?.attributes?.year)}>
|
||||||
{filterHasAttributes(items, ["attributes.events"] as const).map((item, index) => (
|
{filterHasAttributes(items, ["attributes.events"] as const).map((item, index) => (
|
||||||
<ChronologyDate
|
<ChronologyDate
|
||||||
key={index}
|
key={index}
|
||||||
|
|
|
@ -15,10 +15,14 @@ import { Switch } from "components/Inputs/Switch";
|
||||||
import { TextInput } from "components/Inputs/TextInput";
|
import { TextInput } from "components/Inputs/TextInput";
|
||||||
import { WithLabel } from "components/Inputs/WithLabel";
|
import { WithLabel } from "components/Inputs/WithLabel";
|
||||||
import { useDeviceSupportsHover } from "hooks/useMediaQuery";
|
import { useDeviceSupportsHover } from "hooks/useMediaQuery";
|
||||||
import { filterDefined, filterHasAttributes, isDefinedAndNotEmpty } from "helpers/others";
|
import {
|
||||||
|
filterDefined,
|
||||||
|
filterHasAttributes,
|
||||||
|
isDefinedAndNotEmpty,
|
||||||
|
SelectiveNonNullable,
|
||||||
|
} from "helpers/asserts";
|
||||||
import { SmartList } from "components/SmartList";
|
import { SmartList } from "components/SmartList";
|
||||||
import { Select } from "components/Inputs/Select";
|
import { Select } from "components/Inputs/Select";
|
||||||
import { SelectiveNonNullable } from "types/SelectiveNonNullable";
|
|
||||||
import { prettySlug } from "helpers/formatters";
|
import { prettySlug } from "helpers/formatters";
|
||||||
import { getOpenGraph } from "helpers/openGraph";
|
import { getOpenGraph } from "helpers/openGraph";
|
||||||
import { TranslatedPreviewCard } from "components/PreviewCard";
|
import { TranslatedPreviewCard } from "components/PreviewCard";
|
||||||
|
|
|
@ -1,39 +0,0 @@
|
||||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
||||||
|
|
||||||
type JoinDot<K extends string, P extends string> = `${K}${"" extends K ? "" : "."}${P}`;
|
|
||||||
|
|
||||||
export type PathDot<T, Acc extends string = ""> = T extends object
|
|
||||||
? {
|
|
||||||
[K in keyof T]: K extends string ? JoinDot<Acc, K> | PathDot<T[K], JoinDot<Acc, K>> : never;
|
|
||||||
}[keyof T]
|
|
||||||
: Acc;
|
|
||||||
|
|
||||||
type PathHead<T extends unknown[]> = T extends [infer head]
|
|
||||||
? head
|
|
||||||
: T extends [infer head, ...infer rest]
|
|
||||||
? head
|
|
||||||
: "";
|
|
||||||
|
|
||||||
type PathRest<T extends unknown[]> = T extends [infer head, ...infer rest]
|
|
||||||
? rest extends []
|
|
||||||
? never
|
|
||||||
: rest
|
|
||||||
: never;
|
|
||||||
|
|
||||||
type PathLast<T extends unknown[]> = T["length"] extends 1 ? true : false;
|
|
||||||
|
|
||||||
type Recursive<T, Path extends unknown[]> = PathHead<Path> extends keyof T
|
|
||||||
? Omit<T, PathHead<Path>> & {
|
|
||||||
[P in PathHead<Path>]-?: PathLast<Path> extends true
|
|
||||||
? NonNullable<T[P]>
|
|
||||||
: Recursive<NonNullable<T[P]>, PathRest<Path>>;
|
|
||||||
}
|
|
||||||
: T;
|
|
||||||
|
|
||||||
type Split<Str, Acc extends string[] = []> = Str extends `${infer Head}.${infer Rest}`
|
|
||||||
? Split<Rest, [...Acc, Head]>
|
|
||||||
: Str extends `${infer Last}`
|
|
||||||
? [...Acc, Last]
|
|
||||||
: never;
|
|
||||||
|
|
||||||
export type SelectiveNonNullable<T, P extends PathDot<T>> = Recursive<NonNullable<T>, Split<P>>;
|
|
|
@ -1,11 +1,15 @@
|
||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
|
// Type Checking
|
||||||
|
"noFallthroughCasesInSwitch": true,
|
||||||
|
"noUncheckedIndexedAccess": true,
|
||||||
|
"strict": true,
|
||||||
|
|
||||||
"target": "ES6",
|
"target": "ES6",
|
||||||
"lib": ["dom", "dom.iterable", "esnext"],
|
"lib": ["dom", "dom.iterable", "esnext"],
|
||||||
"importHelpers": true,
|
"importHelpers": true,
|
||||||
"allowJs": true,
|
"allowJs": true,
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
"strict": true,
|
|
||||||
"forceConsistentCasingInFileNames": true,
|
"forceConsistentCasingInFileNames": true,
|
||||||
"noEmit": true,
|
"noEmit": true,
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
|
@ -16,7 +20,6 @@
|
||||||
"jsx": "preserve",
|
"jsx": "preserve",
|
||||||
"incremental": true,
|
"incremental": true,
|
||||||
"baseUrl": "src"
|
"baseUrl": "src"
|
||||||
// "noUncheckedIndexedAccess": true
|
|
||||||
},
|
},
|
||||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
|
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
|
||||||
"exclude": ["node_modules"]
|
"exclude": ["node_modules"]
|
||||||
|
|
Loading…
Reference in New Issue