Compare commits
10 Commits
8747d6b604
...
82faaa5179
Author | SHA1 | Date | |
---|---|---|---|
82faaa5179 | |||
0c038fe708 | |||
bb61075d87 | |||
655e9c5e07 | |||
6fd6d7cbb1 | |||
bf44122abe | |||
1850f5a3f0 | |||
99cdd59272 | |||
2730eac4b2 | |||
a65590d47e |
5
.gitignore
vendored
5
.gitignore
vendored
@ -4,6 +4,7 @@
|
|||||||
.nuxt
|
.nuxt
|
||||||
.nitro
|
.nitro
|
||||||
.cache
|
.cache
|
||||||
|
.vite-nodez
|
||||||
dist
|
dist
|
||||||
|
|
||||||
# Node dependencies
|
# Node dependencies
|
||||||
@ -32,10 +33,12 @@ stories/*.txt
|
|||||||
|
|
||||||
# avatars
|
# avatars
|
||||||
public/avatars/
|
public/avatars/
|
||||||
!/**/.gitkeep
|
|
||||||
|
|
||||||
!/.idea/fileTemplates/
|
!/.idea/fileTemplates/
|
||||||
!/.idea/fileTemplates/**/*
|
!/.idea/fileTemplates/**/*
|
||||||
|
|
||||||
!/.idea/conventionalcommit.json
|
!/.idea/conventionalcommit.json
|
||||||
!/.idea/conventionalCommit.xml
|
!/.idea/conventionalCommit.xml
|
||||||
|
**/.auth
|
||||||
|
tests/screenshots/*.*
|
||||||
|
!/**/.gitkeep
|
||||||
|
@ -11,12 +11,26 @@
|
|||||||
wrapCol?: any;
|
wrapCol?: any;
|
||||||
}>();
|
}>();
|
||||||
let dark = inject<boolean>("dark");
|
let dark = inject<boolean>("dark");
|
||||||
|
const stop = (e, ed) => {
|
||||||
|
console.log(e.type.toUpperCase(), e, ed);
|
||||||
|
e.preventDefault();
|
||||||
|
e.cancel();
|
||||||
|
e.stopImmediatePropagation();
|
||||||
|
e.stopPropagation();
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<ClientOnly>
|
<ClientOnly>
|
||||||
<vee-field :name="props.name" v-slot="{ errorMessage, field, value }" :model-value="props.val">
|
<vee-field :name="props.name" v-slot="{ errorMessage, field, value, setValue }" :model-value="props.val">
|
||||||
<a-form-item :validate-status="!!errorMessage ? 'error' : ''" :name="props.name" :label="props.label as any" :help="errorMessage">
|
<a-form-item
|
||||||
|
:data-testid="$attrs['data-testid']"
|
||||||
|
:validate-status="!!errorMessage ? 'error' : ''"
|
||||||
|
:name="props.name"
|
||||||
|
:label="props.label as any"
|
||||||
|
:help="errorMessage"
|
||||||
|
>
|
||||||
<tinymce-editor
|
<tinymce-editor
|
||||||
|
model-events="drag dragdrop dragend draggesture dragover dragstart drop change"
|
||||||
v-bind="field"
|
v-bind="field"
|
||||||
width="100%"
|
width="100%"
|
||||||
@change="
|
@change="
|
||||||
@ -27,6 +41,16 @@
|
|||||||
"
|
"
|
||||||
:initial-value="value"
|
:initial-value="value"
|
||||||
v-model:model-value="field.value"
|
v-model:model-value="field.value"
|
||||||
|
@drag="stop"
|
||||||
|
@deactivate="(e) => console.log(e)"
|
||||||
|
@dragOver="stop"
|
||||||
|
@dragEnter="stop"
|
||||||
|
@dragEnd="stop"
|
||||||
|
@dragDrop="stop"
|
||||||
|
@draggesture="stop"
|
||||||
|
@dragGesture="stop"
|
||||||
|
@dragstart="stop"
|
||||||
|
@drop="stop"
|
||||||
tinymce-script-src="/tinymce/tinymce.min.js"
|
tinymce-script-src="/tinymce/tinymce.min.js"
|
||||||
:init="{
|
:init="{
|
||||||
...props.init,
|
...props.init,
|
||||||
|
@ -67,6 +67,7 @@
|
|||||||
:options="state.data"
|
:options="state.data"
|
||||||
v-model:value="value"
|
v-model:value="value"
|
||||||
:allow-clear="true"
|
:allow-clear="true"
|
||||||
|
v-bind="$attrs"
|
||||||
>
|
>
|
||||||
<template v-if="state.fetching" #notFoundContent>
|
<template v-if="state.fetching" #notFoundContent>
|
||||||
<a-spin size="small" />
|
<a-spin size="small" />
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<a-form-item :validate-status="!!errorMessage ? 'error' : undefined" :help="errorMessage as any" label="Bands">
|
<a-form-item :validate-status="!!errorMessage ? 'error' : undefined" :help="errorMessage as any" label="Bands">
|
||||||
<a-select
|
<a-select
|
||||||
|
v-bind="$attrs"
|
||||||
:allow-clear="true"
|
:allow-clear="true"
|
||||||
mode="multiple"
|
mode="multiple"
|
||||||
option-filter-prop="label"
|
option-filter-prop="label"
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<a-form-item :help="errorMessage" label="Characters" :name="bandName as string" :validate-status="!!errorMessage ? 'error' : undefined">
|
<a-form-item :help="errorMessage" label="Characters" :name="bandName as string" :validate-status="!!errorMessage ? 'error' : undefined">
|
||||||
<a-select mode="multiple" :options="opts" v-model:value="value">
|
<a-select v-bind="$attrs" mode="multiple" :options="opts" v-model:value="value">
|
||||||
<template #removeIcon>
|
<template #removeIcon>
|
||||||
<i class="far fa-circle-x" />
|
<i class="far fa-circle-x" />
|
||||||
</template>
|
</template>
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<a-form-item :help="errorMessage" label="Genre(s)" :validate-status="!!errorMessage ? 'error' : undefined">
|
<a-form-item :help="errorMessage" label="Genre(s)" :validate-status="!!errorMessage ? 'error' : undefined">
|
||||||
<a-select :allow-clear="true" :options="opts" v-model:value="value" mode="multiple">
|
<a-select v-bind="$attrs" :allow-clear="true" :options="opts" v-model:value="value" mode="multiple">
|
||||||
<template #removeIcon>
|
<template #removeIcon>
|
||||||
<i class="far fa-circle-x" />
|
<i class="far fa-circle-x" />
|
||||||
</template>
|
</template>
|
||||||
|
@ -19,19 +19,19 @@
|
|||||||
<a-form-item label="Pairings">
|
<a-form-item label="Pairings">
|
||||||
<a-row :gutter="5" :wrap="true" v-for="(field, idx) in fields" :key="field.key">
|
<a-row :gutter="5" :wrap="true" v-for="(field, idx) in fields" :key="field.key">
|
||||||
<Field :name="fname + 'relationships' + `[${idx}]`">
|
<Field :name="fname + 'relationships' + `[${idx}]`">
|
||||||
<a-select mode="multiple" :options="opts" v-model:value="field.value as string[]" @change="(val) => update(idx, val as string[])">
|
<a-select mode="multiple" v-bind="$attrs" :options="opts" v-model:value="field.value as string[]" @change="(val) => update(idx, val as string[])">
|
||||||
<template #removeIcon>
|
<template #removeIcon>
|
||||||
<i class="far fa-circle-x" />
|
<i class="far fa-circle-x" />
|
||||||
</template>
|
</template>
|
||||||
</a-select>
|
</a-select>
|
||||||
</Field>
|
</Field>
|
||||||
<a-col :span="4">
|
<a-col :span="4">
|
||||||
<a-button @click="(e) => remove(idx)"> - </a-button>
|
<a-button :data-testid="`${$attrs['data-testid']}.${idx}.remove`" @click="(e) => remove(idx)"> - </a-button>
|
||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
</a-row>
|
||||||
<a-row justify="end">
|
<a-row justify="end">
|
||||||
<a-col :span="2">
|
<a-col :span="2">
|
||||||
<a-button @click="(e) => push([])"> + </a-button>
|
<a-button :data-testid="`${$attrs['data-testid']}.add`" @click="(e) => push([])"> + </a-button>
|
||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
</a-row>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
import elCharacters from "../atoms/characters.vue";
|
import elCharacters from "../atoms/characters.vue";
|
||||||
import elPairings from "../atoms/pairings.vue";
|
import elPairings from "../atoms/pairings.vue";
|
||||||
import uploadOrPaste from "./uploadOrPaste.vue";
|
import uploadOrPaste from "./uploadOrPaste.vue";
|
||||||
|
import { IBand } from "@models/band";
|
||||||
// import test1 from
|
// import test1 from
|
||||||
|
|
||||||
let { name, data } = defineProps<{
|
let { name, data } = defineProps<{
|
||||||
@ -16,7 +17,7 @@
|
|||||||
data: FormChapter;
|
data: FormChapter;
|
||||||
}>();
|
}>();
|
||||||
let acData = toRef(data);
|
let acData = toRef(data);
|
||||||
let { data: _bands } = await useApiFetch("/band/all");
|
let { data: _bands } = await useApiFetch<IBand[]>("/band/all");
|
||||||
let bands = ref(_bands);
|
let bands = ref(_bands);
|
||||||
provide("curName", name + ".");
|
provide("curName", name + ".");
|
||||||
provide("bandlist", bands);
|
provide("bandlist", bands);
|
||||||
@ -30,58 +31,59 @@
|
|||||||
updateBands,
|
updateBands,
|
||||||
});
|
});
|
||||||
const wrapc = { span: 12 };
|
const wrapc = { span: 12 };
|
||||||
|
const tbase = `storyform.${name}.form`;
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div :data-testid="tbase">
|
||||||
<a-row :gutter="[10, 0]">
|
<a-row :gutter="[10, 0]">
|
||||||
<a-col :span="12">
|
<a-col :span="12">
|
||||||
<Field :name="name + '.chapterTitle'" v-slot="{ value, field, errorMessage }">
|
<Field :name="name + '.chapterTitle'" v-slot="{ value, field, errorMessage }">
|
||||||
<a-form-item :name="[field.name as string]" label="Chapter title" :help="errorMessage" :status="!!errorMessage ? 'error' : undefined">
|
<a-form-item :name="[field.name as string]" label="Chapter title" :help="errorMessage" :status="!!errorMessage ? 'error' : undefined">
|
||||||
<a-input v-bind="field" />
|
<a-input :data-testid="`${tbase}.title`" v-bind="field" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</Field>
|
</Field>
|
||||||
</a-col>
|
</a-col>
|
||||||
<a-col :span="12">
|
<a-col :span="12">
|
||||||
<el-bands />
|
<el-bands :data-testid="`${tbase}.bands`" />
|
||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
</a-row>
|
||||||
<a-row :gutter="[10, 0]">
|
<a-row :gutter="[10, 0]">
|
||||||
<a-col :span="12">
|
<a-col :span="12">
|
||||||
<base-editor v-model:val="acData.summary" :name="name + '.summary'" :wrap-col="wrapc" label="Summary" :init="bare" />
|
<base-editor :data-testid="`${tbase}.summary`" v-model:val="acData.summary" :name="name + '.summary'" :wrap-col="wrapc" label="Summary" :init="bare" />
|
||||||
</a-col>
|
</a-col>
|
||||||
<a-col :span="12">
|
<a-col :span="12">
|
||||||
<base-editor v-model:val="acData.notes" :name="name + '.notes'" :wrap-col="wrapc" label="Author's notes" :init="bare" />
|
<base-editor :data-testid="`${tbase}.notes`" v-model:val="acData.notes" :name="name + '.notes'" :wrap-col="wrapc" label="Author's notes" :init="bare" />
|
||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
</a-row>
|
||||||
<a-row :gutter="[10, 0]">
|
<a-row :gutter="[10, 0]">
|
||||||
<a-col :span="12">
|
<a-col :span="12">
|
||||||
<el-characters />
|
<el-characters :data-testid="`${tbase}.characters`" />
|
||||||
</a-col>
|
</a-col>
|
||||||
<a-col :span="12">
|
<a-col :span="12">
|
||||||
<el-pairings />
|
<el-pairings :data-testid="`${tbase}.relationships`" />
|
||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
</a-row>
|
||||||
<Field :name="name + '.nsfw'" type="checkbox" :unchecked-value="false" :value="true" v-slot="{ value, field, errorMessage }">
|
<Field :name="name + '.nsfw'" type="checkbox" :unchecked-value="false" :value="true" v-slot="{ value, field, errorMessage }">
|
||||||
<a-checkbox v-bind="field" v-model="field.value"> Has NSFW content </a-checkbox>
|
<a-checkbox :data-testid="`${tbase}.nsfw`" v-bind="field" v-model="field.value"> Has NSFW content </a-checkbox>
|
||||||
<error-message :name="field.name" />
|
<error-message :name="field.name" />
|
||||||
</Field>
|
</Field>
|
||||||
<Field :name="name + '.loggedInOnly'" type="checkbox" :unchecked-value="false" :value="true" v-slot="{ value, field, errorMessage }">
|
<Field :name="name + '.loggedInOnly'" type="checkbox" :unchecked-value="false" :value="true" v-slot="{ value, field, errorMessage }">
|
||||||
<a-checkbox v-bind="field"> Visible only to registered users </a-checkbox>
|
<a-checkbox :data-testid="`${tbase}.loggedInOnly`" v-bind="field"> Visible only to registered users </a-checkbox>
|
||||||
<error-message :name="field.name" />
|
<error-message :name="field.name" />
|
||||||
</Field>
|
</Field>
|
||||||
<Field :name="name + '.hidden'" type="checkbox" :unchecked-value="false" :value="true" v-slot="{ value, field, errorMessage }">
|
<Field :name="name + '.hidden'" type="checkbox" :unchecked-value="false" :value="true" v-slot="{ value, field, errorMessage }">
|
||||||
<a-tooltip>
|
<a-tooltip>
|
||||||
<template #title> Hides your story from everyone except you and site admins. </template>
|
<template #title> Hides your story from everyone except you and site admins. </template>
|
||||||
<a-checkbox v-bind="field"> Hidden </a-checkbox>
|
<a-checkbox v-bind="field" :data-testid="`${tbase}.hidden`"> Hidden </a-checkbox>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
</Field>
|
</Field>
|
||||||
<a-row>
|
<a-row>
|
||||||
<a-col :span="24">
|
<a-col :span="24">
|
||||||
<genre />
|
<genre :data-testid="`${tbase}.genre`" />
|
||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
</a-row>
|
||||||
<a-divider> Contents </a-divider>
|
<a-divider> Contents </a-divider>
|
||||||
<upload-or-paste />
|
<upload-or-paste :data-testid="`${tbase}.uploadOrPaste`" />
|
||||||
<Field :name="name + '.id'" v-if="!!data.id" :model-value="data.id" />
|
<Field :hidden="true" :name="name + '.id'" v-if="!!data.id" :model-value="data.id" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -11,14 +11,15 @@
|
|||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<a-radio-group v-model:value="pvalue">
|
<a-radio-group v-model:value="pvalue">
|
||||||
<a-radio value="pasteOrType">Paste or type content</a-radio>
|
<a-radio value="pasteOrType" :data-testid="$attrs['data-testid'] + '.radio.pasteOrType'">Paste or type content</a-radio>
|
||||||
<a-radio value="upload">Upload a file</a-radio>
|
<a-radio value="upload" :data-testid="$attrs['data-testid'] + '.radio.upload'">Upload a file</a-radio>
|
||||||
</a-radio-group>
|
</a-radio-group>
|
||||||
<br />
|
<br />
|
||||||
<br />
|
<br />
|
||||||
<base-editor label="" v-if="pvalue === 'pasteOrType'" :init="story" :name="fname + 'content'" />
|
<base-editor :data-testid="$attrs['data-testid'] + '.type'" label="" v-if="pvalue === 'pasteOrType'" :init="story" :name="fname + 'content'" />
|
||||||
<a-upload
|
<a-upload
|
||||||
v-model:file-list="fileList"
|
v-model:file-list="fileList"
|
||||||
|
:data-testid="$attrs['data-testid'] + '.upload'"
|
||||||
v-else-if="pvalue === 'upload'"
|
v-else-if="pvalue === 'upload'"
|
||||||
:name="fname + 'file'"
|
:name="fname + 'file'"
|
||||||
accept=".doc,.docx,.md,.markdown"
|
accept=".doc,.docx,.md,.markdown"
|
||||||
@ -32,6 +33,7 @@
|
|||||||
let resp;
|
let resp;
|
||||||
try {
|
try {
|
||||||
resp = bap.file.response;
|
resp = bap.file.response;
|
||||||
|
console.log('RESPONSE', resp);
|
||||||
if (resp.success) {
|
if (resp.success) {
|
||||||
fileField.setValue(resp.fileName);
|
fileField.setValue(resp.fileName);
|
||||||
console.log(fileField.value);
|
console.log(fileField.value);
|
||||||
|
@ -1,6 +1,18 @@
|
|||||||
|
const plugins =
|
||||||
|
"a11ychecker advcode advtable advtemplate typography casechange checklist editimage mediaembed export footnotes formatpainter inlinecss mergetags pageembed permanentpen powerpaste autocorrect tableofcontents accordion advlist anchor autolink autoresize autosave charmap code codesample directionality emoticons fullscreen help image importcss insertdatetime link lists media nonbreaking pagebreak preview quickbars save searchreplace table template visualblocks visualchars wordcount".split(
|
||||||
|
" ",
|
||||||
|
);
|
||||||
|
const reducer = (pv, cv) => {
|
||||||
|
return { ...pv, [cv]: `plugins/${cv}/plugin.min.js` };
|
||||||
|
};
|
||||||
|
|
||||||
|
const external_plugins = plugins.reduce((pv, cv) => {
|
||||||
|
return { ...pv, [cv]: `plugins/${cv}/plugin.min.js` };
|
||||||
|
}, {});
|
||||||
|
const base_url = "/tinymce";
|
||||||
export const fancy = {
|
export const fancy = {
|
||||||
branding: false,
|
branding: false,
|
||||||
selector: "textarea#txt",
|
base_url,
|
||||||
menubar: false,
|
menubar: false,
|
||||||
elementpath: false,
|
elementpath: false,
|
||||||
formats: {
|
formats: {
|
||||||
@ -31,12 +43,12 @@ export const fancy = {
|
|||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
title: "Image Left",
|
title: "Image Left",
|
||||||
selector: "img",
|
|
||||||
styles: { float: "left", margin: "0 10px 0 10px" },
|
styles: { float: "left", margin: "0 10px 0 10px" },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Image Right",
|
title: "Image Right",
|
||||||
selector: "img",
|
|
||||||
styles: { float: "right", margin: "0 0 10px 10px" },
|
styles: { float: "right", margin: "0 0 10px 10px" },
|
||||||
},
|
},
|
||||||
{ title: "Rounded corners", styles: { "border-radius": "0.7em" } },
|
{ title: "Rounded corners", styles: { "border-radius": "0.7em" } },
|
||||||
@ -44,7 +56,7 @@ export const fancy = {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Code/Monospace",
|
title: "Code/Monospace",
|
||||||
selector: "p,div,h1,h2,h3,h4,h5,h6",
|
|
||||||
classes: ["font-mono"],
|
classes: ["font-mono"],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -62,16 +74,11 @@ export const fancy = {
|
|||||||
},
|
},
|
||||||
toolbar: "undo redo | paste | bold italic underline | hr image link | forecolor styles | heading alignment | code",
|
toolbar: "undo redo | paste | bold italic underline | hr image link | forecolor styles | heading alignment | code",
|
||||||
contextmenu: "bold italic underline | hr | link | image | paste",
|
contextmenu: "bold italic underline | hr | link | image | paste",
|
||||||
external_plugins: {
|
external_plugins,
|
||||||
mentions: "/plugins/mentions/plugin.min.js",
|
|
||||||
},
|
|
||||||
plugins:
|
|
||||||
`advlist autolink lists link image charmap preview anchor searchreplace visualblocks advcode fullscreen insertdatetime media table help wordcount save mentions`.split(
|
|
||||||
" ",
|
|
||||||
),
|
|
||||||
};
|
};
|
||||||
export const comment = {
|
export const comment = {
|
||||||
branding: false,
|
branding: false,
|
||||||
|
base_url,
|
||||||
height: 200,
|
height: 200,
|
||||||
menubar: false,
|
menubar: false,
|
||||||
elementpath: false,
|
elementpath: false,
|
||||||
@ -86,21 +93,15 @@ export const comment = {
|
|||||||
inline: "u",
|
inline: "u",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
external_plugins: {
|
|
||||||
mentions: "/plugins/mentions/plugin.min.js",
|
|
||||||
},
|
|
||||||
schema: "html5",
|
schema: "html5",
|
||||||
plugins:
|
external_plugins,
|
||||||
`advlist autolink lists link image charmap preview anchor searchreplace visualblocks code fullscreen insertdatetime media table code help save mentions`.split(
|
|
||||||
" ",
|
|
||||||
),
|
|
||||||
toolbar: "bold italic underline | link",
|
toolbar: "bold italic underline | link",
|
||||||
contextmenu: "bold italic underline | paste | link",
|
contextmenu: "bold italic underline | paste | link",
|
||||||
};
|
};
|
||||||
|
|
||||||
export const story = {
|
export const story = {
|
||||||
|
base_url,
|
||||||
branding: false,
|
branding: false,
|
||||||
selector: "textarea#txt",
|
|
||||||
height: 500,
|
height: 500,
|
||||||
menubar: false,
|
menubar: false,
|
||||||
elementpath: false,
|
elementpath: false,
|
||||||
@ -117,14 +118,12 @@ export const story = {
|
|||||||
},
|
},
|
||||||
content_css: ["/test.css", "/quickfix.css"],
|
content_css: ["/test.css", "/quickfix.css"],
|
||||||
schema: "html5",
|
schema: "html5",
|
||||||
plugins:
|
external_plugins,
|
||||||
`advlist autolink lists link image charmap preview anchor searchreplace visualblocks code fullscreen insertdatetime media table advcode help wordcount save`.split(
|
|
||||||
" ",
|
|
||||||
),
|
|
||||||
toolbar: "undo redo | paste |" + "bold italic underline | hr | alignleft aligncenter " + "alignright alignjustify | " + "| code",
|
toolbar: "undo redo | paste |" + "bold italic underline | hr | alignleft aligncenter " + "alignright alignjustify | " + "| code",
|
||||||
contextmenu: "bold italic underline | hr | paste | link",
|
contextmenu: "bold italic underline | hr | paste | link",
|
||||||
};
|
};
|
||||||
export const bare = {
|
export const bare = {
|
||||||
|
base_url,
|
||||||
branding: false,
|
branding: false,
|
||||||
height: 200,
|
height: 200,
|
||||||
menubar: false,
|
menubar: false,
|
||||||
@ -141,13 +140,7 @@ export const bare = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
schema: "html5",
|
schema: "html5",
|
||||||
external_plugins: {
|
external_plugins,
|
||||||
mentions: "/plugins/mentions/plugin.min.js",
|
|
||||||
},
|
|
||||||
plugins:
|
|
||||||
`advlist autolink lists link image charmap preview anchor searchreplace visualblocks code fullscreen insertdatetime media table advcode help save mentions`.split(
|
|
||||||
" ",
|
|
||||||
),
|
|
||||||
toolbar: "bold italic underline | hr link",
|
toolbar: "bold italic underline | hr link",
|
||||||
contextmenu: "bold italic underline | paste | hr link",
|
contextmenu: "bold italic underline | paste | hr link",
|
||||||
};
|
};
|
||||||
|
@ -26,8 +26,7 @@ export const storyMiddleware = defineNuxtRouteMiddleware(async (to, from) => {
|
|||||||
|
|
||||||
export const storyEditMiddleware = defineNuxtRouteMiddleware(async (to, from) => {
|
export const storyEditMiddleware = defineNuxtRouteMiddleware(async (to, from) => {
|
||||||
const { data: curU } = useAuth();
|
const { data: curU } = useAuth();
|
||||||
const rtr = useRoute();
|
const { data: storyInfo } = await useApiFetch<({ chapters: (IChapter & { text: string })[] } & IStory) | null>(`/story/${to.params.id}/full`);
|
||||||
const { data: storyInfo } = await useApiFetch<({ chapters: (IChapter & { text: string })[] } & IStory) | null>(`/story/${rtr.params.id}/full`);
|
|
||||||
if (!storyInfo.value) show404();
|
if (!storyInfo.value) show404();
|
||||||
if (curU.value?.user?._id !== (storyInfo.value?.author as IUser)._id && curU.value?.user?._id !== (storyInfo.value?.coAuthor as IUser)?._id) {
|
if (curU.value?.user?._id !== (storyInfo.value?.author as IUser)._id && curU.value?.user?._id !== (storyInfo.value?.coAuthor as IUser)?._id) {
|
||||||
return showError({
|
return showError({
|
||||||
@ -38,8 +37,7 @@ export const storyEditMiddleware = defineNuxtRouteMiddleware(async (to, from) =>
|
|||||||
});
|
});
|
||||||
export const draftEditMiddleware = defineNuxtRouteMiddleware(async (to, from) => {
|
export const draftEditMiddleware = defineNuxtRouteMiddleware(async (to, from) => {
|
||||||
const { data: curU } = useAuth();
|
const { data: curU } = useAuth();
|
||||||
const rtr = useRoute();
|
const { data: storyInfo } = await useApiFetch<IDraft | null>(`/draft/${to.params.id}`);
|
||||||
const { data: storyInfo } = await useApiFetch<IDraft | null>(`/draft/${rtr.params.id}`);
|
|
||||||
if (!storyInfo.value) show404();
|
if (!storyInfo.value) show404();
|
||||||
if (curU.value?.user?._id !== (storyInfo.value?.author as IUser)._id && curU.value?.user?._id !== (storyInfo.value?.coAuthor as IUser)?._id) {
|
if (curU.value?.user?._id !== (storyInfo.value?.author as IUser)._id && curU.value?.user?._id !== (storyInfo.value?.coAuthor as IUser)?._id) {
|
||||||
return showError({
|
return showError({
|
||||||
|
@ -1,16 +1,13 @@
|
|||||||
import { resolve } from "path";
|
|
||||||
import * as dotenv from "dotenv";
|
|
||||||
import mongoose from "mongoose";
|
import mongoose from "mongoose";
|
||||||
const FUCKYOU = "/rockfic/abc-rockfic-v3";
|
const FUCKYOU = "/rockfic/abc-rockfic-v3";
|
||||||
dotenv.config({ path: resolve("/home/rockfic/rockfic-staging/.env") });
|
// dotenv.config({ path: resolve("/home/rockfic/rockfic-staging/.env") });
|
||||||
export const hasMigrated = false;
|
export const hasMigrated = true;
|
||||||
console.log("indbconfig");
|
|
||||||
export const uri =
|
export const uri =
|
||||||
process.env.NODE_ENV === "production"
|
process.env.NODE_ENV === "production" && !process.env.TEST
|
||||||
? `mongodb://${process.env.DBUSER}:${process.env.DBPASS}@${process.env.DB}?authSource=admin`
|
? `mongodb://${process.env.DBUSER}:${process.env.DBPASS}@${process.env.DB}?authSource=admin`
|
||||||
: `mongodb://127.0.0.1/${process.env.DBNAME}?authSource=admin`;
|
: `mongodb://127.0.0.1/${process.env.DBNAME}`;
|
||||||
export const olduri =
|
export const olduri =
|
||||||
process.env.NODE_ENV === "production"
|
process.env.NODE_ENV === "production" && !process.env.TEST
|
||||||
? `mongodb://${process.env.DBUSER}:${process.env.DBPASS}@127.0.0.1:27017/rockfic_old?authSource=admin`
|
? `mongodb://${process.env.DBUSER}:${process.env.DBPASS}@127.0.0.1:27017/rockfic_old?authSource=admin`
|
||||||
: `mongodb://127.0.0.1/rockfic_old?authSource=admin`;
|
: `mongodb://127.0.0.1/rockfic_old?authSource=admin`;
|
||||||
|
|
||||||
|
128
lib/testing/helpers.ts
Normal file
128
lib/testing/helpers.ts
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
import { Page } from "playwright-core";
|
||||||
|
import { randomBytes } from "crypto";
|
||||||
|
import { resolve, join } from "path";
|
||||||
|
import { fireEvent } from "@testing-library/vue";
|
||||||
|
|
||||||
|
const sampleFiles = ["smut.md", "smut-2.md", "somno.md"];
|
||||||
|
|
||||||
|
export function rand(min: number, max: number) {
|
||||||
|
return Math.floor(Math.random() * (max - min + 1)) + min;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fillCharacters(page: Page, fieldId: string, count: number) {
|
||||||
|
const el = page.getByTestId(fieldId);
|
||||||
|
const inp = el.locator("input");
|
||||||
|
await inp.focus();
|
||||||
|
let existingIndices: number[] = [];
|
||||||
|
|
||||||
|
while (existingIndices.length <= count) {
|
||||||
|
let downPresses = rand(1, 4);
|
||||||
|
if (existingIndices.includes(downPresses)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
existingIndices.push(downPresses);
|
||||||
|
}
|
||||||
|
for (let k = 0; k < existingIndices.length; k++) {
|
||||||
|
await inp.focus();
|
||||||
|
await inp.press("ArrowDown");
|
||||||
|
for (let l = 0; l < existingIndices[k]; l++) {
|
||||||
|
await inp.press("ArrowDown");
|
||||||
|
}
|
||||||
|
await inp.press("Escape");
|
||||||
|
}
|
||||||
|
await inp.press("Enter");
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fillRelationships(page: Page, id: string) {
|
||||||
|
const add = page.getByTestId(`${id}.form.relationships.add`);
|
||||||
|
for (let i = 0; i < rand(1, 3); i++) {
|
||||||
|
await add.click();
|
||||||
|
|
||||||
|
const pairingMembers = rand(2, 3);
|
||||||
|
|
||||||
|
await fillCharacters(page, `${id}.form.relationships.${i}`, pairingMembers);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function uploadOrPaste(page: Page, selector: string, index: number) {
|
||||||
|
const uop = rand(1, 2) == 1;
|
||||||
|
const innerSel = `${selector}.form.uploadOrPaste`;
|
||||||
|
if (uop) {
|
||||||
|
const fileChoosePromise = page.waitForEvent("filechooser");
|
||||||
|
const el = page.getByTestId(`${innerSel}.radio.upload`);
|
||||||
|
await el.click();
|
||||||
|
const ubtn = page.getByTestId(`${innerSel}.upload`);
|
||||||
|
await ubtn.click();
|
||||||
|
const fc = await fileChoosePromise;
|
||||||
|
await fc.setFiles(join(resolve(import.meta.dirname, "../../tests/inputFiles"), sampleFiles[rand(0, 2)]));
|
||||||
|
} else {
|
||||||
|
const el = page.getByTestId(`${innerSel}.radio.pasteOrType`);
|
||||||
|
await el.click();
|
||||||
|
const content = page.getByTestId(`${innerSel}.type`).frameLocator("iframe").locator("[contenteditable]");
|
||||||
|
await content.pressSequentially(
|
||||||
|
randomBytes(148)
|
||||||
|
.toString("base64")
|
||||||
|
.match(/.{1,2}/g)!
|
||||||
|
.join(" "),
|
||||||
|
);
|
||||||
|
await content.focus();
|
||||||
|
await content.press("Enter");
|
||||||
|
await content.press("Enter");
|
||||||
|
await content.pressSequentially(`--- end of chapter ${index + 1} ---`.toLocaleUpperCase());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function partialChapter(page: Page, i: number) {
|
||||||
|
const b = `storyform.chapters[${i}]`;
|
||||||
|
const collapse = page.getByTestId(`${b}.collapse`);
|
||||||
|
await collapse.click();
|
||||||
|
await page.waitForTimeout(3000);
|
||||||
|
const inp = page.getByTestId(`${b}.form.title`);
|
||||||
|
const summary = page.getByTestId(`${b}.form.summary`).frameLocator("iframe").locator("[contenteditable]");
|
||||||
|
const notes = page.getByTestId(`${b}.form.notes`).frameLocator("iframe").locator("[contenteditable]");
|
||||||
|
|
||||||
|
await inp.pressSequentially(`~ ${i + 1} ~`);
|
||||||
|
await summary.press("Control+A");
|
||||||
|
await summary.press("Backspace");
|
||||||
|
await summary.pressSequentially(
|
||||||
|
randomBytes(25)
|
||||||
|
.toString("hex")
|
||||||
|
.match(/.{1,2}/g)!
|
||||||
|
.join(" "),
|
||||||
|
);
|
||||||
|
await notes.pressSequentially("these are some notes. Brian Tatler fucked and abused Sean Harris!");
|
||||||
|
await notes.focus();
|
||||||
|
await notes.press("Enter");
|
||||||
|
await notes.press("Enter");
|
||||||
|
await notes.pressSequentially("0x" + i.toString(16));
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function fillChapter(page: Page, i: number) {
|
||||||
|
const b = `storyform.chapters[${i}]`;
|
||||||
|
const nsfwBool = rand(1, 2) == 2;
|
||||||
|
|
||||||
|
const bands = page.getByTestId(`${b}.form.bands`);
|
||||||
|
const bandInput = bands.locator("input");
|
||||||
|
const genre = page.getByTestId(`${b}.form.genre`);
|
||||||
|
const genreInput = genre.locator("input");
|
||||||
|
|
||||||
|
await partialChapter(page, i);
|
||||||
|
await bandInput.pressSequentially("Diamond Head");
|
||||||
|
await bandInput.press("Enter");
|
||||||
|
await bandInput.press("Escape");
|
||||||
|
await fillCharacters(page, `${b}.form.characters`, rand(2, 4));
|
||||||
|
await fillRelationships(page, b);
|
||||||
|
const nsfw = page.getByTestId(`${b}.form.nsfw`);
|
||||||
|
nsfwBool && (await nsfw.click());
|
||||||
|
nsfwBool && (await page.getByTestId(`${b}.form.loggedInOnly`).click());
|
||||||
|
await genreInput.focus();
|
||||||
|
await genreInput.pressSequentially("S");
|
||||||
|
await genreInput.press("Enter");
|
||||||
|
await uploadOrPaste(page, b, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function collapseSidebar(page: Page) {
|
||||||
|
await page.locator(".ant-layout-sider-zero-width-trigger").click();
|
||||||
|
}
|
||||||
|
|
||||||
|
// vue stuff
|
@ -25,6 +25,7 @@
|
|||||||
"@sidebase/nuxt-auth": "0.6.0-beta.6",
|
"@sidebase/nuxt-auth": "0.6.0-beta.6",
|
||||||
"@tinymce/tinymce-vue": "^5.1.1",
|
"@tinymce/tinymce-vue": "^5.1.1",
|
||||||
"@types/jsonwebtoken": "^9.0.3",
|
"@types/jsonwebtoken": "^9.0.3",
|
||||||
|
"@types/lodash-es": "^4.17.12",
|
||||||
"@types/turndown": "^5.0.4",
|
"@types/turndown": "^5.0.4",
|
||||||
"@vueuse/core": "^10.4.1",
|
"@vueuse/core": "^10.4.1",
|
||||||
"@vueuse/nuxt": "^10.4.1",
|
"@vueuse/nuxt": "^10.4.1",
|
||||||
@ -41,17 +42,19 @@
|
|||||||
"mongodb": "^6.1.0",
|
"mongodb": "^6.1.0",
|
||||||
"mongoose": "^8.0.2",
|
"mongoose": "^8.0.2",
|
||||||
"mongoose-sequence": "https://github.com/amansingh63/mongoose-sequence",
|
"mongoose-sequence": "https://github.com/amansingh63/mongoose-sequence",
|
||||||
|
"nitropack": "^2.9.4",
|
||||||
|
"nuxi": "^3.10.0",
|
||||||
"nuxt-security": "^0.14.4",
|
"nuxt-security": "^0.14.4",
|
||||||
"nuxt-speedkit": "3.0.0-next.26",
|
"nuxt-speedkit": "3.0.0-next.26",
|
||||||
"pinia": "^2.1.6",
|
"pinia": "^2.1.6",
|
||||||
"sanitize-html": "^2.11.0",
|
"sanitize-html": "^2.11.0",
|
||||||
"sharp": "^0.33.1",
|
"sharp": "^0.33.2",
|
||||||
"string-strip-html": "^13.4.3",
|
"string-strip-html": "^13.4.3",
|
||||||
"tinymce": "^6.7.0",
|
"tinymce": "^6.7.0",
|
||||||
"turndown": "^7.1.2",
|
"turndown": "^7.1.2",
|
||||||
"uuid": "^9.0.1",
|
"uuid": "^9.0.1",
|
||||||
"vee-validate": "^4.11.7",
|
"vee-validate": "^4.11.7",
|
||||||
"vue": "^3.4.4",
|
"vue": "^3.4.21",
|
||||||
"vue-dndrop": "^1.3.1",
|
"vue-dndrop": "^1.3.1",
|
||||||
"vue-recaptcha": "3.0.0-alpha.6",
|
"vue-recaptcha": "3.0.0-alpha.6",
|
||||||
"vuedraggable": "^4.1.0",
|
"vuedraggable": "^4.1.0",
|
||||||
|
@ -2,6 +2,9 @@
|
|||||||
import storyForm from "~/components/story/create/storyForm.vue";
|
import storyForm from "~/components/story/create/storyForm.vue";
|
||||||
import { defaultStory } from "@client/types/form/story";
|
import { defaultStory } from "@client/types/form/story";
|
||||||
const ds = ref(defaultStory);
|
const ds = ref(defaultStory);
|
||||||
|
const { getSession } = useAuth();
|
||||||
|
await getSession({ force: true });
|
||||||
|
|
||||||
definePageMeta({
|
definePageMeta({
|
||||||
middleware: ["auth"],
|
middleware: ["auth"],
|
||||||
});
|
});
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit bffc9f1f85710ea8c62151770f0ef58e51692826
|
Subproject commit bcdaae9743a62dc4172a117471bd3a49462d90be
|
@ -7,9 +7,9 @@ export default eventHandler(async (event) => {
|
|||||||
const wrongMsg = "wrong credentials";
|
const wrongMsg = "wrong credentials";
|
||||||
let reqbody = await readBody(event);
|
let reqbody = await readBody(event);
|
||||||
let user = await User.findOne({ username: reqbody.username }).exec();
|
let user = await User.findOne({ username: reqbody.username }).exec();
|
||||||
log.debug(reqbody, { label: "login/body" });
|
// log.debug(reqbody, { label: "login/body" });
|
||||||
log.debug("USER -> " + user, { label: "login" });
|
// log.debug("USER -> " + user, { label: "login" });
|
||||||
log.debug("conn ->" + mongoose.connection, { label: "login" });
|
// log.debug("conn ->" + mongoose.connection, { label: "login" });
|
||||||
let cok = getHeader(event, "Authorization")?.replace("Bearer ", "");
|
let cok = getHeader(event, "Authorization")?.replace("Bearer ", "");
|
||||||
if (!cok) {
|
if (!cok) {
|
||||||
if (!user) {
|
if (!user) {
|
||||||
|
Loading…
Reference in New Issue
Block a user