feat(quest): add support for private images in answers
This commit is contained in:
@@ -216,6 +216,8 @@
|
|||||||
"finalize": "Antwort finalisieren",
|
"finalize": "Antwort finalisieren",
|
||||||
"finalize_explain": "Dies gibt den Admins die Möglichkeit deine Antwort zu bewerten und dir Punkte zu geben. Du kannst deine Antwort anschließend nicht mehr ändern!",
|
"finalize_explain": "Dies gibt den Admins die Möglichkeit deine Antwort zu bewerten und dir Punkte zu geben. Du kannst deine Antwort anschließend nicht mehr ändern!",
|
||||||
"last_update": "Letztes Update: {date} von {name}",
|
"last_update": "Letztes Update: {date} von {name}",
|
||||||
|
"private_image": "Privates Bild",
|
||||||
|
"private_image_explain": "Private Bilder werden in der öffentlichen Galerie, Diashow und im Showcase ausgeblendet. Admins können sie weiterhin zur Bewertung sehen.",
|
||||||
"required_answer": "Erforderliche Antwort",
|
"required_answer": "Erforderliche Antwort",
|
||||||
"review": "Bewertung",
|
"review": "Bewertung",
|
||||||
"reviewed_by": "von {name} am {date}",
|
"reviewed_by": "von {name} am {date}",
|
||||||
|
|||||||
@@ -216,6 +216,8 @@
|
|||||||
"finalize": "Finalize answer",
|
"finalize": "Finalize answer",
|
||||||
"finalize_explain": "This allows the admins to review your answer and give you points. You cannot change your answer afterwards!",
|
"finalize_explain": "This allows the admins to review your answer and give you points. You cannot change your answer afterwards!",
|
||||||
"last_update": "Last update: {date} by {name}",
|
"last_update": "Last update: {date} by {name}",
|
||||||
|
"private_image": "Private image",
|
||||||
|
"private_image_explain": "Private images are hidden from the public gallery, diashow and showcase. Admins can still see them for review.",
|
||||||
"required_answer": "Required Answer",
|
"required_answer": "Required Answer",
|
||||||
"review": "Review",
|
"review": "Review",
|
||||||
"reviewed_by": "by {name} at {date}",
|
"reviewed_by": "by {name} at {date}",
|
||||||
|
|||||||
@@ -72,6 +72,11 @@ useHead({
|
|||||||
|
|
||||||
const answer = ref(data.value?.answer?.text);
|
const answer = ref(data.value?.answer?.text);
|
||||||
const final = ref(data.value?.answer?.final || false);
|
const final = ref(data.value?.answer?.final || false);
|
||||||
|
const privateImage = ref(data.value?.answer?.picture?.private ?? false);
|
||||||
|
|
||||||
|
const privateChanged = computed(
|
||||||
|
() => (data.value?.answer?.picture?.private ?? false) !== privateImage.value
|
||||||
|
);
|
||||||
|
|
||||||
const textType = {
|
const textType = {
|
||||||
TEXT: 'text',
|
TEXT: 'text',
|
||||||
@@ -114,6 +119,7 @@ async function submit() {
|
|||||||
if (final.value) {
|
if (final.value) {
|
||||||
body.set('final', 'true');
|
body.set('final', 'true');
|
||||||
}
|
}
|
||||||
|
body.set('private', privateImage.value ? 'true' : 'false');
|
||||||
if (newImage.value) {
|
if (newImage.value) {
|
||||||
uploadingImage.value = true;
|
uploadingImage.value = true;
|
||||||
compressing.value = true;
|
compressing.value = true;
|
||||||
@@ -141,6 +147,7 @@ async function submit() {
|
|||||||
|
|
||||||
await refresh();
|
await refresh();
|
||||||
answer.value = data.value?.answer?.text;
|
answer.value = data.value?.answer?.text;
|
||||||
|
privateImage.value = data.value?.answer?.picture?.private ?? false;
|
||||||
newImage.value = undefined;
|
newImage.value = undefined;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (xhr.status === 418) {
|
if (xhr.status === 418) {
|
||||||
@@ -325,6 +332,13 @@ async function submit() {
|
|||||||
type="single"
|
type="single"
|
||||||
file-types="jpg,png,jpeg"
|
file-types="jpg,png,jpeg"
|
||||||
/>
|
/>
|
||||||
|
<VaCheckbox
|
||||||
|
v-if="newImageURL || data.answer?.picture"
|
||||||
|
v-model="privateImage"
|
||||||
|
:disabled="uploading || data.answer?.final"
|
||||||
|
:label="t('page.quest.private_image')"
|
||||||
|
:messages="t('page.quest.private_image_explain')"
|
||||||
|
/>
|
||||||
<p v-if="data.answer?.updatedAt">
|
<p v-if="data.answer?.updatedAt">
|
||||||
{{
|
{{
|
||||||
t('page.quest.last_update', {
|
t('page.quest.last_update', {
|
||||||
@@ -352,7 +366,8 @@ async function submit() {
|
|||||||
!(
|
!(
|
||||||
newImage ||
|
newImage ||
|
||||||
data.answer?.text !== answer ||
|
data.answer?.text !== answer ||
|
||||||
data.answer?.final !== final
|
data.answer?.final !== final ||
|
||||||
|
privateChanged
|
||||||
) || uploading
|
) || uploading
|
||||||
"
|
"
|
||||||
:loading="uploading"
|
:loading="uploading"
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "public"."File" ADD COLUMN "private" BOOLEAN NOT NULL DEFAULT false;
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
generator client {
|
generator client {
|
||||||
provider = "prisma-client"
|
provider = "prisma-client"
|
||||||
engineType = "client"
|
engineType = "client"
|
||||||
output = "../shared/generated/prisma"
|
output = "../shared/generated/prisma"
|
||||||
}
|
}
|
||||||
|
|
||||||
datasource db {
|
datasource db {
|
||||||
@@ -42,9 +42,10 @@ enum UserRole {
|
|||||||
}
|
}
|
||||||
|
|
||||||
model File {
|
model File {
|
||||||
id Int @id @default(autoincrement())
|
id Int @id @default(autoincrement())
|
||||||
uuid String
|
uuid String
|
||||||
url String
|
url String
|
||||||
|
private Boolean @default(false)
|
||||||
|
|
||||||
creator User @relation(fields: [creatorId], references: [id], onUpdate: Cascade, onDelete: Cascade)
|
creator User @relation(fields: [creatorId], references: [id], onUpdate: Cascade, onDelete: Cascade)
|
||||||
creatorId Int
|
creatorId Int
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ export default defineEventHandler(async (event) => {
|
|||||||
where: {
|
where: {
|
||||||
final: true,
|
final: true,
|
||||||
picture: {
|
picture: {
|
||||||
isNot: null
|
private: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -95,7 +95,7 @@ export default defineEventHandler(async (event) => {
|
|||||||
some: {
|
some: {
|
||||||
final: true,
|
final: true,
|
||||||
picture: {
|
picture: {
|
||||||
isNot: null
|
private: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -138,7 +138,8 @@ export default defineEventHandler(async (event) => {
|
|||||||
where: {
|
where: {
|
||||||
review: {
|
review: {
|
||||||
showcase: true
|
showcase: true
|
||||||
}
|
},
|
||||||
|
picture: { private: false }
|
||||||
},
|
},
|
||||||
orderBy: [
|
orderBy: [
|
||||||
{
|
{
|
||||||
@@ -217,6 +218,7 @@ export default defineEventHandler(async (event) => {
|
|||||||
pictureCount,
|
pictureCount,
|
||||||
totalScore,
|
totalScore,
|
||||||
leaderboard,
|
leaderboard,
|
||||||
...hunt
|
...hunt,
|
||||||
|
quests: hunt.quests.filter((q) => q.answers.length > 0)
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -71,7 +71,8 @@ export default defineEventHandler(async (event) => {
|
|||||||
text: true,
|
text: true,
|
||||||
picture: {
|
picture: {
|
||||||
select: {
|
select: {
|
||||||
url: true
|
url: true,
|
||||||
|
private: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
review: {
|
review: {
|
||||||
|
|||||||
@@ -101,7 +101,8 @@ export default defineEventHandler(async (event) => {
|
|||||||
.mime(['image/png', 'image/jpeg', 'image/jpg'])
|
.mime(['image/png', 'image/jpeg', 'image/jpg'])
|
||||||
.max(10_000_000)
|
.max(10_000_000)
|
||||||
.optional(),
|
.optional(),
|
||||||
final: zh.boolAsString.optional()
|
final: zh.boolAsString.optional(),
|
||||||
|
private: zh.boolAsString.default(false)
|
||||||
})
|
})
|
||||||
.parse(formDataObj);
|
.parse(formDataObj);
|
||||||
|
|
||||||
@@ -110,7 +111,8 @@ export default defineEventHandler(async (event) => {
|
|||||||
? quest.answers![0]!
|
? quest.answers![0]!
|
||||||
: {
|
: {
|
||||||
updatedAt: null,
|
updatedAt: null,
|
||||||
id: null
|
id: null,
|
||||||
|
picture: null
|
||||||
};
|
};
|
||||||
|
|
||||||
if (
|
if (
|
||||||
@@ -158,7 +160,8 @@ export default defineEventHandler(async (event) => {
|
|||||||
const file = await tx.file.create({
|
const file = await tx.file.create({
|
||||||
data: {
|
data: {
|
||||||
...picture,
|
...picture,
|
||||||
answerId: prevAnswer.id
|
answerId: prevAnswer.id,
|
||||||
|
private: data.private
|
||||||
},
|
},
|
||||||
select: { id: true }
|
select: { id: true }
|
||||||
});
|
});
|
||||||
@@ -190,6 +193,7 @@ export default defineEventHandler(async (event) => {
|
|||||||
data: {
|
data: {
|
||||||
...picture,
|
...picture,
|
||||||
answerId: answer.id,
|
answerId: answer.id,
|
||||||
|
private: data.private,
|
||||||
answers: {
|
answers: {
|
||||||
connect: answer
|
connect: answer
|
||||||
}
|
}
|
||||||
@@ -210,6 +214,16 @@ export default defineEventHandler(async (event) => {
|
|||||||
lang: data.lang
|
lang: data.lang
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
if (prevAnswer.picture) {
|
||||||
|
await prisma.file.update({
|
||||||
|
where: {
|
||||||
|
id: prevAnswer.picture.id
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
private: data.private
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
await prisma.questAnswer.create({
|
await prisma.questAnswer.create({
|
||||||
data: {
|
data: {
|
||||||
|
|||||||
Reference in New Issue
Block a user