Applied more lint rules and fixed the code accordingly

This commit is contained in:
DrMint 2022-03-27 17:01:14 +02:00
parent 38543ae3dd
commit 4a123a0236
55 changed files with 1575 additions and 1154 deletions

2
.eslintignore Normal file
View File

@ -0,0 +1,2 @@
*.js
*.ts

214
.eslintrc.js Normal file
View File

@ -0,0 +1,214 @@
module.exports = {
parser: "@typescript-eslint/parser",
parserOptions: {
project: `./tsconfig.json`,
},
plugins: ["@typescript-eslint"],
extends: [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"next/core-web-vitals",
],
rules: {
/* POSSIBLES PROBLEMS */
// "array-callback-return": "error",
"no-await-in-loop": "error",
"no-constructor-return": "error",
"no-promise-executor-return": "error",
"no-self-compare": "error",
"no-template-curly-in-string": "error",
"no-unmodified-loop-condition": "error",
"no-unreachable-loop": "error",
"no-unused-private-class-members": "error",
// "no-use-before-define": "error",
"require-atomic-updates": "error",
/* SUGGESTIONS */
"accessor-pairs": "warn",
"arrow-body-style": "warn",
"block-scoped-var": "warn",
// camelcase: "warn",
// "capitalized-comments": "warn",
// "class-methods-use-this": "warn",
// complexity: "warn",
"consistent-return": "warn",
"consistent-this": "warn",
// curly: "warn",
"default-case": "warn",
"default-case-last": "warn",
eqeqeq: "error",
"func-name-matching": "warn",
"func-names": "warn",
"func-style": ["warn", "declaration"],
"grouped-accessor-pairs": "warn",
"guard-for-in": "warn",
"id-denylist": ["error", "data", "err", "e", "cb", "callback", "i"],
// "id-length": "warn",
"id-match": "warn",
"max-classes-per-file": ["error", 1],
// "max-depth": ["warn", 4],
// "max-lines": "warn",
// "max-lines-per-function": "warn",
// "max-nested-callbacks": "warn",
// "max-params": "warn",
// "max-statements": "warn",
"multiline-comment-style": "warn",
"new-cap": "warn",
"no-alert": "warn",
"no-bitwise": "warn",
"no-caller": "warn",
"no-confusing-arrow": "warn",
"no-continue": "warn",
"no-else-return": "warn",
"no-eq-null": "warn",
"no-eval": "warn",
"no-extend-native": "warn",
"no-extra-bind": "warn",
"no-floating-decimal": "warn",
"no-implicit-coercion": "warn",
"no-implicit-globals": "warn",
"no-inline-comments": "warn",
"no-iterator": "warn",
"no-label-var": "warn",
"no-labels": "warn",
"no-lone-blocks": "warn",
"no-lonely-if": "warn",
// "no-magic-numbers": "warn",
"no-mixed-operators": "warn",
"no-multi-assign": "warn",
"no-multi-str": "warn",
"no-negated-condition": "warn",
// "no-nested-ternary": "warn",
"no-new": "warn",
"no-new-func": "warn",
"no-new-object": "warn",
"no-new-wrappers": "warn",
"no-octal-escape": "warn",
"no-param-reassign": "warn",
"no-plusplus": "warn",
"no-proto": "warn",
"no-restricted-exports": "warn",
"no-restricted-globals": "warn",
"no-restricted-imports": "warn",
"no-restricted-properties": "warn",
"no-restricted-syntax": "warn",
"no-return-assign": "warn",
// "no-return-await": "warn",
"no-script-url": "warn",
"no-sequences": "warn",
// "no-ternary": "off",
"no-throw-literal": "warn",
"no-undef": "off",
"no-undef-init": "warn",
// "no-undefined": "warn",
// "no-underscore-dangle": "warn",
"no-unneeded-ternary": "warn",
"no-useless-call": "warn",
"no-useless-computed-key": "warn",
"no-useless-concat": "warn",
"no-useless-rename": "warn",
"no-useless-return": "warn",
"no-var": "warn",
"no-void": "warn",
"no-warning-comments": "warn",
// "object-shorthand": "warn",
"operator-assignment": "warn",
"prefer-arrow-callback": "warn",
"prefer-const": "warn",
"prefer-destructuring": ["warn", { array: false, object: true }],
"prefer-exponentiation-operator": "warn",
"prefer-named-capture-group": "warn",
"prefer-numeric-literals": "warn",
// "prefer-object-has-own": "warn",
"prefer-object-spread": "warn",
"prefer-promise-reject-errors": "warn",
"prefer-regex-literals": "warn",
"prefer-rest-params": "warn",
"prefer-spread": "warn",
"prefer-template": "warn",
// "quote-props": "warn",
radix: "warn",
"require-unicode-regexp": "warn",
// "sort-imports": "warn",
// "sort-keys": "warn",
"sort-vars": "warn",
"spaced-comment": "warn",
strict: "warn",
"symbol-description": "warn",
"vars-on-top": "warn",
yoda: "warn",
/* TYPESCRIPT */
"@typescript-eslint/array-type": "warn",
"@typescript-eslint/ban-tslint-comment": "warn",
"@typescript-eslint/class-literal-property-style": "warn",
"@typescript-eslint/consistent-indexed-object-style": "warn",
"@typescript-eslint/consistent-type-assertions": [
"warn",
{ assertionStyle: "as" },
],
"@typescript-eslint/consistent-type-exports": "error",
"@typescript-eslint/explicit-module-boundary-types": "warn",
"@typescript-eslint/method-signature-style": ["error", "property"],
"@typescript-eslint/no-base-to-string": "warn",
"@typescript-eslint/no-confusing-non-null-assertion": "warn",
"@typescript-eslint/no-confusing-void-expression": [
"error",
{ ignoreArrowShorthand: true },
],
"@typescript-eslint/no-dynamic-delete": "error",
"@typescript-eslint/no-empty-interface": [
"error",
{ allowSingleExtends: true },
],
"@typescript-eslint/no-invalid-void-type": "error",
"@typescript-eslint/no-meaningless-void-operator": "error",
"@typescript-eslint/no-non-null-asserted-nullish-coalescing": "error",
"@typescript-eslint/no-parameter-properties": "error",
"@typescript-eslint/no-require-imports": "error",
// "@typescript-eslint/no-type-alias": "warn",
"@typescript-eslint/no-unnecessary-boolean-literal-compare": "warn",
// "@typescript-eslint/no-unnecessary-condition": "warn",
"@typescript-eslint/no-unnecessary-qualifier": "warn",
"@typescript-eslint/no-unnecessary-type-arguments": "warn",
"@typescript-eslint/prefer-enum-initializers": "error",
"@typescript-eslint/prefer-for-of": "error",
"@typescript-eslint/prefer-includes": "error",
"@typescript-eslint/prefer-literal-enum-member": "error",
"@typescript-eslint/prefer-nullish-coalescing": "warn",
"@typescript-eslint/prefer-optional-chain": "warn",
"@typescript-eslint/prefer-readonly": "warn",
// "@typescript-eslint/prefer-readonly-parameter-types": "warn",
"@typescript-eslint/prefer-reduce-type-parameter": "warn",
// "@typescript-eslint/prefer-regexp-exec": "warn",
"@typescript-eslint/prefer-return-this-type": "warn",
"@typescript-eslint/prefer-string-starts-ends-with": "error",
"@typescript-eslint/promise-function-async": "error",
"@typescript-eslint/require-array-sort-compare": "error",
"@typescript-eslint/sort-type-union-intersection-members": "warn",
// "@typescript-eslint/strict-boolean-expressions": "error",
"@typescript-eslint/switch-exhaustiveness-check": "error",
"@typescript-eslint/typedef": "error",
"@typescript-eslint/unified-signatures": "error",
/* EXTENSION OF ESLINT */
"@typescript-eslint/no-duplicate-imports": "error",
"@typescript-eslint/default-param-last": "warn",
"@typescript-eslint/dot-notation": "warn",
"@typescript-eslint/init-declarations": "warn",
"@typescript-eslint/no-array-constructor": "warn",
"@typescript-eslint/no-implied-eval": "warn",
"@typescript-eslint/no-invalid-this": "warn",
"@typescript-eslint/no-loop-func": "warn",
"@typescript-eslint/no-shadow": "warn",
"@typescript-eslint/no-unused-expressions": "warn",
"@typescript-eslint/no-useless-constructor": "warn",
"@typescript-eslint/require-await": "warn",
/* NEXTJS */
"@next/next/no-img-element": "off",
},
};

View File

@ -1,3 +0,0 @@
{
"extends": "next/core-web-vitals"
}

10
.hintrc Normal file
View File

@ -0,0 +1,10 @@
{
"extends": ["development"],
"hints": {
"no-inline-styles": "off",
"apple-touch-icons": "off",
"compat-api/html": "off",
"axe/text-alternatives": "off",
"axe/parsing": "off"
}
}

296
package-lock.json generated
View File

@ -26,11 +26,14 @@
"@types/nodemailer": "^6.4.4", "@types/nodemailer": "^6.4.4",
"@types/react": "17.0.40", "@types/react": "17.0.40",
"@types/react-dom": "^17.0.13", "@types/react-dom": "^17.0.13",
"eslint": "8.10.0", "@types/turndown": "^5.0.1",
"@typescript-eslint/eslint-plugin": "^5.16.0",
"@typescript-eslint/parser": "^5.16.0",
"eslint": "^8.10.0",
"eslint-config-next": "12.1.0", "eslint-config-next": "12.1.0",
"prettier-plugin-organize-imports": "^2.3.4", "prettier-plugin-organize-imports": "^2.3.4",
"tailwindcss": "^3.0.23", "tailwindcss": "^3.0.23",
"typescript": "4.6.2" "typescript": "^4.6.2"
} }
}, },
"node_modules/@babel/code-frame": { "node_modules/@babel/code-frame": {
@ -480,6 +483,12 @@
"react-dom": ">=16.8" "react-dom": ">=16.8"
} }
}, },
"node_modules/@types/json-schema": {
"version": "7.0.11",
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz",
"integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==",
"dev": true
},
"node_modules/@types/json5": { "node_modules/@types/json5": {
"version": "0.0.29", "version": "0.0.29",
"resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
@ -539,15 +548,54 @@
"integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==", "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==",
"dev": true "dev": true
}, },
"node_modules/@typescript-eslint/parser": { "node_modules/@types/turndown": {
"version": "5.12.0", "version": "5.0.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.12.0.tgz", "resolved": "https://registry.npmjs.org/@types/turndown/-/turndown-5.0.1.tgz",
"integrity": "sha512-MfSwg9JMBojMUoGjUmX+D2stoQj1CBYTCP0qnnVtu9A+YQXVKNtLjasYh+jozOcrb/wau8TCfWOkQTiOAruBog==", "integrity": "sha512-N8Ad4e3oJxh9n9BiZx9cbe/0M3kqDpOTm2wzj13wdDUxDPjfjloWIJaquZzWE1cYTAHpjOH3rcTnXQdpEfS/SQ==",
"dev": true
},
"node_modules/@typescript-eslint/eslint-plugin": {
"version": "5.16.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.16.0.tgz",
"integrity": "sha512-SJoba1edXvQRMmNI505Uo4XmGbxCK9ARQpkvOd00anxzri9RNQk0DDCxD+LIl+jYhkzOJiOMMKYEHnHEODjdCw==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@typescript-eslint/scope-manager": "5.12.0", "@typescript-eslint/scope-manager": "5.16.0",
"@typescript-eslint/types": "5.12.0", "@typescript-eslint/type-utils": "5.16.0",
"@typescript-eslint/typescript-estree": "5.12.0", "@typescript-eslint/utils": "5.16.0",
"debug": "^4.3.2",
"functional-red-black-tree": "^1.0.1",
"ignore": "^5.1.8",
"regexpp": "^3.2.0",
"semver": "^7.3.5",
"tsutils": "^3.21.0"
},
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
"@typescript-eslint/parser": "^5.0.0",
"eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
},
"peerDependenciesMeta": {
"typescript": {
"optional": true
}
}
},
"node_modules/@typescript-eslint/parser": {
"version": "5.16.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.16.0.tgz",
"integrity": "sha512-fkDq86F0zl8FicnJtdXakFs4lnuebH6ZADDw6CYQv0UZeIjHvmEw87m9/29nk2Dv5Lmdp0zQ3zDQhiMWQf/GbA==",
"dev": true,
"dependencies": {
"@typescript-eslint/scope-manager": "5.16.0",
"@typescript-eslint/types": "5.16.0",
"@typescript-eslint/typescript-estree": "5.16.0",
"debug": "^4.3.2" "debug": "^4.3.2"
}, },
"engines": { "engines": {
@ -567,13 +615,13 @@
} }
}, },
"node_modules/@typescript-eslint/scope-manager": { "node_modules/@typescript-eslint/scope-manager": {
"version": "5.12.0", "version": "5.16.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.12.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.16.0.tgz",
"integrity": "sha512-GAMobtIJI8FGf1sLlUWNUm2IOkIjvn7laFWyRx7CLrv6nLBI7su+B7lbStqVlK5NdLvHRFiJo2HhiDF7Ki01WQ==", "integrity": "sha512-P+Yab2Hovg8NekLIR/mOElCDPyGgFZKhGoZA901Yax6WR6HVeGLbsqJkZ+Cvk5nts/dAlFKm8PfL43UZnWdpIQ==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@typescript-eslint/types": "5.12.0", "@typescript-eslint/types": "5.16.0",
"@typescript-eslint/visitor-keys": "5.12.0" "@typescript-eslint/visitor-keys": "5.16.0"
}, },
"engines": { "engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0" "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@ -583,10 +631,36 @@
"url": "https://opencollective.com/typescript-eslint" "url": "https://opencollective.com/typescript-eslint"
} }
}, },
"node_modules/@typescript-eslint/type-utils": {
"version": "5.16.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.16.0.tgz",
"integrity": "sha512-SKygICv54CCRl1Vq5ewwQUJV/8padIWvPgCxlWPGO/OgQLCijY9G7lDu6H+mqfQtbzDNlVjzVWQmeqbLMBLEwQ==",
"dev": true,
"dependencies": {
"@typescript-eslint/utils": "5.16.0",
"debug": "^4.3.2",
"tsutils": "^3.21.0"
},
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
"eslint": "*"
},
"peerDependenciesMeta": {
"typescript": {
"optional": true
}
}
},
"node_modules/@typescript-eslint/types": { "node_modules/@typescript-eslint/types": {
"version": "5.12.0", "version": "5.16.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.12.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.16.0.tgz",
"integrity": "sha512-JowqbwPf93nvf8fZn5XrPGFBdIK8+yx5UEGs2QFAYFI8IWYfrzz+6zqlurGr2ctShMaJxqwsqmra3WXWjH1nRQ==", "integrity": "sha512-oUorOwLj/3/3p/HFwrp6m/J2VfbLC8gjW5X3awpQJ/bSG+YRGFS4dpsvtQ8T2VNveV+LflQHjlLvB6v0R87z4g==",
"dev": true, "dev": true,
"engines": { "engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0" "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@ -597,13 +671,13 @@
} }
}, },
"node_modules/@typescript-eslint/typescript-estree": { "node_modules/@typescript-eslint/typescript-estree": {
"version": "5.12.0", "version": "5.16.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.12.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.16.0.tgz",
"integrity": "sha512-Dd9gVeOqt38QHR0BEA8oRaT65WYqPYbIc5tRFQPkfLquVEFPD1HAtbZT98TLBkEcCkvwDYOAvuSvAD9DnQhMfQ==", "integrity": "sha512-SE4VfbLWUZl9MR+ngLSARptUv2E8brY0luCdgmUevU6arZRY/KxYoLI/3V/yxaURR8tLRN7bmZtJdgmzLHI6pQ==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@typescript-eslint/types": "5.12.0", "@typescript-eslint/types": "5.16.0",
"@typescript-eslint/visitor-keys": "5.12.0", "@typescript-eslint/visitor-keys": "5.16.0",
"debug": "^4.3.2", "debug": "^4.3.2",
"globby": "^11.0.4", "globby": "^11.0.4",
"is-glob": "^4.0.3", "is-glob": "^4.0.3",
@ -623,13 +697,59 @@
} }
} }
}, },
"node_modules/@typescript-eslint/visitor-keys": { "node_modules/@typescript-eslint/utils": {
"version": "5.12.0", "version": "5.16.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.12.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.16.0.tgz",
"integrity": "sha512-cFwTlgnMV6TgezQynx2c/4/tx9Tufbuo9LPzmWqyRC3QC4qTGkAG1C6pBr0/4I10PAI/FlYunI3vJjIcu+ZHMg==", "integrity": "sha512-iYej2ER6AwmejLWMWzJIHy3nPJeGDuCqf8Jnb+jAQVoPpmWzwQOfa9hWVB8GIQE5gsCv/rfN4T+AYb/V06WseQ==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@typescript-eslint/types": "5.12.0", "@types/json-schema": "^7.0.9",
"@typescript-eslint/scope-manager": "5.16.0",
"@typescript-eslint/types": "5.16.0",
"@typescript-eslint/typescript-estree": "5.16.0",
"eslint-scope": "^5.1.1",
"eslint-utils": "^3.0.0"
},
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
"eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
}
},
"node_modules/@typescript-eslint/utils/node_modules/eslint-scope": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
"integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
"dev": true,
"dependencies": {
"esrecurse": "^4.3.0",
"estraverse": "^4.1.1"
},
"engines": {
"node": ">=8.0.0"
}
},
"node_modules/@typescript-eslint/utils/node_modules/estraverse": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
"integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
"dev": true,
"engines": {
"node": ">=4.0"
}
},
"node_modules/@typescript-eslint/visitor-keys": {
"version": "5.16.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.16.0.tgz",
"integrity": "sha512-jqxO8msp5vZDhikTwq9ubyMHqZ67UIvawohr4qF3KhlpL7gzSjOd+8471H3nh5LyABkaI85laEKKU8SnGUK5/g==",
"dev": true,
"dependencies": {
"@typescript-eslint/types": "5.16.0",
"eslint-visitor-keys": "^3.0.0" "eslint-visitor-keys": "^3.0.0"
}, },
"engines": { "engines": {
@ -4038,6 +4158,12 @@
"tippy.js": "^6.3.1" "tippy.js": "^6.3.1"
} }
}, },
"@types/json-schema": {
"version": "7.0.11",
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz",
"integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==",
"dev": true
},
"@types/json5": { "@types/json5": {
"version": "0.0.29", "version": "0.0.29",
"resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
@ -4097,42 +4223,76 @@
"integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==", "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==",
"dev": true "dev": true
}, },
"@typescript-eslint/parser": { "@types/turndown": {
"version": "5.12.0", "version": "5.0.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.12.0.tgz", "resolved": "https://registry.npmjs.org/@types/turndown/-/turndown-5.0.1.tgz",
"integrity": "sha512-MfSwg9JMBojMUoGjUmX+D2stoQj1CBYTCP0qnnVtu9A+YQXVKNtLjasYh+jozOcrb/wau8TCfWOkQTiOAruBog==", "integrity": "sha512-N8Ad4e3oJxh9n9BiZx9cbe/0M3kqDpOTm2wzj13wdDUxDPjfjloWIJaquZzWE1cYTAHpjOH3rcTnXQdpEfS/SQ==",
"dev": true
},
"@typescript-eslint/eslint-plugin": {
"version": "5.16.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.16.0.tgz",
"integrity": "sha512-SJoba1edXvQRMmNI505Uo4XmGbxCK9ARQpkvOd00anxzri9RNQk0DDCxD+LIl+jYhkzOJiOMMKYEHnHEODjdCw==",
"dev": true, "dev": true,
"requires": { "requires": {
"@typescript-eslint/scope-manager": "5.12.0", "@typescript-eslint/scope-manager": "5.16.0",
"@typescript-eslint/types": "5.12.0", "@typescript-eslint/type-utils": "5.16.0",
"@typescript-eslint/typescript-estree": "5.12.0", "@typescript-eslint/utils": "5.16.0",
"debug": "^4.3.2",
"functional-red-black-tree": "^1.0.1",
"ignore": "^5.1.8",
"regexpp": "^3.2.0",
"semver": "^7.3.5",
"tsutils": "^3.21.0"
}
},
"@typescript-eslint/parser": {
"version": "5.16.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.16.0.tgz",
"integrity": "sha512-fkDq86F0zl8FicnJtdXakFs4lnuebH6ZADDw6CYQv0UZeIjHvmEw87m9/29nk2Dv5Lmdp0zQ3zDQhiMWQf/GbA==",
"dev": true,
"requires": {
"@typescript-eslint/scope-manager": "5.16.0",
"@typescript-eslint/types": "5.16.0",
"@typescript-eslint/typescript-estree": "5.16.0",
"debug": "^4.3.2" "debug": "^4.3.2"
} }
}, },
"@typescript-eslint/scope-manager": { "@typescript-eslint/scope-manager": {
"version": "5.12.0", "version": "5.16.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.12.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.16.0.tgz",
"integrity": "sha512-GAMobtIJI8FGf1sLlUWNUm2IOkIjvn7laFWyRx7CLrv6nLBI7su+B7lbStqVlK5NdLvHRFiJo2HhiDF7Ki01WQ==", "integrity": "sha512-P+Yab2Hovg8NekLIR/mOElCDPyGgFZKhGoZA901Yax6WR6HVeGLbsqJkZ+Cvk5nts/dAlFKm8PfL43UZnWdpIQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"@typescript-eslint/types": "5.12.0", "@typescript-eslint/types": "5.16.0",
"@typescript-eslint/visitor-keys": "5.12.0" "@typescript-eslint/visitor-keys": "5.16.0"
}
},
"@typescript-eslint/type-utils": {
"version": "5.16.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.16.0.tgz",
"integrity": "sha512-SKygICv54CCRl1Vq5ewwQUJV/8padIWvPgCxlWPGO/OgQLCijY9G7lDu6H+mqfQtbzDNlVjzVWQmeqbLMBLEwQ==",
"dev": true,
"requires": {
"@typescript-eslint/utils": "5.16.0",
"debug": "^4.3.2",
"tsutils": "^3.21.0"
} }
}, },
"@typescript-eslint/types": { "@typescript-eslint/types": {
"version": "5.12.0", "version": "5.16.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.12.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.16.0.tgz",
"integrity": "sha512-JowqbwPf93nvf8fZn5XrPGFBdIK8+yx5UEGs2QFAYFI8IWYfrzz+6zqlurGr2ctShMaJxqwsqmra3WXWjH1nRQ==", "integrity": "sha512-oUorOwLj/3/3p/HFwrp6m/J2VfbLC8gjW5X3awpQJ/bSG+YRGFS4dpsvtQ8T2VNveV+LflQHjlLvB6v0R87z4g==",
"dev": true "dev": true
}, },
"@typescript-eslint/typescript-estree": { "@typescript-eslint/typescript-estree": {
"version": "5.12.0", "version": "5.16.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.12.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.16.0.tgz",
"integrity": "sha512-Dd9gVeOqt38QHR0BEA8oRaT65WYqPYbIc5tRFQPkfLquVEFPD1HAtbZT98TLBkEcCkvwDYOAvuSvAD9DnQhMfQ==", "integrity": "sha512-SE4VfbLWUZl9MR+ngLSARptUv2E8brY0luCdgmUevU6arZRY/KxYoLI/3V/yxaURR8tLRN7bmZtJdgmzLHI6pQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"@typescript-eslint/types": "5.12.0", "@typescript-eslint/types": "5.16.0",
"@typescript-eslint/visitor-keys": "5.12.0", "@typescript-eslint/visitor-keys": "5.16.0",
"debug": "^4.3.2", "debug": "^4.3.2",
"globby": "^11.0.4", "globby": "^11.0.4",
"is-glob": "^4.0.3", "is-glob": "^4.0.3",
@ -4140,13 +4300,45 @@
"tsutils": "^3.21.0" "tsutils": "^3.21.0"
} }
}, },
"@typescript-eslint/visitor-keys": { "@typescript-eslint/utils": {
"version": "5.12.0", "version": "5.16.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.12.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.16.0.tgz",
"integrity": "sha512-cFwTlgnMV6TgezQynx2c/4/tx9Tufbuo9LPzmWqyRC3QC4qTGkAG1C6pBr0/4I10PAI/FlYunI3vJjIcu+ZHMg==", "integrity": "sha512-iYej2ER6AwmejLWMWzJIHy3nPJeGDuCqf8Jnb+jAQVoPpmWzwQOfa9hWVB8GIQE5gsCv/rfN4T+AYb/V06WseQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"@typescript-eslint/types": "5.12.0", "@types/json-schema": "^7.0.9",
"@typescript-eslint/scope-manager": "5.16.0",
"@typescript-eslint/types": "5.16.0",
"@typescript-eslint/typescript-estree": "5.16.0",
"eslint-scope": "^5.1.1",
"eslint-utils": "^3.0.0"
},
"dependencies": {
"eslint-scope": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
"integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
"dev": true,
"requires": {
"esrecurse": "^4.3.0",
"estraverse": "^4.1.1"
}
},
"estraverse": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
"integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
"dev": true
}
}
},
"@typescript-eslint/visitor-keys": {
"version": "5.16.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.16.0.tgz",
"integrity": "sha512-jqxO8msp5vZDhikTwq9ubyMHqZ67UIvawohr4qF3KhlpL7gzSjOd+8471H3nh5LyABkaI85laEKKU8SnGUK5/g==",
"dev": true,
"requires": {
"@typescript-eslint/types": "5.16.0",
"eslint-visitor-keys": "^3.0.0" "eslint-visitor-keys": "^3.0.0"
} }
}, },

View File

@ -28,10 +28,13 @@
"@types/nodemailer": "^6.4.4", "@types/nodemailer": "^6.4.4",
"@types/react": "17.0.40", "@types/react": "17.0.40",
"@types/react-dom": "^17.0.13", "@types/react-dom": "^17.0.13",
"eslint": "8.10.0", "@types/turndown": "^5.0.1",
"@typescript-eslint/eslint-plugin": "^5.16.0",
"@typescript-eslint/parser": "^5.16.0",
"eslint": "^8.10.0",
"eslint-config-next": "12.1.0", "eslint-config-next": "12.1.0",
"prettier-plugin-organize-imports": "^2.3.4", "prettier-plugin-organize-imports": "^2.3.4",
"tailwindcss": "^3.0.23", "tailwindcss": "^3.0.23",
"typescript": "4.6.2" "typescript": "^4.6.2"
} }
} }

View File

@ -1,7 +1,7 @@
import Button from "components/Button"; import Button from "components/Button";
import { useAppLayout } from "contexts/AppLayoutContext"; import { useAppLayout } from "contexts/AppLayoutContext";
import { StrapiImage } from "graphql/operations-types"; import { StrapiImage } from "graphql/operations-types";
import { useMediaCoarse, useMediaMobile } from "hooks/useMediaQuery"; import { useMediaMobile } from "hooks/useMediaQuery";
import Head from "next/head"; import Head from "next/head";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import { AppStaticProps } from "queries/getAppStaticProps"; import { AppStaticProps } from "queries/getAppStaticProps";
@ -27,7 +27,6 @@ export default function AppLayout(props: AppLayoutProps): JSX.Element {
const { langui, currencies, languages, subPanel, contentPanel } = props; const { langui, currencies, languages, subPanel, contentPanel } = props;
const router = useRouter(); const router = useRouter();
const isMobile = useMediaMobile(); const isMobile = useMediaMobile();
const isCoarse = useMediaCoarse();
const appLayout = useAppLayout(); const appLayout = useAppLayout();
const sensibilitySwipe = 1.1; const sensibilitySwipe = 1.1;
@ -70,23 +69,23 @@ export default function AppLayout(props: AppLayoutProps): JSX.Element {
useEffect(() => { useEffect(() => {
document.getElementsByTagName("html")[0].style.fontSize = `${ document.getElementsByTagName("html")[0].style.fontSize = `${
(appLayout.fontSize || 1) * 100 (appLayout.fontSize ?? 1) * 100
}%`; }%`;
}, [appLayout.fontSize]); }, [appLayout.fontSize]);
const currencyOptions = currencies.map((currency) => { const currencyOptions = currencies.map(
return currency.attributes.code; (currency) => currency.attributes.code
}); );
const [currencySelect, setCurrencySelect] = useState<number>(-1); const [currencySelect, setCurrencySelect] = useState<number>(-1);
useEffect(() => { useEffect(() => {
appLayout.currency && if (appLayout.currency)
setCurrencySelect(currencyOptions.indexOf(appLayout.currency)); setCurrencySelect(currencyOptions.indexOf(appLayout.currency));
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, [appLayout.currency]); }, [appLayout.currency]);
useEffect(() => { useEffect(() => {
currencySelect >= 0 && if (currencySelect >= 0)
appLayout.setCurrency(currencyOptions[currencySelect]); appLayout.setCurrency(currencyOptions[currencySelect]);
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, [currencySelect]); }, [currencySelect]);
@ -98,12 +97,10 @@ export default function AppLayout(props: AppLayoutProps): JSX.Element {
} else { } else {
gridCol = "grid-cols-[20rem_20rem_1fr]"; gridCol = "grid-cols-[20rem_20rem_1fr]";
} }
} else if (appLayout.mainPanelReduced) {
gridCol = "grid-cols-[6rem_0px_1fr]";
} else { } else {
if (appLayout.mainPanelReduced) { gridCol = "grid-cols-[20rem_0px_1fr]";
gridCol = "grid-cols-[6rem_0px_1fr]";
} else {
gridCol = "grid-cols-[20rem_0px_1fr]";
}
} }
return ( return (
@ -152,7 +149,7 @@ export default function AppLayout(props: AppLayoutProps): JSX.Element {
{/* Background when navbar is opened */} {/* Background when navbar is opened */}
<div <div
className={`[grid-area:content] mobile:z-10 absolute inset-0 transition-[backdrop-filter] duration-500 ${ 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)]" ? "[backdrop-filter:blur(2px)]"
: "pointer-events-none touch-none " : "pointer-events-none touch-none "
}`} }`}
@ -161,7 +158,7 @@ export default function AppLayout(props: AppLayoutProps): JSX.Element {
className={`absolute bg-shade inset-0 transition-opacity duration-500 className={`absolute bg-shade inset-0 transition-opacity duration-500
${turnSubIntoContent ? "" : ""} ${turnSubIntoContent ? "" : ""}
${ ${
(appLayout.mainPanelOpen || appLayout.subPanelOpen) && isMobile (appLayout.mainPanelOpen ?? appLayout.subPanelOpen) && isMobile
? "opacity-60" ? "opacity-60"
: "opacity-0" : "opacity-0"
}`} }`}
@ -195,9 +192,7 @@ export default function AppLayout(props: AppLayoutProps): JSX.Element {
${ ${
turnSubIntoContent turnSubIntoContent
? "mobile:border-l-0 mobile:w-full" ? "mobile:border-l-0 mobile:w-full"
: !appLayout.subPanelOpen : !appLayout.subPanelOpen && "mobile:translate-x-[100vw]"
? "mobile:translate-x-[100vw]"
: ""
}`} }`}
> >
{subPanel} {subPanel}
@ -338,7 +333,7 @@ export default function AppLayout(props: AppLayoutProps): JSX.Element {
className="rounded-l-none rounded-r-none border-x-0" className="rounded-l-none rounded-r-none border-x-0"
onClick={() => appLayout.setFontSize(1)} onClick={() => appLayout.setFontSize(1)}
> >
{((appLayout.fontSize || 1) * 100).toLocaleString(undefined, { {((appLayout.fontSize ?? 1) * 100).toLocaleString(undefined, {
maximumFractionDigits: 0, maximumFractionDigits: 0,
})} })}
% %
@ -382,8 +377,10 @@ export default function AppLayout(props: AppLayoutProps): JSX.Element {
type="text" type="text"
placeholder="<player>" placeholder="<player>"
className="w-48" className="w-48"
onInput={(e) => onInput={(event) =>
appLayout.setPlayerName((e.target as HTMLInputElement).value) appLayout.setPlayerName(
(event.target as HTMLInputElement).value
)
} }
/> />
</div> </div>

View File

@ -19,23 +19,22 @@ export default function ChronologyItemComponent(
const { langui } = props; const { langui } = props;
function generateAnchor(year: number, month: number, day: number): string { function generateAnchor(year: number, month: number, day: number): string {
let result: string = ""; let result = "";
result += year; result += year;
if (month) result += "-" + month.toString().padStart(2, "0"); if (month) result += `- ${month.toString().padStart(2, "0")}`;
if (day) result += "-" + day.toString().padStart(2, "0"); if (day) result += `- ${day.toString().padStart(2, "0")}`;
return result; return result;
} }
function generateYear(displayed_date: string, year: number): string { function generateYear(displayed_date: string, year: number): string {
if (displayed_date) { if (displayed_date) {
return displayed_date; return displayed_date;
} else {
return year.toString();
} }
return year.toString();
} }
function generateDate(month: number, day: number): string { function generateDate(month: number, day: number): string {
let lut = [ const lut = [
"Jan", "Jan",
"Feb", "Feb",
"Mar", "Mar",
@ -50,11 +49,11 @@ export default function ChronologyItemComponent(
"Dec", "Dec",
]; ];
let result: string = ""; let result = "";
if (month) { if (month) {
result += lut[month - 1]; result += lut[month - 1];
if (day) { if (day) {
result += " " + day; result += ` ${day}`;
} }
} }
@ -113,7 +112,7 @@ export default function ChronologyItemComponent(
</p> </p>
)} )}
{translation.note ? ( {translation.note ? (
<em>{"Notes: " + translation.note}</em> <em>{`Notes: ${translation.note}`}</em>
) : ( ) : (
"" ""
)} )}
@ -122,7 +121,7 @@ export default function ChronologyItemComponent(
<p className="text-dark text-xs grid place-self-start grid-flow-col gap-1 mt-1"> <p className="text-dark text-xs grid place-self-start grid-flow-col gap-1 mt-1">
{event.source.data ? ( {event.source.data ? (
"(" + event.source.data.attributes.name + ")" `(${event.source.data.attributes.name})`
) : ( ) : (
<> <>
<span className="material-icons !text-sm">warning</span>No <span className="material-icons !text-sm">warning</span>No

View File

@ -49,7 +49,7 @@ export default function ThumbnailHeader(
</div> </div>
<div <div
id={slugify( id={slugify(
prettyinlineTitle(pre_title || "", title, subtitle || "") prettyinlineTitle(pre_title ?? "", title, subtitle ?? "")
)} )}
className="grid place-items-center text-center" className="grid place-items-center text-center"
> >
@ -60,7 +60,7 @@ export default function ThumbnailHeader(
</div> </div>
<div className="grid grid-flow-col gap-8"> <div className="grid grid-flow-col gap-8">
{type && type.data && ( {type?.data && (
<div className="flex flex-col place-items-center gap-2"> <div className="flex flex-col place-items-center gap-2">
<h3 className="text-xl">{langui.type}</h3> <h3 className="text-xl">{langui.type}</h3>
<div className="flex flex-row flex-wrap"> <div className="flex flex-row flex-wrap">

View File

@ -9,11 +9,12 @@ export enum ImageQuality {
} }
export function getAssetURL(url: string, quality: ImageQuality): string { export function getAssetURL(url: string, quality: ImageQuality): string {
url = url.replace(/^\/uploads/, "/" + quality); let newUrl = url;
url = url.replace(/.jpg$/, ".webp"); newUrl = newUrl.replace(/^\/uploads/u, `/${quality}`);
url = url.replace(/.png$/, ".webp"); newUrl = newUrl.replace(/.jpg$/u, ".webp");
if (quality === ImageQuality.Og) url = url.replace(/.webp$/, ".jpg"); newUrl = newUrl.replace(/.png$/u, ".webp");
return process.env.NEXT_PUBLIC_URL_IMG + url; if (quality === ImageQuality.Og) newUrl = newUrl.replace(/.webp$/u, ".jpg");
return process.env.NEXT_PUBLIC_URL_IMG + newUrl;
} }
export function getImgSizesByMaxSize( export function getImgSizesByMaxSize(
@ -24,10 +25,9 @@ export function getImgSizesByMaxSize(
if (width > height) { if (width > height) {
if (width < maxSize) return { width: width, height: height }; if (width < maxSize) return { width: width, height: height };
return { width: maxSize, height: (height / width) * maxSize }; return { width: maxSize, height: (height / width) * maxSize };
} else {
if (height < maxSize) return { width: width, height: height };
return { width: (width / height) * maxSize, height: maxSize };
} }
if (height < maxSize) return { width: width, height: height };
return { width: (width / height) * maxSize, height: maxSize };
} }
export function getImgSizesByQuality( export function getImgSizesByQuality(
@ -44,6 +44,8 @@ export function getImgSizesByQuality(
return getImgSizesByMaxSize(width, height, 1024); return getImgSizesByMaxSize(width, height, 1024);
case ImageQuality.Large: case ImageQuality.Large:
return getImgSizesByMaxSize(width, height, 2048); return getImgSizesByMaxSize(width, height, 2048);
default:
return { width: 0, height: 0 };
} }
} }
@ -80,25 +82,23 @@ export default function Img(props: ImgProps): JSX.Element {
height={imgSize.height} 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
/>
);
} }
} else { return (
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
/>
);
} }
return <></>;
} }

View File

@ -16,8 +16,7 @@ type ContentTOCLineProps = {
export default function ContentTOCLine( export default function ContentTOCLine(
props: ContentTOCLineProps props: ContentTOCLineProps
): JSX.Element { ): JSX.Element {
const content = props.content; const { content, langui } = props;
const langui = props.langui;
const [opened, setOpened] = useState(false); const [opened, setOpened] = useState(false);

View File

@ -17,10 +17,10 @@ export type LibraryContentPreviewProps = {
export default function LibraryContentPreview( export default function LibraryContentPreview(
props: LibraryContentPreviewProps props: LibraryContentPreviewProps
): JSX.Element { ): JSX.Element {
const item = props.item; const { item } = props;
return ( return (
<Link href={"/contents/" + item.slug} passHref> <Link href={`/contents/${item.slug}`} passHref>
<div className="drop-shadow-shade-xl cursor-pointer grid items-end fine:[--cover-opacity:0] hover:[--cover-opacity:1] hover:scale-[1.02] transition-transform"> <div className="drop-shadow-shade-xl cursor-pointer grid items-end fine:[--cover-opacity:0] hover:[--cover-opacity:1] hover:scale-[1.02] transition-transform">
{item.thumbnail.data ? ( {item.thumbnail.data ? (
<Img <Img

View File

@ -26,11 +26,11 @@ export type LibraryItemsPreviewProps = {
export default function LibraryItemsPreview( export default function LibraryItemsPreview(
props: LibraryItemsPreviewProps props: LibraryItemsPreviewProps
): JSX.Element { ): JSX.Element {
const item = props.item; const { item } = props;
const appLayout = useAppLayout(); const appLayout = useAppLayout();
return ( return (
<Link href={"/library/" + item.slug} passHref> <Link href={`/library/${item.slug}`} passHref>
<div <div
className={`drop-shadow-shade-xl cursor-pointer grid items-end hover:rounded-3xl fine:[--cover-opacity:0] hover:[--cover-opacity:1] hover:scale-[1.02] transition-transform ${props.className}`} className={`drop-shadow-shade-xl cursor-pointer grid items-end hover:rounded-3xl fine:[--cover-opacity:0] hover:[--cover-opacity:1] hover:scale-[1.02] transition-transform ${props.className}`}
> >
@ -63,7 +63,7 @@ export default function LibraryItemsPreview(
))} ))}
</div> </div>
{(item.release_date || item.price) && ( {(item.release_date ?? item.price) && (
<div className="grid grid-flow-col w-full"> <div className="grid grid-flow-col w-full">
{item.release_date && ( {item.release_date && (
<p className="mobile:text-xs text-sm"> <p className="mobile:text-xs text-sm">

View File

@ -4,8 +4,8 @@ import Lightbox from "react-image-lightbox";
export type LightBoxProps = { export type LightBoxProps = {
setState: setState:
| Dispatch<SetStateAction<boolean>> | Dispatch<SetStateAction<boolean | undefined>>
| Dispatch<SetStateAction<boolean | undefined>>; | Dispatch<SetStateAction<boolean>>;
state: boolean; state: boolean;
images: string[]; images: string[];
index: number; index: number;

View File

@ -8,6 +8,7 @@ import Markdown from "markdown-to-jsx";
import { NextRouter } from "next/router"; import { NextRouter } from "next/router";
import { slugify } from "queries/helpers"; import { slugify } from "queries/helpers";
import React, { useState } from "react"; import React, { useState } from "react";
import ReactDOMServer from "react-dom/server";
type MarkdawnProps = { type MarkdawnProps = {
className?: string; className?: string;
@ -41,264 +42,233 @@ export default function Markdawn(props: MarkdawnProps): JSX.Element {
slugify: slugify, slugify: slugify,
overrides: { overrides: {
h1: { h1: {
component: (props: { component: (compProps: {
id: string; id: string;
style: React.CSSProperties; style: React.CSSProperties;
children: React.ReactNode; children: React.ReactNode;
}) => { }) => (
return ( <h1 id={compProps.id} style={compProps.style}>
<h1 id={props.id} style={props.style}> {compProps.children}
{props.children} <HeaderToolTip id={compProps.id} />
<HeaderToolTip id={props.id} /> </h1>
</h1> ),
);
},
}, },
h2: { h2: {
component: (props: { component: (compProps: {
id: string; id: string;
style: React.CSSProperties; style: React.CSSProperties;
children: React.ReactNode; children: React.ReactNode;
}) => { }) => (
return ( <h2 id={compProps.id} style={compProps.style}>
<h2 id={props.id} style={props.style}> {compProps.children}
{props.children} <HeaderToolTip id={compProps.id} />
<HeaderToolTip id={props.id} /> </h2>
</h2> ),
);
},
}, },
h3: { h3: {
component: (props: { component: (compProps: {
id: string; id: string;
style: React.CSSProperties; style: React.CSSProperties;
children: React.ReactNode; children: React.ReactNode;
}) => { }) => (
return ( <h3 id={compProps.id} style={compProps.style}>
<h3 id={props.id} style={props.style}> {compProps.children}
{props.children} <HeaderToolTip id={compProps.id} />
<HeaderToolTip id={props.id} /> </h3>
</h3> ),
);
},
}, },
h4: { h4: {
component: (props: { component: (compProps: {
id: string; id: string;
style: React.CSSProperties; style: React.CSSProperties;
children: React.ReactNode; children: React.ReactNode;
}) => { }) => (
return ( <h4 id={compProps.id} style={compProps.style}>
<h4 id={props.id} style={props.style}> {compProps.children}
{props.children} <HeaderToolTip id={compProps.id} />
<HeaderToolTip id={props.id} /> </h4>
</h4> ),
);
},
}, },
h5: { h5: {
component: (props: { component: (compProps: {
id: string; id: string;
style: React.CSSProperties; style: React.CSSProperties;
children: React.ReactNode; children: React.ReactNode;
}) => { }) => (
return ( <h5 id={compProps.id} style={compProps.style}>
<h5 id={props.id} style={props.style}> {compProps.children}
{props.children} <HeaderToolTip id={compProps.id} />
<HeaderToolTip id={props.id} /> </h5>
</h5> ),
);
},
}, },
h6: { h6: {
component: (props: { component: (compProps: {
id: string; id: string;
style: React.CSSProperties; style: React.CSSProperties;
children: React.ReactNode; children: React.ReactNode;
}) => { }) => (
return ( <h6 id={compProps.id} style={compProps.style}>
<h6 id={props.id} style={props.style}> {compProps.children}
{props.children} <HeaderToolTip id={compProps.id} />
<HeaderToolTip id={props.id} /> </h6>
</h6> ),
);
},
}, },
Sep: { Sep: {
component: () => { component: () => <div className="my-24"></div>,
return <div className="my-24"></div>;
},
}, },
SceneBreak: { SceneBreak: {
component: (props: { id: string }) => { component: (compProps: { id: string }) => (
return ( <div
<div id={compProps.id}
id={props.id} className={"h-0 text-center text-3xl text-dark mt-16 mb-20"}
className={ >
"h-0 text-center text-3xl text-dark mt-16 mb-20" * * *
} </div>
> ),
* * *
</div>
);
},
}, },
IntraLink: { IntraLink: {
component: (props: { component: (compProps: {
children: React.ReactNode; children: React.ReactNode;
target?: string; target?: string;
page?: string; page?: string;
}) => { }) => {
const slug = props.target const slug = compProps.target
? slugify(props.target) ? slugify(compProps.target)
: slugify(props.children?.toString()); : slugify(compProps.children?.toString());
return ( return (
<a <a
onClick={() => onClick={async () =>
router.replace( router.replace(
`${props.page ? props.page : ""}#${slug}` `${compProps.page ? compProps.page : ""}#${slug}`
) )
} }
> >
{props.children} {compProps.children}
</a> </a>
); );
}, },
}, },
player: { player: {
component: () => { component: () => (
return ( <span className="text-dark opacity-70">
<span className="text-dark opacity-70"> {appLayout.playerName ? appLayout.playerName : "<player>"}
{appLayout.playerName ? appLayout.playerName : "<player>"} </span>
</span> ),
);
},
}, },
Transcript: { Transcript: {
component: (props) => { component: (compProps) => (
return ( <div className="grid grid-cols-[auto_1fr] mobile:grid-cols-1 gap-x-6 gap-y-2">
<div className="grid grid-cols-[auto_1fr] mobile:grid-cols-1 gap-x-6 gap-y-2"> {compProps.children}
{props.children} </div>
</div> ),
);
},
}, },
Line: { Line: {
component: (props) => { component: (compProps) => (
return ( <>
<> <strong className="text-dark opacity-60 mobile:!-mb-4">
<strong className="text-dark opacity-60 mobile:!-mb-4"> {compProps.name}
{props.name} </strong>
</strong> <p className="whitespace-pre-line">{compProps.children}</p>
<p className="whitespace-pre-line">{props.children}</p> </>
</> ),
);
},
}, },
InsetBox: { InsetBox: {
component: (props) => { component: (compProps) => (
return ( <InsetBox className="my-12">{compProps.children}</InsetBox>
<InsetBox className="my-12">{props.children}</InsetBox> ),
);
},
}, },
li: { li: {
component: (props: { children: React.ReactNode }) => { component: (compProps: { children: React.ReactNode }) => (
return ( <li
<li className={
className={ compProps.children &&
props.children && ReactDOMServer.renderToStaticMarkup(
props.children?.toString().length > 100 <>{compProps.children}</>
? "my-4" ).length > 100
: "" ? "my-4"
} : ""
> }
{props.children} >
</li> {compProps.children}
); </li>
}, ),
}, },
Highlight: { Highlight: {
component: (props: { children: React.ReactNode }) => { component: (compProps: { children: React.ReactNode }) => (
return <mark>{props.children}</mark>; <mark>{compProps.children}</mark>
}, ),
}, },
footer: { footer: {
component: (props: { children: React.ReactNode }) => { component: (compProps: { children: React.ReactNode }) => (
return ( <>
<> <HorizontalLine />
<HorizontalLine /> <div>{compProps.children}</div>
<div>{props.children}</div> </>
</> ),
);
},
}, },
blockquote: { blockquote: {
component: (props: { component: (compProps: {
children: React.ReactNode; children: React.ReactNode;
cite?: string; cite?: string;
}) => { }) => (
return ( <blockquote>
<blockquote> {compProps.cite ? (
{props.cite ? ( <>
<> &ldquo;{compProps.children}&rdquo;
&ldquo;{props.children}&rdquo; <cite> {compProps.cite}</cite>
<cite> {props.cite}</cite> </>
</> ) : (
) : ( compProps.children
props.children )}
)} </blockquote>
</blockquote> ),
);
},
}, },
img: { img: {
component: (props: { component: (compProps: {
alt: string; alt: string;
src: string; src: string;
width?: number; width?: number;
height?: number; height?: number;
caption?: string; caption?: string;
name?: string; name?: string;
}) => { }) => (
return ( <div
<div className="my-8 cursor-pointer"
className="my-8 cursor-pointer" onClick={() => {
onClick={() => { setLightboxOpen(true);
setLightboxOpen(true); setLightboxImages([
setLightboxImages([ compProps.src.startsWith("/uploads/")
props.src.startsWith("/uploads/") ? getAssetURL(compProps.src, ImageQuality.Large)
? getAssetURL(props.src, ImageQuality.Large) : compProps.src,
: props.src, ]);
]); setLightboxIndex(0);
setLightboxIndex(0); }}
}} >
> {compProps.src.startsWith("/uploads/") ? (
{props.src.startsWith("/uploads/") ? ( <div className="relative w-full aspect-video">
<div className="relative w-full aspect-video"> <Img
<Img image={{
image={{ __typename: "UploadFile",
__typename: "UploadFile", alternativeText: compProps.alt,
alternativeText: props.alt, url: compProps.src,
url: props.src, width: compProps.width ?? 1500,
width: props.width || 1500, height: compProps.height ?? 1000,
height: props.height || 1000, caption: compProps.caption ?? "",
caption: props.caption || "", name: compProps.name ?? "",
name: props.name || "", }}
}} layout="fill"
layout="fill" objectFit="contain"
objectFit="contain" quality={ImageQuality.Medium}
quality={ImageQuality.Medium} ></Img>
></Img> </div>
</div> ) : (
) : ( <div className="grid place-content-center">
<div className="grid place-content-center"> {/* eslint-disable-next-line jsx-a11y/alt-text */}
<img {...props} className="max-h-[50vh] " /> <img {...compProps} className="max-h-[50vh] " />
</div> </div>
)} )}
</div> </div>
); ),
},
}, },
}, },
}} }}
@ -323,10 +293,9 @@ function HeaderToolTip(props: { id: string }) {
className="material-icons transition-color hover:text-dark cursor-pointer" className="material-icons transition-color hover:text-dark cursor-pointer"
onClick={() => { onClick={() => {
navigator.clipboard.writeText( navigator.clipboard.writeText(
process.env.NEXT_PUBLIC_URL_SELF + `${process.env.NEXT_PUBLIC_URL_SELF + window.location.pathname}#${
window.location.pathname +
"#" +
props.id props.id
}`
); );
}} }}
> >
@ -344,8 +313,8 @@ export function preprocessMarkDawn(text: string): string {
const visitedSlugs: string[] = []; const visitedSlugs: string[] = [];
const result = text.split("\n").map((line) => { const result = text.split("\n").map((line) => {
if (line === "* * *" || line === "---") { if (line === "* * *" ?? line === "---") {
scenebreakIndex++; scenebreakIndex += 1;
return `<SceneBreak id="scene-break-${scenebreakIndex}">`; return `<SceneBreak id="scene-break-${scenebreakIndex}">`;
} }
@ -393,16 +362,13 @@ function markdawnHeadersParser(
visitedSlugs: string[] visitedSlugs: string[]
): string { ): string {
const lineText = line.slice(headerLevel + 1); const lineText = line.slice(headerLevel + 1);
let slug = slugify(lineText); const slug = slugify(lineText);
let newSlug = slug; let newSlug = slug;
let index = 2; let index = 2;
while (visitedSlugs.includes(newSlug)) { while (visitedSlugs.includes(newSlug)) {
newSlug = `${slug}-${index}`; newSlug = `${slug}-${index}`;
index++; index += 1;
} }
visitedSlugs.push(newSlug); visitedSlugs.push(newSlug);
return `<${headerLevels[headerLevel]} id="${newSlug}">${lineText}</${headerLevels[headerLevel]}>`; return `<${headerLevels[headerLevel]} id="${newSlug}">${lineText}</${headerLevels[headerLevel]}>`;
} }
function getAssetUrl(): React.SetStateAction<string[]> {
throw new Error("Function not implemented.");
}

View File

@ -8,7 +8,7 @@ type TOCProps = {
router: NextRouter; router: NextRouter;
}; };
export default function TOC(props: TOCProps): JSX.Element { export default function TOCComponent(props: TOCProps): JSX.Element {
const { router, text, title } = props; const { router, text, title } = props;
const toc = getTocFromMarkdawn(preprocessMarkDawn(text), title); const toc = getTocFromMarkdawn(preprocessMarkDawn(text), title);
@ -17,7 +17,7 @@ export default function TOC(props: TOCProps): JSX.Element {
<h3 className="text-xl">Table of content</h3> <h3 className="text-xl">Table of content</h3>
<div className="text-left max-w-[14.5rem]"> <div className="text-left max-w-[14.5rem]">
<p className="my-2 overflow-x-hidden relative text-ellipsis whitespace-nowrap text-left"> <p className="my-2 overflow-x-hidden relative text-ellipsis whitespace-nowrap text-left">
<a className="" onClick={() => router.replace(`#${toc.slug}`)}> <a className="" onClick={async () => router.replace(`#${toc.slug}`)}>
{<abbr title={toc.title}>{toc.title}</abbr>} {<abbr title={toc.title}>{toc.title}</abbr>}
</a> </a>
</p> </p>
@ -50,7 +50,7 @@ function TOCLevel(props: TOCLevelProps): JSX.Element {
<span className="text-dark">{`${parentNumbering}${ <span className="text-dark">{`${parentNumbering}${
childIndex + 1 childIndex + 1
}.`}</span>{" "} }.`}</span>{" "}
<a onClick={() => router.replace(`#${child.slug}`)}> <a onClick={async () => router.replace(`#${child.slug}`)}>
{<abbr title={child.title}>{child.title}</abbr>} {<abbr title={child.title}>{child.title}</abbr>}
</a> </a>
</li> </li>
@ -72,8 +72,11 @@ export type TOC = {
}; };
export function getTocFromMarkdawn(text: string, title?: string): TOC { export function getTocFromMarkdawn(text: string, title?: string): TOC {
if (!title) title = "Return to top"; const toc: TOC = {
let toc: TOC = { title: title, slug: slugify(title) || "", children: [] }; title: title ?? "Return to top",
slug: slugify(title) ?? "",
children: [],
};
let h2 = -1; let h2 = -1;
let h3 = -1; let h3 = -1;
let h4 = -1; let h4 = -1;
@ -99,7 +102,7 @@ export function getTocFromMarkdawn(text: string, title?: string): TOC {
slug: getSlug(line), slug: getSlug(line),
children: [], children: [],
}); });
h2++; h2 += 1;
h3 = -1; h3 = -1;
h4 = -1; h4 = -1;
h5 = -1; h5 = -1;
@ -110,7 +113,7 @@ export function getTocFromMarkdawn(text: string, title?: string): TOC {
slug: getSlug(line), slug: getSlug(line),
children: [], children: [],
}); });
h3++; h3 += 1;
h4 = -1; h4 = -1;
h5 = -1; h5 = -1;
scenebreak = 0; scenebreak = 0;
@ -120,7 +123,7 @@ export function getTocFromMarkdawn(text: string, title?: string): TOC {
slug: getSlug(line), slug: getSlug(line),
children: [], children: [],
}); });
h4++; h4 += 1;
h5 = -1; h5 = -1;
scenebreak = 0; scenebreak = 0;
} else if (line.startsWith("<h5 id=")) { } else if (line.startsWith("<h5 id=")) {
@ -129,7 +132,7 @@ export function getTocFromMarkdawn(text: string, title?: string): TOC {
slug: getSlug(line), slug: getSlug(line),
children: [], children: [],
}); });
h5++; h5 += 1;
scenebreak = 0; scenebreak = 0;
} else if (line.startsWith("<h6 id=")) { } else if (line.startsWith("<h6 id=")) {
toc.children[h2].children[h3].children[h4].children[h5].children.push({ toc.children[h2].children[h3].children[h4].children[h5].children.push({
@ -138,8 +141,8 @@ export function getTocFromMarkdawn(text: string, title?: string): TOC {
children: [], children: [],
}); });
} else if (line.startsWith(`<SceneBreak`)) { } else if (line.startsWith(`<SceneBreak`)) {
scenebreak++; scenebreak += 1;
scenebreakIndex++; scenebreakIndex += 1;
const child = { const child = {
title: `Scene break ${scenebreak}`, title: `Scene break ${scenebreak}`,

View File

@ -15,10 +15,10 @@ export type PostPreviewProps = {
}; };
export default function PostPreview(props: PostPreviewProps): JSX.Element { export default function PostPreview(props: PostPreviewProps): JSX.Element {
const post = props.post; const { post } = props;
return ( return (
<Link href={"/news/" + post.slug} passHref> <Link href={`/news/${post.slug}`} passHref>
<div className="drop-shadow-shade-xl cursor-pointer grid items-end hover:scale-[1.02] transition-transform"> <div className="drop-shadow-shade-xl cursor-pointer grid items-end hover:scale-[1.02] transition-transform">
{post.thumbnail.data ? ( {post.thumbnail.data ? (
<Img <Img

View File

@ -13,9 +13,9 @@ type ReturnButtonProps = {
}; };
export enum ReturnButtonType { export enum ReturnButtonType {
Mobile, mobile = "mobile",
Desktop, desktop = "desktop",
Both, both = "both",
} }
export default function ReturnButton(props: ReturnButtonProps): JSX.Element { export default function ReturnButton(props: ReturnButtonProps): JSX.Element {
@ -24,9 +24,9 @@ export default function ReturnButton(props: ReturnButtonProps): JSX.Element {
return ( return (
<div <div
className={`${ className={`${
props.displayOn === ReturnButtonType.Mobile props.displayOn === ReturnButtonType.mobile
? "desktop:hidden" ? "desktop:hidden"
: props.displayOn === ReturnButtonType.Desktop : props.displayOn === ReturnButtonType.desktop
? "mobile:hidden" ? "mobile:hidden"
: "" : ""
} ${props.className}`} } ${props.className}`}

View File

@ -5,8 +5,8 @@ type ContentPanelProps = {
}; };
export enum ContentPanelWidthSizes { export enum ContentPanelWidthSizes {
default, default = "default",
large, large = "large",
} }
export default function ContentPanel(props: ContentPanelProps): JSX.Element { export default function ContentPanel(props: ContentPanelProps): JSX.Element {

View File

@ -14,7 +14,7 @@ type MainPanelProps = {
}; };
export default function MainPanel(props: MainPanelProps): JSX.Element { export default function MainPanel(props: MainPanelProps): JSX.Element {
const langui = props.langui; const { langui } = props;
const router = useRouter(); const router = useRouter();
const isDesktop = useMediaDesktop(); const isDesktop = useMediaDesktop();
const appLayout = useAppLayout(); const appLayout = useAppLayout();

View File

@ -3,8 +3,8 @@ import Button from "./Button";
export type PopupProps = { export type PopupProps = {
setState: setState:
| Dispatch<SetStateAction<boolean>> | Dispatch<SetStateAction<boolean | undefined>>
| Dispatch<SetStateAction<boolean | undefined>>; | Dispatch<SetStateAction<boolean>>;
state?: boolean; state?: boolean;
children: React.ReactNode; children: React.ReactNode;
fillViewport?: boolean; fillViewport?: boolean;
@ -19,8 +19,8 @@ export default function Popup(props: PopupProps): JSX.Element {
? "[backdrop-filter:blur(2px)]" ? "[backdrop-filter:blur(2px)]"
: "pointer-events-none touch-none" : "pointer-events-none touch-none"
}`} }`}
onKeyUp={(e) => { onKeyUp={(event) => {
if (e.key.match("Escape")) props.setState(false); if (event.key.match("Escape")) props.setState(false);
}} }}
tabIndex={0} tabIndex={0}
> >

View File

@ -14,8 +14,7 @@ type RecorderChipProps = {
}; };
export default function RecorderChip(props: RecorderChipProps): JSX.Element { export default function RecorderChip(props: RecorderChipProps): JSX.Element {
const recorder = props.recorder; const { recorder, langui } = props;
const langui = props.langui;
return ( return (
<ToolTip <ToolTip

View File

@ -7,7 +7,6 @@ export type SelectProps = {
selected?: number; selected?: number;
allowEmpty?: boolean; allowEmpty?: boolean;
className?: string; className?: string;
onChange?: Function;
}; };
export default function Select(props: SelectProps): JSX.Element { export default function Select(props: SelectProps): JSX.Element {

View File

@ -4,7 +4,7 @@ import "tippy.js/animations/scale-subtle.css";
interface ToolTipProps extends TippyProps {} interface ToolTipProps extends TippyProps {}
export default function ToolTip(props: ToolTipProps): JSX.Element { export default function ToolTip(props: ToolTipProps): JSX.Element {
let newProps = { ...props }; const newProps = { ...props };
// Set defaults // Set defaults
if (newProps.delay === undefined) newProps.delay = [150, 0]; if (newProps.delay === undefined) newProps.delay = [150, 0];

View File

@ -33,6 +33,7 @@ export interface AppLayoutState {
setPlayerName: React.Dispatch<React.SetStateAction<string | undefined>>; setPlayerName: React.Dispatch<React.SetStateAction<string | undefined>>;
} }
/* eslint-disable @typescript-eslint/no-empty-function */
const initialState: AppLayoutState = { const initialState: AppLayoutState = {
subPanelOpen: false, subPanelOpen: false,
languagePanelOpen: false, languagePanelOpen: false,
@ -57,12 +58,13 @@ const initialState: AppLayoutState = {
setCurrency: () => {}, setCurrency: () => {},
setPlayerName: () => {}, setPlayerName: () => {},
}; };
/* eslint-enable @typescript-eslint/no-empty-function */
const AppContext = React.createContext<AppLayoutState>(initialState); const AppContext = React.createContext<AppLayoutState>(initialState);
export default AppContext; export default AppContext;
export function useAppLayout() { export function useAppLayout(): AppLayoutState {
return useContext(AppContext); return useContext(AppContext);
} }
@ -70,7 +72,7 @@ type Props = {
children: ReactNode; children: ReactNode;
}; };
export const AppContextProvider = (props: Props) => { export function AppContextProvider(props: Props): JSX.Element {
const [subPanelOpen, setSubPanelOpen] = useStateWithLocalStorage< const [subPanelOpen, setSubPanelOpen] = useStateWithLocalStorage<
boolean | undefined boolean | undefined
>("subPanelOpen", initialState.subPanelOpen); >("subPanelOpen", initialState.subPanelOpen);
@ -143,4 +145,4 @@ export const AppContextProvider = (props: Props) => {
{props.children} {props.children}
</AppContext.Provider> </AppContext.Provider>
); );
}; }

View File

@ -1,3 +1,7 @@
/* eslint-disable @typescript-eslint/consistent-indexed-object-style */
/* eslint-disable @typescript-eslint/array-type */
/* eslint-disable no-shadow */
/* eslint-disable id-denylist */
export type Exact<T> = T; export type Exact<T> = T;
export type InputMaybe<T> = T; export type InputMaybe<T> = T;
export type Scalars = { export type Scalars = {
@ -6,30 +10,31 @@ export type Scalars = {
Boolean: boolean; Boolean: boolean;
Int: number; Int: number;
Float: number; Float: number;
JSON: any; JSON: unknown;
DateTime: any; DateTime: unknown;
Time: any; Time: unknown;
Upload: any; Upload: unknown;
LibraryContentRangeDynamicZoneInput: any; LibraryContentRangeDynamicZoneInput: unknown;
LibraryItemMetadataDynamicZoneInput: any; LibraryItemMetadataDynamicZoneInput: unknown;
SourceSourceDynamicZoneInput: any; SourceSourceDynamicZoneInput: unknown;
}; };
/* /*
The following is generated using https://www.graphql-code-generator.com/ * The following is generated using https://www.graphql-code-generator.com/
With the following codegen.yml: * With the following codegen.yml:
*
generates: * generates:
operations-types.ts: * operations-types.ts:
plugins: * plugins:
- typescript-operations * - typescript-operations
*
And the schema.graphql and operation.graphql files from this folder. * And the schema.graphql and operation.graphql files from this folder.
*
But to make the type easier to work with, it went through the following transformation: * But to make the type easier to work with, it went through the following transformation:
- Removed ? * - Removed ?
- Removed | null * - Removed | null
*/ * - Replaced any by unknown
*/
export enum Enum_Componentmetadatabooks_Binding_Type { export enum Enum_Componentmetadatabooks_Binding_Type {
Paperback = "Paperback", Paperback = "Paperback",
@ -939,8 +944,8 @@ export type GetLibraryItemQuery = {
} }
| { | {
__typename: "ComponentRangeTimeRange"; __typename: "ComponentRangeTimeRange";
starting_time: any; starting_time: unknown;
ending_time: any; ending_time: unknown;
} }
| { __typename: "ComponentRangeOther" } | { __typename: "ComponentRangeOther" }
| { __typename: "Error" } | { __typename: "Error" }
@ -1571,7 +1576,7 @@ export type GetPostQuery = {
attributes: { attributes: {
__typename: "Post"; __typename: "Post";
slug: string; slug: string;
updatedAt: any; updatedAt: unknown;
date: { date: {
__typename: "ComponentBasicsDatepicker"; __typename: "ComponentBasicsDatepicker";
year: number; year: number;

View File

@ -36,7 +36,7 @@ import {
GetWebsiteInterfaceQueryVariables, GetWebsiteInterfaceQueryVariables,
} from "graphql/operations-types"; } from "graphql/operations-types";
const graphQL = async (query: string, variables?: string) => { async function graphQL(query: string, variables?: string) {
const res = await fetch(`${process.env.URL_GRAPHQL}`, { const res = await fetch(`${process.env.URL_GRAPHQL}`, {
method: "POST", method: "POST",
body: JSON.stringify({ body: JSON.stringify({
@ -45,11 +45,11 @@ const graphQL = async (query: string, variables?: string) => {
}), }),
headers: { headers: {
"content-type": "application/json", "content-type": "application/json",
Authorization: "Bearer " + process.env.ACCESS_TOKEN, Authorization: `Bearer ${process.env.ACCESS_TOKEN}`,
}, },
}); });
return (await res.json()).data; return (await res.json()).data;
}; }
function getQueryFromOperations(queryName: string): string { function getQueryFromOperations(queryName: string): string {
const operations = readFileSync("./src/graphql/operation.graphql", "utf8"); const operations = readFileSync("./src/graphql/operation.graphql", "utf8");

View File

@ -1,13 +1,13 @@
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
export default function useMediaQuery(query: string): boolean { export default function useMediaQuery(query: string): boolean {
const getMatches = (query: string): boolean => { function getMatches(query: string): boolean {
// Prevents SSR issues // Prevents SSR issues
if (typeof window !== "undefined") { if (typeof window !== "undefined") {
return window.matchMedia(query).matches; return window.matchMedia(query).matches;
} }
return false; return false;
}; }
const [matches, setMatches] = useState<boolean>(getMatches(query)); const [matches, setMatches] = useState<boolean>(getMatches(query));

View File

@ -3,7 +3,7 @@ import ReturnButton, {
ReturnButtonType, ReturnButtonType,
} from "components/PanelComponents/ReturnButton"; } from "components/PanelComponents/ReturnButton";
import ContentPanel from "components/Panels/ContentPanel"; import ContentPanel from "components/Panels/ContentPanel";
import { GetStaticProps } from "next"; import { GetStaticPropsContext } from "next";
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps"; import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
interface FourOhFourProps extends AppStaticProps {} interface FourOhFourProps extends AppStaticProps {}
@ -17,18 +17,20 @@ export default function FourOhFour(props: FourOhFourProps): JSX.Element {
href="/" href="/"
title="Home" title="Home"
langui={langui} langui={langui}
displayOn={ReturnButtonType.Both} displayOn={ReturnButtonType.both}
/> />
</ContentPanel> </ContentPanel>
); );
return <AppLayout navTitle="404" contentPanel={contentPanel} {...props} />; return <AppLayout navTitle="404" contentPanel={contentPanel} {...props} />;
} }
export const getStaticProps: GetStaticProps = async (context) => { export async function getStaticProps(
context: GetStaticPropsContext
): Promise<{ props: FourOhFourProps }> {
const props: FourOhFourProps = { const props: FourOhFourProps = {
...(await getAppStaticProps(context)), ...(await getAppStaticProps(context)),
}; };
return { return {
props: props, props: props,
}; };
}; }

View File

@ -8,7 +8,7 @@ import { AppContextProvider } from "contexts/AppLayoutContext";
import type { AppProps } from "next/app"; import type { AppProps } from "next/app";
import "tailwind.css"; import "tailwind.css";
export default function AccordsLibraryApp(props: AppProps) { export default function AccordsLibraryApp(props: AppProps): JSX.Element {
return ( return (
<AppContextProvider> <AppContextProvider>
<props.Component {...props.pageProps} /> <props.Component {...props.pageProps} />

View File

@ -7,12 +7,13 @@ import Document, {
} from "next/document"; } from "next/document";
class MyDocument extends Document { class MyDocument extends Document {
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
static async getInitialProps(ctx: DocumentContext) { static async getInitialProps(ctx: DocumentContext) {
const initialProps = await Document.getInitialProps(ctx); const initialProps = await Document.getInitialProps(ctx);
return { ...initialProps }; return { ...initialProps };
} }
render() { render(): JSX.Element {
return ( return (
<Html> <Html>
<Head> <Head>

View File

@ -9,7 +9,7 @@ import ContentPanel from "components/Panels/ContentPanel";
import SubPanel from "components/Panels/SubPanel"; import SubPanel from "components/Panels/SubPanel";
import { getPost, getPostLanguages } from "graphql/operations"; import { getPost, getPostLanguages } from "graphql/operations";
import { GetPostQuery } from "graphql/operations-types"; import { GetPostQuery } from "graphql/operations-types";
import { GetStaticProps } from "next"; import { GetStaticPropsContext } from "next";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps"; import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
import { prettySlug } from "queries/helpers"; import { prettySlug } from "queries/helpers";
@ -29,7 +29,7 @@ export default function AccordsHandbook(
<SubPanel> <SubPanel>
<ReturnButton <ReturnButton
href="/about-us" href="/about-us"
displayOn={ReturnButtonType.Desktop} displayOn={ReturnButtonType.desktop}
langui={langui} langui={langui}
title={langui.about_us} title={langui.about_us}
horizontalLine horizontalLine
@ -48,12 +48,12 @@ export default function AccordsHandbook(
<ContentPanel> <ContentPanel>
<ReturnButton <ReturnButton
href="/about-us" href="/about-us"
displayOn={ReturnButtonType.Mobile} displayOn={ReturnButtonType.mobile}
langui={langui} langui={langui}
title={langui.about_us} title={langui.about_us}
className="mb-10" className="mb-10"
/> />
{locales.includes(router.locale || "en") ? ( {locales.includes(router.locale ?? "en") ? (
<Markdawn router={router} text={post.translations[0].body} /> <Markdawn router={router} text={post.translations[0].body} />
) : ( ) : (
<LanguageSwitcher <LanguageSwitcher
@ -80,23 +80,25 @@ export default function AccordsHandbook(
); );
} }
export const getStaticProps: GetStaticProps = async (context) => { export async function getStaticProps(
context: GetStaticPropsContext
): Promise<{ props: AccordsHandbookProps }> {
const slug = "accords-handbook"; const slug = "accords-handbook";
const props: AccordsHandbookProps = { const props: AccordsHandbookProps = {
...(await getAppStaticProps(context)), ...(await getAppStaticProps(context)),
post: ( post: (
await getPost({ await getPost({
slug: slug, slug: slug,
language_code: context.locale || "en", language_code: context.locale ?? "en",
}) })
).posts.data[0].attributes, ).posts.data[0].attributes,
locales: ( locales: (
await getPostLanguages({ slug: slug }) await getPostLanguages({ slug: slug })
).posts.data[0].attributes.translations.map((translation) => { ).posts.data[0].attributes.translations.map(
return translation.language.data.attributes.code; (translation) => translation.language.data.attributes.code
}), ),
}; };
return { return {
props: props, props: props,
}; };
}; }

View File

@ -10,7 +10,7 @@ import ContentPanel from "components/Panels/ContentPanel";
import SubPanel from "components/Panels/SubPanel"; import SubPanel from "components/Panels/SubPanel";
import { getPost, getPostLanguages } from "graphql/operations"; import { getPost, getPostLanguages } from "graphql/operations";
import { GetPostQuery } from "graphql/operations-types"; import { GetPostQuery } from "graphql/operations-types";
import { GetStaticProps } from "next"; import { GetStaticPropsContext } from "next";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import { RequestMailProps, ResponseMailProps } from "pages/api/mail"; import { RequestMailProps, ResponseMailProps } from "pages/api/mail";
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps"; import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
@ -26,7 +26,7 @@ export default function AboutUs(props: ContactProps): JSX.Element {
const { langui, post, locales } = props; const { langui, post, locales } = props;
const router = useRouter(); const router = useRouter();
const [formResponse, setFormResponse] = useState(""); const [formResponse, setFormResponse] = useState("");
const [formState, setFormState] = useState<"stale" | "ongoing" | "completed">( const [formState, setFormState] = useState<"completed" | "ongoing" | "stale">(
"stale" "stale"
); );
@ -37,7 +37,7 @@ export default function AboutUs(props: ContactProps): JSX.Element {
<SubPanel> <SubPanel>
<ReturnButton <ReturnButton
href="/about-us" href="/about-us"
displayOn={ReturnButtonType.Desktop} displayOn={ReturnButtonType.desktop}
langui={langui} langui={langui}
title={langui.about_us} title={langui.about_us}
horizontalLine horizontalLine
@ -56,12 +56,12 @@ export default function AboutUs(props: ContactProps): JSX.Element {
<ContentPanel> <ContentPanel>
<ReturnButton <ReturnButton
href="/about-us" href="/about-us"
displayOn={ReturnButtonType.Mobile} displayOn={ReturnButtonType.mobile}
langui={langui} langui={langui}
title={langui.about_us} title={langui.about_us}
className="mb-10" className="mb-10"
/> />
{locales.includes(router.locale || "en") ? ( {locales.includes(router.locale ?? "en") ? (
<Markdawn router={router} text={post.translations[0].body} /> <Markdawn router={router} text={post.translations[0].body} />
) : ( ) : (
<LanguageSwitcher <LanguageSwitcher
@ -78,10 +78,10 @@ export default function AboutUs(props: ContactProps): JSX.Element {
formState !== "stale" && formState !== "stale" &&
"opacity-60 cursor-not-allowed touch-none pointer-events-none" "opacity-60 cursor-not-allowed touch-none pointer-events-none"
}`} }`}
onSubmit={(e) => { onSubmit={(event) => {
e.preventDefault(); event.preventDefault();
const fields = e.target as unknown as { const fields = event.target as unknown as {
verif: HTMLInputElement; verif: HTMLInputElement;
name: HTMLInputElement; name: HTMLInputElement;
email: HTMLInputElement; email: HTMLInputElement;
@ -91,7 +91,8 @@ export default function AboutUs(props: ContactProps): JSX.Element {
setFormState("ongoing"); setFormState("ongoing");
if ( if (
parseInt(fields.verif.value) == randomNumber1 + randomNumber2 && parseInt(fields.verif.value, 10) ===
randomNumber1 + randomNumber2 &&
formState !== "completed" formState !== "completed"
) { ) {
const content: RequestMailProps = { const content: RequestMailProps = {
@ -107,9 +108,9 @@ export default function AboutUs(props: ContactProps): JSX.Element {
"Content-type": "application/json; charset=UTF-8", "Content-type": "application/json; charset=UTF-8",
}, },
}) })
.then((response) => response.json()) .then(async (responseJson) => responseJson.json())
.then((data: ResponseMailProps) => { .then((response: ResponseMailProps) => {
switch (data.code) { switch (response.code) {
case "OKAY": case "OKAY":
setFormResponse(langui.response_email_success); setFormResponse(langui.response_email_success);
setFormState("completed"); setFormState("completed");
@ -122,7 +123,7 @@ export default function AboutUs(props: ContactProps): JSX.Element {
break; break;
default: default:
setFormResponse(data.message || ""); setFormResponse(response.message ?? "");
setFormState("stale"); setFormState("stale");
break; break;
} }
@ -223,23 +224,25 @@ export default function AboutUs(props: ContactProps): JSX.Element {
); );
} }
export const getStaticProps: GetStaticProps = async (context) => { export async function getStaticProps(
context: GetStaticPropsContext
): Promise<{ props: ContactProps }> {
const slug = "contact"; const slug = "contact";
const props: ContactProps = { const props: ContactProps = {
...(await getAppStaticProps(context)), ...(await getAppStaticProps(context)),
post: ( post: (
await getPost({ await getPost({
slug: slug, slug: slug,
language_code: context.locale || "en", language_code: context.locale ?? "en",
}) })
).posts.data[0].attributes, ).posts.data[0].attributes,
locales: ( locales: (
await getPostLanguages({ slug: slug }) await getPostLanguages({ slug: slug })
).posts.data[0].attributes.translations.map((translation) => { ).posts.data[0].attributes.translations.map(
return translation.language.data.attributes.code; (translation) => translation.language.data.attributes.code
}), ),
}; };
return { return {
props: props, props: props,
}; };
}; }

View File

@ -2,7 +2,7 @@ import AppLayout from "components/AppLayout";
import NavOption from "components/PanelComponents/NavOption"; import NavOption from "components/PanelComponents/NavOption";
import PanelHeader from "components/PanelComponents/PanelHeader"; import PanelHeader from "components/PanelComponents/PanelHeader";
import SubPanel from "components/Panels/SubPanel"; import SubPanel from "components/Panels/SubPanel";
import { GetStaticProps } from "next"; import { GetStaticPropsContext } from "next";
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps"; import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
interface AboutUsProps extends AppStaticProps {} interface AboutUsProps extends AppStaticProps {}
@ -36,11 +36,13 @@ export default function AboutUs(props: AboutUsProps): JSX.Element {
); );
} }
export const getStaticProps: GetStaticProps = async (context) => { export async function getStaticProps(
context: GetStaticPropsContext
): Promise<{ props: AboutUsProps }> {
const props: AboutUsProps = { const props: AboutUsProps = {
...(await getAppStaticProps(context)), ...(await getAppStaticProps(context)),
}; };
return { return {
props: props, props: props,
}; };
}; }

View File

@ -9,7 +9,7 @@ import ContentPanel from "components/Panels/ContentPanel";
import SubPanel from "components/Panels/SubPanel"; import SubPanel from "components/Panels/SubPanel";
import { getPost, getPostLanguages } from "graphql/operations"; import { getPost, getPostLanguages } from "graphql/operations";
import { GetPostQuery } from "graphql/operations-types"; import { GetPostQuery } from "graphql/operations-types";
import { GetStaticProps } from "next"; import { GetStaticPropsContext } from "next";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps"; import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
import { prettySlug } from "queries/helpers"; import { prettySlug } from "queries/helpers";
@ -27,7 +27,7 @@ export default function SiteInformation(props: SiteInfoProps): JSX.Element {
<SubPanel> <SubPanel>
<ReturnButton <ReturnButton
href="/about-us" href="/about-us"
displayOn={ReturnButtonType.Desktop} displayOn={ReturnButtonType.desktop}
langui={langui} langui={langui}
title={langui.about_us} title={langui.about_us}
horizontalLine horizontalLine
@ -46,12 +46,12 @@ export default function SiteInformation(props: SiteInfoProps): JSX.Element {
<ContentPanel> <ContentPanel>
<ReturnButton <ReturnButton
href="/about-us" href="/about-us"
displayOn={ReturnButtonType.Mobile} displayOn={ReturnButtonType.mobile}
langui={langui} langui={langui}
title={langui.about_us} title={langui.about_us}
className="mb-10" className="mb-10"
/> />
{locales.includes(router.locale || "en") ? ( {locales.includes(router.locale ?? "en") ? (
<Markdawn router={router} text={post.translations[0].body} /> <Markdawn router={router} text={post.translations[0].body} />
) : ( ) : (
<LanguageSwitcher <LanguageSwitcher
@ -78,23 +78,25 @@ export default function SiteInformation(props: SiteInfoProps): JSX.Element {
); );
} }
export const getStaticProps: GetStaticProps = async (context) => { export async function getStaticProps(
context: GetStaticPropsContext
): Promise<{ props: SiteInfoProps }> {
const slug = "legality"; const slug = "legality";
const props: SiteInfoProps = { const props: SiteInfoProps = {
...(await getAppStaticProps(context)), ...(await getAppStaticProps(context)),
post: ( post: (
await getPost({ await getPost({
slug: slug, slug: slug,
language_code: context.locale || "en", language_code: context.locale ?? "en",
}) })
).posts.data[0].attributes, ).posts.data[0].attributes,
locales: ( locales: (
await getPostLanguages({ slug: slug }) await getPostLanguages({ slug: slug })
).posts.data[0].attributes.translations.map((translation) => { ).posts.data[0].attributes.translations.map(
return translation.language.data.attributes.code; (translation) => translation.language.data.attributes.code
}), ),
}; };
return { return {
props: props, props: props,
}; };
}; }

View File

@ -9,7 +9,7 @@ import ContentPanel from "components/Panels/ContentPanel";
import SubPanel from "components/Panels/SubPanel"; import SubPanel from "components/Panels/SubPanel";
import { getPost, getPostLanguages } from "graphql/operations"; import { getPost, getPostLanguages } from "graphql/operations";
import { GetPostQuery } from "graphql/operations-types"; import { GetPostQuery } from "graphql/operations-types";
import { GetStaticProps } from "next"; import { GetStaticPropsContext } from "next";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps"; import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
import { prettySlug } from "queries/helpers"; import { prettySlug } from "queries/helpers";
@ -27,7 +27,7 @@ export default function SharingPolicy(props: SharingPolicyProps): JSX.Element {
<SubPanel> <SubPanel>
<ReturnButton <ReturnButton
href="/about-us" href="/about-us"
displayOn={ReturnButtonType.Desktop} displayOn={ReturnButtonType.desktop}
langui={langui} langui={langui}
title={langui.about_us} title={langui.about_us}
horizontalLine horizontalLine
@ -46,12 +46,12 @@ export default function SharingPolicy(props: SharingPolicyProps): JSX.Element {
<ContentPanel> <ContentPanel>
<ReturnButton <ReturnButton
href="/about-us" href="/about-us"
displayOn={ReturnButtonType.Mobile} displayOn={ReturnButtonType.mobile}
langui={langui} langui={langui}
title={langui.about_us} title={langui.about_us}
className="mb-10" className="mb-10"
/> />
{locales.includes(router.locale || "en") ? ( {locales.includes(router.locale ?? "en") ? (
<Markdawn router={router} text={post.translations[0].body} /> <Markdawn router={router} text={post.translations[0].body} />
) : ( ) : (
<LanguageSwitcher <LanguageSwitcher
@ -78,23 +78,25 @@ export default function SharingPolicy(props: SharingPolicyProps): JSX.Element {
); );
} }
export const getStaticProps: GetStaticProps = async (context) => { export async function getStaticProps(
context: GetStaticPropsContext
): Promise<{ props: SharingPolicyProps }> {
const slug = "sharing-policy"; const slug = "sharing-policy";
const props: SharingPolicyProps = { const props: SharingPolicyProps = {
...(await getAppStaticProps(context)), ...(await getAppStaticProps(context)),
post: ( post: (
await getPost({ await getPost({
slug: slug, slug: slug,
language_code: context.locale || "en", language_code: context.locale ?? "en",
}) })
).posts.data[0].attributes, ).posts.data[0].attributes,
locales: ( locales: (
await getPostLanguages({ slug: slug }) await getPostLanguages({ slug: slug })
).posts.data[0].attributes.translations.map((translation) => { ).posts.data[0].attributes.translations.map(
return translation.language.data.attributes.code; (translation) => translation.language.data.attributes.code
}), ),
}; };
return { return {
props: props, props: props,
}; };
}; }

View File

@ -21,10 +21,10 @@ export default async function Mail(
if (req.method === "POST") { if (req.method === "POST") {
const body = req.body as RequestMailProps; const body = req.body as RequestMailProps;
let transporter = nodemailer.createTransport({ const transporter = nodemailer.createTransport({
host: process.env.SMTP_HOST, host: process.env.SMTP_HOST,
port: 587, port: 587,
secure: false, // true for 465, false for other ports secure: false,
auth: { auth: {
user: process.env.SMTP_USER, user: process.env.SMTP_USER,
pass: process.env.SMTP_PASSWORD, pass: process.env.SMTP_PASSWORD,
@ -32,7 +32,7 @@ export default async function Mail(
}); });
// send mail with defined transport object // send mail with defined transport object
let info = await transporter await transporter
.sendMail({ .sendMail({
from: `"${body.name}" <${body.email}>`, from: `"${body.name}" <${body.email}>`,
to: "contact@accords-library.com", to: "contact@accords-library.com",
@ -40,7 +40,7 @@ export default async function Mail(
text: body.message, text: body.message,
}) })
.catch((reason: SMTPError) => { .catch((reason: SMTPError) => {
res.status(reason.responseCode || 500).json({ res.status(reason.responseCode ?? 500).json({
code: reason.code, code: reason.code,
message: reason.response, message: reason.response,
}); });

View File

@ -1,7 +1,7 @@
import AppLayout from "components/AppLayout"; import AppLayout from "components/AppLayout";
import PanelHeader from "components/PanelComponents/PanelHeader"; import PanelHeader from "components/PanelComponents/PanelHeader";
import SubPanel from "components/Panels/SubPanel"; import SubPanel from "components/Panels/SubPanel";
import { GetStaticProps } from "next"; import { GetStaticPropsContext } from "next";
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps"; import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
interface ArchivesProps extends AppStaticProps {} interface ArchivesProps extends AppStaticProps {}
@ -22,11 +22,13 @@ export default function Archives(props: ArchivesProps): JSX.Element {
); );
} }
export const getStaticProps: GetStaticProps = async (context) => { export async function getStaticProps(
context: GetStaticPropsContext
): Promise<{ props: ArchivesProps }> {
const props: ArchivesProps = { const props: ArchivesProps = {
...(await getAppStaticProps(context)), ...(await getAppStaticProps(context)),
}; };
return { return {
props: props, props: props,
}; };
}; }

View File

@ -1,7 +1,7 @@
import AppLayout from "components/AppLayout"; import AppLayout from "components/AppLayout";
import PanelHeader from "components/PanelComponents/PanelHeader"; import PanelHeader from "components/PanelComponents/PanelHeader";
import SubPanel from "components/Panels/SubPanel"; import SubPanel from "components/Panels/SubPanel";
import { GetStaticProps } from "next"; import { GetStaticPropsContext } from "next";
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps"; import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
interface ChroniclesProps extends AppStaticProps {} interface ChroniclesProps extends AppStaticProps {}
@ -22,11 +22,13 @@ export default function Chronicles(props: ChroniclesProps): JSX.Element {
); );
} }
export const getStaticProps: GetStaticProps = async (context) => { export async function getStaticProps(context: GetStaticPropsContext): Promise<{
props: ChroniclesProps;
}> {
const props: ChroniclesProps = { const props: ChroniclesProps = {
...(await getAppStaticProps(context)), ...(await getAppStaticProps(context)),
}; };
return { return {
props: props, props: props,
}; };
}; }

View File

@ -9,7 +9,11 @@ import ContentPanel from "components/Panels/ContentPanel";
import SubPanel from "components/Panels/SubPanel"; import SubPanel from "components/Panels/SubPanel";
import { getContent, getContentsSlugs } from "graphql/operations"; import { getContent, getContentsSlugs } from "graphql/operations";
import { GetContentQuery } from "graphql/operations-types"; import { GetContentQuery } from "graphql/operations-types";
import { GetStaticPaths, GetStaticProps } from "next"; import {
GetStaticPathsContext,
GetStaticPathsResult,
GetStaticPropsContext,
} from "next";
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps"; import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
import { prettyinlineTitle, prettySlug } from "queries/helpers"; import { prettyinlineTitle, prettySlug } from "queries/helpers";
@ -25,7 +29,7 @@ export default function ContentIndex(props: ContentIndexProps): JSX.Element {
href="/contents" href="/contents"
title={"Contents"} title={"Contents"}
langui={langui} langui={langui}
displayOn={ReturnButtonType.Desktop} displayOn={ReturnButtonType.desktop}
horizontalLine horizontalLine
/> />
</SubPanel> </SubPanel>
@ -36,7 +40,7 @@ export default function ContentIndex(props: ContentIndexProps): JSX.Element {
href="/contents" href="/contents"
title={"Contents"} title={"Contents"}
langui={langui} langui={langui}
displayOn={ReturnButtonType.Mobile} displayOn={ReturnButtonType.mobile}
className="mb-10" className="mb-10"
/> />
<div className="grid place-items-center"> <div className="grid place-items-center">
@ -99,9 +103,7 @@ export default function ContentIndex(props: ContentIndexProps): JSX.Element {
if (content.categories.data.length > 0) { if (content.categories.data.length > 0) {
description += `${langui.categories}: `; description += `${langui.categories}: `;
description += content.categories.data description += content.categories.data
.map((category) => { .map((category) => category.attributes.short)
return category.attributes.short;
})
.join(" | "); .join(" | ");
description += "\n"; description += "\n";
} }
@ -132,27 +134,29 @@ export default function ContentIndex(props: ContentIndexProps): JSX.Element {
); );
} }
export const getStaticProps: GetStaticProps = async (context) => { export async function getStaticProps(context: GetStaticPropsContext): Promise<{
props: ContentIndexProps;
}> {
const props: ContentIndexProps = { const props: ContentIndexProps = {
...(await getAppStaticProps(context)), ...(await getAppStaticProps(context)),
content: ( content: (
await getContent({ await getContent({
slug: context.params?.slug?.toString() || "", slug: context.params?.slug?.toString() ?? "",
language_code: context.locale || "en", language_code: context.locale ?? "en",
}) })
).contents.data[0].attributes, ).contents.data[0].attributes,
}; };
return { return {
props: props, props: props,
}; };
}; }
export const getStaticPaths: GetStaticPaths = async (context) => { export async function getStaticPaths(
type Path = { params: { slug: string }; locale: string }; context: GetStaticPathsContext
): Promise<GetStaticPathsResult> {
const data = await getContentsSlugs({}); const contents = await getContentsSlugs({});
const paths: Path[] = []; const paths: GetStaticPathsResult["paths"] = [];
data.contents.data.map((item) => { contents.contents.data.map((item) => {
context.locales?.map((local) => { context.locales?.map((local) => {
paths.push({ params: { slug: item.attributes.slug }, locale: local }); paths.push({ params: { slug: item.attributes.slug }, locale: local });
}); });
@ -161,4 +165,4 @@ export const getStaticPaths: GetStaticPaths = async (context) => {
paths, paths,
fallback: false, fallback: false,
}; };
}; }

View File

@ -19,7 +19,11 @@ import {
getContentText, getContentText,
} from "graphql/operations"; } from "graphql/operations";
import { GetContentTextQuery } from "graphql/operations-types"; import { GetContentTextQuery } from "graphql/operations-types";
import { GetStaticPaths, GetStaticProps } from "next"; import {
GetStaticPathsContext,
GetStaticPathsResult,
GetStaticPropsContext,
} from "next";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps"; import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
import { import {
@ -48,7 +52,7 @@ export default function ContentRead(props: ContentReadProps): JSX.Element {
href={`/contents/${content.slug}`} href={`/contents/${content.slug}`}
title={"Content"} title={"Content"}
langui={langui} langui={langui}
displayOn={ReturnButtonType.Desktop} displayOn={ReturnButtonType.desktop}
horizontalLine horizontalLine
/> />
@ -163,7 +167,7 @@ export default function ContentRead(props: ContentReadProps): JSX.Element {
href={`/contents/${content.slug}`} href={`/contents/${content.slug}`}
title={langui.content} title={langui.content}
langui={langui} langui={langui}
displayOn={ReturnButtonType.Mobile} displayOn={ReturnButtonType.mobile}
className="mb-10" className="mb-10"
/> />
<div className="grid place-items-center"> <div className="grid place-items-center">
@ -192,7 +196,7 @@ export default function ContentRead(props: ContentReadProps): JSX.Element {
<HorizontalLine /> <HorizontalLine />
{locales.includes(router.locale || "en") ? ( {locales.includes(router.locale ?? "en") ? (
<Markdawn router={router} text={content.text_set[0].text} /> <Markdawn router={router} text={content.text_set[0].text} />
) : ( ) : (
<LanguageSwitcher <LanguageSwitcher
@ -219,9 +223,7 @@ export default function ContentRead(props: ContentReadProps): JSX.Element {
if (content.categories.data.length > 0) { if (content.categories.data.length > 0) {
description += `${langui.categories}: `; description += `${langui.categories}: `;
description += content.categories.data description += content.categories.data
.map((category) => { .map((category) => category.attributes.short)
return category.attributes.short;
})
.join(" | "); .join(" | ");
description += "\n"; description += "\n";
} }
@ -247,12 +249,14 @@ export default function ContentRead(props: ContentReadProps): JSX.Element {
); );
} }
export const getStaticProps: GetStaticProps = async (context) => { export async function getStaticProps(
const slug = context.params?.slug?.toString() || ""; context: GetStaticPropsContext
): Promise<{ props: ContentReadProps }> {
const slug = context.params?.slug?.toString() ?? "";
const content = ( const content = (
await getContentText({ await getContentText({
slug: slug, slug: slug,
language_code: context.locale || "en", language_code: context.locale ?? "en",
}) })
).contents.data[0]; ).contents.data[0];
const props: ContentReadProps = { const props: ContentReadProps = {
@ -261,26 +265,21 @@ export const getStaticProps: GetStaticProps = async (context) => {
contentId: content.id, contentId: content.id,
locales: ( locales: (
await getContentLanguages({ slug: slug }) await getContentLanguages({ slug: slug })
).contents.data[0].attributes.text_set.map((translation) => { ).contents.data[0].attributes.text_set.map(
return translation.language.data.attributes.code; (translation) => translation.language.data.attributes.code
}), ),
}; };
return { return {
props: props, props: props,
}; };
}; }
export const getStaticPaths: GetStaticPaths = async (context) => { export async function getStaticPaths(
type Path = { context: GetStaticPathsContext
params: { ): Promise<GetStaticPathsResult> {
slug: string; const contents = await getContentsSlugs({});
}; const paths: GetStaticPathsResult["paths"] = [];
locale: string; contents.contents.data.map((item) => {
};
const data = await getContentsSlugs({});
const paths: Path[] = [];
data.contents.data.map((item) => {
context.locales?.map((local) => { context.locales?.map((local) => {
paths.push({ params: { slug: item.attributes.slug }, locale: local }); paths.push({ params: { slug: item.attributes.slug }, locale: local });
}); });
@ -289,14 +288,13 @@ export const getStaticPaths: GetStaticPaths = async (context) => {
paths, paths,
fallback: false, fallback: false,
}; };
}; }
export function useTesting(props: ContentReadProps) { function useTesting(props: ContentReadProps) {
const router = useRouter(); const router = useRouter();
const { content, contentId } = props; const { content, contentId } = props;
const contentURL = const contentURL = `/admin/content-manager/collectionType/api::content.content/${contentId}`;
"/admin/content-manager/collectionType/api::content.content/" + contentId;
if (router.locale === "en") { if (router.locale === "en") {
if (content.categories.data.length === 0) { if (content.categories.data.length === 0) {
@ -323,18 +321,17 @@ export function useTesting(props: ContentReadProps) {
} }
if (content.text_set.length > 1) { if (content.text_set.length > 1) {
console.warn( prettyTestError(
prettyTestError( router,
router, "More than one textset for this language",
"More than one textset for this language", ["content", "text_set"],
["content", "text_set"], contentURL
contentURL
)
); );
} }
if (content.text_set.length === 1) { if (content.text_set.length === 1) {
const textset = content.text_set[0]; const textset = content.text_set[0];
if (!textset.text) { if (!textset.text) {
prettyTestError( prettyTestError(
router, router,
@ -350,43 +347,41 @@ export function useTesting(props: ContentReadProps) {
["content", "text_set"], ["content", "text_set"],
contentURL contentURL
); );
} else 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"],
contentURL
);
}
if (textset.translators.data.length > 0) {
prettyTestError(
router,
"Transcripts shouldn't have translators",
["content", "text_set"],
contentURL
);
}
} else { } else {
if (textset.source_language.data.attributes.code === router.locale) { // This is a translation
// This is a transcript if (textset.translators.data.length === 0) {
if (textset.transcribers.data.length === 0) { prettyTestError(
prettyTestError( router,
router, "Missing translators attribution",
"Missing transcribers attribution", ["content", "text_set"],
["content", "text_set"], contentURL
contentURL );
); }
} if (textset.transcribers.data.length > 0) {
if (textset.translators.data.length > 0) { prettyTestError(
prettyTestError( router,
router, "Translations shouldn't have transcribers",
"Transcripts shouldn't have translators", ["content", "text_set"],
["content", "text_set"], contentURL
contentURL );
);
}
} else {
// This is a translation
if (textset.translators.data.length === 0) {
prettyTestError(
router,
"Missing translators attribution",
["content", "text_set"],
contentURL
);
}
if (textset.transcribers.data.length > 0) {
prettyTestError(
router,
"Translations shouldn't have transcribers",
["content", "text_set"],
contentURL
);
}
} }
} }
} }

View File

@ -12,7 +12,7 @@ import {
GetContentsQuery, GetContentsQuery,
GetWebsiteInterfaceQuery, GetWebsiteInterfaceQuery,
} from "graphql/operations-types"; } from "graphql/operations-types";
import { GetStaticProps } from "next"; import { GetStaticPropsContext } from "next";
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps"; import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
import { prettyinlineTitle, prettySlug } from "queries/helpers"; import { prettyinlineTitle, prettySlug } from "queries/helpers";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
@ -64,7 +64,7 @@ export default function Contents(props: ContentsProps): JSX.Element {
<> <>
{name && ( {name && (
<h2 <h2
key={"h2" + name} key={`h2${name}`}
className="text-2xl pb-2 pt-10 first-of-type:pt-0 flex flex-row place-items-center gap-2" className="text-2xl pb-2 pt-10 first-of-type:pt-0 flex flex-row place-items-center gap-2"
> >
{name} {name}
@ -76,7 +76,7 @@ export default function Contents(props: ContentsProps): JSX.Element {
</h2> </h2>
)} )}
<div <div
key={"items" + name} key={`items${name}`}
className="grid gap-8 items-end grid-cols-2 desktop:grid-cols-[repeat(auto-fill,_minmax(15rem,1fr))]" className="grid gap-8 items-end grid-cols-2 desktop:grid-cols-[repeat(auto-fill,_minmax(15rem,1fr))]"
> >
{items.map((item) => ( {items.map((item) => (
@ -99,10 +99,12 @@ export default function Contents(props: ContentsProps): JSX.Element {
); );
} }
export const getStaticProps: GetStaticProps = async (context) => { export async function getStaticProps(
context: GetStaticPropsContext
): Promise<{ props: ContentsProps }> {
const contents = ( const contents = (
await getContents({ await getContents({
language_code: context.locale || "en", language_code: context.locale ?? "en",
}) })
).contents.data; ).contents.data;
@ -133,7 +135,7 @@ export const getStaticProps: GetStaticProps = async (context) => {
return { return {
props: props, props: props,
}; };
}; }
function getGroups( function getGroups(
langui: GetWebsiteInterfaceQuery["websiteInterfaces"]["data"][number]["attributes"], langui: GetWebsiteInterfaceQuery["websiteInterfaces"]["data"][number]["attributes"],
@ -141,55 +143,58 @@ function getGroups(
items: ContentsProps["contents"] items: ContentsProps["contents"]
): GroupContentItems { ): GroupContentItems {
switch (groupByType) { switch (groupByType) {
case 0: case 0: {
const typeGroup = new Map(); const group = new Map();
typeGroup.set("Drakengard 1", []); group.set("Drakengard 1", []);
typeGroup.set("Drakengard 1.3", []); group.set("Drakengard 1.3", []);
typeGroup.set("Drakengard 2", []); group.set("Drakengard 2", []);
typeGroup.set("Drakengard 3", []); group.set("Drakengard 3", []);
typeGroup.set("Drakengard 4", []); group.set("Drakengard 4", []);
typeGroup.set("NieR Gestalt", []); group.set("NieR Gestalt", []);
typeGroup.set("NieR Replicant", []); group.set("NieR Replicant", []);
typeGroup.set("NieR Replicant ver.1.22474487139...", []); group.set("NieR Replicant ver.1.22474487139...", []);
typeGroup.set("NieR:Automata", []); group.set("NieR:Automata", []);
typeGroup.set("NieR Re[in]carnation", []); group.set("NieR Re[in]carnation", []);
typeGroup.set("SINoALICE", []); group.set("SINoALICE", []);
typeGroup.set("Voice of Cards", []); group.set("Voice of Cards", []);
typeGroup.set("Final Fantasy XIV", []); group.set("Final Fantasy XIV", []);
typeGroup.set("Thou Shalt Not Die", []); group.set("Thou Shalt Not Die", []);
typeGroup.set("Bakuken", []); group.set("Bakuken", []);
typeGroup.set("YoRHa", []); group.set("YoRHa", []);
typeGroup.set("YoRHa Boys", []); group.set("YoRHa Boys", []);
typeGroup.set(langui.no_category, []); group.set(langui.no_category, []);
items.map((item) => { items.map((item) => {
if (item.attributes.categories.data.length === 0) { if (item.attributes.categories.data.length === 0) {
typeGroup.get(langui.no_category)?.push(item); group.get(langui.no_category)?.push(item);
} else { } else {
item.attributes.categories.data.map((category) => { item.attributes.categories.data.map((category) => {
typeGroup.get(category.attributes.name)?.push(item); group.get(category.attributes.name)?.push(item);
}); });
} }
}); });
return typeGroup; return group;
}
case 1: case 1: {
const groupType: GroupContentItems = new Map(); const group: GroupContentItems = new Map();
items.map((item) => { items.map((item) => {
const type = const type =
item.attributes.type.data.attributes.titles.length > 0 item.attributes.type.data.attributes.titles.length > 0
? item.attributes.type.data.attributes.titles[0].title ? item.attributes.type.data.attributes.titles[0].title
: prettySlug(item.attributes.type.data.attributes.slug); : prettySlug(item.attributes.type.data.attributes.slug);
if (!groupType.has(type)) groupType.set(type, []); if (!group.has(type)) group.set(type, []);
groupType.get(type)?.push(item); group.get(type)?.push(item);
}); });
return groupType; return group;
}
default: default: {
const groupDefault: GroupContentItems = new Map(); const group: GroupContentItems = new Map();
groupDefault.set("", items); group.set("", items);
return groupDefault; return group;
}
} }
} }

View File

@ -3,20 +3,20 @@ import Markdawn from "components/Markdown/Markdawn";
import ContentPanel, { import ContentPanel, {
ContentPanelWidthSizes, ContentPanelWidthSizes,
} from "components/Panels/ContentPanel"; } from "components/Panels/ContentPanel";
import { GetStaticProps } from "next"; import { GetStaticPropsContext } from "next";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import Script from "next/script"; import Script from "next/script";
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps"; import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
import { useCallback, useState } from "react"; import { useCallback, useState } from "react";
import { default as TurndownService } from "turndown";
interface EditorProps extends AppStaticProps {} interface EditorProps extends AppStaticProps {}
export default function Editor(props: EditorProps): JSX.Element { export default function Editor(props: EditorProps): JSX.Element {
const { langui } = props;
const router = useRouter(); const router = useRouter();
const handleInput = useCallback((e) => { const handleInput = useCallback((event) => {
setMarkdown(e.target.value); setMarkdown(event.target.value);
}, []); }, []);
const [markdown, setMarkdown] = useState(""); const [markdown, setMarkdown] = useState("");
@ -53,7 +53,6 @@ export default function Editor(props: EditorProps): JSX.Element {
id="htmlMdTextArea" id="htmlMdTextArea"
title="Ouput textarea" title="Ouput textarea"
onPaste={(event) => { onPaste={(event) => {
const TurndownService = require("turndown").default;
const turndownService = new TurndownService({ const turndownService = new TurndownService({
headingStyle: "atx", headingStyle: "atx",
codeBlockStyle: "fenced", codeBlockStyle: "fenced",
@ -63,9 +62,9 @@ export default function Editor(props: EditorProps): JSX.Element {
}); });
let paste = event.clipboardData.getData("text/html"); let paste = event.clipboardData.getData("text/html");
paste = paste.replace(/<\!--.*?-->/g, ""); paste = paste.replace(/<!--.*?-->/u, "");
paste = turndownService.turndown(paste); paste = turndownService.turndown(paste);
paste = paste.replace(/<\!--.*?-->/g, ""); paste = paste.replace(/<!--.*?-->/u, "");
const target = event.target as HTMLTextAreaElement; const target = event.target as HTMLTextAreaElement;
target.value = paste; target.value = paste;
@ -93,11 +92,13 @@ export default function Editor(props: EditorProps): JSX.Element {
); );
} }
export const getStaticProps: GetStaticProps = async (context) => { export async function getStaticProps(
context: GetStaticPropsContext
): Promise<{ props: EditorProps }> {
const props: EditorProps = { const props: EditorProps = {
...(await getAppStaticProps(context)), ...(await getAppStaticProps(context)),
}; };
return { return {
props: props, props: props,
}; };
}; }

View File

@ -1,5 +1,5 @@
import AppLayout from "components/AppLayout"; import AppLayout from "components/AppLayout";
import { GetStaticProps } from "next"; import { GetStaticPropsContext } from "next";
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps"; import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
interface GalleryProps extends AppStaticProps {} interface GalleryProps extends AppStaticProps {}
@ -22,11 +22,13 @@ export default function Gallery(props: GalleryProps): JSX.Element {
); );
} }
export const getStaticProps: GetStaticProps = async (context) => { export async function getStaticProps(
context: GetStaticPropsContext
): Promise<{ props: GalleryProps }> {
const props: GalleryProps = { const props: GalleryProps = {
...(await getAppStaticProps(context)), ...(await getAppStaticProps(context)),
}; };
return { return {
props: props, props: props,
}; };
}; }

View File

@ -4,7 +4,7 @@ import Markdawn from "components/Markdown/Markdawn";
import ContentPanel from "components/Panels/ContentPanel"; import ContentPanel from "components/Panels/ContentPanel";
import { getPost, getPostLanguages } from "graphql/operations"; import { getPost, getPostLanguages } from "graphql/operations";
import { GetPostQuery } from "graphql/operations-types"; import { GetPostQuery } from "graphql/operations-types";
import { GetStaticProps } from "next"; import { GetStaticPropsContext } from "next";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps"; import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
import { prettySlug } from "queries/helpers"; import { prettySlug } from "queries/helpers";
@ -27,7 +27,7 @@ export default function Home(props: HomeProps): JSX.Element {
Discover Analyse Translate Archive Discover Analyse Translate Archive
</h2> </h2>
</div> </div>
{locales.includes(router.locale || "en") ? ( {locales.includes(router.locale ?? "en") ? (
<Markdawn router={router} text={post.translations[0].body} /> <Markdawn router={router} text={post.translations[0].body} />
) : ( ) : (
<LanguageSwitcher <LanguageSwitcher
@ -53,23 +53,25 @@ export default function Home(props: HomeProps): JSX.Element {
); );
} }
export const getStaticProps: GetStaticProps = async (context) => { export async function getStaticProps(
context: GetStaticPropsContext
): Promise<{ props: HomeProps }> {
const slug = "home"; const slug = "home";
const props: HomeProps = { const props: HomeProps = {
...(await getAppStaticProps(context)), ...(await getAppStaticProps(context)),
post: ( post: (
await getPost({ await getPost({
slug: slug, slug: slug,
language_code: context.locale || "en", language_code: context.locale ?? "en",
}) })
).posts.data[0].attributes, ).posts.data[0].attributes,
locales: ( locales: (
await getPostLanguages({ slug: slug }) await getPostLanguages({ slug: slug })
).posts.data[0].attributes.translations.map((translation) => { ).posts.data[0].attributes.translations.map(
return translation.language.data.attributes.code; (translation) => translation.language.data.attributes.code
}), ),
}; };
return { return {
props: props, props: props,
}; };
}; }

View File

@ -21,7 +21,11 @@ import {
Enum_Componentmetadatabooks_Page_Order, Enum_Componentmetadatabooks_Page_Order,
GetLibraryItemQuery, GetLibraryItemQuery,
} from "graphql/operations-types"; } from "graphql/operations-types";
import { GetStaticPaths, GetStaticProps } from "next"; import {
GetStaticPathsContext,
GetStaticPathsResult,
GetStaticPropsContext,
} from "next";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps"; import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
import { import {
@ -64,7 +68,7 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element {
href="/library/" href="/library/"
title={langui.library} title={langui.library}
langui={langui} langui={langui}
displayOn={ReturnButtonType.Desktop} displayOn={ReturnButtonType.desktop}
horizontalLine horizontalLine
/> />
@ -122,7 +126,7 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element {
href="/library/" href="/library/"
title={langui.library} title={langui.library}
langui={langui} langui={langui}
displayOn={ReturnButtonType.Mobile} displayOn={ReturnButtonType.mobile}
className="mb-10" className="mb-10"
/> />
<div className="grid place-items-center gap-12"> <div className="grid place-items-center gap-12">
@ -189,12 +193,9 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element {
onClick={() => { onClick={() => {
setLightboxOpen(true); setLightboxOpen(true);
setLightboxImages( setLightboxImages(
item.gallery.data.map((image) => { item.gallery.data.map((image) =>
return getAssetURL( getAssetURL(image.attributes.url, ImageQuality.Large)
image.attributes.url, )
ImageQuality.Large
);
})
); );
setLightboxIndex(index); setLightboxIndex(index);
}} }}
@ -408,11 +409,13 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element {
); );
} }
export const getStaticProps: GetStaticProps = async (context) => { export async function getStaticProps(
context: GetStaticPropsContext
): Promise<{ props: LibrarySlugProps }> {
const item = ( const item = (
await getLibraryItem({ await getLibraryItem({
slug: context.params?.slug?.toString() || "", slug: context.params?.slug?.toString() ?? "",
language_code: context.locale || "en", language_code: context.locale ?? "en",
}) })
).libraryItems.data[0]; ).libraryItems.data[0];
const props: LibrarySlugProps = { const props: LibrarySlugProps = {
@ -423,19 +426,14 @@ export const getStaticProps: GetStaticProps = async (context) => {
return { return {
props: props, props: props,
}; };
}; }
export const getStaticPaths: GetStaticPaths = async (context) => { export async function getStaticPaths(
type Path = { context: GetStaticPathsContext
params: { ): Promise<GetStaticPathsResult> {
slug: string; const libraryItems = await getLibraryItemsSlugs({});
}; const paths: GetStaticPathsResult["paths"] = [];
locale: string; libraryItems.libraryItems.data.map((item) => {
};
const data = await getLibraryItemsSlugs({});
const paths: Path[] = [];
data.libraryItems.data.map((item) => {
context.locales?.map((local) => { context.locales?.map((local) => {
paths.push({ params: { slug: item.attributes.slug }, locale: local }); paths.push({ params: { slug: item.attributes.slug }, locale: local });
}); });
@ -444,15 +442,13 @@ export const getStaticPaths: GetStaticPaths = async (context) => {
paths, paths,
fallback: false, fallback: false,
}; };
}; }
function useTesting(props: LibrarySlugProps) { function useTesting(props: LibrarySlugProps) {
const { item, itemId } = props; const { item, itemId } = props;
const router = useRouter(); const router = useRouter();
const libraryItemURL = const libraryItemURL = `/admin/content-manager/collectionType/api::library-item.library-item/${itemId}`;
"/admin/content-manager/collectionType/api::library-item.library-item/" +
itemId;
sortContent(item.contents); sortContent(item.contents);
@ -472,269 +468,264 @@ function useTesting(props: LibrarySlugProps) {
["libraryItem"], ["libraryItem"],
libraryItemURL libraryItemURL
); );
} else if (
item.metadata[0].__typename === "ComponentMetadataGroup" &&
(item.metadata[0].subtype.data.attributes.slug === "relation-set" ||
item.metadata[0].subtype.data.attributes.slug === "variant-set")
) {
// This is a group type item
if (item.price) {
prettyTestError(
router,
"Group-type items shouldn't have price",
["libraryItem"],
libraryItemURL
);
}
if (item.size) {
prettyTestError(
router,
"Group-type items shouldn't have size",
["libraryItem"],
libraryItemURL
);
}
if (item.release_date) {
prettyTestError(
router,
"Group-type items shouldn't have release_date",
["libraryItem"],
libraryItemURL
);
}
if (item.contents.data.length > 0) {
prettyTestError(
router,
"Group-type items shouldn't have contents",
["libraryItem"],
libraryItemURL
);
}
if (item.subitems.data.length === 0) {
prettyTestError(
router,
"Group-type items should have subitems",
["libraryItem"],
libraryItemURL
);
}
} else { } else {
if ( // This is a normal item
item.metadata[0].__typename === "ComponentMetadataGroup" &&
(item.metadata[0].subtype.data.attributes.slug === "relation-set" || if (item.metadata[0].__typename === "ComponentMetadataGroup") {
item.metadata[0].subtype.data.attributes.slug === "variant-set")
) {
// This is a group type item
if (item.price) {
prettyTestError(
router,
"Group-type items shouldn't have price",
["libraryItem"],
libraryItemURL
);
}
if (item.size) {
prettyTestError(
router,
"Group-type items shouldn't have size",
["libraryItem"],
libraryItemURL
);
}
if (item.release_date) {
prettyTestError(
router,
"Group-type items shouldn't have release_date",
["libraryItem"],
libraryItemURL
);
}
if (item.contents.data.length > 0) {
prettyTestError(
router,
"Group-type items shouldn't have contents",
["libraryItem"],
libraryItemURL
);
}
if (item.subitems.data.length === 0) { if (item.subitems.data.length === 0) {
prettyTestError( prettyTestError(
router, router,
"Group-type items should have subitems", "Group-type item should have subitems",
["libraryItem"], ["libraryItem"],
libraryItemURL libraryItemURL
); );
} }
}
if (item.price) {
if (!item.price.amount) {
prettyTestError(
router,
"Missing amount",
["libraryItem", "price"],
libraryItemURL
);
}
if (!item.price.currency) {
prettyTestError(
router,
"Missing currency",
["libraryItem", "price"],
libraryItemURL
);
}
} else { } else {
// This is a normal item prettyTestWarning(
router,
"Missing price",
["libraryItem"],
libraryItemURL
);
}
if (item.metadata[0].__typename === "ComponentMetadataGroup") { if (!item.digital) {
if (item.subitems.data.length === 0) { if (item.size) {
prettyTestError( if (!item.size.width) {
router,
"Group-type item should have subitems",
["libraryItem"],
libraryItemURL
);
}
}
if (!item.price) {
prettyTestWarning(
router,
"Missing price",
["libraryItem"],
libraryItemURL
);
} else {
if (!item.price.amount) {
prettyTestError(
router,
"Missing amount",
["libraryItem", "price"],
libraryItemURL
);
}
if (!item.price.currency) {
prettyTestError(
router,
"Missing currency",
["libraryItem", "price"],
libraryItemURL
);
}
}
if (!item.digital) {
if (!item.size) {
prettyTestWarning( prettyTestWarning(
router, router,
"Missing size", "Missing width",
["libraryItem"], ["libraryItem", "size"],
libraryItemURL libraryItemURL
); );
} else {
if (!item.size.width) {
prettyTestWarning(
router,
"Missing width",
["libraryItem", "size"],
libraryItemURL
);
}
if (!item.size.height) {
prettyTestWarning(
router,
"Missing height",
["libraryItem", "size"],
libraryItemURL
);
}
if (!item.size.thickness) {
prettyTestWarning(
router,
"Missing thickness",
["libraryItem", "size"],
libraryItemURL
);
}
} }
} if (!item.size.height) {
prettyTestWarning(
if (!item.release_date) { router,
"Missing height",
["libraryItem", "size"],
libraryItemURL
);
}
if (!item.size.thickness) {
prettyTestWarning(
router,
"Missing thickness",
["libraryItem", "size"],
libraryItemURL
);
}
} else {
prettyTestWarning( prettyTestWarning(
router, router,
"Missing release_date", "Missing size",
["libraryItem"], ["libraryItem"],
libraryItemURL libraryItemURL
); );
} else {
if (!item.release_date.year) {
prettyTestError(
router,
"Missing year",
["libraryItem", "release_date"],
libraryItemURL
);
}
if (!item.release_date.month) {
prettyTestError(
router,
"Missing month",
["libraryItem", "release_date"],
libraryItemURL
);
}
if (!item.release_date.day) {
prettyTestError(
router,
"Missing day",
["libraryItem", "release_date"],
libraryItemURL
);
}
} }
}
if (item.contents.data.length === 0) { if (item.release_date) {
prettyTestWarning( if (!item.release_date.year) {
prettyTestError(
router, router,
"Missing contents", "Missing year",
["libraryItem"], ["libraryItem", "release_date"],
libraryItemURL libraryItemURL
); );
} else { }
let currentRangePage = 0; if (!item.release_date.month) {
item.contents.data.map((content) => { prettyTestError(
const contentURL = router,
"/admin/content-manager/collectionType/api::content.content/" + "Missing month",
content.id; ["libraryItem", "release_date"],
libraryItemURL
);
}
if (!item.release_date.day) {
prettyTestError(
router,
"Missing day",
["libraryItem", "release_date"],
libraryItemURL
);
}
} else {
prettyTestWarning(
router,
"Missing release_date",
["libraryItem"],
libraryItemURL
);
}
if (content.attributes.scan_set.length === 0) { if (item.contents.data.length === 0) {
prettyTestWarning( prettyTestWarning(
router,
"Missing contents",
["libraryItem"],
libraryItemURL
);
} else {
let currentRangePage = 0;
item.contents.data.map((content) => {
const contentURL = `/admin/content-manager/collectionType/api::content.content/${content.id}`;
if (content.attributes.scan_set.length === 0) {
prettyTestWarning(
router,
"Missing scan_set",
["libraryItem", "content", content.id],
contentURL
);
}
if (content.attributes.range.length === 0) {
prettyTestWarning(
router,
"Missing range",
["libraryItem", "content", content.id],
contentURL
);
} else if (
content.attributes.range[0].__typename === "ComponentRangePageRange"
) {
if (
content.attributes.range[0].starting_page <
currentRangePage + 1
) {
prettyTestError(
router, router,
"Missing scan_set", `Overlapping pages ${content.attributes.range[0].starting_page} to ${currentRangePage}`,
["libraryItem", "content", content.id], ["libraryItem", "content", content.id, "range"],
contentURL libraryItemURL
);
}
if (content.attributes.range.length === 0) {
prettyTestWarning(
router,
"Missing range",
["libraryItem", "content", content.id],
contentURL
); );
} else if ( } else if (
content.attributes.range[0].__typename === content.attributes.range[0].starting_page >
"ComponentRangePageRange" currentRangePage + 1
) { ) {
if (
content.attributes.range[0].starting_page <
currentRangePage + 1
) {
prettyTestError(
router,
`Overlapping pages ${content.attributes.range[0].starting_page} to ${currentRangePage}`,
["libraryItem", "content", content.id, "range"],
libraryItemURL
);
} else if (
content.attributes.range[0].starting_page >
currentRangePage + 1
) {
prettyTestError(
router,
`Missing pages ${currentRangePage + 1} to ${
content.attributes.range[0].starting_page - 1
}`,
["libraryItem", "content", content.id, "range"],
libraryItemURL
);
}
if (!content.attributes.content.data) {
prettyTestWarning(
router,
"Missing content",
["libraryItem", "content", content.id, "range"],
libraryItemURL
);
}
currentRangePage = content.attributes.range[0].ending_page;
}
});
if (item.metadata[0].__typename === "ComponentMetadataBooks") {
if (currentRangePage < item.metadata[0].page_count) {
prettyTestError( prettyTestError(
router, router,
`Missing pages ${currentRangePage + 1} to ${ `Missing pages ${currentRangePage + 1} to ${
item.metadata[0].page_count content.attributes.range[0].starting_page - 1
}`, }`,
["libraryItem", "content"], ["libraryItem", "content", content.id, "range"],
libraryItemURL
);
} else if (currentRangePage > item.metadata[0].page_count) {
prettyTestError(
router,
`Page overflow, content references pages up to ${currentRangePage} when the highest expected was ${item.metadata[0].page_count}`,
["libraryItem", "content"],
libraryItemURL libraryItemURL
); );
} }
if (item.metadata[0].languages.data.length === 0) { if (!content.attributes.content.data) {
prettyTestWarning( prettyTestWarning(
router, router,
"Missing language", "Missing content",
["libraryItem", "metadata"], ["libraryItem", "content", content.id, "range"],
libraryItemURL libraryItemURL
); );
} }
if (!item.metadata[0].page_count) { currentRangePage = content.attributes.range[0].ending_page;
prettyTestWarning( }
router, });
"Missing page_count",
["libraryItem", "metadata"], if (item.metadata[0].__typename === "ComponentMetadataBooks") {
libraryItemURL if (currentRangePage < item.metadata[0].page_count) {
); prettyTestError(
} router,
`Missing pages ${currentRangePage + 1} to ${
item.metadata[0].page_count
}`,
["libraryItem", "content"],
libraryItemURL
);
} else if (currentRangePage > item.metadata[0].page_count) {
prettyTestError(
router,
`Page overflow, content references pages up to ${currentRangePage} when the highest expected was ${item.metadata[0].page_count}`,
["libraryItem", "content"],
libraryItemURL
);
}
if (item.metadata[0].languages.data.length === 0) {
prettyTestWarning(
router,
"Missing language",
["libraryItem", "metadata"],
libraryItemURL
);
}
if (!item.metadata[0].page_count) {
prettyTestWarning(
router,
"Missing page_count",
["libraryItem", "metadata"],
libraryItemURL
);
} }
} }
} }

View File

@ -14,7 +14,7 @@ import {
GetLibraryItemsPreviewQuery, GetLibraryItemsPreviewQuery,
GetWebsiteInterfaceQuery, GetWebsiteInterfaceQuery,
} from "graphql/operations-types"; } from "graphql/operations-types";
import { GetStaticProps } from "next"; import { GetStaticPropsContext } from "next";
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps"; import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
import { convertPrice, prettyDate, prettyinlineTitle } from "queries/helpers"; import { convertPrice, prettyDate, prettyinlineTitle } from "queries/helpers";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
@ -29,7 +29,7 @@ type GroupLibraryItems = Map<
>; >;
export default function Library(props: LibraryProps): JSX.Element { export default function Library(props: LibraryProps): JSX.Element {
const { langui, items, currencies } = props; const { langui, items: libraryItems, currencies } = props;
const [showSubitems, setShowSubitems] = useState<boolean>(false); const [showSubitems, setShowSubitems] = useState<boolean>(false);
const [showPrimaryItems, setShowPrimaryItems] = useState<boolean>(true); const [showPrimaryItems, setShowPrimaryItems] = useState<boolean>(true);
@ -38,7 +38,12 @@ export default function Library(props: LibraryProps): JSX.Element {
const [groupingMethod, setGroupingMethod] = useState<number>(-1); const [groupingMethod, setGroupingMethod] = useState<number>(-1);
const [filteredItems, setFilteredItems] = useState<LibraryProps["items"]>( const [filteredItems, setFilteredItems] = useState<LibraryProps["items"]>(
filterItems(showSubitems, showPrimaryItems, showSecondaryItems, items) filterItems(
showSubitems,
showPrimaryItems,
showSecondaryItems,
libraryItems
)
); );
const [sortedItems, setSortedItem] = useState<LibraryProps["items"]>( const [sortedItems, setSortedItem] = useState<LibraryProps["items"]>(
@ -51,9 +56,14 @@ export default function Library(props: LibraryProps): JSX.Element {
useEffect(() => { useEffect(() => {
setFilteredItems( setFilteredItems(
filterItems(showSubitems, showPrimaryItems, showSecondaryItems, items) filterItems(
showSubitems,
showPrimaryItems,
showSecondaryItems,
libraryItems
)
); );
}, [showSubitems, items, showPrimaryItems, showSecondaryItems]); }, [showSubitems, libraryItems, showPrimaryItems, showSecondaryItems]);
useEffect(() => { useEffect(() => {
setSortedItem(sortBy(sortingMethod, filteredItems, currencies)); setSortedItem(sortBy(sortingMethod, filteredItems, currencies));
@ -116,7 +126,7 @@ export default function Library(props: LibraryProps): JSX.Element {
<> <>
{name && ( {name && (
<h2 <h2
key={"h2" + name} key={`h2${name}`}
className="text-2xl pb-2 pt-10 first-of-type:pt-0 flex flex-row place-items-center gap-2" className="text-2xl pb-2 pt-10 first-of-type:pt-0 flex flex-row place-items-center gap-2"
> >
{name} {name}
@ -128,7 +138,7 @@ export default function Library(props: LibraryProps): JSX.Element {
</h2> </h2>
)} )}
<div <div
key={"items" + name} key={`items${name}`}
className="grid gap-8 items-end mobile:grid-cols-2 desktop:grid-cols-[repeat(auto-fill,_minmax(13rem,1fr))] pb-12 border-b-[3px] border-dotted last-of-type:border-0" className="grid gap-8 items-end mobile:grid-cols-2 desktop:grid-cols-[repeat(auto-fill,_minmax(13rem,1fr))] pb-12 border-b-[3px] border-dotted last-of-type:border-0"
> >
{items.map((item) => ( {items.map((item) => (
@ -155,19 +165,21 @@ export default function Library(props: LibraryProps): JSX.Element {
); );
} }
export const getStaticProps: GetStaticProps = async (context) => { export async function getStaticProps(
context: GetStaticPropsContext
): Promise<{ props: LibraryProps }> {
const props: LibraryProps = { const props: LibraryProps = {
...(await getAppStaticProps(context)), ...(await getAppStaticProps(context)),
items: ( items: (
await getLibraryItemsPreview({ await getLibraryItemsPreview({
language_code: context.locale || "en", language_code: context.locale ?? "en",
}) })
).libraryItems.data, ).libraryItems.data,
}; };
return { return {
props: props, props: props,
}; };
}; }
function getGroups( function getGroups(
langui: GetWebsiteInterfaceQuery["websiteInterfaces"]["data"][number]["attributes"], langui: GetWebsiteInterfaceQuery["websiteInterfaces"]["data"][number]["attributes"],
@ -175,7 +187,7 @@ function getGroups(
items: LibraryProps["items"] items: LibraryProps["items"]
): GroupLibraryItems { ): GroupLibraryItems {
switch (groupByType) { switch (groupByType) {
case 0: case 0: {
const typeGroup = new Map(); const typeGroup = new Map();
typeGroup.set("Drakengard 1", []); typeGroup.set("Drakengard 1", []);
typeGroup.set("Drakengard 1.3", []); typeGroup.set("Drakengard 1.3", []);
@ -207,63 +219,73 @@ function getGroups(
}); });
return typeGroup; return typeGroup;
}
case 1: case 1: {
const groupType: GroupLibraryItems = new Map(); const group: GroupLibraryItems = new Map();
groupType.set(langui.audio, []); group.set(langui.audio, []);
groupType.set(langui.game, []); group.set(langui.game, []);
groupType.set(langui.textual, []); group.set(langui.textual, []);
groupType.set(langui.video, []); group.set(langui.video, []);
groupType.set(langui.other, []); group.set(langui.other, []);
groupType.set(langui.group, []); group.set(langui.group, []);
groupType.set(langui.no_type, []); group.set(langui.no_type, []);
items.map((item) => { items.map((item) => {
if (item.attributes.metadata.length > 0) { if (item.attributes.metadata.length > 0) {
switch (item.attributes.metadata[0].__typename) { switch (item.attributes.metadata[0].__typename) {
case "ComponentMetadataAudio": case "ComponentMetadataAudio":
groupType.get(langui.audio)?.push(item); group.get(langui.audio)?.push(item);
break; break;
case "ComponentMetadataGame": case "ComponentMetadataGame":
groupType.get(langui.game)?.push(item); group.get(langui.game)?.push(item);
break; break;
case "ComponentMetadataBooks": case "ComponentMetadataBooks":
groupType.get(langui.textual)?.push(item); group.get(langui.textual)?.push(item);
break; break;
case "ComponentMetadataVideo": case "ComponentMetadataVideo":
groupType.get(langui.video)?.push(item); group.get(langui.video)?.push(item);
break; break;
case "ComponentMetadataOther": case "ComponentMetadataOther":
groupType.get(langui.other)?.push(item); group.get(langui.other)?.push(item);
break; break;
case "ComponentMetadataGroup": case "ComponentMetadataGroup":
switch ( switch (
item.attributes.metadata[0].subitems_type.data.attributes.slug item.attributes.metadata[0].subitems_type.data.attributes.slug
) { ) {
case "audio": case "audio":
groupType.get(langui.audio)?.push(item); group.get(langui.audio)?.push(item);
break; break;
case "video": case "video":
groupType.get(langui.video)?.push(item); group.get(langui.video)?.push(item);
break; break;
case "game": case "game":
groupType.get(langui.game)?.push(item); group.get(langui.game)?.push(item);
break; break;
case "textual": case "textual":
groupType.get(langui.textual)?.push(item); group.get(langui.textual)?.push(item);
break; break;
case "mixed": case "mixed":
groupType.get(langui.group)?.push(item); group.get(langui.group)?.push(item);
break; break;
default: {
throw new Error(
"An unexpected subtype of group-metadata was given"
);
}
} }
break; break;
default: {
throw new Error("An unexpected type of metadata was given");
}
} }
} else { } else {
groupType.get(langui.no_type)?.push(item); group.get(langui.no_type)?.push(item);
} }
}); });
return groupType; return group;
}
case 2: case 2: {
const years: number[] = []; const years: number[] = [];
items.map((item) => { items.map((item) => {
if (item.attributes.release_date) { if (item.attributes.release_date) {
@ -271,28 +293,28 @@ function getGroups(
years.push(item.attributes.release_date.year); years.push(item.attributes.release_date.year);
} }
}); });
const groupYear: GroupLibraryItems = new Map(); const group: GroupLibraryItems = new Map();
years.sort(); years.sort((a, b) => a - b);
years.map((year) => { years.map((year) => {
groupYear.set(year.toString(), []); group.set(year.toString(), []);
}); });
groupYear.set(langui.no_year, []); group.set(langui.no_year, []);
items.map((item) => { items.map((item) => {
if (item.attributes.release_date) { if (item.attributes.release_date) {
groupYear group.get(item.attributes.release_date.year.toString())?.push(item);
.get(item.attributes.release_date.year.toString())
?.push(item);
} else { } else {
groupYear.get(langui.no_year)?.push(item); group.get(langui.no_year)?.push(item);
} }
}); });
return groupYear; return group;
}
default: default: {
const groupDefault: GroupLibraryItems = new Map(); const group: GroupLibraryItems = new Map();
groupDefault.set("", items); group.set("", items);
return groupDefault; return group;
}
} }
} }
@ -353,13 +375,13 @@ function sortBy(
case 2: case 2:
return [...items].sort((a, b) => { return [...items].sort((a, b) => {
const dateA = const dateA =
a.attributes.release_date !== null a.attributes.release_date === null
? prettyDate(a.attributes.release_date) ? "9999"
: "9999"; : prettyDate(a.attributes.release_date);
const dateB = const dateB =
b.attributes.release_date !== null b.attributes.release_date === null
? prettyDate(b.attributes.release_date) ? "9999"
: "9999"; : prettyDate(b.attributes.release_date);
return dateA.localeCompare(dateB); return dateA.localeCompare(dateB);
}); });
default: default:

View File

@ -1,7 +1,7 @@
import AppLayout from "components/AppLayout"; import AppLayout from "components/AppLayout";
import PanelHeader from "components/PanelComponents/PanelHeader"; import PanelHeader from "components/PanelComponents/PanelHeader";
import SubPanel from "components/Panels/SubPanel"; import SubPanel from "components/Panels/SubPanel";
import { GetStaticProps } from "next"; import { GetStaticPropsContext } from "next";
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps"; import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
interface MerchProps extends AppStaticProps {} interface MerchProps extends AppStaticProps {}
@ -20,11 +20,13 @@ export default function Merch(props: MerchProps): JSX.Element {
return <AppLayout navTitle={langui.merch} subPanel={subPanel} {...props} />; return <AppLayout navTitle={langui.merch} subPanel={subPanel} {...props} />;
} }
export const getStaticProps: GetStaticProps = async (context) => { export async function getStaticProps(
context: GetStaticPropsContext
): Promise<{ props: MerchProps }> {
const props: MerchProps = { const props: MerchProps = {
...(await getAppStaticProps(context)), ...(await getAppStaticProps(context)),
}; };
return { return {
props: props, props: props,
}; };
}; }

View File

@ -14,7 +14,11 @@ import RecorderChip from "components/RecorderChip";
import ToolTip from "components/ToolTip"; import ToolTip from "components/ToolTip";
import { getPost, getPostLanguages, getPostsSlugs } from "graphql/operations"; import { getPost, getPostLanguages, getPostsSlugs } from "graphql/operations";
import { GetPostQuery, StrapiImage } from "graphql/operations-types"; import { GetPostQuery, StrapiImage } from "graphql/operations-types";
import { GetStaticPaths, GetStaticProps } from "next"; import {
GetStaticPathsContext,
GetStaticPathsResult,
GetStaticPropsContext,
} from "next";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps"; import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
import { getStatusDescription, prettySlug } from "queries/helpers"; import { getStatusDescription, prettySlug } from "queries/helpers";
@ -42,7 +46,7 @@ export default function LibrarySlug(props: PostProps): JSX.Element {
href="/news" href="/news"
title={langui.news} title={langui.news}
langui={langui} langui={langui}
displayOn={ReturnButtonType.Desktop} displayOn={ReturnButtonType.desktop}
horizontalLine horizontalLine
/> />
@ -87,7 +91,7 @@ export default function LibrarySlug(props: PostProps): JSX.Element {
href="/news" href="/news"
title={langui.news} title={langui.news}
langui={langui} langui={langui}
displayOn={ReturnButtonType.Mobile} displayOn={ReturnButtonType.mobile}
className="mb-10" className="mb-10"
/> />
@ -109,7 +113,7 @@ export default function LibrarySlug(props: PostProps): JSX.Element {
<HorizontalLine /> <HorizontalLine />
{locales.includes(router.locale || "en") ? ( {locales.includes(router.locale ?? "en") ? (
<Markdawn router={router} text={post.translations[0].body} /> <Markdawn router={router} text={post.translations[0].body} />
) : ( ) : (
<LanguageSwitcher <LanguageSwitcher
@ -138,12 +142,14 @@ export default function LibrarySlug(props: PostProps): JSX.Element {
); );
} }
export const getStaticProps: GetStaticProps = async (context) => { export async function getStaticProps(
const slug = context.params?.slug?.toString() || ""; context: GetStaticPropsContext
): Promise<{ props: PostProps }> {
const slug = context.params?.slug?.toString() ?? "";
const post = ( const post = (
await getPost({ await getPost({
slug: slug, slug: slug,
language_code: context.locale || "en", language_code: context.locale ?? "en",
}) })
).posts.data[0]; ).posts.data[0];
const props: PostProps = { const props: PostProps = {
@ -152,26 +158,21 @@ export const getStaticProps: GetStaticProps = async (context) => {
postId: post.id, postId: post.id,
locales: ( locales: (
await getPostLanguages({ slug: slug }) await getPostLanguages({ slug: slug })
).posts.data[0].attributes.translations.map((translation) => { ).posts.data[0].attributes.translations.map(
return translation.language.data.attributes.code; (translation) => translation.language.data.attributes.code
}), ),
}; };
return { return {
props: props, props: props,
}; };
}; }
export const getStaticPaths: GetStaticPaths = async (context) => { export async function getStaticPaths(
type Path = { context: GetStaticPathsContext
params: { ): Promise<GetStaticPathsResult> {
slug: string; const posts = await getPostsSlugs({});
}; const paths: GetStaticPathsResult["paths"] = [];
locale: string; posts.posts.data.map((item) => {
};
const data = await getPostsSlugs({});
const paths: Path[] = [];
data.posts.data.map((item) => {
context.locales?.map((local) => { context.locales?.map((local) => {
paths.push({ params: { slug: item.attributes.slug }, locale: local }); paths.push({ params: { slug: item.attributes.slug }, locale: local });
}); });
@ -180,4 +181,4 @@ export const getStaticPaths: GetStaticPaths = async (context) => {
paths, paths,
fallback: false, fallback: false,
}; };
}; }

View File

@ -7,7 +7,7 @@ import ContentPanel, {
import SubPanel from "components/Panels/SubPanel"; import SubPanel from "components/Panels/SubPanel";
import { getPostsPreview } from "graphql/operations"; import { getPostsPreview } from "graphql/operations";
import { GetPostsPreviewQuery } from "graphql/operations-types"; import { GetPostsPreviewQuery } from "graphql/operations-types";
import { GetStaticProps } from "next"; import { GetStaticPropsContext } from "next";
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps"; import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
interface NewsProps extends AppStaticProps { interface NewsProps extends AppStaticProps {
@ -46,14 +46,16 @@ export default function News(props: NewsProps): JSX.Element {
); );
} }
export const getStaticProps: GetStaticProps = async (context) => { export async function getStaticProps(
context: GetStaticPropsContext
): Promise<{ props: NewsProps }> {
const props: NewsProps = { const props: NewsProps = {
...(await getAppStaticProps(context)), ...(await getAppStaticProps(context)),
posts: await ( posts: await (
await getPostsPreview({ language_code: context.locale || "en" }) await getPostsPreview({ language_code: context.locale ?? "en" })
).posts.data, ).posts.data,
}; };
return { return {
props: props, props: props,
}; };
}; }

View File

@ -12,7 +12,7 @@ import {
GetChronologyItemsQuery, GetChronologyItemsQuery,
GetErasQuery, GetErasQuery,
} from "graphql/operations-types"; } from "graphql/operations-types";
import { GetStaticProps } from "next"; import { GetStaticPropsContext } from "next";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps"; import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
import { import {
@ -31,7 +31,7 @@ export default function Chronology(props: ChronologyProps): JSX.Element {
const { chronologyItems, chronologyEras, langui } = props; const { chronologyItems, chronologyEras, langui } = props;
// Group by year the Chronology items // Group by year the Chronology items
let chronologyItemYearGroups: GetChronologyItemsQuery["chronologyItems"]["data"][number][][][] = const chronologyItemYearGroups: GetChronologyItemsQuery["chronologyItems"]["data"][number][][][] =
[]; [];
chronologyEras.map(() => { chronologyEras.map(() => {
@ -44,20 +44,21 @@ export default function Chronology(props: ChronologyProps): JSX.Element {
item.attributes.year > item.attributes.year >
chronologyEras[currentChronologyEraIndex].attributes.ending_year chronologyEras[currentChronologyEraIndex].attributes.ending_year
) { ) {
currentChronologyEraIndex++; currentChronologyEraIndex += 1;
} }
if ( if (
!chronologyItemYearGroups[currentChronologyEraIndex].hasOwnProperty( Object.prototype.hasOwnProperty.call(
chronologyItemYearGroups[currentChronologyEraIndex],
item.attributes.year item.attributes.year
) )
) { ) {
chronologyItemYearGroups[currentChronologyEraIndex][ chronologyItemYearGroups[currentChronologyEraIndex][
item.attributes.year item.attributes.year
] = [item]; ].push(item);
} else { } else {
chronologyItemYearGroups[currentChronologyEraIndex][ chronologyItemYearGroups[currentChronologyEraIndex][
item.attributes.year item.attributes.year
].push(item); ] = [item];
} }
}); });
@ -67,22 +68,20 @@ export default function Chronology(props: ChronologyProps): JSX.Element {
href="/wiki" href="/wiki"
title={langui.wiki} title={langui.wiki}
langui={langui} langui={langui}
displayOn={ReturnButtonType.Desktop} displayOn={ReturnButtonType.desktop}
horizontalLine horizontalLine
/> />
{chronologyEras.map((era) => ( {chronologyEras.map((era) => (
<NavOption <NavOption
key={era.id} key={era.id}
url={"#" + era.attributes.slug} url={`#${era.attributes.slug}`}
title={ title={
era.attributes.title.length > 0 era.attributes.title.length > 0
? era.attributes.title[0].title ? era.attributes.title[0].title
: prettySlug(era.attributes.slug) : prettySlug(era.attributes.slug)
} }
subtitle={ subtitle={`${era.attributes.starting_year}${era.attributes.ending_year}`}
era.attributes.starting_year + " → " + era.attributes.ending_year
}
border border
/> />
))} ))}
@ -95,7 +94,7 @@ export default function Chronology(props: ChronologyProps): JSX.Element {
href="/wiki" href="/wiki"
title={langui.wiki} title={langui.wiki}
langui={langui} langui={langui}
displayOn={ReturnButtonType.Mobile} displayOn={ReturnButtonType.mobile}
className="mb-10" className="mb-10"
/> />
@ -139,29 +138,29 @@ export default function Chronology(props: ChronologyProps): JSX.Element {
); );
} }
export const getStaticProps: GetStaticProps = async (context) => { export async function getStaticProps(
context: GetStaticPropsContext
): Promise<{ props: ChronologyProps }> {
const props: ChronologyProps = { const props: ChronologyProps = {
...(await getAppStaticProps(context)), ...(await getAppStaticProps(context)),
chronologyItems: ( chronologyItems: (
await getChronologyItems({ await getChronologyItems({
language_code: context.locale || "en", language_code: context.locale ?? "en",
}) })
).chronologyItems.data, ).chronologyItems.data,
chronologyEras: (await getEras({ language_code: context.locale || "en" })) chronologyEras: (await getEras({ language_code: context.locale ?? "en" }))
.chronologyEras.data, .chronologyEras.data,
}; };
return { return {
props: props, props: props,
}; };
}; }
function useTesting(props: ChronologyProps) { function useTesting(props: ChronologyProps) {
const router = useRouter(); const router = useRouter();
const { chronologyItems, chronologyEras } = props; const { chronologyItems, chronologyEras } = props;
chronologyEras.map((era) => { chronologyEras.map((era) => {
const chronologyErasURL = const chronologyErasURL = `/admin/content-manager/collectionType/api::chronology-era.chronology-era/${chronologyItems[0].id}`;
"/admin/content-manager/collectionType/api::chronology-era.chronology-era/" +
chronologyItems[0].id;
if (era.attributes.title.length === 0) { if (era.attributes.title.length === 0) {
prettyTestError( prettyTestError(
@ -196,20 +195,11 @@ function useTesting(props: ChronologyProps) {
}); });
chronologyItems.map((item) => { chronologyItems.map((item) => {
const chronologyItemsURL = const chronologyItemsURL = `/admin/content-manager/collectionType/api::chronology-item.chronology-item/${chronologyItems[0].id}`;
"/admin/content-manager/collectionType/api::chronology-item.chronology-item/" +
chronologyItems[0].id;
const date = `${item.attributes.year}/${item.attributes.month}/${item.attributes.day}`; const date = `${item.attributes.year}/${item.attributes.month}/${item.attributes.day}`;
if (!(item.attributes.events.length > 0)) { if (item.attributes.events.length > 0) {
prettyTestError(
router,
"No events for this date",
["chronologyItems", date],
chronologyItemsURL
);
} else {
item.attributes.events.map((event) => { item.attributes.events.map((event) => {
if (!event.source.data) { if (!event.source.data) {
prettyTestError( prettyTestError(
@ -228,6 +218,13 @@ function useTesting(props: ChronologyProps) {
); );
} }
}); });
} else {
prettyTestError(
router,
"No events for this date",
["chronologyItems", date],
chronologyItemsURL
);
} }
}); });
} }

View File

@ -2,7 +2,7 @@ import AppLayout from "components/AppLayout";
import NavOption from "components/PanelComponents/NavOption"; import NavOption from "components/PanelComponents/NavOption";
import PanelHeader from "components/PanelComponents/PanelHeader"; import PanelHeader from "components/PanelComponents/PanelHeader";
import SubPanel from "components/Panels/SubPanel"; import SubPanel from "components/Panels/SubPanel";
import { GetStaticProps } from "next"; import { GetStaticPropsContext } from "next";
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps"; import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
interface WikiProps extends AppStaticProps {} interface WikiProps extends AppStaticProps {}
@ -23,11 +23,13 @@ export default function Wiki(props: WikiProps): JSX.Element {
return <AppLayout navTitle={langui.wiki} subPanel={subPanel} {...props} />; return <AppLayout navTitle={langui.wiki} subPanel={subPanel} {...props} />;
} }
export const getStaticProps: GetStaticProps = async (context) => { export async function getStaticProps(
context: GetStaticPropsContext
): Promise<{ props: WikiProps }> {
const props: WikiProps = { const props: WikiProps = {
...(await getAppStaticProps(context)), ...(await getAppStaticProps(context)),
}; };
return { return {
props: props, props: props,
}; };
}; }

View File

@ -8,8 +8,7 @@ import {
GetLanguagesQuery, GetLanguagesQuery,
GetWebsiteInterfaceQuery, GetWebsiteInterfaceQuery,
} from "graphql/operations-types"; } from "graphql/operations-types";
import { GetStaticPropsContext, PreviewData } from "next"; import { GetStaticPropsContext } from "next";
import { ParsedUrlQuery } from "querystring";
export interface AppStaticProps { export interface AppStaticProps {
langui: GetWebsiteInterfaceQuery["websiteInterfaces"]["data"][number]["attributes"]; langui: GetWebsiteInterfaceQuery["websiteInterfaces"]["data"][number]["attributes"];
@ -18,24 +17,20 @@ export interface AppStaticProps {
} }
export async function getAppStaticProps( export async function getAppStaticProps(
context: GetStaticPropsContext<ParsedUrlQuery, PreviewData> context: GetStaticPropsContext
): Promise<AppStaticProps> { ): Promise<AppStaticProps> {
const languages = (await getLanguages({})).languages.data; const languages = (await getLanguages({})).languages.data;
languages.sort((a, b) => { languages.sort((a, b) =>
return a.attributes.localized_name.localeCompare( a.attributes.localized_name.localeCompare(b.attributes.localized_name)
b.attributes.localized_name );
);
});
const currencies = (await getCurrencies({})).currencies.data; const currencies = (await getCurrencies({})).currencies.data;
currencies.sort((a, b) => { currencies.sort((a, b) => a.attributes.code.localeCompare(b.attributes.code));
return a.attributes.code.localeCompare(b.attributes.code);
});
return { return {
langui: ( langui: (
await getWebsiteInterface({ await getWebsiteInterface({
language_code: context.locale || "en", language_code: context.locale ?? "en",
}) })
).websiteInterfaces.data[0].attributes, ).websiteInterfaces.data[0].attributes,
currencies: currencies, currencies: currencies,

View File

@ -17,13 +17,9 @@ import { NextRouter } from "next/router";
export function prettyDate( export function prettyDate(
datePicker: GetLibraryItemsPreviewQuery["libraryItems"]["data"][number]["attributes"]["release_date"] datePicker: GetLibraryItemsPreviewQuery["libraryItems"]["data"][number]["attributes"]["release_date"]
): string { ): string {
return ( return `${datePicker.year}/${datePicker.month
datePicker.year + .toString()
"/" + .padStart(2, "0")}/${datePicker.day.toString().padStart(2, "0")}`;
datePicker.month.toString().padStart(2, "0") +
"/" +
datePicker.day.toString().padStart(2, "0")
);
} }
export function prettyPrice( export function prettyPrice(
@ -74,9 +70,9 @@ export function prettyinlineTitle(
subtitle: string subtitle: string
): string { ): string {
let result = ""; let result = "";
if (pretitle) result += pretitle + ": "; if (pretitle) result += `${pretitle}: `;
result += title; result += title;
if (subtitle) result += " - " + subtitle; if (subtitle) result += ` - ${subtitle}`;
return result; return result;
} }
@ -86,7 +82,6 @@ export function prettyItemType(
}, },
langui: GetWebsiteInterfaceQuery["websiteInterfaces"]["data"][number]["attributes"] langui: GetWebsiteInterfaceQuery["websiteInterfaces"]["data"][number]["attributes"]
): string { ): string {
const type = metadata.__typename;
switch (metadata.__typename) { switch (metadata.__typename) {
case "ComponentMetadataAudio": case "ComponentMetadataAudio":
return langui.audio; return langui.audio;
@ -106,6 +101,7 @@ export function prettyItemType(
} }
export function prettyItemSubType(metadata: { export function prettyItemSubType(metadata: {
/* eslint-disable @typescript-eslint/no-explicit-any */
__typename: GetLibraryItemsPreviewQuery["libraryItems"]["data"][number]["attributes"]["metadata"][number]["__typename"]; __typename: GetLibraryItemsPreviewQuery["libraryItems"]["data"][number]["attributes"]["metadata"][number]["__typename"];
subtype?: any; subtype?: any;
platforms?: any; platforms?: any;
@ -138,6 +134,7 @@ export function prettyItemSubType(metadata: {
default: default:
return ""; return "";
} }
/* eslint-enable @typescript-eslint/no-explicit-any */
} }
export function prettyLanguage( export function prettyLanguage(
@ -184,7 +181,7 @@ function prettyTestWritter(
): void { ): void {
const line = [ const line = [
level, level,
process.env.NEXT_PUBLIC_URL_SELF + "/" + locale + asPath, `${process.env.NEXT_PUBLIC_URL_SELF}/${locale}${asPath}`,
locale, locale,
subCategory?.join(" -> "), subCategory?.join(" -> "),
message, message,
@ -206,7 +203,7 @@ export function capitalizeString(string: string): string {
} }
let words = string.split(" "); let words = string.split(" ");
words = words.map((word) => (word = capitalizeWord(word))); words = words.map((word) => capitalizeWord(word));
return words.join(" "); return words.join(" ");
} }
@ -275,20 +272,22 @@ export function getStatusDescription(
} }
export function slugify(string: string | undefined): string { export function slugify(string: string | undefined): string {
if (!string) return ""; if (!string) {
return "";
}
return string return string
.replace(/[ÀÁÂÃÄÅàáâãäåæÆ]/g, "a") .replace(/[ÀÁÂÃÄÅàáâãäåæÆ]/u, "a")
.replace(/[çÇ]/g, "c") .replace(/[çÇ]/u, "c")
.replace(/[ðÐ]/g, "d") .replace(/[ðÐ]/u, "d")
.replace(/[ÈÉÊËéèêë]/g, "e") .replace(/[ÈÉÊËéèêë]/u, "e")
.replace(/[ÏïÎîÍíÌì]/g, "i") .replace(/[ÏïÎîÍíÌì]/u, "i")
.replace(/[Ññ]/g, "n") .replace(/[Ññ]/u, "n")
.replace(/[øØœŒÕõÔôÓóÒò]/g, "o") .replace(/[øØœŒÕõÔôÓóÒò]/u, "o")
.replace(/[ÜüÛûÚúÙù]/g, "u") .replace(/[ÜüÛûÚúÙù]/u, "u")
.replace(/[ŸÿÝý]/g, "y") .replace(/[ŸÿÝý]/u, "y")
.replace(/[^a-z0-9- ]/gi, "") .replace(/[^a-z0-9- ]/iu, "")
.trim() .trim()
.replace(/ /gi, "-") .replace(/ /iu, "-")
.toLowerCase(); .toLowerCase();
} }

View File

@ -2,167 +2,163 @@
@tailwind components; @tailwind components;
@tailwind utilities; @tailwind utilities;
@layer base { * {
* { @apply box-border font-body font-medium scroll-smooth scroll-m-8;
@apply box-border font-body font-medium scroll-smooth scroll-m-8;
}
h1,
h2,
h3,
h4,
h5,
h6 {
@apply font-headers font-black;
}
a {
@apply transition-colors underline-offset-2 decoration-dotted underline decoration-dark hover:text-dark cursor-pointer;
}
*::selection {
@apply bg-dark text-light;
}
mark {
@apply bg-mid px-2;
}
/* SCROLLBARS STYLING */
* {
@apply [scrollbar-color:theme(colors.dark)_transparent] [scrollbar-width:thin];
}
*::-webkit-scrollbar {
@apply w-3 mobile:w-0;
}
*::-webkit-scrollbar-track {
@apply bg-light;
}
*::-webkit-scrollbar-thumb {
@apply bg-dark rounded-full border-[3px] border-solid border-light;
}
/* CHANGE FORMATTED DEFAULTS */
.formatted h1,
.formatted h2,
.formatted h3,
.formatted h4,
.formatted h5,
.formatted h6 {
@apply text-center flex gap-3 justify-center;
}
.formatted h1 {
@apply text-4xl my-16;
}
.formatted h1 + h2 {
@apply -mt-10;
}
.formatted h2 {
@apply text-3xl my-12;
}
.formatted h2 + h3 {
@apply -mt-8;
}
.formatted h3 {
@apply text-2xl my-8;
}
.formatted h3 + h4 {
@apply -mt-6;
}
.formatted h4 {
@apply text-xl my-6;
}
.formatted h5 {
@apply text-lg my-4;
}
.formatted p,
.formatted strong {
@apply my-2 text-justify;
}
.formatted strong {
@apply font-black;
}
.formatted footer {
@apply border-t-[3px] border-dotted pt-6;
}
.formatted footer > div {
@apply my-2 px-6 py-4 rounded-xl;
}
.formatted footer > div:target {
@apply bg-mid shadow-inner-sm shadow-shade;
}
.formatted li::marker {
@apply text-dark;
}
.formatted blockquote {
@apply border-l-dark;
}
.formatted ul {
@apply list-disc pl-4;
}
.formatted ol {
@apply list-decimal pl-4;
}
.formatted blockquote {
@apply border-2 border-mid rounded-lg p-5 text-center my-8;
}
.formatted blockquote cite {
@apply text-dark block;
}
/* INPUT */
input,
textarea {
@apply rounded-full p-2 text-center bg-light outline outline-mid outline-2 outline-offset-[-2px] hover:outline-[transparent] text-dark hover:bg-mid transition-all placeholder:text-dark placeholder:opacity-60;
}
input::placeholder {
@apply text-dark opacity-60;
}
input:focus-visible,
textarea:focus-within {
@apply outline-none bg-mid shadow-inner-sm shadow-shade;
}
textarea {
@apply rounded-2xl text-left p-6;
}
input[type="submit"] {
@apply grid place-content-center place-items-center border-[1px] border-dark text-dark rounded-full px-4 pt-[0.4rem] pb-[0.5rem] transition-all cursor-pointer hover:text-light hover:bg-dark hover:drop-shadow-shade-lg active:bg-black active:text-light active:drop-shadow-black-lg active:border-black;
}
} }
@layer components { h1,
.texture-paper-dots { h2,
@apply [background-image:var(--theme-texture-dots)] [background-blend-mode:var(--theme-texture-dots-blend)] bg-local bg-[length:10cm]; h3,
} h4,
h5,
h6 {
@apply font-headers font-black;
}
a {
@apply transition-colors underline-offset-2 decoration-dotted underline decoration-dark hover:text-dark cursor-pointer;
}
*::selection {
@apply bg-dark text-light;
}
mark {
@apply bg-mid px-2;
}
/* SCROLLBARS STYLING */
* {
@apply [scrollbar-color:theme(colors.dark)_transparent] [scrollbar-width:thin];
}
*::-webkit-scrollbar {
@apply w-3 mobile:w-0;
}
*::-webkit-scrollbar-track {
@apply bg-light;
}
*::-webkit-scrollbar-thumb {
@apply bg-dark rounded-full border-[3px] border-solid border-light;
}
/* CHANGE FORMATTED DEFAULTS */
.formatted h1,
.formatted h2,
.formatted h3,
.formatted h4,
.formatted h5,
.formatted h6 {
@apply text-center flex gap-3 justify-center;
}
.formatted h1 {
@apply text-4xl my-16;
}
.formatted h1 + h2 {
@apply -mt-10;
}
.formatted h2 {
@apply text-3xl my-12;
}
.formatted h2 + h3 {
@apply -mt-8;
}
.formatted h3 {
@apply text-2xl my-8;
}
.formatted h3 + h4 {
@apply -mt-6;
}
.formatted h4 {
@apply text-xl my-6;
}
.formatted h5 {
@apply text-lg my-4;
}
.formatted p,
.formatted strong {
@apply my-2 text-justify;
}
.formatted strong {
@apply font-black;
}
.formatted footer {
@apply border-t-[3px] border-dotted pt-6;
}
.formatted footer > div {
@apply my-2 px-6 py-4 rounded-xl;
}
.formatted footer > div:target {
@apply bg-mid shadow-inner-sm shadow-shade;
}
.formatted li::marker {
@apply text-dark;
}
.formatted blockquote {
@apply border-l-dark;
}
.formatted ul {
@apply list-disc pl-4;
}
.formatted ol {
@apply list-decimal pl-4;
}
.formatted blockquote {
@apply border-2 border-mid rounded-lg p-5 text-center my-8;
}
.formatted blockquote cite {
@apply text-dark block;
}
/* INPUT */
input,
textarea {
@apply rounded-full p-2 text-center bg-light outline outline-mid outline-2 outline-offset-[-2px] hover:outline-[transparent] text-dark hover:bg-mid transition-all placeholder:text-dark placeholder:opacity-60;
}
input::placeholder {
@apply text-dark opacity-60;
}
input:focus-visible,
textarea:focus-within {
@apply outline-none bg-mid shadow-inner-sm shadow-shade;
}
textarea {
@apply rounded-2xl text-left p-6;
}
input[type="submit"] {
@apply grid place-content-center place-items-center border-[1px] border-dark text-dark rounded-full px-4 pt-[0.4rem] pb-[0.5rem] transition-all cursor-pointer hover:text-light hover:bg-dark hover:drop-shadow-shade-lg active:bg-black active:text-light active:drop-shadow-black-lg active:border-black;
}
.texture-paper-dots {
@apply [background-image:var(--theme-texture-dots)] [background-blend-mode:var(--theme-texture-dots-blend)] bg-local bg-[length:10cm];
} }
/* TIPPY */ /* TIPPY */