Added scans + removed useless router as props + use graphql aliases for getting available languages

This commit is contained in:
DrMint 2022-03-28 10:43:25 +02:00
parent 4a123a0236
commit 9b0404a742
25 changed files with 971 additions and 183 deletions

View File

@ -149,7 +149,7 @@ export default function AppLayout(props: AppLayoutProps): JSX.Element {
{/* Background when navbar is opened */}
<div
className={`[grid-area:content] mobile:z-10 absolute inset-0 transition-[backdrop-filter] duration-500 ${
(appLayout.mainPanelOpen ?? appLayout.subPanelOpen) && isMobile
(appLayout.mainPanelOpen || appLayout.subPanelOpen) && isMobile
? "[backdrop-filter:blur(2px)]"
: "pointer-events-none touch-none "
}`}
@ -158,7 +158,7 @@ export default function AppLayout(props: AppLayoutProps): JSX.Element {
className={`absolute bg-shade inset-0 transition-opacity duration-500
${turnSubIntoContent ? "" : ""}
${
(appLayout.mainPanelOpen ?? appLayout.subPanelOpen) && isMobile
(appLayout.mainPanelOpen || appLayout.subPanelOpen) && isMobile
? "opacity-60"
: "opacity-0"
}`}

View File

@ -2,22 +2,24 @@ import {
GetLanguagesQuery,
GetWebsiteInterfaceQuery,
} from "graphql/operations-types";
import { NextRouter } from "next/router";
import { useRouter } from "next/router";
import { prettyLanguage } from "queries/helpers";
import Button from "./Button";
type HorizontalLineProps = {
className?: string;
locales: string[];
router: NextRouter;
languages: GetLanguagesQuery["languages"]["data"];
langui: GetWebsiteInterfaceQuery["websiteInterfaces"]["data"][number]["attributes"];
href?: string;
};
export default function HorizontalLine(
props: HorizontalLineProps
): JSX.Element {
const { locales, router, langui } = props;
const { locales, langui, href } = props;
const router = useRouter();
return (
<div className="w-full grid place-content-center">
<div className="flex flex-col place-items-center text-center gap-4 my-12 border-2 border-mid rounded-xl p-8 max-w-lg">
@ -27,7 +29,7 @@ export default function HorizontalLine(
<Button
key={index}
active={locale === router.locale}
href={router.asPath}
href={href}
locale={locale}
>
{prettyLanguage(locale, props.languages)}

View File

@ -16,7 +16,7 @@ type ContentTOCLineProps = {
export default function ContentTOCLine(
props: ContentTOCLineProps
): JSX.Element {
const { content, langui } = props;
const { content, langui, parentSlug } = props;
const [opened, setOpened] = useState(false);
@ -77,7 +77,7 @@ export default function ContentTOCLine(
{content.attributes.scan_set.length > 0 && (
<Button
href={`/contents/${content.attributes.content.data.attributes.slug}/scans/`}
href={`/library/${parentSlug}/scans#${content.attributes.slug}`}
>
{langui.view_scans}
</Button>

View File

@ -63,7 +63,7 @@ export default function LibraryItemsPreview(
))}
</div>
{(item.release_date ?? item.price) && (
{(item.release_date || item.price) && (
<div className="grid grid-flow-col w-full">
{item.release_date && (
<p className="mobile:text-xs text-sm">

View File

@ -5,7 +5,7 @@ import LightBox from "components/LightBox";
import ToolTip from "components/ToolTip";
import { useAppLayout } from "contexts/AppLayoutContext";
import Markdown from "markdown-to-jsx";
import { NextRouter } from "next/router";
import { useRouter } from "next/router";
import { slugify } from "queries/helpers";
import React, { useState } from "react";
import ReactDOMServer from "react-dom/server";
@ -13,14 +13,13 @@ import ReactDOMServer from "react-dom/server";
type MarkdawnProps = {
className?: string;
text: string;
router: NextRouter;
};
export default function Markdawn(props: MarkdawnProps): JSX.Element {
const appLayout = useAppLayout();
const text = preprocessMarkDawn(props.text);
const { router } = props;
const router = useRouter();
const [lightboxOpen, setLightboxOpen] = useState(false);
const [lightboxImages, setLightboxImages] = useState([""]);
@ -41,6 +40,21 @@ export default function Markdawn(props: MarkdawnProps): JSX.Element {
options={{
slugify: slugify,
overrides: {
a: {
component: (compProps: {
href: string;
children: React.ReactNode;
}) => {
if (compProps.href.startsWith("/")) {
return (
<a onClick={async () => router.push(compProps.href)}>
{compProps.children}
</a>
);
}
return <a href={compProps.href}>{compProps.children}</a>;
},
},
h1: {
component: (compProps: {
id: string;
@ -313,7 +327,7 @@ export function preprocessMarkDawn(text: string): string {
const visitedSlugs: string[] = [];
const result = text.split("\n").map((line) => {
if (line === "* * *" ?? line === "---") {
if (line === "* * *" || line === "---") {
scenebreakIndex += 1;
return `<SceneBreak id="scene-break-${scenebreakIndex}">`;
}

View File

@ -1,16 +1,16 @@
import { NextRouter } from "next/router";
import { useRouter } from "next/router";
import { slugify } from "queries/helpers";
import { preprocessMarkDawn } from "./Markdawn";
type TOCProps = {
text: string;
title?: string;
router: NextRouter;
};
export default function TOCComponent(props: TOCProps): JSX.Element {
const { router, text, title } = props;
const { text, title } = props;
const toc = getTocFromMarkdawn(preprocessMarkDawn(text), title);
const router = useRouter();
return (
<>
@ -21,11 +21,7 @@ export default function TOCComponent(props: TOCProps): JSX.Element {
{<abbr title={toc.title}>{toc.title}</abbr>}
</a>
</p>
<TOCLevel
tocchildren={toc.children}
parentNumbering=""
router={router}
/>
<TOCLevel tocchildren={toc.children} parentNumbering="" />
</div>
</>
);
@ -34,11 +30,11 @@ export default function TOCComponent(props: TOCProps): JSX.Element {
type TOCLevelProps = {
tocchildren: TOC[];
parentNumbering: string;
router: NextRouter;
};
function TOCLevel(props: TOCLevelProps): JSX.Element {
const { tocchildren, parentNumbering, router } = props;
const router = useRouter();
const { tocchildren, parentNumbering } = props;
return (
<ol className="pl-4 text-left">
{tocchildren.map((child, childIndex) => (
@ -57,7 +53,6 @@ function TOCLevel(props: TOCLevelProps): JSX.Element {
<TOCLevel
tocchildren={child.children}
parentNumbering={`${parentNumbering}${childIndex + 1}.`}
router={router}
/>
</>
))}

View File

@ -1,5 +1,4 @@
import ToolTip from "components/ToolTip";
import Link from "next/link";
import { useRouter } from "next/router";
import { MouseEventHandler } from "react";
@ -35,27 +34,32 @@ export default function NavOption(props: NavOptionProps): JSX.Element {
className="text-left"
disabled={!props.reduced}
>
<Link href={props.url} passHref>
<div
onClick={props.onClick}
className={`relative grid grid-flow-col grid-cols-[auto] auto-cols-fr justify-center ${
props.icon ? "text-left" : "text-center"
} ${divCommon}`}
>
{props.icon && (
<span className="material-icons mt-[.1em]">{props.icon}</span>
)}
<div
onClick={(event) => {
if (props.onClick) props.onClick(event);
if (props.url) {
if (props.url.startsWith("#")) {
router.replace(props.url);
} else {
router.push(props.url);
}
}
}}
className={`relative grid grid-flow-col grid-cols-[auto] auto-cols-fr justify-center ${
props.icon ? "text-left" : "text-center"
} ${divCommon}`}
>
{props.icon && (
<span className="material-icons mt-[.1em]">{props.icon}</span>
)}
{!props.reduced && (
<div>
<h3 className="text-2xl">{props.title}</h3>
{props.subtitle && (
<p className="col-start-2">{props.subtitle}</p>
)}
</div>
)}
</div>
</Link>
{!props.reduced && (
<div>
<h3 className="text-2xl">{props.title}</h3>
{props.subtitle && <p className="col-start-2">{props.subtitle}</p>}
</div>
)}
</div>
</ToolTip>
);
}

View File

@ -109,7 +109,7 @@ export default function MainPanel(props: MainPanelProps): JSX.Element {
</ToolTip>
)}
<ToolTip
{/* <ToolTip
content={<h3 className="text-2xl">{langui.open_search}</h3>}
placement="right"
className="text-left"
@ -130,7 +130,7 @@ export default function MainPanel(props: MainPanelProps): JSX.Element {
search
</span>
</Button>
</ToolTip>
</ToolTip> */}
</div>
</div>
</div>

View File

@ -1011,6 +1011,15 @@ query getContentText($slug: String, $language_code: String) {
}
}
}
text_set_languages: text_set {
language {
data {
attributes {
code
}
}
}
}
text_set(filters: { language: { code: { eq: $language_code } } }) {
status
text
@ -1233,6 +1242,15 @@ query getPost($slug: String, $language_code: String) {
}
}
}
translations_languages: translations {
language {
data {
attributes {
code
}
}
}
}
translations(filters: { language: { code: { eq: $language_code } } }) {
status
title
@ -1319,24 +1337,6 @@ query getPostsPreview($language_code: String) {
}
}
query getPostLanguages($slug: String) {
posts(filters: { slug: { eq: $slug } }) {
data {
attributes {
translations {
language {
data {
attributes {
code
}
}
}
}
}
}
}
}
query getContentLanguages($slug: String) {
contents(filters: { slug: { eq: $slug } }) {
data {
@ -1372,3 +1372,192 @@ query getContentLanguages($slug: String) {
}
}
}
query getLibraryItemScans($slug: String, $language_code: String) {
libraryItems(filters: { slug: { eq: $slug } }) {
data {
id
attributes {
slug
title
subtitle
thumbnail {
data {
attributes {
name
alternativeText
caption
width
height
url
}
}
}
contents(pagination: { limit: -1 }) {
data {
id
attributes {
slug
range {
__typename
... on ComponentRangePageRange {
starting_page
ending_page
}
... on ComponentRangeTimeRange {
starting_time
ending_time
}
}
scan_set_languages: scan_set {
language {
data {
attributes {
code
}
}
}
}
scan_set(
filters: {
or: [
{ language: { code: { eq: "xx" } } }
{ language: { code: { eq: $language_code } } }
]
}
) {
status
source_language {
data {
attributes {
code
}
}
}
scanners {
data {
id
attributes {
username
anonymize
anonymous_code
pronouns
bio(
filters: { language: { code: { eq: $language_code } } }
) {
bio
}
languages {
data {
attributes {
code
}
}
}
avatar {
data {
attributes {
name
alternativeText
caption
width
height
url
}
}
}
}
}
}
cleaners {
data {
id
attributes {
username
anonymize
anonymous_code
pronouns
bio(
filters: { language: { code: { eq: $language_code } } }
) {
bio
}
languages {
data {
attributes {
code
}
}
}
avatar {
data {
attributes {
name
alternativeText
caption
width
height
url
}
}
}
}
}
}
typesetters {
data {
id
attributes {
username
anonymize
anonymous_code
pronouns
bio(
filters: { language: { code: { eq: $language_code } } }
) {
bio
}
languages {
data {
attributes {
code
}
}
}
avatar {
data {
attributes {
name
alternativeText
caption
width
height
url
}
}
}
}
}
}
notes
pages(pagination: { limit: -1 }) {
data {
id
attributes {
name
alternativeText
caption
width
height
url
}
}
}
}
}
}
}
}
}
}
}

View File

@ -32,7 +32,7 @@ export type Scalars = {
*
* But to make the type easier to work with, it went through the following transformation:
* - Removed ?
* - Removed | null
* - Removed
* - Replaced any by unknown
*/
@ -74,6 +74,13 @@ export enum Enum_Componentsetstextset_Status {
Done = "Done",
}
export enum Enum_Componentsetsscanset_Status {
Incomplete = "Incomplete",
Draft = "Draft",
Review = "Review",
Done = "Done",
}
export type StrapiImage = {
__typename: "UploadFile";
name: string;
@ -1360,6 +1367,19 @@ export type GetContentTextQuery = {
};
}>;
};
text_set_languages: Array<{
__typename: "ComponentSetsTextSet";
language: {
__typename: "LanguageEntityResponse";
data: {
__typename: "LanguageEntity";
attributes: {
__typename: "Language";
code: string;
};
};
};
}>;
text_set: Array<{
__typename: "ComponentSetsTextSet";
status: Enum_Componentsetstextset_Status;
@ -1576,14 +1596,14 @@ export type GetPostQuery = {
attributes: {
__typename: "Post";
slug: string;
updatedAt: unknown;
updatedAt: any;
hidden: boolean;
date: {
__typename: "ComponentBasicsDatepicker";
year: number;
month: number;
day: number;
};
hidden: boolean;
authors: {
__typename: "RecorderRelationResponseCollection";
data: Array<{
@ -1629,11 +1649,7 @@ export type GetPostQuery = {
data: Array<{
__typename: "CategoryEntity";
id: string;
attributes: {
__typename: "Category";
name: string;
short: string;
};
attributes: { __typename: "Category"; name: string; short: string };
}>;
};
thumbnail: {
@ -1651,6 +1667,16 @@ export type GetPostQuery = {
};
};
};
translations_languages: Array<{
__typename: "ComponentTranslationsPosts";
language: {
__typename: "LanguageEntityResponse";
data: {
__typename: "LanguageEntity";
attributes: { __typename: "Language"; code: string };
};
};
}>;
translations: Array<{
__typename: "ComponentTranslationsPosts";
status: Enum_Componenttranslationsposts_Status;
@ -1833,3 +1859,238 @@ export type GetContentLanguagesQuery = {
}>;
};
};
export type GetLibraryItemScansQueryVariables = Exact<{
slug: InputMaybe<Scalars["String"]>;
language_code: InputMaybe<Scalars["String"]>;
}>;
export type GetLibraryItemScansQuery = {
__typename: "Query";
libraryItems: {
__typename: "LibraryItemEntityResponseCollection";
data: Array<{
__typename: "LibraryItemEntity";
id: string;
attributes: {
__typename: "LibraryItem";
slug: string;
title: string;
subtitle: string;
thumbnail: {
__typename: "UploadFileEntityResponse";
data: {
__typename: "UploadFileEntity";
attributes: {
__typename: "UploadFile";
name: string;
alternativeText: string;
caption: string;
width: number;
height: number;
url: string;
};
};
};
contents: {
__typename: "RangedContentRelationResponseCollection";
data: Array<{
__typename: "RangedContentEntity";
id: string;
attributes: {
__typename: "RangedContent";
slug: string;
range: Array<
| {
__typename: "ComponentRangePageRange";
starting_page: number;
ending_page: number;
}
| {
__typename: "ComponentRangeTimeRange";
starting_time: any;
ending_time: any;
}
| { __typename: "ComponentRangeOther" }
| { __typename: "Error" }
>;
scan_set_languages: Array<{
__typename: "ComponentSetsScanSet";
language: {
__typename: "LanguageEntityResponse";
data: {
__typename: "LanguageEntity";
attributes: {
__typename: "Language";
code: string;
};
};
};
}>;
scan_set: Array<{
__typename: "ComponentSetsScanSet";
status: Enum_Componentsetsscanset_Status;
notes: string;
source_language: {
__typename: "LanguageEntityResponse";
data: {
__typename: "LanguageEntity";
attributes: {
__typename: "Language";
code: string;
};
};
};
scanners: {
__typename: "RecorderRelationResponseCollection";
data: Array<{
__typename: "RecorderEntity";
id: string;
attributes: {
__typename: "Recorder";
username: string;
anonymize: boolean;
anonymous_code: string;
pronouns: string;
bio: Array<{
__typename: "ComponentTranslationsBio";
bio: string;
}>;
languages: {
__typename: "LanguageRelationResponseCollection";
data: Array<{
__typename: "LanguageEntity";
attributes: {
__typename: "Language";
code: string;
};
}>;
};
avatar: {
__typename: "UploadFileEntityResponse";
data: {
__typename: "UploadFileEntity";
attributes: {
__typename: "UploadFile";
name: string;
alternativeText: string;
caption: string;
width: number;
height: number;
url: string;
};
};
};
};
}>;
};
cleaners: {
__typename: "RecorderRelationResponseCollection";
data: Array<{
__typename: "RecorderEntity";
id: string;
attributes: {
__typename: "Recorder";
username: string;
anonymize: boolean;
anonymous_code: string;
pronouns: string;
bio: Array<{
__typename: "ComponentTranslationsBio";
bio: string;
}>;
languages: {
__typename: "LanguageRelationResponseCollection";
data: Array<{
__typename: "LanguageEntity";
attributes: {
__typename: "Language";
code: string;
};
}>;
};
avatar: {
__typename: "UploadFileEntityResponse";
data: {
__typename: "UploadFileEntity";
attributes: {
__typename: "UploadFile";
name: string;
alternativeText: string;
caption: string;
width: number;
height: number;
url: string;
};
};
};
};
}>;
};
typesetters: {
__typename: "RecorderRelationResponseCollection";
data: Array<{
__typename: "RecorderEntity";
id: string;
attributes: {
__typename: "Recorder";
username: string;
anonymize: boolean;
anonymous_code: string;
pronouns: string;
bio: Array<{
__typename: "ComponentTranslationsBio";
bio: string;
}>;
languages: {
__typename: "LanguageRelationResponseCollection";
data: Array<{
__typename: "LanguageEntity";
attributes: {
__typename: "Language";
code: string;
};
}>;
};
avatar: {
__typename: "UploadFileEntityResponse";
data: {
__typename: "UploadFileEntity";
attributes: {
__typename: "UploadFile";
name: string;
alternativeText: string;
caption: string;
width: number;
height: number;
url: string;
};
};
};
};
}>;
};
pages: {
__typename: "UploadFileRelationResponseCollection";
data: Array<{
__typename: "UploadFileEntity";
id: string;
attributes: {
__typename: "UploadFile";
name: string;
alternativeText: string;
caption: string;
width: number;
height: number;
url: string;
};
}>;
};
}>;
};
}>;
};
};
}>;
};
};

View File

@ -2,8 +2,6 @@ import { readFileSync } from "fs";
import {
GetChronologyItemsQuery,
GetChronologyItemsQueryVariables,
GetContentLanguagesQuery,
GetContentLanguagesQueryVariables,
GetContentQuery,
GetContentQueryVariables,
GetContentsQuery,
@ -20,12 +18,12 @@ import {
GetLanguagesQueryVariables,
GetLibraryItemQuery,
GetLibraryItemQueryVariables,
GetLibraryItemScansQuery,
GetLibraryItemScansQueryVariables,
GetLibraryItemsPreviewQuery,
GetLibraryItemsPreviewQueryVariables,
GetLibraryItemsSlugsQuery,
GetLibraryItemsSlugsQueryVariables,
GetPostLanguagesQuery,
GetPostLanguagesQueryVariables,
GetPostQuery,
GetPostQueryVariables,
GetPostsPreviewQuery,
@ -172,16 +170,9 @@ export async function getPostsPreview(
return await graphQL(query, JSON.stringify(variables));
}
export async function getPostLanguages(
variables: GetPostLanguagesQueryVariables
): Promise<GetPostLanguagesQuery> {
const query = getQueryFromOperations("getPostLanguages");
return await graphQL(query, JSON.stringify(variables));
}
export async function getContentLanguages(
variables: GetContentLanguagesQueryVariables
): Promise<GetContentLanguagesQuery> {
const query = getQueryFromOperations("getContentLanguages");
export async function getLibraryItemScans(
variables: GetLibraryItemScansQueryVariables
): Promise<GetLibraryItemScansQuery> {
const query = getQueryFromOperations("getLibraryItemScans");
return await graphQL(query, JSON.stringify(variables));
}

View File

@ -242,6 +242,24 @@ type ComponentBasicsDatepicker {
day: Int
}
enum ENUM_COMPONENTBASICSFILESIZE_UNIT {
kb
mb
gb
}
input ComponentBasicsFileSizeInput {
id: ID
size: Float
unit: ENUM_COMPONENTBASICSFILESIZE_UNIT
}
type ComponentBasicsFileSize {
id: ID!
size: Float!
unit: ENUM_COMPONENTBASICSFILESIZE_UNIT!
}
input ComponentBasicsPriceInput {
id: ID
amount: Float
@ -1268,6 +1286,29 @@ type ComponentTranslationsWeaponStory {
language: LanguageEntityResponse
}
input ComponentTranslationsWebArchivesFiltersInput {
language: LanguageFiltersInput
description: StringFilterInput
notes: StringFilterInput
and: [ComponentTranslationsWebArchivesFiltersInput]
or: [ComponentTranslationsWebArchivesFiltersInput]
not: ComponentTranslationsWebArchivesFiltersInput
}
input ComponentTranslationsWebArchivesInput {
id: ID
language: ID
description: String
notes: String
}
type ComponentTranslationsWebArchives {
id: ID!
language: LanguageEntityResponse
description: String
notes: String
}
input UploadFileFiltersInput {
id: IDFilterInput
name: StringFilterInput
@ -2137,6 +2178,7 @@ input PostInput {
translations: [ComponentTranslationsPostsInput]
hidden: Boolean
thumbnail: ID
date: ComponentBasicsDatepickerInput
}
type Post {
@ -2158,6 +2200,7 @@ type Post {
): [ComponentTranslationsPosts]
hidden: Boolean!
thumbnail: UploadFileEntityResponse
date: ComponentBasicsDatepicker!
createdAt: DateTime
updatedAt: DateTime
}
@ -2554,6 +2597,76 @@ type WeaponStoryTypeEntityResponseCollection {
meta: ResponseCollectionMeta!
}
enum ENUM_WEBARCHIVE_TYPE {
website
webpage
online_doc
}
enum ENUM_WEBARCHIVE_FORMAT {
zip
wacz
}
input WebArchiveFiltersInput {
id: IDFilterInput
type: StringFilterInput
source_url: StringFilterInput
format: StringFilterInput
num_pages: IntFilterInput
author: StringFilterInput
still_online: BooleanFilterInput
createdAt: DateTimeFilterInput
updatedAt: DateTimeFilterInput
and: [WebArchiveFiltersInput]
or: [WebArchiveFiltersInput]
not: WebArchiveFiltersInput
}
input WebArchiveInput {
type: ENUM_WEBARCHIVE_TYPE
source_url: String
format: ENUM_WEBARCHIVE_FORMAT
date: ComponentBasicsDatepickerInput
num_pages: Int
author: String
still_online: Boolean
size: ComponentBasicsFileSizeInput
descriptions: [ComponentTranslationsWebArchivesInput]
}
type WebArchive {
type: ENUM_WEBARCHIVE_TYPE!
source_url: String!
format: ENUM_WEBARCHIVE_FORMAT!
date: ComponentBasicsDatepicker!
num_pages: Int
author: String
still_online: Boolean!
size: ComponentBasicsFileSize!
descriptions(
filters: ComponentTranslationsWebArchivesFiltersInput
pagination: PaginationArg = {}
sort: [String] = []
): [ComponentTranslationsWebArchives]
createdAt: DateTime
updatedAt: DateTime
}
type WebArchiveEntity {
id: ID
attributes: WebArchive
}
type WebArchiveEntityResponse {
data: WebArchiveEntity
}
type WebArchiveEntityResponseCollection {
data: [WebArchiveEntity!]!
meta: ResponseCollectionMeta!
}
input WebsiteInterfaceFiltersInput {
id: IDFilterInput
library: StringFilterInput
@ -2668,6 +2781,23 @@ input WebsiteInterfaceFiltersInput {
content: StringFilterInput
result: StringFilterInput
results: StringFilterInput
language_switch_message: StringFilterInput
open_settings: StringFilterInput
change_language: StringFilterInput
open_search: StringFilterInput
chronology: StringFilterInput
accords_handbook: StringFilterInput
legality: StringFilterInput
members: StringFilterInput
sharing_policy: StringFilterInput
contact_us: StringFilterInput
email: StringFilterInput
email_gdpr_notice: StringFilterInput
message: StringFilterInput
send: StringFilterInput
response_invalid_code: StringFilterInput
response_invalid_email: StringFilterInput
response_email_success: StringFilterInput
createdAt: DateTimeFilterInput
updatedAt: DateTimeFilterInput
and: [WebsiteInterfaceFiltersInput]
@ -2788,6 +2918,23 @@ input WebsiteInterfaceInput {
content: String
result: String
results: String
language_switch_message: String
open_settings: String
change_language: String
open_search: String
chronology: String
accords_handbook: String
legality: String
members: String
sharing_policy: String
contact_us: String
email: String
email_gdpr_notice: String
message: String
send: String
response_invalid_code: String
response_invalid_email: String
response_email_success: String
}
type WebsiteInterface {
@ -2903,6 +3050,23 @@ type WebsiteInterface {
content: String
result: String
results: String
language_switch_message: String
open_settings: String
change_language: String
open_search: String
chronology: String
accords_handbook: String
legality: String
members: String
sharing_policy: String
contact_us: String
email: String
email_gdpr_notice: String
message: String
send: String
response_invalid_code: String
response_invalid_email: String
response_email_success: String
createdAt: DateTime
updatedAt: DateTime
}
@ -3009,6 +3173,7 @@ type WikiPageTypeEntityResponseCollection {
union GenericMorph =
ComponentBasicsCredits
| ComponentBasicsDatepicker
| ComponentBasicsFileSize
| ComponentBasicsPrice
| ComponentBasicsSize
| ComponentCollectionsComponentEvent
@ -3060,6 +3225,7 @@ union GenericMorph =
| ComponentTranslationsWeaponStoryStory
| ComponentTranslationsWeaponStoryType
| ComponentTranslationsWeaponStory
| ComponentTranslationsWebArchives
| UploadFile
| AudioSubtype
| Category
@ -3085,6 +3251,7 @@ union GenericMorph =
| WeaponStory
| WeaponStoryGroup
| WeaponStoryType
| WebArchive
| WebsiteInterface
| WikiPage
| WikiPageType
@ -3253,6 +3420,12 @@ type Query {
pagination: PaginationArg = {}
sort: [String] = []
): WeaponStoryTypeEntityResponseCollection
webArchive(id: ID): WebArchiveEntityResponse
webArchives(
filters: WebArchiveFiltersInput
pagination: PaginationArg = {}
sort: [String] = []
): WebArchiveEntityResponseCollection
websiteInterface(id: ID): WebsiteInterfaceEntityResponse
websiteInterfaces(
filters: WebsiteInterfaceFiltersInput
@ -3394,6 +3567,9 @@ type Mutation {
data: WeaponStoryTypeInput!
): WeaponStoryTypeEntityResponse
deleteWeaponStoryType(id: ID!): WeaponStoryTypeEntityResponse
createWebArchive(data: WebArchiveInput!): WebArchiveEntityResponse
updateWebArchive(id: ID!, data: WebArchiveInput!): WebArchiveEntityResponse
deleteWebArchive(id: ID!): WebArchiveEntityResponse
createWebsiteInterface(
data: WebsiteInterfaceInput!
): WebsiteInterfaceEntityResponse

View File

@ -7,23 +7,23 @@ import ReturnButton, {
} from "components/PanelComponents/ReturnButton";
import ContentPanel from "components/Panels/ContentPanel";
import SubPanel from "components/Panels/SubPanel";
import { getPost, getPostLanguages } from "graphql/operations";
import { getPost } from "graphql/operations";
import { GetPostQuery } from "graphql/operations-types";
import { GetStaticPropsContext } from "next";
import { useRouter } from "next/router";
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
import { prettySlug } from "queries/helpers";
import { getLocalesFromLanguages, prettySlug } from "queries/helpers";
interface AccordsHandbookProps extends AppStaticProps {
post: GetPostQuery["posts"]["data"][number]["attributes"];
locales: string[];
}
export default function AccordsHandbook(
props: AccordsHandbookProps
): JSX.Element {
const { langui, post, locales } = props;
const { langui, post } = props;
const router = useRouter();
const locales = getLocalesFromLanguages(post.translations_languages);
const subPanel = (
<SubPanel>
@ -37,7 +37,6 @@ export default function AccordsHandbook(
{post.translations.length > 0 && post.translations[0].body && (
<TOC
text={post.translations[0].body}
router={router}
title={post.translations[0].title}
/>
)}
@ -54,11 +53,10 @@ export default function AccordsHandbook(
className="mb-10"
/>
{locales.includes(router.locale ?? "en") ? (
<Markdawn router={router} text={post.translations[0].body} />
<Markdawn text={post.translations[0].body} />
) : (
<LanguageSwitcher
locales={locales}
router={router}
languages={props.languages}
langui={props.langui}
/>
@ -92,11 +90,6 @@ export async function getStaticProps(
language_code: context.locale ?? "en",
})
).posts.data[0].attributes,
locales: (
await getPostLanguages({ slug: slug })
).posts.data[0].attributes.translations.map(
(translation) => translation.language.data.attributes.code
),
};
return {
props: props,

View File

@ -8,27 +8,27 @@ import ReturnButton, {
} from "components/PanelComponents/ReturnButton";
import ContentPanel from "components/Panels/ContentPanel";
import SubPanel from "components/Panels/SubPanel";
import { getPost, getPostLanguages } from "graphql/operations";
import { getPost } from "graphql/operations";
import { GetPostQuery } from "graphql/operations-types";
import { GetStaticPropsContext } from "next";
import { useRouter } from "next/router";
import { RequestMailProps, ResponseMailProps } from "pages/api/mail";
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
import { randomInt } from "queries/helpers";
import { getLocalesFromLanguages, randomInt } from "queries/helpers";
import { useState } from "react";
interface ContactProps extends AppStaticProps {
post: GetPostQuery["posts"]["data"][number]["attributes"];
locales: string[];
}
export default function AboutUs(props: ContactProps): JSX.Element {
const { langui, post, locales } = props;
const { langui, post } = props;
const router = useRouter();
const [formResponse, setFormResponse] = useState("");
const [formState, setFormState] = useState<"completed" | "ongoing" | "stale">(
"stale"
);
const locales = getLocalesFromLanguages(post.translations_languages);
const [randomNumber1, setRandomNumber1] = useState(randomInt(0, 10));
const [randomNumber2, setRandomNumber2] = useState(randomInt(0, 10));
@ -45,7 +45,6 @@ export default function AboutUs(props: ContactProps): JSX.Element {
{post.translations.length > 0 && post.translations[0].body && (
<TOC
text={post.translations[0].body}
router={router}
title={post.translations[0].title}
/>
)}
@ -62,11 +61,10 @@ export default function AboutUs(props: ContactProps): JSX.Element {
className="mb-10"
/>
{locales.includes(router.locale ?? "en") ? (
<Markdawn router={router} text={post.translations[0].body} />
<Markdawn text={post.translations[0].body} />
) : (
<LanguageSwitcher
locales={locales}
router={router}
languages={props.languages}
langui={props.langui}
/>
@ -236,11 +234,6 @@ export async function getStaticProps(
language_code: context.locale ?? "en",
})
).posts.data[0].attributes,
locales: (
await getPostLanguages({ slug: slug })
).posts.data[0].attributes.translations.map(
(translation) => translation.language.data.attributes.code
),
};
return {
props: props,

View File

@ -22,7 +22,7 @@ export default function AboutUs(props: AboutUsProps): JSX.Element {
border
/>
<NavOption title={langui.legality} url="/about-us/legality" border />
<NavOption title={langui.members} url="/about-us/members" border />
{/* <NavOption title={langui.members} url="/about-us/members" border /> */}
<NavOption
title={langui.sharing_policy}
url="/about-us/sharing-policy"

View File

@ -7,21 +7,21 @@ import ReturnButton, {
} from "components/PanelComponents/ReturnButton";
import ContentPanel from "components/Panels/ContentPanel";
import SubPanel from "components/Panels/SubPanel";
import { getPost, getPostLanguages } from "graphql/operations";
import { getPost } from "graphql/operations";
import { GetPostQuery } from "graphql/operations-types";
import { GetStaticPropsContext } from "next";
import { useRouter } from "next/router";
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
import { prettySlug } from "queries/helpers";
import { getLocalesFromLanguages, prettySlug } from "queries/helpers";
interface SiteInfoProps extends AppStaticProps {
post: GetPostQuery["posts"]["data"][number]["attributes"];
locales: string[];
}
export default function SiteInformation(props: SiteInfoProps): JSX.Element {
const { langui, post, locales } = props;
const { langui, post } = props;
const router = useRouter();
const locales = getLocalesFromLanguages(post.translations_languages);
const subPanel = (
<SubPanel>
@ -35,7 +35,6 @@ export default function SiteInformation(props: SiteInfoProps): JSX.Element {
{post.translations.length > 0 && post.translations[0].body && (
<TOC
text={post.translations[0].body}
router={router}
title={post.translations[0].title}
/>
)}
@ -52,11 +51,10 @@ export default function SiteInformation(props: SiteInfoProps): JSX.Element {
className="mb-10"
/>
{locales.includes(router.locale ?? "en") ? (
<Markdawn router={router} text={post.translations[0].body} />
<Markdawn text={post.translations[0].body} />
) : (
<LanguageSwitcher
locales={locales}
router={router}
languages={props.languages}
langui={props.langui}
/>
@ -90,11 +88,6 @@ export async function getStaticProps(
language_code: context.locale ?? "en",
})
).posts.data[0].attributes,
locales: (
await getPostLanguages({ slug: slug })
).posts.data[0].attributes.translations.map(
(translation) => translation.language.data.attributes.code
),
};
return {
props: props,

View File

@ -7,20 +7,20 @@ import ReturnButton, {
} from "components/PanelComponents/ReturnButton";
import ContentPanel from "components/Panels/ContentPanel";
import SubPanel from "components/Panels/SubPanel";
import { getPost, getPostLanguages } from "graphql/operations";
import { getPost } from "graphql/operations";
import { GetPostQuery } from "graphql/operations-types";
import { GetStaticPropsContext } from "next";
import { useRouter } from "next/router";
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
import { prettySlug } from "queries/helpers";
import { getLocalesFromLanguages, prettySlug } from "queries/helpers";
interface SharingPolicyProps extends AppStaticProps {
post: GetPostQuery["posts"]["data"][number]["attributes"];
locales: string[];
}
export default function SharingPolicy(props: SharingPolicyProps): JSX.Element {
const { langui, post, locales } = props;
const { langui, post } = props;
const locales = getLocalesFromLanguages(post.translations_languages);
const router = useRouter();
const subPanel = (
@ -35,7 +35,6 @@ export default function SharingPolicy(props: SharingPolicyProps): JSX.Element {
{post.translations.length > 0 && post.translations[0].body && (
<TOC
text={post.translations[0].body}
router={router}
title={post.translations[0].title}
/>
)}
@ -52,11 +51,10 @@ export default function SharingPolicy(props: SharingPolicyProps): JSX.Element {
className="mb-10"
/>
{locales.includes(router.locale ?? "en") ? (
<Markdawn router={router} text={post.translations[0].body} />
<Markdawn text={post.translations[0].body} />
) : (
<LanguageSwitcher
locales={locales}
router={router}
languages={props.languages}
langui={props.langui}
/>
@ -90,11 +88,6 @@ export async function getStaticProps(
language_code: context.locale ?? "en",
})
).posts.data[0].attributes,
locales: (
await getPostLanguages({ slug: slug })
).posts.data[0].attributes.translations.map(
(translation) => translation.language.data.attributes.code
),
};
return {
props: props,

View File

@ -13,11 +13,7 @@ import ContentPanel from "components/Panels/ContentPanel";
import SubPanel from "components/Panels/SubPanel";
import RecorderChip from "components/RecorderChip";
import ToolTip from "components/ToolTip";
import {
getContentLanguages,
getContentsSlugs,
getContentText,
} from "graphql/operations";
import { getContentsSlugs, getContentText } from "graphql/operations";
import { GetContentTextQuery } from "graphql/operations-types";
import {
GetStaticPathsContext,
@ -27,6 +23,7 @@ import {
import { useRouter } from "next/router";
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
import {
getLocalesFromLanguages,
getStatusDescription,
prettyinlineTitle,
prettyLanguage,
@ -38,13 +35,13 @@ import {
interface ContentReadProps extends AppStaticProps {
content: GetContentTextQuery["contents"]["data"][number]["attributes"];
contentId: GetContentTextQuery["contents"]["data"][number]["id"];
locales: string[];
}
export default function ContentRead(props: ContentReadProps): JSX.Element {
useTesting(props);
const { langui, content, languages, locales } = props;
const { langui, content, languages } = props;
const router = useRouter();
const locales = getLocalesFromLanguages(content.text_set_languages);
const subPanel = (
<SubPanel>
@ -146,7 +143,6 @@ export default function ContentRead(props: ContentReadProps): JSX.Element {
<HorizontalLine />
<TOC
text={content.text_set[0].text}
router={router}
title={
content.titles.length > 0
? prettyinlineTitle(
@ -197,11 +193,10 @@ export default function ContentRead(props: ContentReadProps): JSX.Element {
<HorizontalLine />
{locales.includes(router.locale ?? "en") ? (
<Markdawn router={router} text={content.text_set[0].text} />
<Markdawn text={content.text_set[0].text} />
) : (
<LanguageSwitcher
locales={locales}
router={router}
languages={props.languages}
langui={props.langui}
/>
@ -263,11 +258,6 @@ export async function getStaticProps(
...(await getAppStaticProps(context)),
content: content.attributes,
contentId: content.id,
locales: (
await getContentLanguages({ slug: slug })
).contents.data[0].attributes.text_set.map(
(translation) => translation.language.data.attributes.code
),
};
return {
props: props,

View File

@ -4,7 +4,6 @@ import ContentPanel, {
ContentPanelWidthSizes,
} from "components/Panels/ContentPanel";
import { GetStaticPropsContext } from "next";
import { useRouter } from "next/router";
import Script from "next/script";
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
import { useCallback, useState } from "react";
@ -13,8 +12,6 @@ import { default as TurndownService } from "turndown";
interface EditorProps extends AppStaticProps {}
export default function Editor(props: EditorProps): JSX.Element {
const router = useRouter();
const handleInput = useCallback((event) => {
setMarkdown(event.target.value);
}, []);
@ -77,7 +74,7 @@ export default function Editor(props: EditorProps): JSX.Element {
<div>
<h2>Preview</h2>
<div className="bg-mid rounded-xl p-8">
<Markdawn router={router} className="max-w-full" text={markdown} />
<Markdawn className="max-w-full" text={markdown} />
</div>
</div>
</div>

View File

@ -2,20 +2,20 @@ import AppLayout from "components/AppLayout";
import LanguageSwitcher from "components/LanguageSwitcher";
import Markdawn from "components/Markdown/Markdawn";
import ContentPanel from "components/Panels/ContentPanel";
import { getPost, getPostLanguages } from "graphql/operations";
import { getPost } from "graphql/operations";
import { GetPostQuery } from "graphql/operations-types";
import { GetStaticPropsContext } from "next";
import { useRouter } from "next/router";
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
import { prettySlug } from "queries/helpers";
import { getLocalesFromLanguages, prettySlug } from "queries/helpers";
interface HomeProps extends AppStaticProps {
post: GetPostQuery["posts"]["data"][number]["attributes"];
locales: string[];
}
export default function Home(props: HomeProps): JSX.Element {
const { post, locales } = props;
const { post } = props;
const locales = getLocalesFromLanguages(post.translations_languages);
const router = useRouter();
const contentPanel = (
@ -28,11 +28,10 @@ export default function Home(props: HomeProps): JSX.Element {
</h2>
</div>
{locales.includes(router.locale ?? "en") ? (
<Markdawn router={router} text={post.translations[0].body} />
<Markdawn text={post.translations[0].body} />
) : (
<LanguageSwitcher
locales={locales}
router={router}
languages={props.languages}
langui={props.langui}
/>
@ -65,11 +64,6 @@ export async function getStaticProps(
language_code: context.locale ?? "en",
})
).posts.data[0].attributes,
locales: (
await getPostLanguages({ slug: slug })
).posts.data[0].attributes.translations.map(
(translation) => translation.language.data.attributes.code
),
};
return {
props: props,

View File

@ -106,7 +106,12 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element {
)}
{item.contents.data.length > 0 && (
<NavOption title={langui.contents} url="#contents" border />
<NavOption
title={langui.contents}
url="#contents"
border
onClick={() => appLayout.setSubPanelOpen(false)}
/>
)}
</div>
</SubPanel>

View File

@ -0,0 +1,180 @@
import AppLayout from "components/AppLayout";
import Img, { getAssetURL, ImageQuality } from "components/Img";
import LanguageSwitcher from "components/LanguageSwitcher";
import LightBox from "components/LightBox";
import NavOption from "components/PanelComponents/NavOption";
import ReturnButton, {
ReturnButtonType,
} from "components/PanelComponents/ReturnButton";
import ContentPanel, {
ContentPanelWidthSizes,
} from "components/Panels/ContentPanel";
import SubPanel from "components/Panels/SubPanel";
import { useAppLayout } from "contexts/AppLayoutContext";
import { getLibraryItemScans, getLibraryItemsSlugs } from "graphql/operations";
import { GetLibraryItemScansQuery } from "graphql/operations-types";
import {
GetStaticPathsContext,
GetStaticPathsResult,
GetStaticPropsContext,
} from "next";
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
import { prettyinlineTitle, prettySlug, sortContent } from "queries/helpers";
import { useState } from "react";
interface Props extends AppStaticProps {
item: GetLibraryItemScansQuery["libraryItems"]["data"][number]["attributes"];
itemId: GetLibraryItemScansQuery["libraryItems"]["data"][number]["id"];
}
export default function LibrarySlug(props: Props): JSX.Element {
const { item, langui } = props;
const appLayout = useAppLayout();
sortContent(item.contents);
const [lightboxOpen, setLightboxOpen] = useState(false);
const [lightboxImages, setLightboxImages] = useState([""]);
const [lightboxIndex, setLightboxIndex] = useState(0);
const subPanel = (
<SubPanel>
<ReturnButton
href={`/library/${item.slug}`}
title={langui.item}
langui={langui}
displayOn={ReturnButtonType.desktop}
horizontalLine
/>
{item.contents.data.map((content) => (
<NavOption
key={content.id}
url={`#${content.attributes.slug}`}
title={prettySlug(content.attributes.slug, item.slug)}
subtitle={
content.attributes.range.length > 0 &&
content.attributes.range[0].__typename === "ComponentRangePageRange"
? `${content.attributes.range[0].starting_page}${content.attributes.range[0].ending_page}`
: undefined
}
onClick={() => appLayout.setSubPanelOpen(false)}
border
/>
))}
</SubPanel>
);
const contentPanel = (
<ContentPanel width={ContentPanelWidthSizes.large}>
<LightBox
state={lightboxOpen}
setState={setLightboxOpen}
images={lightboxImages}
index={lightboxIndex}
setIndex={setLightboxIndex}
/>
<ReturnButton
href={`/library/${item.slug}`}
title={langui.item}
langui={langui}
displayOn={ReturnButtonType.mobile}
className="mb-10"
/>
{item.contents.data.map((content) => (
<>
<h2
id={content.attributes.slug}
key={`h2${content.id}`}
className="text-2xl pb-2 pt-10 first-of-type:pt-0 flex flex-row place-items-center gap-2"
>
{prettySlug(content.attributes.slug, item.slug)}
</h2>
{content.attributes.scan_set.length > 0 ? (
<div
key={`items${content.id}`}
className="grid gap-8 items-end mobile:grid-cols-2 desktop:grid-cols-[repeat(auto-fill,_minmax(10rem,1fr))] pb-12 border-b-[3px] border-dotted last-of-type:border-0"
>
{content.attributes.scan_set[0].pages.data.map((page, index) => (
<div
key={page.id}
className="drop-shadow-shade-lg hover:scale-[1.02] cursor-pointer transition-transform"
onClick={() => {
setLightboxOpen(true);
setLightboxImages(
content.attributes.scan_set[0].pages.data.map((image) =>
getAssetURL(image.attributes.url, ImageQuality.Large)
)
);
setLightboxIndex(index);
}}
>
<Img image={page.attributes} quality={ImageQuality.Small} />
</div>
))}
</div>
) : (
<div className="pb-12 border-b-[3px] border-dotted last-of-type:border-0">
<LanguageSwitcher
locales={content.attributes.scan_set_languages.map(
(language) => language.language.data.attributes.code
)}
languages={props.languages}
langui={props.langui}
href={`#${content.attributes.slug}`}
/>
</div>
)}
</>
))}
</ContentPanel>
);
return (
<AppLayout
navTitle={langui.library}
title={prettyinlineTitle("", item.title, item.subtitle)}
contentPanel={contentPanel}
subPanel={subPanel}
thumbnail={item.thumbnail.data?.attributes}
{...props}
/>
);
}
export async function getStaticProps(
context: GetStaticPropsContext
): Promise<{ props: Props }> {
const item = (
await getLibraryItemScans({
slug: context.params?.slug?.toString() ?? "",
language_code: context.locale ?? "en",
})
).libraryItems.data[0];
const props: Props = {
...(await getAppStaticProps(context)),
item: item.attributes,
itemId: item.id,
};
return {
props: props,
};
}
export async function getStaticPaths(
context: GetStaticPathsContext
): Promise<GetStaticPathsResult> {
const libraryItems = await getLibraryItemsSlugs({});
const paths: GetStaticPathsResult["paths"] = [];
libraryItems.libraryItems.data.map((item) => {
context.locales?.map((local) => {
paths.push({ params: { slug: item.attributes.slug }, locale: local });
});
});
return {
paths,
fallback: false,
};
}

View File

@ -12,7 +12,7 @@ import ContentPanel from "components/Panels/ContentPanel";
import SubPanel from "components/Panels/SubPanel";
import RecorderChip from "components/RecorderChip";
import ToolTip from "components/ToolTip";
import { getPost, getPostLanguages, getPostsSlugs } from "graphql/operations";
import { getPost, getPostsSlugs } from "graphql/operations";
import { GetPostQuery, StrapiImage } from "graphql/operations-types";
import {
GetStaticPathsContext,
@ -21,16 +21,20 @@ import {
} from "next";
import { useRouter } from "next/router";
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
import { getStatusDescription, prettySlug } from "queries/helpers";
import {
getLocalesFromLanguages,
getStatusDescription,
prettySlug,
} from "queries/helpers";
interface PostProps extends AppStaticProps {
post: GetPostQuery["posts"]["data"][number]["attributes"];
postId: GetPostQuery["posts"]["data"][number]["id"];
locales: string[];
}
export default function LibrarySlug(props: PostProps): JSX.Element {
const { post, locales, langui } = props;
const { post, langui } = props;
const locales = getLocalesFromLanguages(post.translations_languages);
const router = useRouter();
const thumbnail: StrapiImage | undefined =
@ -79,7 +83,6 @@ export default function LibrarySlug(props: PostProps): JSX.Element {
{post.translations.length > 0 && post.translations[0].body && (
<TOC
text={post.translations[0].body}
router={router}
title={post.translations[0].title}
/>
)}
@ -114,11 +117,10 @@ export default function LibrarySlug(props: PostProps): JSX.Element {
<HorizontalLine />
{locales.includes(router.locale ?? "en") ? (
<Markdawn router={router} text={post.translations[0].body} />
<Markdawn text={post.translations[0].body} />
) : (
<LanguageSwitcher
locales={locales}
router={router}
languages={props.languages}
langui={props.langui}
/>
@ -156,11 +158,6 @@ export async function getStaticProps(
...(await getAppStaticProps(context)),
post: post.attributes,
postId: post.id,
locales: (
await getPostLanguages({ slug: slug })
).posts.data[0].attributes.translations.map(
(translation) => translation.language.data.attributes.code
),
};
return {
props: props,

View File

@ -7,6 +7,7 @@ import ReturnButton, {
} from "components/PanelComponents/ReturnButton";
import ContentPanel from "components/Panels/ContentPanel";
import SubPanel from "components/Panels/SubPanel";
import { useAppLayout } from "contexts/AppLayoutContext";
import { getChronologyItems, getEras } from "graphql/operations";
import {
GetChronologyItemsQuery,
@ -29,6 +30,7 @@ interface ChronologyProps extends AppStaticProps {
export default function Chronology(props: ChronologyProps): JSX.Element {
useTesting(props);
const { chronologyItems, chronologyEras, langui } = props;
const appLayout = useAppLayout();
// Group by year the Chronology items
const chronologyItemYearGroups: GetChronologyItemsQuery["chronologyItems"]["data"][number][][][] =
@ -83,6 +85,7 @@ export default function Chronology(props: ChronologyProps): JSX.Element {
}
subtitle={`${era.attributes.starting_year}${era.attributes.ending_year}`}
border
onClick={() => appLayout.setSubPanelOpen(false)}
/>
))}
</SubPanel>

View File

@ -232,9 +232,13 @@ export function getOgImage(quality: ImageQuality, image: StrapiImage): OgImage {
};
}
export function sortContent(
contents: GetLibraryItemQuery["libraryItems"]["data"][number]["attributes"]["contents"]
) {
export function sortContent(contents: {
data: {
attributes: {
range: GetLibraryItemQuery["libraryItems"]["data"][number]["attributes"]["contents"]["data"][number]["attributes"]["range"];
};
}[];
}) {
contents.data.sort((a, b) => {
if (
a.attributes.range[0].__typename === "ComponentRangePageRange" &&
@ -294,3 +298,17 @@ export function slugify(string: string | undefined): string {
export function randomInt(min: number, max: number) {
return Math.floor(Math.random() * (max - min)) + min;
}
export function getLocalesFromLanguages(
languages: {
language: {
data: {
attributes: {
code: string;
};
};
};
}[]
) {
return languages.map((language) => language.language.data.attributes.code);
}