style(*): cleanup unused imports
This commit is contained in:
parent
5baa00bbb4
commit
c8e84c909e
@ -3,6 +3,5 @@
|
||||
"useTabs": true,
|
||||
"trailingComma": "all",
|
||||
"arrowParens": "always",
|
||||
"vueIndentScriptAndStyle": true,
|
||||
"editorconfig": true
|
||||
"vueIndentScriptAndStyle": true
|
||||
}
|
||||
|
8
app.vue
8
app.vue
@ -1,14 +1,11 @@
|
||||
<script lang="ts" setup>
|
||||
import { theme } from "ant-design-vue";
|
||||
|
||||
const { getSession, signIn } = useAuth();
|
||||
|
||||
await getSession({ force: true });
|
||||
|
||||
const { data } = await useAuth();
|
||||
|
||||
const dop = data?.value as any;
|
||||
let darkBool = ref(dop?.user?.profile?.nightMode || false);
|
||||
let darkBool = ref(data.value?.user?.profile?.nightMode || false);
|
||||
// provide("user", ref(dop?.user || null));
|
||||
provide("dark", darkBool);
|
||||
useHead({
|
||||
@ -17,8 +14,7 @@
|
||||
return darkBool.value ? "dark" : undefined;
|
||||
}).value,
|
||||
},
|
||||
titleTemplate: (title) =>
|
||||
title ? `Rockfic | ${title}` : "Rockfic | Band fiction that rocks",
|
||||
titleTemplate: (title) => (title ? `Rockfic | ${title}` : "Rockfic | Band fiction that rocks"),
|
||||
});
|
||||
// provide("loaded", useNuxtApp().$loaded);
|
||||
// let loaded = ref<boolean[]>([]);
|
||||
|
@ -1,9 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import TinymceEditor from "@tinymce/tinymce-vue";
|
||||
import { useDark } from "@vueuse/core";
|
||||
import { NamePath } from "ant-design-vue/es/form/interface";
|
||||
import { Field as VeeField } from "vee-validate";
|
||||
import tinymce from "tinymce";
|
||||
|
||||
const props = defineProps<{
|
||||
name: string;
|
||||
init: any;
|
||||
@ -16,17 +14,8 @@
|
||||
</script>
|
||||
<template>
|
||||
<ClientOnly>
|
||||
<vee-field
|
||||
:name="props.name"
|
||||
v-slot="{ errorMessage, field, value }"
|
||||
:model-value="props.val"
|
||||
>
|
||||
<a-form-item
|
||||
:validate-status="!!errorMessage ? 'error' : ''"
|
||||
:name="props.name"
|
||||
:label="props.label as any"
|
||||
:help="errorMessage"
|
||||
>
|
||||
<vee-field :name="props.name" v-slot="{ errorMessage, field, value }" :model-value="props.val">
|
||||
<a-form-item :validate-status="!!errorMessage ? 'error' : ''" :name="props.name" :label="props.label as any" :help="errorMessage">
|
||||
<tinymce-editor
|
||||
v-bind="field"
|
||||
width="100%"
|
||||
|
@ -1,7 +1,4 @@
|
||||
<script lang="ts" setup>
|
||||
import { log } from "@server/logger";
|
||||
import { MenuProps } from "ant-design-vue";
|
||||
|
||||
const { data, status } = useAuth();
|
||||
const itemMap = ref({
|
||||
home: "/",
|
||||
@ -18,11 +15,7 @@
|
||||
admin: "/admin",
|
||||
logout: "/auth/logout",
|
||||
});
|
||||
let cur = ref<string>(
|
||||
Object.keys(itemMap.value).find(
|
||||
(a) => itemMap.value[a] === useRoute().path,
|
||||
) || useRoute().path,
|
||||
);
|
||||
let cur = ref<string>(Object.keys(itemMap.value).find((a) => itemMap.value[a] === useRoute().path) || useRoute().path);
|
||||
let selected: string[] = [cur.value];
|
||||
|
||||
const clickFn = (minfo) => {
|
||||
@ -61,18 +54,11 @@
|
||||
<a-menu-item key="reviews"> Manage Reviews </a-menu-item>
|
||||
<a-menu-item key="messages"> Private Messages </a-menu-item>
|
||||
</a-sub-menu>
|
||||
<a-menu-item key="admin" v-if="data?.user?.profile.isAdmin || false">
|
||||
Admin
|
||||
</a-menu-item>
|
||||
<a-menu-item key="admin" v-if="data?.user?.profile.isAdmin || false"> Admin </a-menu-item>
|
||||
<a-menu-item key="logout" v-if="!!data?.user"> Logout </a-menu-item>
|
||||
</a-menu>
|
||||
<div>
|
||||
<a-button
|
||||
v-if="data?.user"
|
||||
type="primary"
|
||||
tooltip="Post a New Story"
|
||||
@click="() => navigateTo('/new-story')"
|
||||
>
|
||||
<a-button v-if="data?.user" type="primary" tooltip="Post a New Story" @click="() => navigateTo('/new-story')">
|
||||
<!-- <template #icon>
|
||||
</template> -->
|
||||
<icon istyle="regular" name="file-plus" />
|
||||
@ -80,16 +66,8 @@
|
||||
</a-button>
|
||||
</div>
|
||||
<div class="acbut" v-if="!data">
|
||||
<a-button size="large" @click="() => navigateTo('/auth/login')">
|
||||
Login
|
||||
</a-button>
|
||||
<a-button
|
||||
size="large"
|
||||
type="primary"
|
||||
@click="() => navigateTo('/auth/register')"
|
||||
>
|
||||
Register
|
||||
</a-button>
|
||||
<a-button size="large" @click="() => navigateTo('/auth/login')"> Login </a-button>
|
||||
<a-button size="large" type="primary" @click="() => navigateTo('/auth/register')"> Register </a-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -1,12 +1,9 @@
|
||||
<script setup lang="ts">
|
||||
import type {
|
||||
MenuItemType,
|
||||
SubMenuType,
|
||||
} from "ant-design-vue/es/menu/src/interface";
|
||||
import type { MenuItemType, SubMenuType } from "ant-design-vue/es/menu/src/interface";
|
||||
import { ItemType, theme } from "ant-design-vue";
|
||||
import Icon from "../icon.vue";
|
||||
import { ISidebarItem } from "@models/sidebarEntry";
|
||||
import { AButton, NuxtLink } from "#components";
|
||||
import { NuxtLink } from "#components";
|
||||
|
||||
const loaded = inject<Ref<boolean>>("loaded");
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
<script lang="ts" setup>
|
||||
import type { IStory } from "@models/stories";
|
||||
import { log } from "~/lib/server/logger";
|
||||
import { format } from "date-fns";
|
||||
import icon from "../icon.vue";
|
||||
import { theme } from "ant-design-vue";
|
||||
@ -14,18 +13,8 @@
|
||||
const idxo = (prop.last || false ? prop.story.chapters.length : 1) - 1;
|
||||
// console.log("idx0->", idxo)
|
||||
// log.debug("posti->", prop.story.chapters[ prop.story.chapters.length - 1 ]);
|
||||
const shortDate = format(
|
||||
Date.parse(
|
||||
prop.story.chapters[prop.story.chapters.length - 1]?.posted!.toString(),
|
||||
),
|
||||
"yyyy/MM/dd",
|
||||
);
|
||||
const longDate = format(
|
||||
Date.parse(
|
||||
prop.story.chapters[prop.story.chapters.length - 1]?.posted!.toString(),
|
||||
),
|
||||
"iiii',' yyyy-MM-dd",
|
||||
);
|
||||
const shortDate = format(Date.parse(prop.story.chapters[prop.story.chapters.length - 1]?.posted!.toString()), "yyyy/MM/dd");
|
||||
const longDate = format(Date.parse(prop.story.chapters[prop.story.chapters.length - 1]?.posted!.toString()), "iiii',' yyyy-MM-dd");
|
||||
</script>
|
||||
<template>
|
||||
<a-card>
|
||||
@ -36,26 +25,16 @@
|
||||
{{ story.title }}
|
||||
</NuxtLink>
|
||||
<a-tooltip placement="topLeft">
|
||||
<template #title>
|
||||
You'll need to log in to read this story. Register if you don't
|
||||
already have an account -- it's free!
|
||||
</template>
|
||||
<template #title> You'll need to log in to read this story. Register if you don't already have an account -- it's free! </template>
|
||||
<icon v-if="!data?.user" istyle="solid" name="lock" />
|
||||
</a-tooltip>
|
||||
</div>
|
||||
|
||||
<div
|
||||
style="display: flex; font-size: 0.9em; align-items: baseline"
|
||||
class="headerthing"
|
||||
>
|
||||
<div style="display: flex; font-size: 0.9em; align-items: baseline" class="headerthing">
|
||||
<span> a </span>
|
||||
<div
|
||||
style=""
|
||||
v-for="(band, idx) in story.chapters[idxo].bands.filter((a) => !!a)"
|
||||
>
|
||||
<div style="" v-for="(band, idx) in story.chapters[idxo].bands.filter((a) => !!a)">
|
||||
<span>
|
||||
<NuxtLink :to="`/band/${band._id}`"> {{ band.name }} </NuxtLink
|
||||
>{{ idx < story.chapters[idxo].bands.length - 1 ? ", " : "" }}
|
||||
<NuxtLink :to="`/band/${band._id}`"> {{ band.name }} </NuxtLink>{{ idx < story.chapters[idxo].bands.length - 1 ? ", " : "" }}
|
||||
</span>
|
||||
</div>
|
||||
<span> fic by </span>
|
||||
@ -100,9 +79,7 @@
|
||||
<div class="storyMeta">
|
||||
<div class="inner">
|
||||
<span v-if="story.chapters.length > 1">
|
||||
<NuxtLink :to="`/story/${story._id}/chapters`">
|
||||
{{ story.chapters.length }} chapters
|
||||
</NuxtLink>
|
||||
<NuxtLink :to="`/story/${story._id}/chapters`"> {{ story.chapters.length }} chapters </NuxtLink>
|
||||
</span>
|
||||
<span v-else> {{ story.chapters.length }} chapter </span>
|
||||
<span>
|
||||
@ -121,15 +98,10 @@
|
||||
{{ story.chapters[idxo].characters.join(", ") }}
|
||||
</meta-item>
|
||||
<meta-item label="Relationship(s)">
|
||||
<div
|
||||
style="display: inline-block"
|
||||
v-for="(rel, idx) in story.chapters[idxo].relationships"
|
||||
>
|
||||
<div style="display: inline-block" v-for="(rel, idx) in story.chapters[idxo].relationships">
|
||||
<span>
|
||||
{{ Array.isArray(rel) ? rel.join("/") : rel }}
|
||||
{{
|
||||
idx < story.chapters[idxo].relationships.length - 1 ? "," : ""
|
||||
}}
|
||||
{{ idx < story.chapters[idxo].relationships.length - 1 ? "," : "" }}
|
||||
</span>
|
||||
</div>
|
||||
<span v-if="story.chapters[idxo].relationships.length < 1">
|
||||
@ -149,12 +121,7 @@
|
||||
<div class="stats">
|
||||
<span>
|
||||
<span class="staticon">
|
||||
<icon
|
||||
:istyle="!dark ? 'solid' : 'regular'"
|
||||
icolor="#ff2883"
|
||||
:size="12"
|
||||
name="heart"
|
||||
/>
|
||||
<icon :istyle="!dark ? 'solid' : 'regular'" icolor="#ff2883" :size="12" name="heart" />
|
||||
</span>
|
||||
<span>
|
||||
{{ story.favs }}
|
||||
@ -162,12 +129,7 @@
|
||||
</span>
|
||||
<span>
|
||||
<span class="staticon">
|
||||
<icon
|
||||
:istyle="!dark ? 'solid' : 'regular'"
|
||||
icolor="#1787d7"
|
||||
:size="12"
|
||||
name="book-open"
|
||||
/>
|
||||
<icon :istyle="!dark ? 'solid' : 'regular'" icolor="#1787d7" :size="12" name="book-open" />
|
||||
</span>
|
||||
<span>
|
||||
{{ story.views }}
|
||||
@ -175,12 +137,7 @@
|
||||
</span>
|
||||
<span>
|
||||
<span class="staticon">
|
||||
<icon
|
||||
:istyle="!dark ? 'solid' : 'regular'"
|
||||
icolor="#51e07c"
|
||||
:size="12"
|
||||
name="thumbs-up"
|
||||
/>
|
||||
<icon :istyle="!dark ? 'solid' : 'regular'" icolor="#51e07c" :size="12" name="thumbs-up" />
|
||||
</span>
|
||||
<span>
|
||||
{{ story.recs }}
|
||||
@ -188,12 +145,7 @@
|
||||
</span>
|
||||
<span>
|
||||
<span class="staticon">
|
||||
<icon
|
||||
:istyle="!dark ? 'solid' : 'regular'"
|
||||
icolor="#c2d420"
|
||||
:size="12"
|
||||
name="download"
|
||||
/>
|
||||
<icon :istyle="!dark ? 'solid' : 'regular'" icolor="#c2d420" :size="12" name="download" />
|
||||
</span>
|
||||
<span>
|
||||
{{ story.downloads }}
|
||||
|
@ -1,5 +1,5 @@
|
||||
<script lang="ts" setup>
|
||||
import { Form as veeForm, Field as veeField, useForm } from "vee-validate";
|
||||
import { Form as veeForm, Field as veeField } from "vee-validate";
|
||||
import { IReview } from "@models/stories/review";
|
||||
import { comment } from "@client/editorConfig";
|
||||
import { SingleChapterResult } from "@client/types/slightlyDifferentStory";
|
||||
@ -25,13 +25,10 @@
|
||||
};
|
||||
|
||||
const replySubmit = async (values) => {
|
||||
const { data } = await useApiFetch<any>(
|
||||
`/review/${props.review._id}/reply`,
|
||||
{
|
||||
const { data } = await useApiFetch<any>(`/review/${props.review._id}/reply`, {
|
||||
method: "post",
|
||||
body: values,
|
||||
},
|
||||
);
|
||||
});
|
||||
review.value.replies.push(data.value.data);
|
||||
replyFormVisible.value = false;
|
||||
};
|
||||
@ -49,12 +46,7 @@
|
||||
<a-comment>
|
||||
<template #actions>
|
||||
<div v-if="!!data?.user" class="review-actions">
|
||||
<a-button
|
||||
v-if="isCommentAuthor"
|
||||
@click="() => (isEditing = !isEditing)"
|
||||
>
|
||||
Edit
|
||||
</a-button>
|
||||
<a-button v-if="isCommentAuthor" @click="() => (isEditing = !isEditing)"> Edit </a-button>
|
||||
<a-popconfirm
|
||||
title="Are you sure you want to permanently delete this review?"
|
||||
ok-text="Yes"
|
||||
@ -64,13 +56,7 @@
|
||||
>
|
||||
<a-button> Delete </a-button>
|
||||
</a-popconfirm>
|
||||
<a-button
|
||||
v-if="isAuthor"
|
||||
type="primary"
|
||||
@click="() => (replyFormVisible = !replyFormVisible)"
|
||||
>
|
||||
Reply
|
||||
</a-button>
|
||||
<a-button v-if="isAuthor" type="primary" @click="() => (replyFormVisible = !replyFormVisible)"> Reply </a-button>
|
||||
</div>
|
||||
</template>
|
||||
<template #author>
|
||||
@ -91,25 +77,14 @@
|
||||
<div>
|
||||
<vee-form @submit="editSubmit" v-if="isEditing">
|
||||
<vee-field name="content" v-slot="{ value, field, errorMessage }">
|
||||
<base-editor
|
||||
:val="review.text"
|
||||
:width="150"
|
||||
label=""
|
||||
:name="field.name"
|
||||
:init="comment"
|
||||
/>
|
||||
<base-editor :val="review.text" :width="150" label="" :name="field.name" :init="comment" />
|
||||
</vee-field>
|
||||
<a-button type="primary" html-type="submit"> Edit review </a-button>
|
||||
</vee-form>
|
||||
<div v-else v-html="review.text" />
|
||||
<vee-form @submit="replySubmit" v-if="replyFormVisible">
|
||||
<vee-field name="content" v-slot="{ value, field, errorMessage }">
|
||||
<base-editor
|
||||
:width="150"
|
||||
label=""
|
||||
:name="field.name"
|
||||
:init="comment"
|
||||
/>
|
||||
<base-editor :width="150" label="" :name="field.name" :init="comment" />
|
||||
</vee-field>
|
||||
<a-button type="primary" html-type="submit"> Post response </a-button>
|
||||
</vee-form>
|
||||
|
@ -3,9 +3,6 @@
|
||||
import { RuleExpression, useField } from "vee-validate";
|
||||
import { cs } from "@client/storyFormSchema";
|
||||
import { IBand } from "@models/band";
|
||||
import { log } from "@server/logger";
|
||||
|
||||
import iconEl from "../icon.vue";
|
||||
|
||||
const bandlist = inject<IBand[]>("bandlist");
|
||||
const fname = inject<string>("curName");
|
||||
@ -19,20 +16,13 @@
|
||||
label: a.name,
|
||||
disabled: a.locked || false,
|
||||
}));
|
||||
let bandField = useField(
|
||||
fname + "bands",
|
||||
cs.fields.bands as unknown as MaybeRef<RuleExpression<number[]>>,
|
||||
);
|
||||
let bandField = useField(fname + "bands", cs.fields.bands as unknown as MaybeRef<RuleExpression<number[]>>);
|
||||
const { value, errorMessage, name, setValue } = bandField;
|
||||
// setValue(sb)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a-form-item
|
||||
:validate-status="!!errorMessage ? 'error' : undefined"
|
||||
:help="errorMessage"
|
||||
label="Bands"
|
||||
>
|
||||
<a-form-item :validate-status="!!errorMessage ? 'error' : undefined" :help="errorMessage as any" label="Bands">
|
||||
<a-select
|
||||
:allow-clear="true"
|
||||
mode="multiple"
|
||||
|
@ -1,15 +1,9 @@
|
||||
<script setup lang="ts">
|
||||
import {
|
||||
Form as VeeForm,
|
||||
Field,
|
||||
useForm,
|
||||
useField,
|
||||
ErrorMessage,
|
||||
} from "vee-validate";
|
||||
import { Field, ErrorMessage } from "vee-validate";
|
||||
import { NamePath } from "ant-design-vue/es/form/interface";
|
||||
import { FormChapter } from "@client/types/form/story";
|
||||
|
||||
import { story, bare } from "@client/editorConfig";
|
||||
import { bare } from "@client/editorConfig";
|
||||
import elBands from "../atoms/bands.vue";
|
||||
import genre from "../atoms/genre.vue";
|
||||
import elCharacters from "../atoms/characters.vue";
|
||||
@ -41,16 +35,8 @@
|
||||
<div>
|
||||
<a-row :gutter="[10, 0]">
|
||||
<a-col :span="12">
|
||||
<Field
|
||||
:name="name + '.chapterTitle'"
|
||||
v-slot="{ value, field, errorMessage }"
|
||||
>
|
||||
<a-form-item
|
||||
:name="[field.name]"
|
||||
label="Chapter title"
|
||||
:help="errorMessage"
|
||||
:status="!!errorMessage ? 'error' : undefined"
|
||||
>
|
||||
<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-input v-bind="field" />
|
||||
</a-form-item>
|
||||
</Field>
|
||||
@ -61,22 +47,10 @@
|
||||
</a-row>
|
||||
<a-row :gutter="[10, 0]">
|
||||
<a-col :span="12">
|
||||
<base-editor
|
||||
v-model:val="acData.summary"
|
||||
:name="name + '.summary'"
|
||||
:wrap-col="wrapc"
|
||||
label="Summary"
|
||||
:init="bare"
|
||||
/>
|
||||
<base-editor v-model:val="acData.summary" :name="name + '.summary'" :wrap-col="wrapc" label="Summary" :init="bare" />
|
||||
</a-col>
|
||||
<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 v-model:val="acData.notes" :name="name + '.notes'" :wrap-col="wrapc" label="Author's notes" :init="bare" />
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-row :gutter="[10, 0]">
|
||||
@ -87,39 +61,17 @@
|
||||
<el-pairings />
|
||||
</a-col>
|
||||
</a-row>
|
||||
<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>
|
||||
<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>
|
||||
<error-message :name="field.name" />
|
||||
</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>
|
||||
<error-message :name="field.name" />
|
||||
</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>
|
||||
<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-tooltip>
|
||||
</Field>
|
||||
|
@ -2,25 +2,10 @@
|
||||
import draggable from "vuedraggable";
|
||||
import { v4 } from "uuid";
|
||||
import lmove from "lodash-move";
|
||||
import {
|
||||
Field,
|
||||
Form as veeForm,
|
||||
FieldArray,
|
||||
FieldEntry,
|
||||
useForm,
|
||||
} from "vee-validate";
|
||||
import { Field, FieldArray, useForm } from "vee-validate";
|
||||
import { storySchema } from "@client/storyFormSchema";
|
||||
import {
|
||||
FormChapter,
|
||||
FormStory,
|
||||
defaultChapter,
|
||||
} from "@client/types/form/story";
|
||||
import {
|
||||
autoEdit,
|
||||
autoSave,
|
||||
debouncedAutoEdit,
|
||||
debouncedAutoSave,
|
||||
} from "@client/utils";
|
||||
import { FormStory, defaultChapter } from "@client/types/form/story";
|
||||
import { autoEdit, autoSave, debouncedAutoEdit, debouncedAutoSave } from "@client/utils";
|
||||
|
||||
import findUser from "~/components/findUser.vue";
|
||||
|
||||
@ -79,35 +64,17 @@
|
||||
@submit="onSubmit"
|
||||
@invalid-submit="inval"
|
||||
> -->
|
||||
<form
|
||||
@submit="subCb"
|
||||
@change="
|
||||
() =>
|
||||
canDraft
|
||||
? debouncedAutoSave(values)
|
||||
: debouncedAutoEdit(values, endpoint, endpointMethod)
|
||||
"
|
||||
>
|
||||
<form @submit="subCb" @change="() => (canDraft ? debouncedAutoSave(values) : debouncedAutoEdit(values, endpoint, endpointMethod))">
|
||||
<!-- <a-form v-bind:model="acData"> -->
|
||||
<Field name="title" v-slot="{ value, field, errorMessage }">
|
||||
<a-form-item
|
||||
label="Title"
|
||||
:help="errorMessage"
|
||||
:validate-status="!!errorMessage ? 'error' : ''"
|
||||
>
|
||||
<a-form-item label="Title" :help="errorMessage" :validate-status="!!errorMessage ? 'error' : ''">
|
||||
<a-input v-bind="field" :value="value" />
|
||||
</a-form-item>
|
||||
</Field>
|
||||
<a-form-item label="Co-author (optional)">
|
||||
<find-user :initial-option="null" fieldName="coAuthor" :multi="false" />
|
||||
</a-form-item>
|
||||
<Field
|
||||
:unchecked-value="false"
|
||||
:value="true"
|
||||
type="checkbox"
|
||||
name="completed"
|
||||
v-slot="{ value, field, errorMessage }"
|
||||
>
|
||||
<Field :unchecked-value="false" :value="true" type="checkbox" name="completed" v-slot="{ value, field, errorMessage }">
|
||||
<a-checkbox v-bind="field"> Complete </a-checkbox>
|
||||
</Field>
|
||||
<a-divider />
|
||||
@ -125,11 +92,7 @@
|
||||
if (e.moved) {
|
||||
// log.debug(e.moved);
|
||||
move(e.moved.oldIndex, e.moved.newIndex);
|
||||
acData.chapters = lmove(
|
||||
acData.chapters,
|
||||
e.moved.oldIndex,
|
||||
e.moved.newIndex,
|
||||
);
|
||||
acData.chapters = lmove(acData.chapters, e.moved.oldIndex, e.moved.newIndex);
|
||||
// log.debug(toRaw(acData.chapters.map((a) => toRaw(a))));
|
||||
}
|
||||
}
|
||||
@ -194,16 +157,8 @@
|
||||
</template>
|
||||
</draggable>
|
||||
</field-array>
|
||||
<a-button type="primary" html-type="submit">{{
|
||||
submitText || "Post"
|
||||
}}</a-button>
|
||||
<a-button
|
||||
html-type="submit"
|
||||
v-if="canDraft"
|
||||
@click="() => (otherBtnInvoked = true)"
|
||||
>
|
||||
Save for Later
|
||||
</a-button>
|
||||
<a-button type="primary" html-type="submit">{{ submitText || "Post" }}</a-button>
|
||||
<a-button html-type="submit" v-if="canDraft" @click="() => (otherBtnInvoked = true)"> Save for Later </a-button>
|
||||
</form>
|
||||
<!-- </vee-form> -->
|
||||
</template>
|
||||
|
@ -1,11 +1,5 @@
|
||||
<script lang="ts" setup>
|
||||
import {
|
||||
Form as VeeForm,
|
||||
Field as veeField,
|
||||
useForm,
|
||||
useField,
|
||||
ErrorMessage,
|
||||
} from "vee-validate";
|
||||
import { useField } from "vee-validate";
|
||||
import { story } from "@client/editorConfig";
|
||||
import icon from "~/components/icon.vue";
|
||||
import baseEditor from "../../baseEditor.vue";
|
||||
@ -22,12 +16,7 @@
|
||||
</a-radio-group>
|
||||
<br />
|
||||
<br />
|
||||
<base-editor
|
||||
label=""
|
||||
v-if="pvalue === 'pasteOrType'"
|
||||
:init="story"
|
||||
:name="fname + 'content'"
|
||||
/>
|
||||
<base-editor label="" v-if="pvalue === 'pasteOrType'" :init="story" :name="fname + 'content'" />
|
||||
<a-upload
|
||||
v-model:file-list="fileList"
|
||||
v-else-if="pvalue === 'upload'"
|
||||
@ -53,10 +42,6 @@
|
||||
}
|
||||
"
|
||||
>
|
||||
<a-button type="primary">
|
||||
<icon istyle="regular" name="upload" /><span style="margin-left: 0.5em">
|
||||
Upload a file</span
|
||||
>
|
||||
</a-button>
|
||||
<a-button type="primary"> <icon istyle="regular" name="upload" /><span style="margin-left: 0.5em"> Upload a file</span> </a-button>
|
||||
</a-upload>
|
||||
</template>
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { AsyncData, UseFetchOptions } from "#app";
|
||||
import { NitroFetchRequest } from "nitropack";
|
||||
import { AsyncData } from "#app";
|
||||
|
||||
const useApiFetch = async <T>(url: string, options?: any) => {
|
||||
// const { token } = useAuth();
|
||||
|
@ -4,7 +4,7 @@
|
||||
import cfooter from "~/components/layouts/footer.vue";
|
||||
import sidebarThing from "~/components/layouts/sidebar.vue";
|
||||
import icon from "~/components/icon.vue";
|
||||
import { ISidebarItem } from "@models/sidebarEntry";
|
||||
|
||||
const { useToken } = theme;
|
||||
const { token } = useToken();
|
||||
|
||||
@ -52,10 +52,7 @@
|
||||
<div class="stat-block">
|
||||
<div>
|
||||
<a-typography-text> Band fiction that rocks </a-typography-text>
|
||||
<a-typography-text type="secondary">
|
||||
With {{ totals?.stories ?? 0 }} stories by
|
||||
{{ totals?.authors ?? 0 }} authors
|
||||
</a-typography-text>
|
||||
<a-typography-text type="secondary"> With {{ totals?.stories ?? 0 }} stories by {{ totals?.authors ?? 0 }} authors </a-typography-text>
|
||||
</div>
|
||||
</div>
|
||||
<navbar />
|
||||
|
@ -1,39 +1,20 @@
|
||||
import * as yup from "yup";
|
||||
import { FormChapter, FormStory } from "./types/form/story";
|
||||
import { FormChapter } from "./types/form/story";
|
||||
|
||||
const emptySummary = "Summary cannot be blank";
|
||||
const emptyChapterTitle = "Chapter title cannot be blank.";
|
||||
const blankTitle = "Title cannot be blank.";
|
||||
|
||||
export const cs = yup.object<FormChapter>().shape({
|
||||
chapterTitle: yup
|
||||
.string()
|
||||
.ensure()
|
||||
.min(1, emptyChapterTitle)
|
||||
.trim(emptyChapterTitle)
|
||||
.required(emptyChapterTitle),
|
||||
chapterTitle: yup.string().ensure().min(1, emptyChapterTitle).trim(emptyChapterTitle).required(emptyChapterTitle),
|
||||
summary: yup.string().ensure().min(10, emptySummary).required(emptySummary),
|
||||
notes: yup.string().ensure(),
|
||||
bands: yup
|
||||
.array()
|
||||
.ensure()
|
||||
.of(yup.number())
|
||||
.min(1, "One or more bands must be selected."),
|
||||
characters: yup
|
||||
.array()
|
||||
.ensure()
|
||||
.min(1, "One or more characters must be selected"),
|
||||
bands: yup.array().ensure().of(yup.number()).min(1, "One or more bands must be selected."),
|
||||
characters: yup.array().ensure().min(1, "One or more characters must be selected"),
|
||||
relationships: yup
|
||||
.array()
|
||||
.ensure()
|
||||
.of(
|
||||
yup
|
||||
.array()
|
||||
.ensure()
|
||||
.of(yup.string())
|
||||
.min(2, "Pairings must have at least two characters!")
|
||||
.max(3, "Pairings can have no more than three characters!"),
|
||||
),
|
||||
.of(yup.array().ensure().of(yup.string()).min(2, "Pairings must have at least two characters!").max(3, "Pairings can have no more than three characters!")),
|
||||
nsfw: yup.boolean().oneOf([true, false]),
|
||||
loggedInOnly: yup.boolean().when("nsfw", ([nsfw], schema) => {
|
||||
return nsfw
|
||||
@ -44,20 +25,13 @@ export const cs = yup.object<FormChapter>().shape({
|
||||
: schema.oneOf([true, false]);
|
||||
}),
|
||||
hidden: yup.boolean().oneOf([true, false]),
|
||||
pot: yup
|
||||
.string()
|
||||
.oneOf(["pasteOrType", "upload"])
|
||||
.required("Story content is required!"),
|
||||
pot: yup.string().oneOf(["pasteOrType", "upload"]).required("Story content is required!"),
|
||||
storytext: yup.string().when("pot", ([pot], schema) => {
|
||||
return pot === "pasteOrType"
|
||||
? schema
|
||||
.test(
|
||||
"numWords",
|
||||
"Story must be at least 50 words",
|
||||
(value: any, context) => {
|
||||
.test("numWords", "Story must be at least 50 words", (value: any, context) => {
|
||||
return value?.split(/\W+/).length > 50 || false;
|
||||
},
|
||||
)
|
||||
})
|
||||
.required("Story text can't be blank!")
|
||||
: schema.min(0);
|
||||
}),
|
||||
@ -98,10 +72,6 @@ export const cs = yup.object<FormChapter>().shape({
|
||||
|
||||
export const storySchema = yup.object().shape({
|
||||
title: yup.string().ensure().min(5, blankTitle).required(blankTitle),
|
||||
chapters: yup
|
||||
.array()
|
||||
.min(1, "There must be at least one chapter.")
|
||||
.of(cs)
|
||||
.ensure(),
|
||||
chapters: yup.array().min(1, "There must be at least one chapter.").of(cs).ensure(),
|
||||
completed: yup.boolean().oneOf([true, false]),
|
||||
});
|
||||
|
@ -1,5 +1,3 @@
|
||||
import { readFileSync } from "fs";
|
||||
import { resolve } from "path";
|
||||
// import chardet from "chardet";
|
||||
// import iconv from "iconv-lite";
|
||||
import { GridFSBucketReadStream } from "mongodb";
|
||||
@ -15,20 +13,13 @@ export function countWords(string: string) {
|
||||
return stripHtml(string).result.split(/W+/).length;
|
||||
}
|
||||
|
||||
export function populate<T>(
|
||||
field: string,
|
||||
model: string,
|
||||
): PreMiddlewareFunction<Query<T, T>> {
|
||||
export function populate<T>(field: string, model: string): PreMiddlewareFunction<Query<T, T>> {
|
||||
return function (next: () => any) {
|
||||
this.populate(field, undefined, model);
|
||||
next();
|
||||
};
|
||||
}
|
||||
export function populateSelected<T>(
|
||||
field: string,
|
||||
model: string,
|
||||
selection: string,
|
||||
): PreMiddlewareFunction<Query<T, T>> {
|
||||
export function populateSelected<T>(field: string, model: string, selection: string): PreMiddlewareFunction<Query<T, T>> {
|
||||
return function (next: () => any) {
|
||||
this.populate(field, selection, model);
|
||||
next();
|
||||
@ -40,15 +31,11 @@ export function isFicmasHidden(story: IStory): boolean {
|
||||
((story.ficmas as IFicmas)?.year == new Date().getFullYear() &&
|
||||
(story.ficmas as IFicmas)?.anniversary &&
|
||||
new Date() < new Date(Date.parse("Aug 1 " + new Date().getFullYear()))) ||
|
||||
((story.ficmas as IFicmas)?.year == new Date().getFullYear() &&
|
||||
!(story.ficmas as IFicmas)?.anniversary &&
|
||||
ficsHidden(Date.now()))
|
||||
((story.ficmas as IFicmas)?.year == new Date().getFullYear() && !(story.ficmas as IFicmas)?.anniversary && ficsHidden(Date.now()))
|
||||
);
|
||||
}
|
||||
|
||||
export function stringifyStream(
|
||||
stream: GridFSBucketReadStream,
|
||||
): Promise<string> {
|
||||
export function stringifyStream(stream: GridFSBucketReadStream): Promise<string> {
|
||||
let chunks: Buffer[] = [];
|
||||
return new Promise((res, rej) => {
|
||||
stream.on("data", (c) => chunks.push(Buffer.from(c)));
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { H3Event, EventHandlerRequest } from "h3";
|
||||
import { GridFSBucket } from "mongodb";
|
||||
import mongoose, { Document } from "mongoose";
|
||||
import { Document } from "mongoose";
|
||||
import { norm, stringifyStream } from "@functions";
|
||||
import { IStory } from "@models/stories";
|
||||
import { IChapter } from "@models/stories/chapter";
|
||||
@ -16,11 +15,7 @@ export default async function (
|
||||
const cloned: any & { chapters: IChapter[] } = { ...finObj };
|
||||
delete finObj.chapters;
|
||||
const bucket = getBucket();
|
||||
let ds = bucket.openDownloadStreamByName(
|
||||
`/stories/${
|
||||
cloned.chapters[cindex || event.context.chapterIndex || 0].id
|
||||
}.txt`,
|
||||
);
|
||||
let ds = bucket.openDownloadStreamByName(`/stories/${cloned.chapters[cindex || event.context.chapterIndex || 0].id}.txt`);
|
||||
let stream = await stringifyStream(ds);
|
||||
finObj.currentChapter = {
|
||||
...cloned.chapters[cindex || event.context.chapterIndex || 0],
|
||||
|
@ -1,4 +1,3 @@
|
||||
import { Band } from "@models/band";
|
||||
import { Challenge } from "@models/challenges/gen";
|
||||
import { IStory, Story } from "@models/stories";
|
||||
import { log } from "../logger";
|
||||
|
@ -1,16 +1,12 @@
|
||||
import { H3Event, EventHandlerRequest } from "h3";
|
||||
import { apiRoot } from "./constants";
|
||||
export default async function (id: number): Promise<number> {
|
||||
let { data: lookup } = await useFetch<any>(
|
||||
`${apiRoot}/session-sharing/lookup`,
|
||||
{
|
||||
let { data: lookup } = await useFetch<any>(`${apiRoot}/session-sharing/lookup`, {
|
||||
method: "get",
|
||||
query: {
|
||||
params: {
|
||||
id,
|
||||
},
|
||||
},
|
||||
},
|
||||
);
|
||||
});
|
||||
return lookup.value.uid as number;
|
||||
}
|
||||
|
@ -1,12 +1,10 @@
|
||||
import winston from "winston";
|
||||
const { combine, timestamp, json, splat, printf, colorize } = winston.format;
|
||||
|
||||
winston.add;
|
||||
// winston.add;
|
||||
|
||||
const fmt = printf(({ timestamp, level, message, label, durationMs }) => {
|
||||
return `${timestamp} [${label || "misc"}] ${message} ${
|
||||
!!durationMs ? " (took " + durationMs + "ms)" : ""
|
||||
}`;
|
||||
return `${timestamp} [${label || "misc"}] ${message} ${!!durationMs ? " (took " + durationMs + "ms)" : ""}`;
|
||||
});
|
||||
|
||||
const cfmt = combine(json(), timestamp(), fmt);
|
||||
|
@ -2,7 +2,6 @@ import { EventHandlerRequest, H3Event } from "h3";
|
||||
import { messages } from "@server/constants";
|
||||
import { IStory } from "@models/stories";
|
||||
import { isFicmasHidden } from "@functions";
|
||||
import { IDraft } from "@models/stories/draft";
|
||||
import axios from "axios";
|
||||
import { IUser } from "@models/user";
|
||||
export function isIdNan(ev: H3Event<EventHandlerRequest>) {
|
||||
@ -33,11 +32,7 @@ export function isLoggedIn(ev: H3Event<EventHandlerRequest>) {
|
||||
}
|
||||
}
|
||||
|
||||
export async function storyCheck(
|
||||
event: H3Event<EventHandlerRequest>,
|
||||
story: IStory,
|
||||
idx: number,
|
||||
) {
|
||||
export async function storyCheck(event: H3Event<EventHandlerRequest>, story: IStory, idx: number) {
|
||||
let ret: any = {};
|
||||
if (!story) {
|
||||
ret.statusCode = 404;
|
||||
@ -49,11 +44,7 @@ export async function storyCheck(
|
||||
message: `TOP SECRET! This story is part of an ongoing challenge. You'll be able to read it after the challenge's reveal date.`,
|
||||
};
|
||||
}
|
||||
} else if (
|
||||
story.chapters[idx]?.hidden &&
|
||||
event.context.currentUser?._id !== (story.author as IUser)._id &&
|
||||
!event.context.currentUser?.profile.isAdmin
|
||||
) {
|
||||
} else if (story.chapters[idx]?.hidden && event.context.currentUser?._id !== (story.author as IUser)._id && !event.context.currentUser?.profile.isAdmin) {
|
||||
ret.statusCode = 403;
|
||||
ret.message = messages[403];
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import mongoose, { connect, Document, Model } from "mongoose";
|
||||
import mongoose, { Model } from "mongoose";
|
||||
const { Schema, model } = mongoose;
|
||||
import SequenceFactory from "mongoose-sequence";
|
||||
import { hasMigrated } from "@dbconfig";
|
||||
@ -30,11 +30,5 @@ const BandSchema = new mongoose.Schema<IBand>({
|
||||
],
|
||||
});
|
||||
|
||||
hasMigrated &&
|
||||
!mongoose.models.Band &&
|
||||
BandSchema.plugin(AutoIncrement, { id: "band" });
|
||||
export const Band: Model<IBand> = /* mongoose.models.Band || */ model<IBand>(
|
||||
"Band",
|
||||
BandSchema,
|
||||
"bands",
|
||||
);
|
||||
hasMigrated && !mongoose.models.Band && BandSchema.plugin(AutoIncrement, { id: "band" });
|
||||
export const Band: Model<IBand> = /* mongoose.models.Band || */ model<IBand>("Band", BandSchema, "bands");
|
||||
|
@ -1,4 +1,4 @@
|
||||
import mongoose, { Schema, PopulatedDoc, Document, Model } from "mongoose";
|
||||
import mongoose, { PopulatedDoc, Model } from "mongoose";
|
||||
import { IUser } from "@models/user";
|
||||
import SequenceFactory from "mongoose-sequence";
|
||||
import { hasMigrated } from "@dbconfig";
|
||||
@ -67,8 +67,5 @@ const biffnoschema = new mongoose.Schema<IBiffno>({
|
||||
},
|
||||
});
|
||||
|
||||
hasMigrated &&
|
||||
!mongoose.models.Biffno &&
|
||||
biffnoschema.plugin(AutoIncrement, { start_seq: 1, id: "bif_id" });
|
||||
export const Biffno: Model<IBiffno> =
|
||||
mongoose.models.Biffno || mongoose.model("Biffno", biffnoschema, "biffno");
|
||||
hasMigrated && !mongoose.models.Biffno && biffnoschema.plugin(AutoIncrement, { start_seq: 1, id: "bif_id" });
|
||||
export const Biffno: Model<IBiffno> = mongoose.models.Biffno || mongoose.model("Biffno", biffnoschema, "biffno");
|
||||
|
@ -1,10 +1,4 @@
|
||||
import mongoose, {
|
||||
Schema,
|
||||
PopulatedDoc,
|
||||
Document,
|
||||
Model,
|
||||
model,
|
||||
} from "mongoose";
|
||||
import mongoose, { PopulatedDoc, Model, model } from "mongoose";
|
||||
|
||||
import { IBand } from "@models/band";
|
||||
import { IUser } from "@models/user";
|
||||
@ -48,9 +42,6 @@ export const FicmasSchema = new mongoose.Schema<IFicmas>({
|
||||
},
|
||||
});
|
||||
|
||||
hasMigrated &&
|
||||
!mongoose.models.Ficmas &&
|
||||
FicmasSchema.plugin(AutoIncrement, { id: "ficmas_wishes", inc_field: "_id" });
|
||||
hasMigrated && !mongoose.models.Ficmas && FicmasSchema.plugin(AutoIncrement, { id: "ficmas_wishes", inc_field: "_id" });
|
||||
|
||||
export const Ficmas: Model<IFicmas> =
|
||||
mongoose.models.Ficmas || model("Ficmas", FicmasSchema, "ficmas_wishes");
|
||||
export const Ficmas: Model<IFicmas> = mongoose.models.Ficmas || model("Ficmas", FicmasSchema, "ficmas_wishes");
|
||||
|
@ -1,4 +1,4 @@
|
||||
import mongoose, { Schema, PopulatedDoc, Document, Model } from "mongoose";
|
||||
import mongoose, { Model } from "mongoose";
|
||||
import SequenceFactory from "mongoose-sequence";
|
||||
import { hasMigrated } from "@dbconfig";
|
||||
|
||||
@ -45,9 +45,7 @@ const challengeSchema = new mongoose.Schema<IChallenge>({
|
||||
},
|
||||
});
|
||||
|
||||
hasMigrated &&
|
||||
!mongoose.models.Challenge &&
|
||||
challengeSchema.plugin(AutoIncrement, { id: "challenges" });
|
||||
hasMigrated && !mongoose.models.Challenge && challengeSchema.plugin(AutoIncrement, { id: "challenges" });
|
||||
export const Challenge: Model<IChallenge> =
|
||||
// mongoose.models.Challenge ||
|
||||
mongoose.model("Challenge", challengeSchema, "challenges");
|
||||
|
@ -1,11 +1,4 @@
|
||||
import mongoose, {
|
||||
Schema,
|
||||
connect,
|
||||
PopulatedDoc,
|
||||
Document,
|
||||
Model,
|
||||
} from "mongoose";
|
||||
import SequenceFactory from "mongoose-sequence";
|
||||
import mongoose, { Schema, PopulatedDoc, Model } from "mongoose";
|
||||
|
||||
import { IPrivMsg } from "./privMsg";
|
||||
import { IUser } from "./user";
|
||||
@ -41,8 +34,4 @@ const InboxSchema = new Schema<IInbox>({
|
||||
],
|
||||
});
|
||||
|
||||
export const Inbox: Model<IInbox> = mongoose.model<IInbox>(
|
||||
"Inbox",
|
||||
InboxSchema,
|
||||
"inboxes",
|
||||
);
|
||||
export const Inbox: Model<IInbox> = mongoose.model<IInbox>("Inbox", InboxSchema, "inboxes");
|
||||
|
@ -1,4 +1,4 @@
|
||||
import mongoose, { Schema, PopulatedDoc, Document, Model } from "mongoose";
|
||||
import mongoose, { PopulatedDoc, Model } from "mongoose";
|
||||
import SequenceFactory from "mongoose-sequence";
|
||||
import { hasMigrated } from "@dbconfig";
|
||||
import { IUser } from "./user";
|
||||
@ -50,13 +50,6 @@ const PMSchema = new mongoose.Schema<IPrivMsg>({
|
||||
},
|
||||
});
|
||||
|
||||
hasMigrated &&
|
||||
!mongoose.models.PrivMsg &&
|
||||
PMSchema.plugin(AutoIncrement, { id: "private_message" });
|
||||
hasMigrated && !mongoose.models.PrivMsg && PMSchema.plugin(AutoIncrement, { id: "private_message" });
|
||||
|
||||
export const PrivMsg: Model<IPrivMsg> =
|
||||
/* mongoose.models.PrivMsg || */ mongoose.model(
|
||||
"PrivMsg",
|
||||
PMSchema,
|
||||
"private_messages",
|
||||
);
|
||||
export const PrivMsg: Model<IPrivMsg> = /* mongoose.models.PrivMsg || */ mongoose.model("PrivMsg", PMSchema, "private_messages");
|
||||
|
@ -1,4 +1,4 @@
|
||||
import mongoose, { connect, PopulatedDoc, Document } from "mongoose";
|
||||
import mongoose from "mongoose";
|
||||
const { Schema, model } = mongoose;
|
||||
|
||||
interface IAbstractQM {
|
||||
|
@ -1,4 +1,4 @@
|
||||
import mongoose, { Schema, PopulatedDoc, Document, Model } from "mongoose";
|
||||
import mongoose, { Model } from "mongoose";
|
||||
|
||||
export enum Color {
|
||||
"orange" = "orange",
|
||||
@ -35,9 +35,4 @@ const SISchema = new mongoose.Schema<ISidebarItem>({
|
||||
});
|
||||
|
||||
export const SidebarItem: Model<ISidebarItem> =
|
||||
mongoose.models.SidebarItem ||
|
||||
/* mongoose.models.SidebarItem || */ mongoose.model(
|
||||
"SidebarItem",
|
||||
SISchema,
|
||||
"sidebar",
|
||||
);
|
||||
mongoose.models.SidebarItem || /* mongoose.models.SidebarItem || */ mongoose.model("SidebarItem", SISchema, "sidebar");
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Schema, PopulatedDoc, Document, Model } from "mongoose";
|
||||
import { Schema, PopulatedDoc } from "mongoose";
|
||||
import { IBand } from "@models/band";
|
||||
export interface IChapter {
|
||||
title: string;
|
||||
|
@ -1,19 +1,12 @@
|
||||
import { IStory } from ".";
|
||||
import { hasMigrated } from "@dbconfig";
|
||||
import { IBand } from "@models/band";
|
||||
import { IFicmas } from "@models/challenges/ficmas";
|
||||
import { IChallenge } from "@models/challenges/gen";
|
||||
import { IUser } from "@models/user";
|
||||
import mongoose, { Schema, PopulatedDoc, Document, Model } from "mongoose";
|
||||
import mongoose, { Schema, Model } from "mongoose";
|
||||
import SequenceFactory from "mongoose-sequence";
|
||||
import { Chapter } from "./chapter";
|
||||
|
||||
const AutoIncrement = SequenceFactory(mongoose);
|
||||
|
||||
export type IDraft = Omit<
|
||||
IStory,
|
||||
"recs" | "favs" | "reviews" | "views" | "downloads" | "posted"
|
||||
>;
|
||||
export type IDraft = Omit<IStory, "recs" | "favs" | "reviews" | "views" | "downloads" | "posted">;
|
||||
|
||||
// const Cha
|
||||
|
||||
@ -39,9 +32,6 @@ const DraftSchema = new Schema<IDraft>(
|
||||
{ timestamps: true },
|
||||
);
|
||||
|
||||
hasMigrated &&
|
||||
!mongoose.models.Draft &&
|
||||
DraftSchema.plugin(AutoIncrement, { id: "drafts" });
|
||||
hasMigrated && !mongoose.models.Draft && DraftSchema.plugin(AutoIncrement, { id: "drafts" });
|
||||
|
||||
export const Draft: Model<IDraft> =
|
||||
/* mongoose.models.Draft || */ mongoose.model("Draft", DraftSchema, "drafts");
|
||||
export const Draft: Model<IDraft> = /* mongoose.models.Draft || */ mongoose.model("Draft", DraftSchema, "drafts");
|
||||
|
@ -1,4 +1,4 @@
|
||||
import mongoose, { Schema, PopulatedDoc, Document, Model } from "mongoose";
|
||||
import mongoose, { PopulatedDoc, Model } from "mongoose";
|
||||
import SequenceFactory from "mongoose-sequence";
|
||||
|
||||
const AutoIncrement = SequenceFactory(mongoose);
|
||||
@ -87,13 +87,6 @@ const StorySchema = new mongoose.Schema<IStory>({
|
||||
default: new Date(),
|
||||
},
|
||||
});
|
||||
hasMigrated &&
|
||||
!mongoose.models.Story &&
|
||||
Chapter.plugin(AutoIncrement, { id: "chapterid", inc_field: "id" });
|
||||
hasMigrated && !mongoose.models.Story && Chapter.plugin(AutoIncrement, { id: "chapterid", inc_field: "id" });
|
||||
hasMigrated && StorySchema.plugin(AutoIncrement, { id: "storyid" });
|
||||
export const Story: Model<IStory> =
|
||||
/* mongoose.models.Story || */ mongoose.model(
|
||||
"Story",
|
||||
StorySchema,
|
||||
"stories",
|
||||
);
|
||||
export const Story: Model<IStory> = /* mongoose.models.Story || */ mongoose.model("Story", StorySchema, "stories");
|
||||
|
@ -1,4 +1,4 @@
|
||||
import mongoose, { Schema, PopulatedDoc, Document, Model } from "mongoose";
|
||||
import mongoose, { PopulatedDoc, Model } from "mongoose";
|
||||
import SequenceFactory from "mongoose-sequence";
|
||||
import { hasMigrated } from "@dbconfig";
|
||||
import { populate, populateSelected } from "@functions";
|
||||
@ -63,22 +63,9 @@ CommentSchema
|
||||
// .pre("find", populateSelected("replyingTo", modelName, "-replies -author"))
|
||||
.pre("findOne", populate("replies", modelName))
|
||||
.pre("find", populate("replies", modelName))
|
||||
.pre(
|
||||
"findOne",
|
||||
populateSelected("author", "User", "profile username _id blocked"),
|
||||
)
|
||||
.pre(
|
||||
"find",
|
||||
populateSelected("author", "User", "profile username _id blocked"),
|
||||
);
|
||||
.pre("findOne", populateSelected("author", "User", "profile username _id blocked"))
|
||||
.pre("find", populateSelected("author", "User", "profile username _id blocked"));
|
||||
|
||||
hasMigrated &&
|
||||
!mongoose.models.Review &&
|
||||
CommentSchema.plugin(AutoIncrement, { id: "reviews" });
|
||||
hasMigrated && !mongoose.models.Review && CommentSchema.plugin(AutoIncrement, { id: "reviews" });
|
||||
|
||||
export const Review: Model<IReview> =
|
||||
/* mongoose.models.Review || */ mongoose.model(
|
||||
modelName,
|
||||
CommentSchema,
|
||||
"reviews",
|
||||
);
|
||||
export const Review: Model<IReview> = /* mongoose.models.Review || */ mongoose.model(modelName, CommentSchema, "reviews");
|
||||
|
@ -1,10 +1,4 @@
|
||||
import mongoose, {
|
||||
Schema,
|
||||
connect,
|
||||
PopulatedDoc,
|
||||
Document,
|
||||
Model,
|
||||
} from "mongoose";
|
||||
import mongoose, { PopulatedDoc, Document, Model } from "mongoose";
|
||||
import SequenceFactory from "mongoose-sequence";
|
||||
import bcrypt from "bcryptjs";
|
||||
import md5 from "blueimp-md5";
|
||||
@ -274,25 +268,15 @@ UserSchema.static("generateHash", function (password: string): string {
|
||||
return bcrypt.hashSync(password, bcrypt.genSaltSync(8));
|
||||
});
|
||||
UserSchema.methods.validPassword = function (password: string): boolean {
|
||||
return (
|
||||
md5(password) === this.password ||
|
||||
bcrypt.compareSync(password, this.password) ||
|
||||
false
|
||||
);
|
||||
return md5(password) === this.password || bcrypt.compareSync(password, this.password) || false;
|
||||
};
|
||||
|
||||
UserSchema.methods.generateJWT = function (jwtKey: string): string {
|
||||
let token = jwt.sign(
|
||||
{ id: this._id, isAdmin: this.profile.isAdmin },
|
||||
jwtKey,
|
||||
{
|
||||
let token = jwt.sign({ id: this._id, isAdmin: this.profile.isAdmin }, jwtKey, {
|
||||
expiresIn: "14 days",
|
||||
},
|
||||
);
|
||||
});
|
||||
return token;
|
||||
};
|
||||
|
||||
hasMigrated &&
|
||||
!mongoose.models.User &&
|
||||
UserSchema.plugin(AutoIncrement, { id: "userid", inc_field: "_id" });
|
||||
hasMigrated && !mongoose.models.User && UserSchema.plugin(AutoIncrement, { id: "userid", inc_field: "_id" });
|
||||
export const User = mongoose.model<IUser, UModel>("User", UserSchema, "users");
|
||||
|
@ -1,6 +1,5 @@
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive } from "vue";
|
||||
import useApiFetch from "../../composables/useApiFetch";
|
||||
import { reactive } from "vue";
|
||||
import { notification } from "ant-design-vue";
|
||||
interface FormState {
|
||||
username: string;
|
||||
@ -38,28 +37,11 @@
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<a-form
|
||||
:model="formState"
|
||||
name="basic"
|
||||
:label-col="{ span: 8 }"
|
||||
autocomplete="off"
|
||||
:colon="false"
|
||||
layout="vertical"
|
||||
@finish="onFinish"
|
||||
>
|
||||
<a-form-item
|
||||
label="Username"
|
||||
name="username"
|
||||
:rules="[{ required: true, message: 'Username required!' }]"
|
||||
>
|
||||
<a-form :model="formState" name="basic" :label-col="{ span: 8 }" autocomplete="off" :colon="false" layout="vertical" @finish="onFinish">
|
||||
<a-form-item label="Username" name="username" :rules="[{ required: true, message: 'Username required!' }]">
|
||||
<a-input v-model:value="formState.username" />
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
:colon="false"
|
||||
label="Password"
|
||||
name="password"
|
||||
:rules="[{ required: true, message: 'Password required!' }]"
|
||||
>
|
||||
<a-form-item :colon="false" label="Password" name="password" :rules="[{ required: true, message: 'Password required!' }]">
|
||||
<a-input-password v-model:value="formState.password" />
|
||||
</a-form-item>
|
||||
<a-form-item>
|
||||
|
@ -1,21 +1,10 @@
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive } from "vue";
|
||||
import {
|
||||
Form as veeForm,
|
||||
Field as veeField,
|
||||
useField,
|
||||
useForm,
|
||||
useSetFieldValue,
|
||||
useFormErrors,
|
||||
useFormValues,
|
||||
RuleExpression,
|
||||
} from "vee-validate";
|
||||
import { Field as veeField, useField, useForm } from "vee-validate";
|
||||
import * as yup from "yup";
|
||||
import { useRecaptchaProvider } from "vue-recaptcha";
|
||||
|
||||
import { useChallengeV2 } from "vue-recaptcha";
|
||||
import { notification } from "ant-design-vue";
|
||||
import { log } from "@server/logger";
|
||||
import termsOfServices from "~/components/tos.vue";
|
||||
useRecaptchaProvider();
|
||||
|
||||
@ -34,24 +23,11 @@
|
||||
});
|
||||
// const { execute } = useChallengeV3('submit');
|
||||
const vschema = yup.object<FormState>().shape({
|
||||
username: yup
|
||||
.string()
|
||||
.ensure()
|
||||
.trim()
|
||||
.min(1)
|
||||
.required("Username is required!"),
|
||||
password: yup
|
||||
.string()
|
||||
.ensure()
|
||||
.trim()
|
||||
.min(8)
|
||||
.required("Password is required!"),
|
||||
username: yup.string().ensure().trim().min(1).required("Username is required!"),
|
||||
password: yup.string().ensure().trim().min(8).required("Password is required!"),
|
||||
email: yup.string().ensure().trim().email().required("Email is required!"),
|
||||
// recaptcha: yup.string().required('Please verify you are human.'),
|
||||
agree: yup
|
||||
.boolean()
|
||||
.oneOf([true], "Please agree to the terms.")
|
||||
.required("Please agree to the terms."),
|
||||
agree: yup.boolean().oneOf([true], "Please agree to the terms.").required("Please agree to the terms."),
|
||||
});
|
||||
const dv: FormState = {
|
||||
username: "",
|
||||
@ -120,48 +96,26 @@ notification[ "error" ]({
|
||||
<template>
|
||||
<form @submit="onFinish">
|
||||
<vee-field name="username" v-slot="{ field, errorMessage, value }">
|
||||
<a-form-item
|
||||
label="Username"
|
||||
:name="field.name"
|
||||
:validate-status="!!errorMessage ? 'error' : ''"
|
||||
:help="errorMessage"
|
||||
>
|
||||
<a-form-item label="Username" :name="field.name" :validate-status="!!errorMessage ? 'error' : ''" :help="errorMessage">
|
||||
<a-input v-bind="field" v-model:value="field.value" />
|
||||
</a-form-item>
|
||||
</vee-field>
|
||||
<vee-field name="email" v-slot="{ field, errorMessage, value }">
|
||||
<a-form-item
|
||||
label="Email address"
|
||||
:name="field.name"
|
||||
:validate-status="!!errorMessage ? 'error' : ''"
|
||||
:help="errorMessage"
|
||||
>
|
||||
<a-form-item label="Email address" :name="field.name" :validate-status="!!errorMessage ? 'error' : ''" :help="errorMessage">
|
||||
<a-input v-bind="field" v-model:value="field.value" />
|
||||
</a-form-item>
|
||||
</vee-field>
|
||||
<vee-field name="password" v-slot="{ field, errorMessage, value }">
|
||||
<a-form-item
|
||||
label="Password"
|
||||
:name="field.name"
|
||||
:validate-status="!!errorMessage ? 'error' : ''"
|
||||
:help="errorMessage"
|
||||
>
|
||||
<a-form-item label="Password" :name="field.name" :validate-status="!!errorMessage ? 'error' : ''" :help="errorMessage">
|
||||
<a-input-password v-bind="field" v-model:value="field.value" />
|
||||
</a-form-item>
|
||||
</vee-field>
|
||||
|
||||
<a-typography-title :level="4" :style="{ textAlign: 'center' }"
|
||||
>Terms</a-typography-title
|
||||
>
|
||||
<a-typography-title :level="4" :style="{ textAlign: 'center' }">Terms</a-typography-title>
|
||||
<div class="maxHeightScroller">
|
||||
<div style="height: 100%">
|
||||
<terms-of-services />
|
||||
<vee-field
|
||||
name="agree"
|
||||
:unchecked-value="false"
|
||||
type="checkbox"
|
||||
v-slot="{ field, value, errorMessage }"
|
||||
>
|
||||
<vee-field name="agree" :unchecked-value="false" type="checkbox" v-slot="{ field, value, errorMessage }">
|
||||
<a-checkbox
|
||||
@update:checked="
|
||||
(n) => {
|
||||
@ -179,9 +133,7 @@ notification[ "error" ]({
|
||||
<div ref="root" />
|
||||
<a-row :align="'middle'" justify="center">
|
||||
<a-col>
|
||||
<a-button size="large" type="primary" html-type="submit"
|
||||
>Sign me up!</a-button
|
||||
>
|
||||
<a-button size="large" type="primary" html-type="submit">Sign me up!</a-button>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</form>
|
||||
|
@ -1,6 +1,4 @@
|
||||
<script setup lang="ts">
|
||||
import { IChapter } from "@models/stories/chapter";
|
||||
import { IStory } from "@models/stories";
|
||||
import { storyEditMiddleware } from "@client/middleware";
|
||||
import { SingleChapterResult } from "@client/types/slightlyDifferentStory";
|
||||
import SingleChapter from "~/components/story/create/singleChapter.vue";
|
||||
@ -13,9 +11,7 @@
|
||||
const rtr = useRoute();
|
||||
const {
|
||||
data: { value: originalStory },
|
||||
} = await useApiFetch<SingleChapterResult | null>(
|
||||
`/story/${rtr.params.id}/${rtr.params.cidx}`,
|
||||
);
|
||||
} = await useApiFetch<SingleChapterResult | null>(`/story/${rtr.params.id}/${rtr.params.cidx}`);
|
||||
if (originalStory === null) {
|
||||
throw createError({
|
||||
statusCode: 404,
|
||||
@ -28,8 +24,5 @@
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<single-chapter
|
||||
:data="toFormChapter(originalStory!.currentChapter)"
|
||||
:name="originalStory!.currentChapter.title"
|
||||
/>
|
||||
<single-chapter :data="toFormChapter(originalStory!.currentChapter)" :name="originalStory!.currentChapter.title" />
|
||||
</template>
|
||||
|
@ -6,12 +6,12 @@
|
||||
import { IChapter } from "@models/stories/chapter";
|
||||
|
||||
import { storyEditMiddleware } from "@client/middleware";
|
||||
import { IBand } from "@models/band";
|
||||
import { IUser } from "@models/user";
|
||||
const rtr = useRoute();
|
||||
const {
|
||||
data: { value: originalStory },
|
||||
} = await useApiFetch<
|
||||
({ chapters: (IChapter & { text: string })[] } & IStory) | null
|
||||
>(`/story/${rtr.params.id}/full`);
|
||||
} = await useApiFetch<({ chapters: (IChapter & { text: string })[] } & IStory) | null>(`/story/${rtr.params.id}/full`);
|
||||
if (originalStory === null) {
|
||||
console.log("IT DOESN'T EXIST DAWG");
|
||||
throw createError({
|
||||
@ -20,18 +20,18 @@
|
||||
});
|
||||
}
|
||||
definePageMeta({
|
||||
middleware: [storyEditMiddleware, "auth"],
|
||||
middleware: ["auth", storyEditMiddleware],
|
||||
});
|
||||
const story: FormStory = {
|
||||
title: originalStory!.title,
|
||||
coAuthor: originalStory?.coAuthor ? originalStory.coAuthor._id : null,
|
||||
coAuthor: originalStory?.coAuthor ? (originalStory.coAuthor as IUser)._id : null,
|
||||
completed: originalStory!.completed,
|
||||
chapters: originalStory!.chapters.map((a, i) => ({
|
||||
...a,
|
||||
id: a.id,
|
||||
chapterTitle: a.title,
|
||||
index: i + 1,
|
||||
bands: a.bands.map((a) => a._id),
|
||||
bands: (a.bands as IBand[]).map((a) => a._id),
|
||||
content: a.text,
|
||||
uuidKey: v4(),
|
||||
})),
|
||||
@ -41,14 +41,6 @@
|
||||
});
|
||||
</script>
|
||||
<template>
|
||||
<a-typography-title style="text-align: center">
|
||||
Editing "{{ originalStory?.title }}"
|
||||
</a-typography-title>
|
||||
<story-form
|
||||
:can-draft="false"
|
||||
:data="story"
|
||||
:endpoint="`/story/${rtr.params.id}`"
|
||||
endpoint-method="put"
|
||||
>
|
||||
</story-form>
|
||||
<a-typography-title style="text-align: center"> Editing "{{ originalStory?.title }}" </a-typography-title>
|
||||
<story-form :can-draft="false" :data="story" :endpoint="`/story/${rtr.params.id}`" endpoint-method="put"> </story-form>
|
||||
</template>
|
||||
|
@ -1,7 +1,6 @@
|
||||
<script lang="ts" setup>
|
||||
import { format, formatDistanceToNow, formatRelative } from "date-fns";
|
||||
import { format, formatDistanceToNow } from "date-fns";
|
||||
import { IUser } from "@models/user";
|
||||
import { IStory } from "@models/stories";
|
||||
import { favourites } from "@client/listActions";
|
||||
import singleStory from "~/components/listings/singleStory.vue";
|
||||
import icon from "~/components/icon.vue";
|
||||
@ -16,10 +15,7 @@
|
||||
}
|
||||
const activeKey = ref("main");
|
||||
const activeFavKey = ref("favs/stories");
|
||||
const uLastVisit = Date.parse(
|
||||
(userInfo.value?.lastVisit ||
|
||||
userInfo.value?.lastLogin) as unknown as string,
|
||||
);
|
||||
const uLastVisit = Date.parse((userInfo.value?.lastVisit || userInfo.value?.lastLogin) as unknown as string);
|
||||
|
||||
const isSelf = userInfo.value?._id === parseInt(rtr.params.id as string);
|
||||
useHead({
|
||||
@ -32,10 +28,7 @@
|
||||
<div style="height: fit-content">
|
||||
<a-card-meta style="align-items: center; margin: 0.5em">
|
||||
<template #avatar>
|
||||
<a-avatar
|
||||
:size="75"
|
||||
:src="`/avatars/${userInfo?.profile.avatar}.png`"
|
||||
/>
|
||||
<a-avatar :size="75" :src="`/avatars/${userInfo?.profile.avatar}.png`" />
|
||||
</template>
|
||||
<template #title>
|
||||
<a-typography-title :level="1" style="margin-top: 0.5em">
|
||||
@ -48,15 +41,9 @@
|
||||
<template #text> Administrator </template>
|
||||
</a-badge-ribbon>
|
||||
</template>
|
||||
<a-descriptions
|
||||
:column="2"
|
||||
:labelStyle="{ fontWeight: 'bold' }"
|
||||
:colon="false"
|
||||
>
|
||||
<a-descriptions :column="2" :labelStyle="{ fontWeight: 'bold' }" :colon="false">
|
||||
<a-descriptions-item label="Last visit">
|
||||
<div v-if="userInfo?.banned" style="color: red; font-weight: bold">
|
||||
BANNED
|
||||
</div>
|
||||
<div v-if="userInfo?.banned" style="color: red; font-weight: bold">BANNED</div>
|
||||
<div v-else-if="userInfo?.profile.hidden">
|
||||
<i>Unknown</i>
|
||||
</div>
|
||||
@ -64,38 +51,23 @@
|
||||
<span>
|
||||
{{ format(uLastVisit, "MM/dd/yyyy @ hh:mm:ss a") }}
|
||||
</span>
|
||||
<span style="margin-left: 0.6em">
|
||||
({{ formatDistanceToNow(uLastVisit, { addSuffix: true }) }})
|
||||
</span>
|
||||
<span style="margin-left: 0.6em"> ({{ formatDistanceToNow(uLastVisit, { addSuffix: true }) }}) </span>
|
||||
</div>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="Website">
|
||||
<a
|
||||
target="_blank"
|
||||
:href="`${
|
||||
userInfo?.profile.website.startsWith('http') ? '' : 'http://'
|
||||
}${userInfo?.profile.website}`"
|
||||
>
|
||||
<a target="_blank" :href="`${userInfo?.profile.website.startsWith('http') ? '' : 'http://'}${userInfo?.profile.website}`">
|
||||
{{ userInfo?.profile.website }}
|
||||
</a>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="Blog/Journal">
|
||||
<a
|
||||
target="_blank"
|
||||
:href="`${
|
||||
userInfo?.profile.blog.startsWith('http') ? '' : 'http://'
|
||||
}${userInfo?.profile.blog}`"
|
||||
>
|
||||
<a target="_blank" :href="`${userInfo?.profile.blog.startsWith('http') ? '' : 'http://'}${userInfo?.profile.blog}`">
|
||||
{{ userInfo?.profile.blog }}
|
||||
</a>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="Occupation">
|
||||
{{ userInfo?.profile.occupation }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item
|
||||
label="Email"
|
||||
v-if="userInfo?.profile.showEmail || ses?.user?.profile.isAdmin"
|
||||
>
|
||||
<a-descriptions-item label="Email" v-if="userInfo?.profile.showEmail || ses?.user?.profile.isAdmin">
|
||||
{{ userInfo?.email }}
|
||||
</a-descriptions-item>
|
||||
</a-descriptions>
|
||||
@ -129,18 +101,7 @@
|
||||
<single-story :last="true" :story="item" />
|
||||
</a-col>
|
||||
<a-col :span="1" v-if="isSelf">
|
||||
<a
|
||||
style="color: red"
|
||||
@click="
|
||||
() =>
|
||||
favourites(
|
||||
userInfo?.favs.stories || [],
|
||||
item._id,
|
||||
true,
|
||||
'story',
|
||||
)
|
||||
"
|
||||
>
|
||||
<a style="color: red" @click="() => favourites(userInfo?.favs.stories || [], item._id, true, 'story')">
|
||||
<icon istyle="regular" name="trash" color="#f00" />
|
||||
</a>
|
||||
</a-col>
|
||||
@ -149,16 +110,10 @@
|
||||
</a-list>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="favs/authors" tab="Authors">
|
||||
<a-list
|
||||
item-layout="horizontal"
|
||||
:data-source="userInfo?.favs.authors"
|
||||
:grid="{ gutter: 16, column: 3 }"
|
||||
>
|
||||
<a-list item-layout="horizontal" :data-source="userInfo?.favs.authors" :grid="{ gutter: 16, column: 3 }">
|
||||
<template #renderItem="{ item }">
|
||||
<a-list-item style="display: flex; align-items: center">
|
||||
<a-list-item-meta
|
||||
style="align-items: center; width: min-content"
|
||||
>
|
||||
<a-list-item-meta style="align-items: center; width: min-content">
|
||||
<template #avatar>
|
||||
<a-avatar :src="`/avatars/${item.profile.avatar}.png`" />
|
||||
</template>
|
||||
@ -170,18 +125,7 @@
|
||||
</a-list-item-meta>
|
||||
<template #actions v-if="isSelf">
|
||||
<span>
|
||||
<a
|
||||
style="color: red"
|
||||
@click="
|
||||
() =>
|
||||
favourites(
|
||||
userInfo?.favs.authors || [],
|
||||
item._id,
|
||||
true,
|
||||
'author',
|
||||
)
|
||||
"
|
||||
>
|
||||
<a style="color: red" @click="() => favourites(userInfo?.favs.authors || [], item._id, true, 'author')">
|
||||
<icon istyle="regular" name="trash" color="#f00" />
|
||||
</a>
|
||||
</span>
|
||||
|
@ -1,5 +1,3 @@
|
||||
import mongoose from "mongoose";
|
||||
import * as net from "net";
|
||||
import plugnplay from "@server/plugnplay";
|
||||
export default defineNuxtPlugin({
|
||||
name: "mongo",
|
||||
|
@ -1,6 +1,6 @@
|
||||
import mongoose from "mongoose";
|
||||
import jwt from "jsonwebtoken";
|
||||
import { IUser, User } from "@models/user";
|
||||
import { User } from "@models/user";
|
||||
import { log } from "@server/logger";
|
||||
|
||||
export default eventHandler(async (event) => {
|
||||
@ -25,8 +25,7 @@ export default eventHandler(async (event) => {
|
||||
if (!user.auth.emailVerified) {
|
||||
throw createError({
|
||||
statusCode: 401,
|
||||
message:
|
||||
'Account inactive!<br><a href="/activate/resend">Resend verification</a>?',
|
||||
message: 'Account inactive!<br><a href="/activate/resend">Resend verification</a>?',
|
||||
});
|
||||
}
|
||||
let tok = user.generateJWT(useRuntimeConfig().jwt);
|
||||
|
@ -1,11 +1,5 @@
|
||||
import jwt from "jsonwebtoken";
|
||||
import { log } from "@server/logger";
|
||||
export default eventHandler((event) => {
|
||||
let ahead = (
|
||||
getHeaders(event).authorization ||
|
||||
getCookie(event, "auth:token") ||
|
||||
""
|
||||
)?.replace("Bearer ", "");
|
||||
let ahead = (getHeaders(event).authorization || getCookie(event, "auth:token") || "")?.replace("Bearer ", "");
|
||||
if (event.context.currentUser) {
|
||||
return {
|
||||
token: ahead,
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { messages } from "@server/constants";
|
||||
import { isAdmin } from "@server/middlewareButNotReally";
|
||||
import { isLoggedIn } from "@server/middlewareButNotReally";
|
||||
import { Band, IBand } from "@models/band";
|
||||
|
||||
export default eventHandler(async (ev) => {
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { listQuerier } from "@server/dbHelpers";
|
||||
import { Band } from "@models/band";
|
||||
import { Story } from "@models/stories";
|
||||
|
||||
export default eventHandler(async (event) => {
|
||||
const params = getRouterParams(event);
|
||||
|
@ -1,4 +1,3 @@
|
||||
import { usernameRegex } from "@server/constants";
|
||||
import { User } from "@models/user";
|
||||
|
||||
export default eventHandler(async (event) => {
|
||||
|
@ -1,7 +1,6 @@
|
||||
import san from "sanitize-html";
|
||||
import { storyQuerier } from "@server/dbHelpers";
|
||||
import { isLoggedIn } from "@server/middlewareButNotReally";
|
||||
import { Story } from "@models/stories";
|
||||
import { Review } from "@models/stories/review";
|
||||
|
||||
export default eventHandler(async (ev) => {
|
||||
|
@ -1,16 +1,10 @@
|
||||
import { Readable } from "stream";
|
||||
import { Document } from "mongoose";
|
||||
import { IStory, Story } from "@models/stories";
|
||||
import { FormStory } from "@client/types/form/story";
|
||||
import { storyQuerier } from "@server/dbHelpers";
|
||||
import { isLoggedIn } from "@server/middlewareButNotReally";
|
||||
import { canModify } from "@server/middlewareButNotReally/storyPrivileges";
|
||||
import {
|
||||
bodyHandler,
|
||||
getBucket,
|
||||
modelFormChapter,
|
||||
replaceOrUploadContent,
|
||||
} from "@server/storyHelpers";
|
||||
import { bodyHandler, getBucket, modelFormChapter, replaceOrUploadContent } from "@server/storyHelpers";
|
||||
import { countWords } from "@functions";
|
||||
import { messages } from "@server/constants";
|
||||
|
||||
|
@ -1,10 +1,8 @@
|
||||
import { Readable } from "stream";
|
||||
import san from "sanitize-html";
|
||||
import { FormStory } from "@client/types/form/story";
|
||||
import { isLoggedIn } from "@server/middlewareButNotReally";
|
||||
import { getBucket, bodyHandler, modelFormChapter } from "@server/storyHelpers";
|
||||
import { Story } from "@models/stories";
|
||||
import { sanitizeConf } from "@server/constants";
|
||||
import { countWords } from "@functions";
|
||||
|
||||
export default eventHandler(async (ev) => {
|
||||
@ -24,9 +22,7 @@ export default eventHandler(async (ev) => {
|
||||
});
|
||||
for (const c of body.chapters) {
|
||||
story.chapters.push(modelFormChapter(c));
|
||||
story.chapters[story.chapters.length - 1].words = countWords(
|
||||
await bodyHandler(c),
|
||||
);
|
||||
story.chapters[story.chapters.length - 1].words = countWords(await bodyHandler(c));
|
||||
}
|
||||
await story.save();
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { FavPayload, SubPayload } from "@client/types/form/favSub";
|
||||
import { FavPayload } from "@client/types/form/favSub";
|
||||
import { isLoggedIn } from "@server/middlewareButNotReally";
|
||||
import { User } from "@models/user";
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
import san from "sanitize-html";
|
||||
import { weirdToNormalChars } from "weird-to-normal-chars";
|
||||
import { Profile, MyStuff } from "@client/types/form/myStuff";
|
||||
import { apiRoot, messages } from "@server/constants";
|
||||
import { MyStuff } from "@client/types/form/myStuff";
|
||||
import { apiRoot } from "@server/constants";
|
||||
import { isLoggedIn } from "@server/middlewareButNotReally";
|
||||
import { Review } from "@models/stories/review";
|
||||
import { IUser, User } from "@models/user";
|
||||
@ -51,14 +50,11 @@ export default eventHandler(async (ev) => {
|
||||
if (exists) {
|
||||
throw createError(emsg("username"));
|
||||
}
|
||||
let { data: lookup } = await axios.get(
|
||||
`${apiRoot}/session-sharing/lookup`,
|
||||
{
|
||||
let { data: lookup } = await axios.get(`${apiRoot}/session-sharing/lookup`, {
|
||||
params: {
|
||||
id: ev.context.currentUser!._id,
|
||||
},
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
await axios.put(`${apiRoot}/v3/users/${lookup.value.uid}`, {
|
||||
body: {
|
||||
|
@ -1,4 +1,3 @@
|
||||
import mongoose from "mongoose";
|
||||
import { log } from "@server/logger";
|
||||
import plugnplay from "@server/plugnplay";
|
||||
|
||||
|
@ -1,23 +1,26 @@
|
||||
import jwt from "jsonwebtoken";
|
||||
import { log } from "@server/logger";
|
||||
import { User } from "@models/user";
|
||||
import { messages } from "@server/constants";
|
||||
import { AccessToken } from "@models/oauth";
|
||||
|
||||
export default defineEventHandler(async (event) => {
|
||||
let ahead = (
|
||||
getHeaders(event).authorization ||
|
||||
getCookie(event, "auth:token") ||
|
||||
""
|
||||
)?.replace("Bearer ", "");
|
||||
// console.log("in here fucknuts", ahead);
|
||||
// log.debug(`'${ahead}'`, { label: "idk" });
|
||||
let ahead = (getHeaders(event).authorization || getCookie(event, "auth:token") || "")?.replace("Bearer ", "");
|
||||
if (ahead) {
|
||||
let toktok = jwt.verify(
|
||||
ahead,
|
||||
// ahead.replace("Bearer ", ""),
|
||||
useRuntimeConfig().jwt,
|
||||
) as jwt.JwtPayload;
|
||||
let toktok: jwt.JwtPayload;
|
||||
try {
|
||||
toktok = jwt.verify(ahead, useRuntimeConfig().jwt) as jwt.JwtPayload;
|
||||
let user = await User.findById(toktok.id as number).exec();
|
||||
if (user && toktok) event.context.currentUser = user;
|
||||
// setCookie(event, "auth:token", ahead)
|
||||
} catch (e) {
|
||||
const t = await AccessToken.findOne({ token: ahead });
|
||||
if (!t)
|
||||
throw createError({
|
||||
statusCode: 401,
|
||||
message: messages[401],
|
||||
});
|
||||
let user = await User.findById(t.userID);
|
||||
if (user) event.context.currentUser = user;
|
||||
// else throw createError({statusCode: 401, message: messages[401]})
|
||||
}
|
||||
}
|
||||
});
|
||||
|
1
typings/express.d.ts
vendored
1
typings/express.d.ts
vendored
@ -1,4 +1,3 @@
|
||||
import { Document } from "mongoose";
|
||||
import { IStory } from "@models/stories";
|
||||
import { IUser } from "@models/user";
|
||||
import { Request } from "express";
|
||||
|
1
typings/h3.d.ts
vendored
1
typings/h3.d.ts
vendored
@ -1,4 +1,3 @@
|
||||
import type { H3Event, H3EventContext } from "h3";
|
||||
import { IFicmas } from "@models/challenges/ficmas";
|
||||
import { IUser } from "@models/user";
|
||||
declare module "h3" {
|
||||
|
Loading…
Reference in New Issue
Block a user