Added testing and display recorders info
This commit is contained in:
		
							parent
							
								
									1e85f99d55
								
							
						
					
					
						commit
						a085a8b95c
					
				
							
								
								
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -1,5 +1,7 @@ | ||||
| # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. | ||||
| 
 | ||||
| /testing_logs/* | ||||
| 
 | ||||
| # dependencies | ||||
| /node_modules | ||||
| /.pnp | ||||
| @ -35,3 +37,5 @@ yarn-error.log* | ||||
| 
 | ||||
| # typescript | ||||
| *.tsbuildinfo | ||||
| 
 | ||||
| !.gitkeep | ||||
|  | ||||
							
								
								
									
										32
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										32
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							| @ -4,6 +4,7 @@ | ||||
|   "requires": true, | ||||
|   "packages": { | ||||
|     "": { | ||||
|       "name": "accords-library.com", | ||||
|       "dependencies": { | ||||
|         "@fontsource/material-icons": "^4.5.2", | ||||
|         "@fontsource/material-icons-rounded": "^4.5.2", | ||||
| @ -21,6 +22,7 @@ | ||||
|         "@tailwindcss/typography": "^0.5.2", | ||||
|         "@types/node": "17.0.18", | ||||
|         "@types/react": "17.0.39", | ||||
|         "@types/react-dom": "^17.0.11", | ||||
|         "eslint": "8.9.0", | ||||
|         "eslint-config-next": "12.1.0", | ||||
|         "tailwindcss": "^3.0.23", | ||||
| @ -496,6 +498,15 @@ | ||||
|         "csstype": "^3.0.2" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/@types/react-dom": { | ||||
|       "version": "17.0.11", | ||||
|       "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.11.tgz", | ||||
|       "integrity": "sha512-f96K3k+24RaLGVu/Y2Ng3e1EbZ8/cVJvypZWd7cy0ofCBaf2lcM46xNhycMZ2xGwbBjRql7hOlZ+e2WlJ5MH3Q==", | ||||
|       "dev": true, | ||||
|       "dependencies": { | ||||
|         "@types/react": "*" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/@types/scheduler": { | ||||
|       "version": "0.16.2", | ||||
|       "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", | ||||
| @ -976,7 +987,6 @@ | ||||
|       "dependencies": { | ||||
|         "anymatch": "~3.1.2", | ||||
|         "braces": "~3.0.2", | ||||
|         "fsevents": "~2.3.2", | ||||
|         "glob-parent": "~5.1.2", | ||||
|         "is-binary-path": "~2.1.0", | ||||
|         "is-glob": "~4.0.1", | ||||
| @ -2510,17 +2520,6 @@ | ||||
|       "integrity": "sha512-s885kWvnIlxsUFHq9UGyIyLiuD0G3BUC/xrH0CEnH5lHEWkwQcHOORgbDF0hbrW9vr/7am4ETfX4A7M6DjrE7Q==", | ||||
|       "dependencies": { | ||||
|         "@next/env": "12.1.0", | ||||
|         "@next/swc-android-arm64": "12.1.0", | ||||
|         "@next/swc-darwin-arm64": "12.1.0", | ||||
|         "@next/swc-darwin-x64": "12.1.0", | ||||
|         "@next/swc-linux-arm-gnueabihf": "12.1.0", | ||||
|         "@next/swc-linux-arm64-gnu": "12.1.0", | ||||
|         "@next/swc-linux-arm64-musl": "12.1.0", | ||||
|         "@next/swc-linux-x64-gnu": "12.1.0", | ||||
|         "@next/swc-linux-x64-musl": "12.1.0", | ||||
|         "@next/swc-win32-arm64-msvc": "12.1.0", | ||||
|         "@next/swc-win32-ia32-msvc": "12.1.0", | ||||
|         "@next/swc-win32-x64-msvc": "12.1.0", | ||||
|         "caniuse-lite": "^1.0.30001283", | ||||
|         "postcss": "8.4.5", | ||||
|         "styled-jsx": "5.0.0", | ||||
| @ -3986,6 +3985,15 @@ | ||||
|         "csstype": "^3.0.2" | ||||
|       } | ||||
|     }, | ||||
|     "@types/react-dom": { | ||||
|       "version": "17.0.11", | ||||
|       "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.11.tgz", | ||||
|       "integrity": "sha512-f96K3k+24RaLGVu/Y2Ng3e1EbZ8/cVJvypZWd7cy0ofCBaf2lcM46xNhycMZ2xGwbBjRql7hOlZ+e2WlJ5MH3Q==", | ||||
|       "dev": true, | ||||
|       "requires": { | ||||
|         "@types/react": "*" | ||||
|       } | ||||
|     }, | ||||
|     "@types/scheduler": { | ||||
|       "version": "0.16.2", | ||||
|       "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", | ||||
|  | ||||
| @ -5,8 +5,7 @@ | ||||
|     "dev": "next dev", | ||||
|     "build": "next build", | ||||
|     "start": "next start", | ||||
|     "lint": "next lint", | ||||
|     "text": "NODE_ENV=test next build" | ||||
|     "lint": "next lint" | ||||
|   }, | ||||
|   "dependencies": { | ||||
|     "@fontsource/material-icons": "^4.5.2", | ||||
| @ -25,6 +24,7 @@ | ||||
|     "@tailwindcss/typography": "^0.5.2", | ||||
|     "@types/node": "17.0.18", | ||||
|     "@types/react": "17.0.39", | ||||
|     "@types/react-dom": "^17.0.11", | ||||
|     "eslint": "8.9.0", | ||||
|     "eslint-config-next": "12.1.0", | ||||
|     "tailwindcss": "^3.0.23", | ||||
|  | ||||
| @ -1,11 +1,10 @@ | ||||
| { | ||||
|   "name": "Accord's Library", | ||||
|   "short_name": "Accord's Lib", | ||||
|   "start_url": ".", | ||||
|   "display": "standalone", | ||||
|   "background_color": "#FFEDD8", | ||||
|   "theme_color": "#FFEDD8", | ||||
|   "categories": ["books", "education", "entertainment", "news", "games"], | ||||
|   "description": "Accord's Library aims at gathering and archiving all of Yoko Taro’s work. Yoko Taro is a Japanese video game director and scenario writer.", | ||||
|   "dir": "auto", | ||||
|   "display": "fullscreen", | ||||
| 
 | ||||
|   "icons": [ | ||||
|     { | ||||
|       "src": "/android-chrome-192x192.png", | ||||
| @ -17,5 +16,44 @@ | ||||
|       "sizes": "512x512", | ||||
|       "type": "image/png" | ||||
|     } | ||||
|   ] | ||||
|   ], | ||||
| 
 | ||||
|   "name": "Accord's Library", | ||||
|   "short_name": "Accord's Lib", | ||||
|   "start_url": ".", | ||||
| 
 | ||||
|   "shortcuts": [ | ||||
|     { | ||||
|       "name": "Library", | ||||
|       "url": "/library", | ||||
|       "description": "Browse all physical and digital media" | ||||
|     }, | ||||
|     { | ||||
|       "name": "Contents", | ||||
|       "url": "/contents", | ||||
|       "description": "Explore all content and filter by type or category" | ||||
|     }, | ||||
|     { | ||||
|       "name": "Wiki", | ||||
|       "url": "/wiki", | ||||
|       "description": "An encyclopedia for everything related to DrakeNieR" | ||||
|     }, | ||||
|     { | ||||
|       "name": "Chronicles", | ||||
|       "url": "/chronicles", | ||||
|       "description": "Experience all events and content in chronological order" | ||||
|     }, | ||||
|     { | ||||
|       "name": "News", | ||||
|       "url": "/news", | ||||
|       "description": "All the latest info" | ||||
|     }, | ||||
|     { | ||||
|       "name": "Gallery", | ||||
|       "url": "/gallery", | ||||
|       "description": "Thousands of offcial artworks" | ||||
|     } | ||||
|   ], | ||||
| 
 | ||||
|   "theme_color": "#FFEDD8" | ||||
| } | ||||
|  | ||||
| @ -1 +1 @@ | ||||
| npx next build | ||||
| npx next build | ||||
							
								
								
									
										2
									
								
								run_accords_testing.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										2
									
								
								run_accords_testing.sh
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,2 @@ | ||||
| NODE_ENV=test | ||||
| npx next build |& tee ./testing_logs/$(date +"%Y-%m-%d---%H-%M-%S").log | ||||
| @ -7,7 +7,7 @@ import Head from "next/head"; | ||||
| import { useSwipeable } from "react-swipeable"; | ||||
| import { useRouter } from "next/router"; | ||||
| import Button from "components/Button"; | ||||
| import { getOgImage, prettyLanguage } from "queries/helpers"; | ||||
| import { getOgImage, OgImage, prettyLanguage } from "queries/helpers"; | ||||
| import { useMediaCoarse, useMediaMobile } from "hooks/useMediaQuery"; | ||||
| import ReactTooltip from "react-tooltip"; | ||||
| import { useAppLayout } from "contexts/AppLayoutContext"; | ||||
| @ -22,10 +22,10 @@ type AppLayoutProps = { | ||||
|   navTitle: string; | ||||
|   thumbnail?: StrapiImage; | ||||
|   description?: string; | ||||
|   extra?: React.ReactNode; | ||||
| }; | ||||
| 
 | ||||
| export default function AppLayout(props: AppLayoutProps): JSX.Element { | ||||
|   const titlePrefix = "Accord’s Library"; | ||||
|   const router = useRouter(); | ||||
|   const isMobile = useMediaMobile(); | ||||
|   const isCoarse = useMediaCoarse(); | ||||
| @ -75,9 +75,21 @@ export default function AppLayout(props: AppLayoutProps): JSX.Element { | ||||
| 
 | ||||
|   const turnSubIntoContent = props.subPanel && !props.contentPanel; | ||||
| 
 | ||||
|   const ogImage = getOgImage(ImageQuality.Og, props.thumbnail); | ||||
|   const titlePrefix = "Accord’s Library"; | ||||
|   const metaImage: OgImage = props.thumbnail | ||||
|     ? getOgImage(ImageQuality.Og, props.thumbnail) | ||||
|     : { | ||||
|         image: "/default_og.jpg", | ||||
|         width: 1200, | ||||
|         height: 630, | ||||
|         alt: "Accord's Library Logo", | ||||
|       }; | ||||
|   const ogTitle = props.title ? props.title : props.navTitle; | ||||
| 
 | ||||
|   const metaDescription = props.description | ||||
|     ? props.description | ||||
|     : "Accord's Library aims at gathering and archiving all of Yoko Taro’s work. Yoko Taro is a Japanese video game director and scenario writer."; | ||||
| 
 | ||||
|   return ( | ||||
|     <div className={appLayout.darkMode ? "set-theme-dark" : "set-theme-light"}> | ||||
|       <div | ||||
| @ -94,36 +106,26 @@ export default function AppLayout(props: AppLayoutProps): JSX.Element { | ||||
| 
 | ||||
|           {props.description && ( | ||||
|             <> | ||||
|               <meta name="description" content={props.description} /> | ||||
|               <meta | ||||
|                 name="twitter:description" | ||||
|                 content={props.description} | ||||
|               ></meta> | ||||
|               <meta name="description" content={metaDescription} /> | ||||
|               <meta name="twitter:description" content={metaDescription}></meta> | ||||
|             </> | ||||
|           )} | ||||
| 
 | ||||
|           {ogImage && ( | ||||
|             <> | ||||
|               <meta property="og:image" content={ogImage.image}></meta> | ||||
|               <meta | ||||
|                 property="og:image:secure_url" | ||||
|                 content={ogImage.image} | ||||
|               ></meta> | ||||
|               <meta | ||||
|                 property="og:image:width" | ||||
|                 content={ogImage.width.toString()} | ||||
|               ></meta> | ||||
|               <meta | ||||
|                 property="og:image:height" | ||||
|                 content={ogImage.height.toString()} | ||||
|               ></meta> | ||||
|               <meta property="og:image:alt" content={ogImage.alt}></meta> | ||||
|               <meta property="og:image:type" content="image/jpeg"></meta> | ||||
|               <meta name="twitter:card" content="summary_large_image"></meta> | ||||
|           <meta property="og:image" content={metaImage.image}></meta> | ||||
|           <meta property="og:image:secure_url" content={metaImage.image}></meta> | ||||
|           <meta | ||||
|             property="og:image:width" | ||||
|             content={metaImage.width.toString()} | ||||
|           ></meta> | ||||
|           <meta | ||||
|             property="og:image:height" | ||||
|             content={metaImage.height.toString()} | ||||
|           ></meta> | ||||
|           <meta property="og:image:alt" content={metaImage.alt}></meta> | ||||
|           <meta property="og:image:type" content="image/jpeg"></meta> | ||||
|           <meta name="twitter:card" content="summary_large_image"></meta> | ||||
| 
 | ||||
|               <meta name="twitter:image" content={ogImage.image}></meta> | ||||
|             </> | ||||
|           )} | ||||
|           <meta name="twitter:image" content={metaImage.image}></meta> | ||||
|         </Head> | ||||
| 
 | ||||
|         {/* Navbar */} | ||||
| @ -263,6 +265,8 @@ export default function AppLayout(props: AppLayoutProps): JSX.Element { | ||||
|           className="drop-shadow-shade-xl !opacity-100 !bg-light !rounded-lg after:!border-r-light text-left !text-black" | ||||
|         /> | ||||
|       </div> | ||||
| 
 | ||||
|       {props.extra} | ||||
|     </div> | ||||
|   ); | ||||
| } | ||||
|  | ||||
| @ -1,12 +1,25 @@ | ||||
| type ChipProps = { | ||||
|   className?: string; | ||||
|   children: React.ReactChild | React.ReactChild[]; | ||||
|   "data-tip"?: string; | ||||
|   "data-for"?: string; | ||||
|   "data-html"?: boolean; | ||||
|   "data-multiline"?: boolean; | ||||
| }; | ||||
| 
 | ||||
| export default function Chip(props: ChipProps): JSX.Element { | ||||
|   return ( | ||||
|     <div | ||||
|       className={`grid place-content-center place-items-center text-xs pb-[0.14rem] px-1.5 border-[1px] rounded-full opacity-70 ${props.className}`} | ||||
|       className={`grid place-content-center place-items-center text-xs pb-[0.14rem] px-1.5 border-[1px] rounded-full opacity-70 transition-[color,_opacity,border-color] ${ | ||||
|         props.className | ||||
|       } ${ | ||||
|         props["data-tip"] && | ||||
|         "hover:text-dark hover:border-dark hover:opacity-100" | ||||
|       }`}
 | ||||
|       data-tip={props["data-tip"]} | ||||
|       data-for={props["data-for"]} | ||||
|       data-html={props["data-html"]} | ||||
|       data-multiline={props["data-multiline"]} | ||||
|     > | ||||
|       {props.children} | ||||
|     </div> | ||||
|  | ||||
| @ -87,7 +87,7 @@ export default function ChronologyItemComponent( | ||||
|                 <div className="place-items-start place-content-start grid grid-flow-col gap-2"> | ||||
|                   {translation.status !== | ||||
|                     Enum_Componenttranslationschronologyitem_Status.Done && ( | ||||
|                     <div | ||||
|                     <Chip | ||||
|                       data-tip={ | ||||
|                         translation.status === | ||||
|                         Enum_Componenttranslationschronologyitem_Status.Incomplete | ||||
| @ -102,8 +102,8 @@ export default function ChronologyItemComponent( | ||||
|                       } | ||||
|                       data-for={"ChronologyTooltip"} | ||||
|                     > | ||||
|                       <Chip>{translation.status}</Chip> | ||||
|                     </div> | ||||
|                       {translation.status} | ||||
|                     </Chip> | ||||
|                   )} | ||||
|                   {translation.title ? <h3>{translation.title}</h3> : ""} | ||||
|                 </div> | ||||
|  | ||||
| @ -5,6 +5,7 @@ import { | ||||
| import { prettySlug } from "queries/helpers"; | ||||
| import Button from "components/Button"; | ||||
| import Img, { ImageQuality } from "components/Img"; | ||||
| import InsetBox from "components/InsetBox"; | ||||
| 
 | ||||
| export type ThumbnailHeaderProps = { | ||||
|   content: { | ||||
| @ -25,7 +26,7 @@ export default function ThumbnailHeader( | ||||
| 
 | ||||
|   return ( | ||||
|     <> | ||||
|       <div className="grid place-items-center gap-12  mb-12"> | ||||
|       <div className="grid place-items-center gap-12 mb-12"> | ||||
|         <div className="drop-shadow-shade-lg"> | ||||
|           {content.thumbnail.data ? ( | ||||
|             <Img | ||||
| @ -76,6 +77,9 @@ export default function ThumbnailHeader( | ||||
|           "" | ||||
|         )} | ||||
|       </div> | ||||
|       {content.titles.length > 0 && content.titles[0].description && ( | ||||
|         <InsetBox className="mt-8">{content.titles[0].description}</InsetBox> | ||||
|       )} | ||||
|     </> | ||||
|   ); | ||||
| } | ||||
|  | ||||
| @ -56,6 +56,7 @@ type ImgProps = { | ||||
|   layout?: ImageProps["layout"]; | ||||
|   objectFit?: ImageProps["objectFit"]; | ||||
|   priority?: ImageProps["priority"]; | ||||
|   rawImg?: boolean; | ||||
| }; | ||||
| 
 | ||||
| export default function Img(props: ImgProps): JSX.Element { | ||||
| @ -64,20 +65,37 @@ export default function Img(props: ImgProps): JSX.Element { | ||||
|     props.image.height, | ||||
|     props.quality ? props.quality : ImageQuality.Small | ||||
|   ); | ||||
|   return ( | ||||
|     <Image | ||||
|       className={props.className} | ||||
|       src={getAssetURL( | ||||
|         props.image.url, | ||||
|         props.quality ? props.quality : ImageQuality.Small | ||||
|       )} | ||||
|       alt={props.alt ? props.alt : props.image.alternativeText} | ||||
|       width={props.layout === "fill" ? undefined : imgSize.width} | ||||
|       height={props.layout === "fill" ? undefined : imgSize.height} | ||||
|       layout={props.layout} | ||||
|       objectFit={props.objectFit} | ||||
|       priority={props.priority} | ||||
|       unoptimized | ||||
|     /> | ||||
|   ); | ||||
| 
 | ||||
|   if (props.rawImg) { | ||||
|     return ( | ||||
|       // eslint-disable-next-line @next/next/no-img-element
 | ||||
|       <img | ||||
|         className={props.className} | ||||
|         src={getAssetURL( | ||||
|           props.image.url, | ||||
|           props.quality ? props.quality : ImageQuality.Small | ||||
|         )} | ||||
|         alt={props.alt ? props.alt : props.image.alternativeText} | ||||
|         width={imgSize.width} | ||||
|         height={imgSize.height} | ||||
|       /> | ||||
|     ); | ||||
|   } else { | ||||
|     return ( | ||||
|       <Image | ||||
|         className={props.className} | ||||
|         src={getAssetURL( | ||||
|           props.image.url, | ||||
|           props.quality ? props.quality : ImageQuality.Small | ||||
|         )} | ||||
|         alt={props.alt ? props.alt : props.image.alternativeText} | ||||
|         width={props.layout === "fill" ? undefined : imgSize.width} | ||||
|         height={props.layout === "fill" ? undefined : imgSize.height} | ||||
|         layout={props.layout} | ||||
|         objectFit={props.objectFit} | ||||
|         priority={props.priority} | ||||
|         unoptimized | ||||
|       /> | ||||
|     ); | ||||
|   } | ||||
| } | ||||
|  | ||||
| @ -1,6 +1,7 @@ | ||||
| import { useRouter } from "next/router"; | ||||
| import Link from "next/link"; | ||||
| import { MouseEventHandler } from "react"; | ||||
| import ReactDOMServer from "react-dom/server"; | ||||
| 
 | ||||
| type NavOptionProps = { | ||||
|   url: string; | ||||
| @ -29,16 +30,14 @@ export default function NavOption(props: NavOptionProps): JSX.Element { | ||||
|         onClick={props.onClick} | ||||
|         data-html | ||||
|         data-multiline | ||||
|         data-tip={` | ||||
|           <div class="px-4 py-3"> | ||||
|           <h3 class="text-2xl">${props.title}</h3> | ||||
|           ${ | ||||
|             props.subtitle | ||||
|               ? `<p class="max-w-[10rem]">${props.subtitle}</p>` | ||||
|               : "" | ||||
|           } | ||||
|         data-tip={ReactDOMServer.renderToStaticMarkup( | ||||
|           <div className="px-4 py-3"> | ||||
|             <h3 className="text-2xl">{props.title}</h3> | ||||
|             {props.subtitle && ( | ||||
|               <p className="max-w-[10rem]">{props.subtitle}</p> | ||||
|             )} | ||||
|           </div> | ||||
|         `}
 | ||||
|         )} | ||||
|         data-for={props.tooltipId} | ||||
|         className={`grid grid-flow-col grid-cols-[auto] auto-cols-fr justify-center ${ | ||||
|           props.icon ? "text-left" : "text-center" | ||||
|  | ||||
| @ -183,6 +183,7 @@ export default function MainPanel(props: MainPanelProps): JSX.Element { | ||||
|           )} | ||||
|         </p> | ||||
|         <a | ||||
|           aria-label="Read more about the license we use for this website" | ||||
|           className="transition-[filter] colorize-black hover:colorize-dark" | ||||
|           href="https://creativecommons.org/licenses/by-sa/4.0/" | ||||
|         > | ||||
| @ -201,12 +202,14 @@ export default function MainPanel(props: MainPanelProps): JSX.Element { | ||||
|         </p> | ||||
|         <div className="mt-12 mb-4 grid h-4 grid-flow-col place-content-center gap-8"> | ||||
|           <a | ||||
|             aria-label="Browse our GitHub repository, which include this website source code" | ||||
|             className="transition-colors [mask:url('/icons/github-brands.svg')] ![mask-size:contain] ![mask-repeat:no-repeat] ![mask-position:center] w-10 aspect-square bg-black hover:bg-dark" | ||||
|             href="https://github.com/Accords-Library" | ||||
|             target="_blank" | ||||
|             rel="noopener noreferrer" | ||||
|           ></a> | ||||
|           <a | ||||
|             aria-label="Join our Discord server!" | ||||
|             className="transition-colors [mask:url('/icons/discord-brands.svg')] ![mask-size:contain] ![mask-repeat:no-repeat] ![mask-position:center] w-10 aspect-square bg-black hover:bg-dark" | ||||
|             href="/discord" | ||||
|             target="_blank" | ||||
|  | ||||
							
								
								
									
										60
									
								
								src/components/RecorderChip.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								src/components/RecorderChip.tsx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,60 @@ | ||||
| import Chip from "components/Chip"; | ||||
| import { GetContentTextQuery } from "graphql/operations-types"; | ||||
| import Img, { ImageQuality } from "./Img"; | ||||
| import ReactDOMServer from "react-dom/server"; | ||||
| 
 | ||||
| type RecorderChipProps = { | ||||
|   className?: string; | ||||
|   recorder: GetContentTextQuery["contents"]["data"][number]["attributes"]["text_set"][number]["transcribers"]["data"][number]; | ||||
| }; | ||||
| 
 | ||||
| export default function RecorderChip(props: RecorderChipProps): JSX.Element { | ||||
|   const recorder = props.recorder; | ||||
|   return ( | ||||
|     <Chip | ||||
|       key={recorder.id} | ||||
|       data-tip={ReactDOMServer.renderToStaticMarkup( | ||||
|         <div className="p-2 py-5 grid gap-2"> | ||||
|           <div className="grid grid-flow-col gap-2 place-items-center place-content-start"> | ||||
|             {recorder.attributes.avatar.data && ( | ||||
|               <Img | ||||
|                 className="w-8 rounded-full" | ||||
|                 image={recorder.attributes.avatar.data.attributes} | ||||
|                 quality={ImageQuality.Small} | ||||
|                 rawImg | ||||
|               /> | ||||
|             )} | ||||
|             <h3 className="text-xl">{recorder.attributes.username}</h3> | ||||
|           </div> | ||||
|           {recorder.attributes.languages.data.length > 0 && ( | ||||
|             <div className="flex flex-row flex-wrap gap-1"> | ||||
|               <p>Languages:</p> | ||||
|               {recorder.attributes.languages.data.map((language) => ( | ||||
|                 <Chip key={language.attributes.code}> | ||||
|                   {language.attributes.code.toUpperCase()} | ||||
|                 </Chip> | ||||
|               ))} | ||||
|             </div> | ||||
|           )} | ||||
|           {recorder.attributes.pronouns && ( | ||||
|             <div className="flex flex-row flex-wrap gap-1"> | ||||
|               <p>Pronouns:</p> | ||||
|               <Chip>{recorder.attributes.pronouns}</Chip> | ||||
|             </div> | ||||
|           )} | ||||
|           <p> | ||||
|             {recorder.attributes.bio.length > 0 && | ||||
|               recorder.attributes.bio[0].bio} | ||||
|           </p> | ||||
|         </div> | ||||
|       )} | ||||
|       data-for={"RecordersTooltip"} | ||||
|       data-multiline | ||||
|       data-html | ||||
|     > | ||||
|       {recorder.attributes.anonymize | ||||
|         ? `Recorder#${recorder.attributes.anonymous_code}` | ||||
|         : recorder.attributes.username} | ||||
|     </Chip> | ||||
|   ); | ||||
| } | ||||
| @ -73,7 +73,7 @@ query getWebsiteInterface($language_code: String) { | ||||
| } | ||||
| 
 | ||||
| query getEras($language_code: String) { | ||||
|   chronologyEras { | ||||
|   chronologyEras(sort: "starting_year") { | ||||
|     data { | ||||
|       id | ||||
|       attributes { | ||||
| @ -730,6 +730,7 @@ query getContent($slug: String, $language_code: String) { | ||||
|           pre_title | ||||
|           title | ||||
|           subtitle | ||||
|           description | ||||
|         } | ||||
|         categories { | ||||
|           data { | ||||
| @ -817,6 +818,7 @@ query getContentText($slug: String, $language_code: String) { | ||||
|           pre_title | ||||
|           title | ||||
|           subtitle | ||||
|           description | ||||
|         } | ||||
|         categories { | ||||
|           data { | ||||
| @ -875,16 +877,28 @@ query getContentText($slug: String, $language_code: String) { | ||||
|           source_language { | ||||
|             data { | ||||
|               attributes { | ||||
|                 name | ||||
|                 code | ||||
|               } | ||||
|             } | ||||
|           } | ||||
|           transcribers { | ||||
|             data { | ||||
|               id | ||||
|               attributes { | ||||
|                 username | ||||
|                 anonymize | ||||
|                 anonymous_code | ||||
|                 pronouns | ||||
|                 bio(filters: { language: { code: { eq: $language_code } } }) { | ||||
|                   bio | ||||
|                 } | ||||
|                 languages { | ||||
|                   data { | ||||
|                     attributes { | ||||
|                       code | ||||
|                     } | ||||
|                   } | ||||
|                 } | ||||
|                 avatar { | ||||
|                   data { | ||||
|                     attributes { | ||||
| @ -902,10 +916,22 @@ query getContentText($slug: String, $language_code: String) { | ||||
|           } | ||||
|           translators { | ||||
|             data { | ||||
|               id | ||||
|               attributes { | ||||
|                 username | ||||
|                 anonymize | ||||
|                 anonymous_code | ||||
|                 pronouns | ||||
|                 bio(filters: { language: { code: { eq: $language_code } } }) { | ||||
|                   bio | ||||
|                 } | ||||
|                 languages { | ||||
|                   data { | ||||
|                     attributes { | ||||
|                       code | ||||
|                     } | ||||
|                   } | ||||
|                 } | ||||
|                 avatar { | ||||
|                   data { | ||||
|                     attributes { | ||||
| @ -923,10 +949,22 @@ query getContentText($slug: String, $language_code: String) { | ||||
|           } | ||||
|           proofreaders { | ||||
|             data { | ||||
|               id | ||||
|               attributes { | ||||
|                 username | ||||
|                 anonymize | ||||
|                 anonymous_code | ||||
|                 pronouns | ||||
|                 bio(filters: { language: { code: { eq: $language_code } } }) { | ||||
|                   bio | ||||
|                 } | ||||
|                 languages { | ||||
|                   data { | ||||
|                     attributes { | ||||
|                       code | ||||
|                     } | ||||
|                   } | ||||
|                 } | ||||
|                 avatar { | ||||
|                   data { | ||||
|                     attributes { | ||||
|  | ||||
| @ -996,6 +996,7 @@ export type GetContentQuery = { | ||||
|           pre_title: string; | ||||
|           title: string; | ||||
|           subtitle: string; | ||||
|           description: string; | ||||
|         }>; | ||||
|         categories: { | ||||
|           __typename: "CategoryRelationResponseCollection"; | ||||
| @ -1116,6 +1117,7 @@ export type GetContentTextQuery = { | ||||
|           pre_title: string; | ||||
|           title: string; | ||||
|           subtitle: string; | ||||
|           description: string; | ||||
|         }>; | ||||
|         categories: { | ||||
|           __typename: "CategoryRelationResponseCollection"; | ||||
| @ -1194,18 +1196,34 @@ export type GetContentTextQuery = { | ||||
|             __typename: "LanguageEntityResponse"; | ||||
|             data: { | ||||
|               __typename: "LanguageEntity"; | ||||
|               attributes: { __typename: "Language"; name: string }; | ||||
|               attributes: { __typename: "Language"; code: string }; | ||||
|             }; | ||||
|           }; | ||||
|           transcribers: { | ||||
|             __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: { | ||||
| @ -1228,11 +1246,27 @@ export type GetContentTextQuery = { | ||||
|             __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: { | ||||
| @ -1255,11 +1289,27 @@ export type GetContentTextQuery = { | ||||
|             __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: { | ||||
|  | ||||
| @ -398,6 +398,23 @@ type ComponentCollectionsComponentLibraryObiBelt { | ||||
|   inside_full: UploadFileEntityResponse | ||||
| } | ||||
| 
 | ||||
| input ComponentCollectionsComponentTitlesFiltersInput { | ||||
|   title: StringFilterInput | ||||
|   and: [ComponentCollectionsComponentTitlesFiltersInput] | ||||
|   or: [ComponentCollectionsComponentTitlesFiltersInput] | ||||
|   not: ComponentCollectionsComponentTitlesFiltersInput | ||||
| } | ||||
| 
 | ||||
| input ComponentCollectionsComponentTitlesInput { | ||||
|   id: ID | ||||
|   title: String | ||||
| } | ||||
| 
 | ||||
| type ComponentCollectionsComponentTitles { | ||||
|   id: ID! | ||||
|   title: String! | ||||
| } | ||||
| 
 | ||||
| input ComponentCollectionsComponentWeaponStoryFiltersInput { | ||||
|   source: SourceFiltersInput | ||||
|   categories: CategoryFiltersInput | ||||
| @ -428,6 +445,17 @@ type ComponentCollectionsComponentWeaponStory { | ||||
|   ): CategoryRelationResponseCollection | ||||
| } | ||||
| 
 | ||||
| type ComponentCollectionsComponentWikiDefinition { | ||||
|   id: ID! | ||||
|   definition: String | ||||
|   categories( | ||||
|     filters: CategoryFiltersInput | ||||
|     pagination: PaginationArg = {} | ||||
|     sort: [String] = [] | ||||
|   ): CategoryRelationResponseCollection | ||||
|   source: SourceEntityResponse | ||||
| } | ||||
| 
 | ||||
| type ComponentMetadataAudio { | ||||
|   id: ID! | ||||
|   subtype: AudioSubtypeEntityResponse | ||||
| @ -771,6 +799,69 @@ type ComponentSetsVideoSet { | ||||
|   notes: String | ||||
| } | ||||
| 
 | ||||
| enum ENUM_COMPONENTSETSWIKISET_STATUS { | ||||
|   Incomplete | ||||
|   Draft | ||||
|   Review | ||||
|   Done | ||||
| } | ||||
| 
 | ||||
| input ComponentSetsWikiSetFiltersInput { | ||||
|   language: LanguageFiltersInput | ||||
|   status: StringFilterInput | ||||
|   summary: StringFilterInput | ||||
|   body: StringFilterInput | ||||
|   source_language: LanguageFiltersInput | ||||
|   authors: RecorderFiltersInput | ||||
|   translators: RecorderFiltersInput | ||||
|   proofreaders: RecorderFiltersInput | ||||
|   and: [ComponentSetsWikiSetFiltersInput] | ||||
|   or: [ComponentSetsWikiSetFiltersInput] | ||||
|   not: ComponentSetsWikiSetFiltersInput | ||||
| } | ||||
| 
 | ||||
| input ComponentSetsWikiSetInput { | ||||
|   id: ID | ||||
|   language: ID | ||||
|   status: ENUM_COMPONENTSETSWIKISET_STATUS | ||||
|   titles: [ComponentCollectionsComponentTitlesInput] | ||||
|   summary: String | ||||
|   body: String | ||||
|   source_language: ID | ||||
|   authors: [ID] | ||||
|   translators: [ID] | ||||
|   proofreaders: [ID] | ||||
| } | ||||
| 
 | ||||
| type ComponentSetsWikiSet { | ||||
|   id: ID! | ||||
|   language: LanguageEntityResponse | ||||
|   status: ENUM_COMPONENTSETSWIKISET_STATUS! | ||||
|   titles( | ||||
|     filters: ComponentCollectionsComponentTitlesFiltersInput | ||||
|     pagination: PaginationArg = {} | ||||
|     sort: [String] = [] | ||||
|   ): [ComponentCollectionsComponentTitles] | ||||
|   summary: String | ||||
|   body: String | ||||
|   source_language: LanguageEntityResponse | ||||
|   authors( | ||||
|     filters: RecorderFiltersInput | ||||
|     pagination: PaginationArg = {} | ||||
|     sort: [String] = [] | ||||
|   ): RecorderRelationResponseCollection | ||||
|   translators( | ||||
|     filters: RecorderFiltersInput | ||||
|     pagination: PaginationArg = {} | ||||
|     sort: [String] = [] | ||||
|   ): RecorderRelationResponseCollection | ||||
|   proofreaders( | ||||
|     filters: RecorderFiltersInput | ||||
|     pagination: PaginationArg = {} | ||||
|     sort: [String] = [] | ||||
|   ): RecorderRelationResponseCollection | ||||
| } | ||||
| 
 | ||||
| type ComponentSourceUrlSource { | ||||
|   id: ID! | ||||
|   title: String | ||||
| @ -794,9 +885,30 @@ type ComponentTranslationsAudioSets { | ||||
|   credits: ComponentBasicsCredits! | ||||
| } | ||||
| 
 | ||||
| input ComponentTranslationsBioFiltersInput { | ||||
|   language: LanguageFiltersInput | ||||
|   bio: StringFilterInput | ||||
|   and: [ComponentTranslationsBioFiltersInput] | ||||
|   or: [ComponentTranslationsBioFiltersInput] | ||||
|   not: ComponentTranslationsBioFiltersInput | ||||
| } | ||||
| 
 | ||||
| input ComponentTranslationsBioInput { | ||||
|   id: ID | ||||
|   language: ID | ||||
|   bio: String | ||||
| } | ||||
| 
 | ||||
| type ComponentTranslationsBio { | ||||
|   id: ID! | ||||
|   language: LanguageEntityResponse | ||||
|   bio: String | ||||
| } | ||||
| 
 | ||||
| input ComponentTranslationsChronologyEraFiltersInput { | ||||
|   title: StringFilterInput | ||||
|   language: LanguageFiltersInput | ||||
|   description: StringFilterInput | ||||
|   and: [ComponentTranslationsChronologyEraFiltersInput] | ||||
|   or: [ComponentTranslationsChronologyEraFiltersInput] | ||||
|   not: ComponentTranslationsChronologyEraFiltersInput | ||||
| @ -806,12 +918,14 @@ input ComponentTranslationsChronologyEraInput { | ||||
|   id: ID | ||||
|   title: String | ||||
|   language: ID | ||||
|   description: String | ||||
| } | ||||
| 
 | ||||
| type ComponentTranslationsChronologyEra { | ||||
|   id: ID! | ||||
|   title: String | ||||
|   title: String! | ||||
|   language: LanguageEntityResponse | ||||
|   description: String | ||||
| } | ||||
| 
 | ||||
| enum ENUM_COMPONENTTRANSLATIONSCHRONOLOGYITEM_STATUS { | ||||
| @ -1017,6 +1131,7 @@ input ComponentTranslationsTitleFiltersInput { | ||||
|   title: StringFilterInput | ||||
|   subtitle: StringFilterInput | ||||
|   pre_title: StringFilterInput | ||||
|   description: StringFilterInput | ||||
|   and: [ComponentTranslationsTitleFiltersInput] | ||||
|   or: [ComponentTranslationsTitleFiltersInput] | ||||
|   not: ComponentTranslationsTitleFiltersInput | ||||
| @ -1028,6 +1143,7 @@ input ComponentTranslationsTitleInput { | ||||
|   title: String | ||||
|   subtitle: String | ||||
|   pre_title: String | ||||
|   description: String | ||||
| } | ||||
| 
 | ||||
| type ComponentTranslationsTitle { | ||||
| @ -1036,6 +1152,7 @@ type ComponentTranslationsTitle { | ||||
|   title: String! | ||||
|   subtitle: String | ||||
|   pre_title: String | ||||
|   description: String | ||||
| } | ||||
| 
 | ||||
| enum ENUM_COMPONENTTRANSLATIONSVIDEOSETS_STATUS { | ||||
| @ -2051,6 +2168,7 @@ input RecorderFiltersInput { | ||||
|   anonymize: BooleanFilterInput | ||||
|   anonymous_code: StringFilterInput | ||||
|   languages: LanguageFiltersInput | ||||
|   pronouns: StringFilterInput | ||||
|   createdAt: DateTimeFilterInput | ||||
|   updatedAt: DateTimeFilterInput | ||||
|   and: [RecorderFiltersInput] | ||||
| @ -2064,6 +2182,8 @@ input RecorderInput { | ||||
|   anonymous_code: String | ||||
|   avatar: ID | ||||
|   languages: [ID] | ||||
|   pronouns: String | ||||
|   bio: [ComponentTranslationsBioInput] | ||||
| } | ||||
| 
 | ||||
| type Recorder { | ||||
| @ -2076,6 +2196,12 @@ type Recorder { | ||||
|     pagination: PaginationArg = {} | ||||
|     sort: [String] = [] | ||||
|   ): LanguageRelationResponseCollection | ||||
|   pronouns: String | ||||
|   bio( | ||||
|     filters: ComponentTranslationsBioFiltersInput | ||||
|     pagination: PaginationArg = {} | ||||
|     sort: [String] = [] | ||||
|   ): [ComponentTranslationsBio] | ||||
|   createdAt: DateTime | ||||
|   updatedAt: DateTime | ||||
| } | ||||
| @ -2359,12 +2485,7 @@ input WebsiteInterfaceFiltersInput { | ||||
|   language: LanguageFiltersInput | ||||
|   main_library: StringFilterInput | ||||
|   main_library_description: StringFilterInput | ||||
|   main_hub: StringFilterInput | ||||
|   main_hub_description: StringFilterInput | ||||
|   main_chronology: StringFilterInput | ||||
|   main_chronology_description: StringFilterInput | ||||
|   main_news: StringFilterInput | ||||
|   main_data: StringFilterInput | ||||
|   main_merch: StringFilterInput | ||||
|   main_gallery: StringFilterInput | ||||
|   main_archives: StringFilterInput | ||||
| @ -2394,13 +2515,6 @@ input WebsiteInterfaceFiltersInput { | ||||
|   global_price: StringFilterInput | ||||
|   library_item_physical_size: StringFilterInput | ||||
|   library_item_type_information: StringFilterInput | ||||
|   chronology_description: StringFilterInput | ||||
|   chronology_timelines: StringFilterInput | ||||
|   chronology_timelines_description: StringFilterInput | ||||
|   chronology_overview: StringFilterInput | ||||
|   chronology_overview_description: StringFilterInput | ||||
|   chronology_walkthrough: StringFilterInput | ||||
|   chronology_walkthrough_description: StringFilterInput | ||||
|   library_item_front_matter: StringFilterInput | ||||
|   library_item_back_matter: StringFilterInput | ||||
|   library_item_type_textual: StringFilterInput | ||||
| @ -2419,6 +2533,21 @@ input WebsiteInterfaceFiltersInput { | ||||
|   global_hardcover: StringFilterInput | ||||
|   global_left_to_right: StringFilterInput | ||||
|   global_right_to_left: StringFilterInput | ||||
|   main_wiki: StringFilterInput | ||||
|   main_wiki_description: StringFilterInput | ||||
|   main_chronicles: StringFilterInput | ||||
|   main_chronicles_description: StringFilterInput | ||||
|   library_items: StringFilterInput | ||||
|   library_items_description: StringFilterInput | ||||
|   library_content: StringFilterInput | ||||
|   library_content_description: StringFilterInput | ||||
|   wiki_description: StringFilterInput | ||||
|   news_description: StringFilterInput | ||||
|   chronicles_description: StringFilterInput | ||||
|   gallery_description: StringFilterInput | ||||
|   archives_description: StringFilterInput | ||||
|   about_us_description: StringFilterInput | ||||
|   merch_description: StringFilterInput | ||||
|   createdAt: DateTimeFilterInput | ||||
|   updatedAt: DateTimeFilterInput | ||||
|   and: [WebsiteInterfaceFiltersInput] | ||||
| @ -2430,12 +2559,7 @@ input WebsiteInterfaceInput { | ||||
|   language: ID | ||||
|   main_library: String | ||||
|   main_library_description: String | ||||
|   main_hub: String | ||||
|   main_hub_description: String | ||||
|   main_chronology: String | ||||
|   main_chronology_description: String | ||||
|   main_news: String | ||||
|   main_data: String | ||||
|   main_merch: String | ||||
|   main_gallery: String | ||||
|   main_archives: String | ||||
| @ -2465,13 +2589,6 @@ input WebsiteInterfaceInput { | ||||
|   global_price: String | ||||
|   library_item_physical_size: String | ||||
|   library_item_type_information: String | ||||
|   chronology_description: String | ||||
|   chronology_timelines: String | ||||
|   chronology_timelines_description: String | ||||
|   chronology_overview: String | ||||
|   chronology_overview_description: String | ||||
|   chronology_walkthrough: String | ||||
|   chronology_walkthrough_description: String | ||||
|   library_item_front_matter: String | ||||
|   library_item_back_matter: String | ||||
|   library_item_type_textual: String | ||||
| @ -2490,18 +2607,28 @@ input WebsiteInterfaceInput { | ||||
|   global_hardcover: String | ||||
|   global_left_to_right: String | ||||
|   global_right_to_left: String | ||||
|   main_wiki: String | ||||
|   main_wiki_description: String | ||||
|   main_chronicles: String | ||||
|   main_chronicles_description: String | ||||
|   library_items: String | ||||
|   library_items_description: String | ||||
|   library_content: String | ||||
|   library_content_description: String | ||||
|   wiki_description: String | ||||
|   news_description: String | ||||
|   chronicles_description: String | ||||
|   gallery_description: String | ||||
|   archives_description: String | ||||
|   about_us_description: String | ||||
|   merch_description: String | ||||
| } | ||||
| 
 | ||||
| type WebsiteInterface { | ||||
|   language: LanguageEntityResponse | ||||
|   main_library: String | ||||
|   main_library_description: String | ||||
|   main_hub: String | ||||
|   main_hub_description: String | ||||
|   main_chronology: String | ||||
|   main_chronology_description: String | ||||
|   main_news: String | ||||
|   main_data: String | ||||
|   main_merch: String | ||||
|   main_gallery: String | ||||
|   main_archives: String | ||||
| @ -2531,13 +2658,6 @@ type WebsiteInterface { | ||||
|   global_price: String | ||||
|   library_item_physical_size: String | ||||
|   library_item_type_information: String | ||||
|   chronology_description: String | ||||
|   chronology_timelines: String | ||||
|   chronology_timelines_description: String | ||||
|   chronology_overview: String | ||||
|   chronology_overview_description: String | ||||
|   chronology_walkthrough: String | ||||
|   chronology_walkthrough_description: String | ||||
|   library_item_front_matter: String | ||||
|   library_item_back_matter: String | ||||
|   library_item_type_textual: String | ||||
| @ -2556,6 +2676,21 @@ type WebsiteInterface { | ||||
|   global_hardcover: String | ||||
|   global_left_to_right: String | ||||
|   global_right_to_left: String | ||||
|   main_wiki: String | ||||
|   main_wiki_description: String | ||||
|   main_chronicles: String | ||||
|   main_chronicles_description: String | ||||
|   library_items: String | ||||
|   library_items_description: String | ||||
|   library_content: String | ||||
|   library_content_description: String | ||||
|   wiki_description: String | ||||
|   news_description: String | ||||
|   chronicles_description: String | ||||
|   gallery_description: String | ||||
|   archives_description: String | ||||
|   about_us_description: String | ||||
|   merch_description: String | ||||
|   createdAt: DateTime | ||||
|   updatedAt: DateTime | ||||
| } | ||||
| @ -2574,6 +2709,91 @@ type WebsiteInterfaceEntityResponseCollection { | ||||
|   meta: ResponseCollectionMeta! | ||||
| } | ||||
| 
 | ||||
| input WikiPageFiltersInput { | ||||
|   id: IDFilterInput | ||||
|   slug: StringFilterInput | ||||
|   type: WikiPageTypeFiltersInput | ||||
|   createdAt: DateTimeFilterInput | ||||
|   updatedAt: DateTimeFilterInput | ||||
|   and: [WikiPageFiltersInput] | ||||
|   or: [WikiPageFiltersInput] | ||||
|   not: WikiPageFiltersInput | ||||
| } | ||||
| 
 | ||||
| input WikiPageInput { | ||||
|   slug: String | ||||
|   thumbnail: ID | ||||
|   wiki_set: [ComponentSetsWikiSetInput] | ||||
|   type: ID | ||||
| } | ||||
| 
 | ||||
| type WikiPage { | ||||
|   slug: String! | ||||
|   thumbnail: UploadFileEntityResponse | ||||
|   wiki_set( | ||||
|     filters: ComponentSetsWikiSetFiltersInput | ||||
|     pagination: PaginationArg = {} | ||||
|     sort: [String] = [] | ||||
|   ): [ComponentSetsWikiSet] | ||||
|   type: WikiPageTypeEntityResponse | ||||
|   createdAt: DateTime | ||||
|   updatedAt: DateTime | ||||
| } | ||||
| 
 | ||||
| type WikiPageEntity { | ||||
|   id: ID | ||||
|   attributes: WikiPage | ||||
| } | ||||
| 
 | ||||
| type WikiPageEntityResponse { | ||||
|   data: WikiPageEntity | ||||
| } | ||||
| 
 | ||||
| type WikiPageEntityResponseCollection { | ||||
|   data: [WikiPageEntity!]! | ||||
|   meta: ResponseCollectionMeta! | ||||
| } | ||||
| 
 | ||||
| input WikiPageTypeFiltersInput { | ||||
|   id: IDFilterInput | ||||
|   slug: StringFilterInput | ||||
|   createdAt: DateTimeFilterInput | ||||
|   updatedAt: DateTimeFilterInput | ||||
|   and: [WikiPageTypeFiltersInput] | ||||
|   or: [WikiPageTypeFiltersInput] | ||||
|   not: WikiPageTypeFiltersInput | ||||
| } | ||||
| 
 | ||||
| input WikiPageTypeInput { | ||||
|   slug: String | ||||
|   titles: [ComponentTranslationsSimpleTitleInput] | ||||
| } | ||||
| 
 | ||||
| type WikiPageType { | ||||
|   slug: String! | ||||
|   titles( | ||||
|     filters: ComponentTranslationsSimpleTitleFiltersInput | ||||
|     pagination: PaginationArg = {} | ||||
|     sort: [String] = [] | ||||
|   ): [ComponentTranslationsSimpleTitle] | ||||
|   createdAt: DateTime | ||||
|   updatedAt: DateTime | ||||
| } | ||||
| 
 | ||||
| type WikiPageTypeEntity { | ||||
|   id: ID | ||||
|   attributes: WikiPageType | ||||
| } | ||||
| 
 | ||||
| type WikiPageTypeEntityResponse { | ||||
|   data: WikiPageTypeEntity | ||||
| } | ||||
| 
 | ||||
| type WikiPageTypeEntityResponseCollection { | ||||
|   data: [WikiPageTypeEntity!]! | ||||
|   meta: ResponseCollectionMeta! | ||||
| } | ||||
| 
 | ||||
| union GenericMorph = | ||||
|     ComponentBasicsCredits | ||||
|   | ComponentBasicsDatepicker | ||||
| @ -2585,7 +2805,9 @@ union GenericMorph = | ||||
|   | ComponentCollectionsComponentLibraryDustJacket | ||||
|   | ComponentCollectionsComponentLibraryImages | ||||
|   | ComponentCollectionsComponentLibraryObiBelt | ||||
|   | ComponentCollectionsComponentTitles | ||||
|   | ComponentCollectionsComponentWeaponStory | ||||
|   | ComponentCollectionsComponentWikiDefinition | ||||
|   | ComponentMetadataAudio | ||||
|   | ComponentMetadataBooks | ||||
|   | ComponentMetadataGame | ||||
| @ -2606,8 +2828,10 @@ union GenericMorph = | ||||
|   | ComponentSetsScanSet | ||||
|   | ComponentSetsTextSet | ||||
|   | ComponentSetsVideoSet | ||||
|   | ComponentSetsWikiSet | ||||
|   | ComponentSourceUrlSource | ||||
|   | ComponentTranslationsAudioSets | ||||
|   | ComponentTranslationsBio | ||||
|   | ComponentTranslationsChronologyEra | ||||
|   | ComponentTranslationsChronologyItem | ||||
|   | ComponentTranslationsGlossaryDefinition | ||||
| @ -2648,6 +2872,8 @@ union GenericMorph = | ||||
|   | WeaponStoryGroup | ||||
|   | WeaponStoryType | ||||
|   | WebsiteInterface | ||||
|   | WikiPage | ||||
|   | WikiPageType | ||||
| 
 | ||||
| input FileInfoInput { | ||||
|   name: String | ||||
| @ -2814,6 +3040,18 @@ type Query { | ||||
|     pagination: PaginationArg = {} | ||||
|     sort: [String] = [] | ||||
|   ): WebsiteInterfaceEntityResponseCollection | ||||
|   wikiPage(id: ID): WikiPageEntityResponse | ||||
|   wikiPages( | ||||
|     filters: WikiPageFiltersInput | ||||
|     pagination: PaginationArg = {} | ||||
|     sort: [String] = [] | ||||
|   ): WikiPageEntityResponseCollection | ||||
|   wikiPageType(id: ID): WikiPageTypeEntityResponse | ||||
|   wikiPageTypes( | ||||
|     filters: WikiPageTypeFiltersInput | ||||
|     pagination: PaginationArg = {} | ||||
|     sort: [String] = [] | ||||
|   ): WikiPageTypeEntityResponseCollection | ||||
| } | ||||
| 
 | ||||
| type Mutation { | ||||
| @ -2939,6 +3177,15 @@ type Mutation { | ||||
|     data: WebsiteInterfaceInput! | ||||
|   ): WebsiteInterfaceEntityResponse | ||||
|   deleteWebsiteInterface(id: ID!): WebsiteInterfaceEntityResponse | ||||
|   createWikiPage(data: WikiPageInput!): WikiPageEntityResponse | ||||
|   updateWikiPage(id: ID!, data: WikiPageInput!): WikiPageEntityResponse | ||||
|   deleteWikiPage(id: ID!): WikiPageEntityResponse | ||||
|   createWikiPageType(data: WikiPageTypeInput!): WikiPageTypeEntityResponse | ||||
|   updateWikiPageType( | ||||
|     id: ID! | ||||
|     data: WikiPageTypeInput! | ||||
|   ): WikiPageTypeEntityResponse | ||||
|   deleteWikiPageType(id: ID!): WikiPageTypeEntityResponse | ||||
|   upload( | ||||
|     refId: ID | ||||
|     ref: String | ||||
|  | ||||
| @ -39,7 +39,16 @@ class MyDocument extends Document { | ||||
|           <meta name="application-name" content="Accord's Library" /> | ||||
|           <meta name="msapplication-TileColor" content="#feecd6" /> | ||||
|           <meta name="msapplication-TileImage" content="/mstile-144x144.png" /> | ||||
|           <meta name="theme-color" content="#feecd6" /> | ||||
|           <meta | ||||
|             name="theme-color" | ||||
|             media="(prefers-color-scheme: light)" | ||||
|             content="#feecd6" | ||||
|           /> | ||||
|           <meta | ||||
|             name="theme-color" | ||||
|             media="(prefers-color-scheme: dark)" | ||||
|             content="#26221e" | ||||
|           /> | ||||
| 
 | ||||
|           <meta name="apple-mobile-web-app-capable" content="yes" /> | ||||
|           <meta | ||||
|  | ||||
| @ -81,6 +81,9 @@ export default function ContentIndex(props: ContentIndexProps): JSX.Element { | ||||
|       langui={langui} | ||||
|       contentPanel={contentPanel} | ||||
|       subPanel={subPanel} | ||||
|       description={ | ||||
|         content.titles.length > 0 ? content.titles[0].description : undefined | ||||
|       } | ||||
|     /> | ||||
|   ); | ||||
| } | ||||
|  | ||||
| @ -5,6 +5,7 @@ import { | ||||
|   getWebsiteInterface, | ||||
| } from "graphql/operations"; | ||||
| import { | ||||
|   Enum_Componentsetstextset_Status, | ||||
|   GetContentTextQuery, | ||||
|   GetWebsiteInterfaceQuery, | ||||
| } from "graphql/operations-types"; | ||||
| @ -15,7 +16,18 @@ import ReturnButton from "components/PanelComponents/ReturnButton"; | ||||
| import ThumbnailHeader from "components/Content/ThumbnailHeader"; | ||||
| import AppLayout from "components/AppLayout"; | ||||
| import Markdawn from "components/Markdown/Markdawn"; | ||||
| import { prettyinlineTitle, prettySlug } from "queries/helpers"; | ||||
| import { | ||||
|   prettyinlineTitle, | ||||
|   prettyLanguage, | ||||
|   prettySlug, | ||||
|   prettyTestError, | ||||
|   prettyTestWarning, | ||||
| } from "queries/helpers"; | ||||
| import Button from "components/Button"; | ||||
| import { useRouter } from "next/router"; | ||||
| import Chip from "components/Chip"; | ||||
| import ReactTooltip from "react-tooltip"; | ||||
| import RecorderChip from "components/RecorderChip"; | ||||
| 
 | ||||
| type ContentReadProps = { | ||||
|   content: GetContentTextQuery; | ||||
| @ -25,6 +37,10 @@ type ContentReadProps = { | ||||
| export default function ContentRead(props: ContentReadProps): JSX.Element { | ||||
|   const content = props.content.contents.data[0].attributes; | ||||
|   const langui = props.langui.websiteInterfaces.data[0].attributes; | ||||
|   const router = useRouter(); | ||||
| 
 | ||||
|   useTesting(props.content); | ||||
| 
 | ||||
|   const subPanel = ( | ||||
|     <SubPanel> | ||||
|       <ReturnButton | ||||
| @ -32,6 +48,93 @@ export default function ContentRead(props: ContentReadProps): JSX.Element { | ||||
|         title={"Content"} | ||||
|         langui={langui} | ||||
|       /> | ||||
| 
 | ||||
|       <HorizontalLine /> | ||||
| 
 | ||||
|       {content.text_set.length > 0 ? ( | ||||
|         <div className="grid gap-5"> | ||||
|           <h2 className="text-xl"> | ||||
|             {content.text_set[0].source_language.data.attributes.code === | ||||
|             router.locale | ||||
|               ? "This content is a transcript" | ||||
|               : "This content is a fan-translation"} | ||||
|           </h2> | ||||
| 
 | ||||
|           {content.text_set[0].source_language.data.attributes.code !== | ||||
|             router.locale && ( | ||||
|             <div className="grid place-items-center gap-2"> | ||||
|               <p className="font-headers">Source language:</p> | ||||
|               <Button | ||||
|                 href={router.asPath} | ||||
|                 locale={ | ||||
|                   content.text_set[0].source_language.data.attributes.code | ||||
|                 } | ||||
|               > | ||||
|                 {prettyLanguage( | ||||
|                   content.text_set[0].source_language.data.attributes.code | ||||
|                 )} | ||||
|               </Button> | ||||
|             </div> | ||||
|           )} | ||||
| 
 | ||||
|           <div className="grid grid-flow-col place-items-center place-content-center gap-2"> | ||||
|             <p className="font-headers">Status:</p> | ||||
| 
 | ||||
|             <Chip | ||||
|               data-tip={ | ||||
|                 content.text_set[0].status === | ||||
|                 Enum_Componentsetstextset_Status.Incomplete | ||||
|                   ? "This entry is only partially translated/transcribed." | ||||
|                   : content.text_set[0].status === | ||||
|                     Enum_Componentsetstextset_Status.Draft | ||||
|                   ? "This entry is just a draft. It usually means that this is a work-in-progress. Translation/transcription might be poor and/or computer-generated." | ||||
|                   : content.text_set[0].status === | ||||
|                     Enum_Componentsetstextset_Status.Review | ||||
|                   ? "This entry has not yet being proofread. The content should still be accurate." | ||||
|                   : "This entry has been checked and proofread. If you notice any translation errors or typos, please contact us so we can fix it!" | ||||
|               } | ||||
|               data-for={"StatusTooltip"} | ||||
|             > | ||||
|               {content.text_set[0].status} | ||||
|             </Chip> | ||||
|           </div> | ||||
| 
 | ||||
|           {content.text_set[0].transcribers.data.length > 0 && ( | ||||
|             <div> | ||||
|               <p className="font-headers">Transcribers:</p> | ||||
|               <div className="grid place-items-center place-content-center gap-2"> | ||||
|                 {content.text_set[0].transcribers.data.map((recorder) => ( | ||||
|                   <RecorderChip key={recorder.id} recorder={recorder} /> | ||||
|                 ))} | ||||
|               </div> | ||||
|             </div> | ||||
|           )} | ||||
| 
 | ||||
|           {content.text_set[0].translators.data.length > 0 && ( | ||||
|             <div> | ||||
|               <p className="font-headers">Translators:</p> | ||||
|               <div className="grid place-items-center place-content-center gap-2"> | ||||
|                 {content.text_set[0].translators.data.map((recorder) => ( | ||||
|                   <RecorderChip key={recorder.id} recorder={recorder} /> | ||||
|                 ))} | ||||
|               </div> | ||||
|             </div> | ||||
|           )} | ||||
| 
 | ||||
|           {content.text_set[0].proofreaders.data.length > 0 && ( | ||||
|             <div> | ||||
|               <p className="font-headers">Proofreaders:</p> | ||||
|               <div className="grid place-items-center place-content-center gap-2"> | ||||
|                 {content.text_set[0].proofreaders.data.map((recorder) => ( | ||||
|                   <RecorderChip key={recorder.id} recorder={recorder} /> | ||||
|                 ))} | ||||
|               </div> | ||||
|             </div> | ||||
|           )} | ||||
|         </div> | ||||
|       ) : ( | ||||
|         "" | ||||
|       )} | ||||
|     </SubPanel> | ||||
|   ); | ||||
|   const contentPanel = ( | ||||
| @ -50,18 +153,49 @@ export default function ContentRead(props: ContentReadProps): JSX.Element { | ||||
|     </ContentPanel> | ||||
|   ); | ||||
| 
 | ||||
|   const extra = ( | ||||
|     <> | ||||
|       <ReactTooltip | ||||
|         id="StatusTooltip" | ||||
|         place="top" | ||||
|         type="light" | ||||
|         effect="solid" | ||||
|         delayShow={50} | ||||
|         clickable={true} | ||||
|         className="drop-shadow-shade-xl !opacity-100 !bg-light !rounded-lg desktop:after:!border-t-light text-left !text-black max-w-xs" | ||||
|       /> | ||||
| 
 | ||||
|       <ReactTooltip | ||||
|         id="RecordersTooltip" | ||||
|         place="top" | ||||
|         type="light" | ||||
|         effect="solid" | ||||
|         delayShow={100} | ||||
|         delayUpdate={100} | ||||
|         delayHide={100} | ||||
|         clickable={true} | ||||
|         className="drop-shadow-shade-xl !opacity-100 !bg-light !rounded-lg desktop:after:!border-t-light text-left !text-black max-w-[22rem]" | ||||
|       /> | ||||
|     </> | ||||
|   ); | ||||
| 
 | ||||
|   return ( | ||||
|     <AppLayout | ||||
|       navTitle="Contents" | ||||
|       title={ | ||||
|         content.titles.length > 0 | ||||
|           ? prettyinlineTitle(content.titles[0].pre_title, content.titles[0].title, content.titles[0].subtitle) | ||||
|           ? prettyinlineTitle( | ||||
|               content.titles[0].pre_title, | ||||
|               content.titles[0].title, | ||||
|               content.titles[0].subtitle | ||||
|             ) | ||||
|           : prettySlug(content.slug) | ||||
|       } | ||||
|       thumbnail={content.thumbnail.data.attributes} | ||||
|       langui={langui} | ||||
|       contentPanel={contentPanel} | ||||
|       subPanel={subPanel} | ||||
|       extra={extra} | ||||
|     /> | ||||
|   ); | ||||
| } | ||||
| @ -109,3 +243,72 @@ export const getStaticPaths: GetStaticPaths = async (context) => { | ||||
|     fallback: false, | ||||
|   }; | ||||
| }; | ||||
| 
 | ||||
| export function useTesting(content: GetContentTextQuery) { | ||||
|   const router = useRouter(); | ||||
|   const contentAtr = content.contents.data[0].attributes; | ||||
|   if (contentAtr.categories.data.length === 0) { | ||||
|     prettyTestError(router, "Missing categories", ["content"]); | ||||
|   } | ||||
| 
 | ||||
|   if (contentAtr.ranged_contents.data.length === 0) { | ||||
|     prettyTestWarning(router, "Unconnected to any source", ["content"]); | ||||
|   } | ||||
| 
 | ||||
|   if (contentAtr.text_set.length === 0) { | ||||
|     prettyTestWarning(router, "Has no textset, nor audioset, nor videoset", [ | ||||
|       "content", | ||||
|     ]); | ||||
|   } | ||||
| 
 | ||||
|   if (contentAtr.text_set.length > 1) { | ||||
|     console.warn( | ||||
|       prettyTestError(router, "More than one textset for this language", [ | ||||
|         "content", | ||||
|         "text_set", | ||||
|       ]) | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|   if (contentAtr.text_set.length === 1) { | ||||
|     const textset = contentAtr.text_set[0]; | ||||
|     if (!textset.text) { | ||||
|       prettyTestError(router, "Missing text", ["content", "text_set"]); | ||||
|     } | ||||
|     if (!textset.source_language.data) { | ||||
|       prettyTestError(router, "Missing source language", [ | ||||
|         "content", | ||||
|         "text_set", | ||||
|       ]); | ||||
|     } | ||||
|     if (textset.source_language.data.attributes.code === router.locale) { | ||||
|       // This is a transcript
 | ||||
|       if (textset.transcribers.data.length === 0) { | ||||
|         prettyTestError(router, "Missing transcribers attribution", [ | ||||
|           "content", | ||||
|           "text_set", | ||||
|         ]); | ||||
|       } | ||||
|       if (textset.translators.data.length > 0) { | ||||
|         prettyTestError(router, "Transcripts shouldn't have translators", [ | ||||
|           "content", | ||||
|           "text_set", | ||||
|         ]); | ||||
|       } | ||||
|     } else { | ||||
|       // This is a translation
 | ||||
|       if (textset.translators.data.length === 0) { | ||||
|         prettyTestError(router, "Missing translators attribution", [ | ||||
|           "content", | ||||
|           "text_set", | ||||
|         ]); | ||||
|       } | ||||
|       if (textset.transcribers.data.length > 0) { | ||||
|         prettyTestError(router, "Translations shouldn't have transcribers", [ | ||||
|           "content", | ||||
|           "text_set", | ||||
|         ]); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| @ -16,7 +16,11 @@ import NavOption from "components/PanelComponents/NavOption"; | ||||
| import ReturnButton from "components/PanelComponents/ReturnButton"; | ||||
| import HorizontalLine from "components/HorizontalLine"; | ||||
| import AppLayout from "components/AppLayout"; | ||||
| import { prettySlug } from "queries/helpers"; | ||||
| import { | ||||
|   prettySlug, | ||||
|   prettyTestError, | ||||
|   prettyTestWarning, | ||||
| } from "queries/helpers"; | ||||
| import InsetBox from "components/InsetBox"; | ||||
| import { useRouter } from "next/router"; | ||||
| import ReactTooltip from "react-tooltip"; | ||||
| @ -165,41 +169,52 @@ export function useTesting( | ||||
|   const router = useRouter(); | ||||
|   chronologyEras.chronologyEras.data.map((era) => { | ||||
|     if (era.attributes.title.length === 0) { | ||||
|       console.warn( | ||||
|         `${router.pathname} | ${router.locale} | chronologyEras | ${era.attributes.slug} | Missing translation for title and description, using slug instead` | ||||
|       prettyTestError( | ||||
|         router, | ||||
|         "Missing translation for title and description, using slug instead", | ||||
|         ["chronologyEras", era.attributes.slug] | ||||
|       ); | ||||
|     } else if (era.attributes.title.length > 1) { | ||||
|       console.warn( | ||||
|         `${router.pathname} | ${router.locale} | chronologyEras | ${era.attributes.slug} | More than one title and description` | ||||
|       ); | ||||
|       prettyTestError(router, "More than one title and description", [ | ||||
|         "chronologyEras", | ||||
|         era.attributes.slug, | ||||
|       ]); | ||||
|     } else { | ||||
|       if (!era.attributes.title[0].title) | ||||
|         console.warn( | ||||
|           `${router.pathname} | ${router.locale} | chronologyEras | ${era.attributes.slug} | Missing title, using slug instead` | ||||
|         ); | ||||
|         prettyTestError(router, "Missing title, using slug instead", [ | ||||
|           "chronologyEras", | ||||
|           era.attributes.slug, | ||||
|         ]); | ||||
|       if (!era.attributes.title[0].description) | ||||
|         console.warn( | ||||
|           `${router.pathname} | ${router.locale} | chronologyEras | ${era.attributes.slug} | Missing description` | ||||
|         ); | ||||
|         prettyTestError(router, "Missing description", [ | ||||
|           "chronologyEras", | ||||
|           era.attributes.slug, | ||||
|         ]); | ||||
|     } | ||||
|   }); | ||||
| 
 | ||||
|   chronologyItems.chronologyItems.data.map((item) => { | ||||
|     const date = `${item.attributes.year}/${item.attributes.month}/${item.attributes.day}`; | ||||
|     if (!(item.attributes.events.length > 0)) { | ||||
|       console.warn( | ||||
|         `${router.pathname} | ${router.locale} | chronologyItems | ${item.attributes.year}/${item.attributes.month}/${item.attributes.day} | No events for this date` | ||||
|       ); | ||||
|       prettyTestError(router, "No events for this date", [ | ||||
|         "chronologyItems", | ||||
|         date, | ||||
|       ]); | ||||
|     } else { | ||||
|       item.attributes.events.map((event) => { | ||||
|         if (!event.source.data) { | ||||
|           console.warn( | ||||
|             `${router.pathname} | ${router.locale} | chronologyItems | ${item.attributes.year}/${item.attributes.month}/${item.attributes.day} | ${event.id} | No source for this event` | ||||
|           ); | ||||
|           prettyTestError(router, "No source for this event", [ | ||||
|             "chronologyItems", | ||||
|             date, | ||||
|             event.id, | ||||
|           ]); | ||||
|         } | ||||
|         if (!(event.translations.length > 0)) { | ||||
|           console.warn( | ||||
|             `${router.pathname} | ${router.locale} | chronologyItems | ${item.attributes.year}/${item.attributes.month}/${item.attributes.day} | ${event.id} | No translation for this event` | ||||
|           ); | ||||
|           prettyTestWarning(router, "No translation for this event", [ | ||||
|             "chronologyItems", | ||||
|             date, | ||||
|             event.id, | ||||
|           ]); | ||||
|         } | ||||
|       }); | ||||
|     } | ||||
|  | ||||
| @ -8,6 +8,7 @@ import { | ||||
|   GetWebsiteInterfaceQuery, | ||||
|   StrapiImage, | ||||
| } from "graphql/operations-types"; | ||||
| import { NextRouter } from "next/router"; | ||||
| 
 | ||||
| export function prettyDate( | ||||
|   datePicker: GetLibraryItemsPreviewQuery["libraryItems"]["data"][number]["attributes"]["release_date"] | ||||
| @ -117,6 +118,39 @@ export function prettyLanguage(code: string): string { | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| export function prettyTestWarning( | ||||
|   router: NextRouter, | ||||
|   message: string, | ||||
|   subCategory?: string[] | ||||
| ): void { | ||||
|   prettyTestWritter(TestingLevel.Warning, router, message, subCategory); | ||||
| } | ||||
| 
 | ||||
| export function prettyTestError( | ||||
|   router: NextRouter, | ||||
|   message: string, | ||||
|   subCategory?: string[] | ||||
| ): void { | ||||
|   prettyTestWritter(TestingLevel.Error, router, message, subCategory); | ||||
| } | ||||
| 
 | ||||
| enum TestingLevel { | ||||
|   Warning = "warn", | ||||
|   Error = "error", | ||||
| } | ||||
| 
 | ||||
| function prettyTestWritter( | ||||
|   level: TestingLevel, | ||||
|   { asPath, locale }: NextRouter, | ||||
|   message: string, | ||||
|   subCategory?: string[] | ||||
| ): void { | ||||
|   subCategory?.push(""); | ||||
|   console.warn( | ||||
|     `${level}  - ${asPath} | ${locale} | ${subCategory?.join(" | ")}${message}` | ||||
|   ); | ||||
| } | ||||
| 
 | ||||
| export function capitalizeString(string: string): string { | ||||
|   function capitalizeWord(word: string): string { | ||||
|     return word.charAt(0).toUpperCase() + word.substring(1); | ||||
| @ -131,28 +165,23 @@ export function convertMmToInch(mm: number): string { | ||||
|   return (mm * 0.03937008).toPrecision(3); | ||||
| } | ||||
| 
 | ||||
| type OgImage = { | ||||
| export type OgImage = { | ||||
|   image: string; | ||||
|   width: number; | ||||
|   height: number; | ||||
|   alt: string; | ||||
| }; | ||||
| 
 | ||||
| export function getOgImage( | ||||
|   quality: ImageQuality, | ||||
|   image?: StrapiImage | ||||
| ): OgImage | undefined { | ||||
|   if (image) { | ||||
|     const imgSize = getImgSizesByQuality( | ||||
|       image.width, | ||||
|       image.height, | ||||
|       quality ? quality : ImageQuality.Small | ||||
|     ); | ||||
|     return { | ||||
|       image: getAssetURL(image.url, quality), | ||||
|       width: imgSize.width, | ||||
|       height: imgSize.height, | ||||
|       alt: image.alternativeText, | ||||
|     }; | ||||
|   } | ||||
| export function getOgImage(quality: ImageQuality, image: StrapiImage): OgImage { | ||||
|   const imgSize = getImgSizesByQuality( | ||||
|     image.width, | ||||
|     image.height, | ||||
|     quality ? quality : ImageQuality.Small | ||||
|   ); | ||||
|   return { | ||||
|     image: getAssetURL(image.url, quality), | ||||
|     width: imgSize.width, | ||||
|     height: imgSize.height, | ||||
|     alt: image.alternativeText, | ||||
|   }; | ||||
| } | ||||
|  | ||||
| @ -77,6 +77,10 @@ | ||||
|     @apply text-dark; | ||||
|   } | ||||
| 
 | ||||
|   .prose blockquote { | ||||
|     @apply border-l-dark | ||||
|   } | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| @layer components { | ||||
|  | ||||
							
								
								
									
										0
									
								
								testing_logs/.gitkeep
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								testing_logs/.gitkeep
									
									
									
									
									
										Normal file
									
								
							| @ -2,6 +2,7 @@ | ||||
|   "compilerOptions": { | ||||
|     "target": "ESNext", | ||||
|     "lib": ["dom", "dom.iterable", "esnext"], | ||||
|     "importHelpers": true, | ||||
|     "allowJs": true, | ||||
|     "skipLibCheck": true, | ||||
|     "strict": true, | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 DrMint
						DrMint