From 8f843f321d4c1aa4aa810af5e00421657576bdbe Mon Sep 17 00:00:00 2001 From: DebaucheryLibrarian Date: Sun, 6 Oct 2024 02:45:56 +0200 Subject: [PATCH] Expanded edit fields. Added revision history to scene and user pages. --- assets/css/states.css | 4 + assets/css/theme.css | 3 + assets/img/icons/bubble-blocked.svg | 4 + assets/img/icons/bubble-cancel.svg | 4 + assets/img/icons/bubble-check.svg | 4 + assets/img/icons/bubble-lines3.svg | 4 + assets/img/icons/bubble-link.svg | 4 + assets/img/icons/bubble-notification2.svg | 4 + assets/img/icons/bubble-plus.svg | 4 + assets/img/icons/hammer2.svg | 4 + assets/img/icons/hand.svg | 4 + assets/img/icons/spam.svg | 4 + assets/img/icons/user-block.svg | 5 + assets/img/icons/user-cancel.svg | 5 + assets/img/icons/user-check.svg | 5 + assets/img/icons/user-lock.svg | 5 + assets/img/icons/user-minus.svg | 5 + assets/img/icons/user-plus.svg | 5 + components/actors/bio.vue | 4 +- components/actors/search.vue | 20 +- components/admin/admin.vue | 71 +++ components/edit/actors.vue | 28 +- components/edit/movies.vue | 173 +++++++ components/edit/revisions.vue | 488 ++++++++++++++++++ components/edit/tags.vue | 28 +- components/form/checkbox.vue | 10 +- components/header/header.vue | 14 + components/movies/search.vue | 102 ++++ config/default.cjs | 3 + ecosystem.config.cjs | 2 +- package-lock.json | 20 + package.json | 1 + pages/admin/+Page.vue | 9 + pages/admin/+onBeforeRender.js | 13 + pages/admin/revisions/+Page.vue | 18 + pages/admin/revisions/+onBeforeRender.js | 30 ++ pages/admin/revisions/+route.js | 1 + pages/scene/+Page.vue | 26 +- pages/scene/edit/+Page.vue | 101 +++- pages/scene/edit/+route.js | 2 +- pages/scene/revisions/+Page.vue | 37 ++ pages/scene/revisions/+onBeforeRender.js | 34 ++ pages/scene/revisions/+route.js | 1 + pages/users/@username/+Page.vue | 24 +- pages/users/@username/+onBeforeRender.js | 22 +- renderer/+onRenderHtml.js | 4 +- src/actors.js | 6 +- src/auth.js | 1 + src/scenes.js | 242 +++++++-- src/users.js | 20 + src/web/auth.js | 5 + src/web/scenes.js | 35 +- src/web/server.js | 54 +- src/web/stashes.js | 17 + src/web/users.js | 26 +- static | 2 +- ....timestamp-1726092225447-9df18bc0290a7.mjs | 49 ++ 57 files changed, 1664 insertions(+), 156 deletions(-) create mode 100755 assets/img/icons/bubble-blocked.svg create mode 100755 assets/img/icons/bubble-cancel.svg create mode 100755 assets/img/icons/bubble-check.svg create mode 100755 assets/img/icons/bubble-lines3.svg create mode 100755 assets/img/icons/bubble-link.svg create mode 100755 assets/img/icons/bubble-notification2.svg create mode 100755 assets/img/icons/bubble-plus.svg create mode 100755 assets/img/icons/hammer2.svg create mode 100755 assets/img/icons/hand.svg create mode 100755 assets/img/icons/spam.svg create mode 100755 assets/img/icons/user-block.svg create mode 100755 assets/img/icons/user-cancel.svg create mode 100755 assets/img/icons/user-check.svg create mode 100755 assets/img/icons/user-lock.svg create mode 100755 assets/img/icons/user-minus.svg create mode 100755 assets/img/icons/user-plus.svg create mode 100644 components/admin/admin.vue create mode 100644 components/edit/movies.vue create mode 100644 components/edit/revisions.vue create mode 100644 components/movies/search.vue create mode 100644 pages/admin/+Page.vue create mode 100644 pages/admin/+onBeforeRender.js create mode 100644 pages/admin/revisions/+Page.vue create mode 100644 pages/admin/revisions/+onBeforeRender.js create mode 100644 pages/admin/revisions/+route.js create mode 100644 pages/scene/revisions/+Page.vue create mode 100644 pages/scene/revisions/+onBeforeRender.js create mode 100644 pages/scene/revisions/+route.js create mode 100644 vite.config.js.timestamp-1726092225447-9df18bc0290a7.mjs diff --git a/assets/css/states.css b/assets/css/states.css index cba281a..596d88f 100755 --- a/assets/css/states.css +++ b/assets/css/states.css @@ -61,3 +61,7 @@ .noshrink { flex-shrink: 0; } + +.capitalize { + text-transform: capitalize; +} diff --git a/assets/css/theme.css b/assets/css/theme.css index 22aa4c1..88e1fa3 100644 --- a/assets/css/theme.css +++ b/assets/css/theme.css @@ -81,6 +81,9 @@ --success: #5c2; --notice: #25c; + --approve: #3a1; + --reject: #a22; + --gold: #d5b522; } diff --git a/assets/img/icons/bubble-blocked.svg b/assets/img/icons/bubble-blocked.svg new file mode 100755 index 0000000..790d466 --- /dev/null +++ b/assets/img/icons/bubble-blocked.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/img/icons/bubble-cancel.svg b/assets/img/icons/bubble-cancel.svg new file mode 100755 index 0000000..a4e20d9 --- /dev/null +++ b/assets/img/icons/bubble-cancel.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/img/icons/bubble-check.svg b/assets/img/icons/bubble-check.svg new file mode 100755 index 0000000..54bf80b --- /dev/null +++ b/assets/img/icons/bubble-check.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/img/icons/bubble-lines3.svg b/assets/img/icons/bubble-lines3.svg new file mode 100755 index 0000000..635aab0 --- /dev/null +++ b/assets/img/icons/bubble-lines3.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/img/icons/bubble-link.svg b/assets/img/icons/bubble-link.svg new file mode 100755 index 0000000..700414a --- /dev/null +++ b/assets/img/icons/bubble-link.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/img/icons/bubble-notification2.svg b/assets/img/icons/bubble-notification2.svg new file mode 100755 index 0000000..ce6e5b3 --- /dev/null +++ b/assets/img/icons/bubble-notification2.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/img/icons/bubble-plus.svg b/assets/img/icons/bubble-plus.svg new file mode 100755 index 0000000..9d91556 --- /dev/null +++ b/assets/img/icons/bubble-plus.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/img/icons/hammer2.svg b/assets/img/icons/hammer2.svg new file mode 100755 index 0000000..43b6463 --- /dev/null +++ b/assets/img/icons/hammer2.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/img/icons/hand.svg b/assets/img/icons/hand.svg new file mode 100755 index 0000000..778dc07 --- /dev/null +++ b/assets/img/icons/hand.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/img/icons/spam.svg b/assets/img/icons/spam.svg new file mode 100755 index 0000000..73ccb6c --- /dev/null +++ b/assets/img/icons/spam.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/img/icons/user-block.svg b/assets/img/icons/user-block.svg new file mode 100755 index 0000000..25b2e44 --- /dev/null +++ b/assets/img/icons/user-block.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/assets/img/icons/user-cancel.svg b/assets/img/icons/user-cancel.svg new file mode 100755 index 0000000..320ba94 --- /dev/null +++ b/assets/img/icons/user-cancel.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/assets/img/icons/user-check.svg b/assets/img/icons/user-check.svg new file mode 100755 index 0000000..df273b4 --- /dev/null +++ b/assets/img/icons/user-check.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/assets/img/icons/user-lock.svg b/assets/img/icons/user-lock.svg new file mode 100755 index 0000000..4f67f24 --- /dev/null +++ b/assets/img/icons/user-lock.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/assets/img/icons/user-minus.svg b/assets/img/icons/user-minus.svg new file mode 100755 index 0000000..5f98fcb --- /dev/null +++ b/assets/img/icons/user-minus.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/assets/img/icons/user-plus.svg b/assets/img/icons/user-plus.svg new file mode 100755 index 0000000..6798cb1 --- /dev/null +++ b/assets/img/icons/user-plus.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/components/actors/bio.vue b/components/actors/bio.vue index 5ba1dcb..f04fe5b 100644 --- a/components/actors/bio.vue +++ b/components/actors/bio.vue @@ -8,7 +8,7 @@ class="avatar-container" > @@ -296,7 +296,7 @@ + + diff --git a/components/edit/actors.vue b/components/edit/actors.vue index 37c52ed..932afe8 100644 --- a/components/edit/actors.vue +++ b/components/edit/actors.vue @@ -85,11 +85,13 @@ watch(() => props.scene, () => { newActors.value = []; }); &.disabled { .actor { - color: var(--shadow); + background: var(--glass-weak-50); + color: var(--glass-strong-10); .remove, .add { - background: var(--shadow-weak-40); + fill: var(--shadow-weak-30); + background: var(--shadow-weak-50); } } @@ -103,9 +105,14 @@ watch(() => props.scene, () => { newActors.value = []; }); align-items: center; margin-left: .25rem; + &:hover { + box-shadow: 0 0 3px var(--shadow-weak-20); + } + .icon { height: 100%; padding: 0 .5rem; + background: var(--success); fill: var(--text-light); } } @@ -114,8 +121,9 @@ watch(() => props.scene, () => { newActors.value = []; }); .actor { display: flex; align-items: stretch; - background: var(--glass-weak-30); border-radius: .25rem; + background: var(--background); + box-shadow: 0 0 3px var(--shadow-weak-30); &.deleted { color: var(--glass); @@ -129,8 +137,8 @@ watch(() => props.scene, () => { newActors.value = []; }); .add { height: auto; padding: .25rem .3rem; - fill: var(--highlight-strong-10); border-radius: .25rem; + fill: var(--highlight-strong-10); &:hover { fill: var(--text-light); @@ -139,11 +147,19 @@ watch(() => props.scene, () => { newActors.value = []; }); } .remove { - background: var(--error); + fill: var(--error); + + &:hover { + background: var(--error); + } } .add { - background: var(--success); + fill: var(--success); + + &:hover { + background: var(--success); + } } } diff --git a/components/edit/movies.vue b/components/edit/movies.vue new file mode 100644 index 0000000..e4755a8 --- /dev/null +++ b/components/edit/movies.vue @@ -0,0 +1,173 @@ + + + + + diff --git a/components/edit/revisions.vue b/components/edit/revisions.vue new file mode 100644 index 0000000..67c476a --- /dev/null +++ b/components/edit/revisions.vue @@ -0,0 +1,488 @@ + + + + + diff --git a/components/edit/tags.vue b/components/edit/tags.vue index 43eb3eb..65339a1 100644 --- a/components/edit/tags.vue +++ b/components/edit/tags.vue @@ -85,11 +85,13 @@ watch(() => props.scene, () => { newTags.value = []; }); &.disabled { .tag { - color: var(--shadow); + background: var(--glass-weak-50); + color: var(--glass-strong-10); .remove, .add { - background: var(--shadow-weak-40); + fill: var(--shadow-weak-30); + background: var(--shadow-weak-50); } } @@ -103,9 +105,14 @@ watch(() => props.scene, () => { newTags.value = []; }); align-items: center; margin-left: .25rem; + &:hover { + box-shadow: 0 0 3px var(--shadow-weak-20); + } + .icon { height: 100%; padding: 0 .5rem; + background: var(--success); fill: var(--text-light); } } @@ -114,8 +121,9 @@ watch(() => props.scene, () => { newTags.value = []; }); .tag { display: flex; align-items: stretch; - background: var(--glass-weak-30); border-radius: .25rem; + background: var(--background); + box-shadow: 0 0 3px var(--shadow-weak-30); &.deleted { color: var(--glass); @@ -129,8 +137,8 @@ watch(() => props.scene, () => { newTags.value = []; }); .add { height: auto; padding: .25rem .3rem; - fill: var(--highlight-strong-10); border-radius: .25rem; + fill: var(--highlight-strong-10); &:hover { fill: var(--text-light); @@ -139,11 +147,19 @@ watch(() => props.scene, () => { newTags.value = []; }); } .remove { - background: var(--error); + fill: var(--error); + + &:hover { + background: var(--error); + } } .add { - background: var(--success); + fill: var(--success); + + &:hover { + background: var(--success); + } } } diff --git a/components/form/checkbox.vue b/components/form/checkbox.vue index 5b26446..d317385 100755 --- a/components/form/checkbox.vue +++ b/components/form/checkbox.vue @@ -11,6 +11,7 @@ :checked="checked" type="checkbox" class="check-checkbox" + :disabled="disabled" @change="$emit('change', $event.target.checked)" > @@ -33,6 +34,10 @@ defineProps({ type: String, default: null, }, + disabled: { + type: Boolean, + default: false, + }, }); defineEmits(['change']); @@ -98,6 +103,10 @@ defineEmits(['change']); } } +.check-checkbox:disabled + .check { + background: var(--shadow); +} + .check-container.minus .check-checkbox:checked + .check { background: var(--error); @@ -108,7 +117,6 @@ defineEmits(['change']); .check-label { overflow: hidden; - text-transform: capitalize; text-overflow: ellipsis; margin: 0 .5rem 0 0; } diff --git a/components/header/header.vue b/components/header/header.vue index aaf6d1d..6b91741 100644 --- a/components/header/header.vue +++ b/components/header/header.vue @@ -189,6 +189,20 @@ Settings + +
  • + + + + + + + + + + diff --git a/config/default.cjs b/config/default.cjs index 6e919fd..4f6d127 100755 --- a/config/default.cjs +++ b/config/default.cjs @@ -63,6 +63,9 @@ module.exports = { usernameLength: [2, 24], usernamePattern: /^[a-zA-Z0-9_-]+$/, }, + bans: { + defaultExpiry: 60 * 24 * 3, // in minutes, 3 days + }, apiAccess: { graphqlEnabled: true, keySize: 24, // bytes diff --git a/ecosystem.config.cjs b/ecosystem.config.cjs index 7f3a78f..846f10d 100644 --- a/ecosystem.config.cjs +++ b/ecosystem.config.cjs @@ -3,7 +3,7 @@ module.exports = { apps: [ { - name: 'newtraxxx', + name: 'traxxx', script: 'npm', args: 'run server:prod', exec_mode: 'cluster', diff --git a/package-lock.json b/package-lock.json index 5068a9b..81e82b4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -43,6 +43,7 @@ "manticoresearch": "^4.0.0", "markdown-it": "^14.0.0", "mathjs": "^12.2.1", + "merkle-json": "^2.6.0", "mitt": "^3.0.1", "mysql": "^2.18.1", "nanoid": "^5.0.4", @@ -7324,6 +7325,17 @@ "node": ">= 8" } }, + "node_modules/merkle-json": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/merkle-json/-/merkle-json-2.6.0.tgz", + "integrity": "sha512-sJM+SNINn3/5GzFyY8MMCj+647UbDVcZv3wcynX1vv9Vhnm1gWGI5ZPOA+EYm3iInITyQHKnmcpYKqZkeY+iAQ==", + "dependencies": { + "merkle-json": "^2.1.0" + }, + "engines": { + "node": ">=6.11.0" + } + }, "node_modules/methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", @@ -15647,6 +15659,14 @@ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==" }, + "merkle-json": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/merkle-json/-/merkle-json-2.6.0.tgz", + "integrity": "sha512-sJM+SNINn3/5GzFyY8MMCj+647UbDVcZv3wcynX1vv9Vhnm1gWGI5ZPOA+EYm3iInITyQHKnmcpYKqZkeY+iAQ==", + "requires": { + "merkle-json": "^2.1.0" + } + }, "methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", diff --git a/package.json b/package.json index eb9f69c..a87ab54 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,7 @@ "manticoresearch": "^4.0.0", "markdown-it": "^14.0.0", "mathjs": "^12.2.1", + "merkle-json": "^2.6.0", "mitt": "^3.0.1", "mysql": "^2.18.1", "nanoid": "^5.0.4", diff --git a/pages/admin/+Page.vue b/pages/admin/+Page.vue new file mode 100644 index 0000000..e81d112 --- /dev/null +++ b/pages/admin/+Page.vue @@ -0,0 +1,9 @@ + + + diff --git a/pages/admin/+onBeforeRender.js b/pages/admin/+onBeforeRender.js new file mode 100644 index 0000000..469e839 --- /dev/null +++ b/pages/admin/+onBeforeRender.js @@ -0,0 +1,13 @@ +import { render } from 'vike/abort'; /* eslint-disable-line import/extensions */ + +export function onBeforeRender(pageContext) { + if (pageContext.user.role === 'user') { + throw render(404); + } + + return { + pageContext: { + title: pageContext.routeParams.section, + }, + }; +} diff --git a/pages/admin/revisions/+Page.vue b/pages/admin/revisions/+Page.vue new file mode 100644 index 0000000..bb1a79f --- /dev/null +++ b/pages/admin/revisions/+Page.vue @@ -0,0 +1,18 @@ + + + + + diff --git a/pages/admin/revisions/+onBeforeRender.js b/pages/admin/revisions/+onBeforeRender.js new file mode 100644 index 0000000..87e97fb --- /dev/null +++ b/pages/admin/revisions/+onBeforeRender.js @@ -0,0 +1,30 @@ +import { render } from 'vike/abort'; /* eslint-disable-line import/extensions */ +import { fetchSceneRevisions } from '#/src/scenes.js'; + +export async function onBeforeRender(pageContext) { + if (!pageContext.user || pageContext.user.role === 'user') { + throw render(404); + } + + const { + revisions, + actors, + tags, + movies, + } = await fetchSceneRevisions(null, { + isFinalized: false, + limit: 50, + }, pageContext.user); + + return { + pageContext: { + title: pageContext.routeParams.section, + pageProps: { + revisions, + actors, + tags, + movies, + }, + }, + }; +} diff --git a/pages/admin/revisions/+route.js b/pages/admin/revisions/+route.js new file mode 100644 index 0000000..d9cb684 --- /dev/null +++ b/pages/admin/revisions/+route.js @@ -0,0 +1 @@ +export default '/admin/@section/*'; diff --git a/pages/scene/+Page.vue b/pages/scene/+Page.vue index b426735..efa9f96 100644 --- a/pages/scene/+Page.vue +++ b/pages/scene/+Page.vue @@ -286,7 +286,7 @@ v-if="user" class="icon-link" target="_blank" - :href="`/user/${user.username}/summaries?t=${selectedTemplate}`" + :href="`/user/${user.username}/templates?t=${selectedTemplate}`" > {{ userTemplate.name }}
  • + +
    + Edit scene + + Revisions +
    @@ -670,6 +687,13 @@ function copySummary() { } } +.scene-actions { + display: flex; + justify-content: center; + gap: 2rem; + margin-top: 1rem; +} + .icon-link { display: flex; height: auto; diff --git a/pages/scene/edit/+Page.vue b/pages/scene/edit/+Page.vue index 6baf09d..3a91bed 100644 --- a/pages/scene/edit/+Page.vue +++ b/pages/scene/edit/+Page.vue @@ -1,6 +1,40 @@ @@ -56,6 +70,7 @@ import { formatDistanceStrict } from 'date-fns'; import Stashes from '#/components/stashes/stashes.vue'; import Alerts from '#/components/alerts/alerts.vue'; import Summaries from '#/components/scenes/summaries.vue'; +import Revisions from '#/components/edit/revisions.vue'; const pageContext = inject('pageContext'); const domain = pageContext.routeParams.domain; @@ -125,8 +140,9 @@ const mockupRelease = {