This commit is contained in:
parent
6d70187cb9
commit
c578538fe0
10 changed files with 195 additions and 107 deletions
|
|
@ -36,7 +36,7 @@ return [
|
|||
$newFile = $page->createFile([
|
||||
'source' => $upload['tmp_name'],
|
||||
'filename' => $name,
|
||||
'template' => 'document',
|
||||
'template' => 'pdf',
|
||||
'content' => [
|
||||
'date' => date('Y-m-d h:i')
|
||||
]
|
||||
|
|
|
|||
|
|
@ -12,6 +12,11 @@ function getFileData($file) {
|
|||
'name' => $file->filename(),
|
||||
'label' => (string) $file->label(),
|
||||
'type' => (string) $file->type(),
|
||||
'cover' => $file->cover()->isNotEmpty() ? $file->cover()->toFile()->thumb([
|
||||
'width' => 1000,
|
||||
'quality' => 80,
|
||||
'format' => 'webp'
|
||||
])->url() : null
|
||||
];
|
||||
|
||||
if ($file->description()->exists()) {
|
||||
|
|
|
|||
|
|
@ -65,7 +65,11 @@
|
|||
:class="{ active: isCurrent(project) }"
|
||||
>
|
||||
<router-link
|
||||
:to="project.uri"
|
||||
:to="
|
||||
isEmptyBrief(project)
|
||||
? project.uri + '/client-brief'
|
||||
: project.uri
|
||||
"
|
||||
:class="hasUnreadNotification(project) ? 'new' : undefined"
|
||||
@click="collapse()"
|
||||
>{{ project.title }}</router-link
|
||||
|
|
@ -107,11 +111,13 @@ import { useProjectsStore } from "../stores/projects";
|
|||
import { useRoute } from "vue-router";
|
||||
import { useUserStore } from "../stores/user";
|
||||
import { usePageStore } from "../stores/page";
|
||||
import { useProjectStore } from "../stores/project";
|
||||
|
||||
const route = useRoute();
|
||||
const isExpanded = ref(true);
|
||||
const { user } = storeToRefs(useUserStore());
|
||||
const { currentProjects, archivedProjects } = storeToRefs(useProjectsStore());
|
||||
const { isEmptyBrief } = useProjectStore();
|
||||
const { page } = storeToRefs(usePageStore());
|
||||
|
||||
const unreadNotificationsCount = computed(() => {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
<template>
|
||||
<router-link :to="project.uri">
|
||||
<router-link
|
||||
:to="isEmptyBrief(project) ? project.uri + '/client-brief' : project.uri"
|
||||
>
|
||||
<article class="project-item | flex | rounded-2xl | px-32 py-32">
|
||||
<hgroup>
|
||||
<h3>{{ project.title }}</h3>
|
||||
|
|
@ -11,7 +13,11 @@
|
|||
</p>
|
||||
</hgroup>
|
||||
<img :src="project.logo" alt="Logo" class="project-logo | rounded-sm" />
|
||||
<ol class="project-steps" :data-steps="project.steps.length" :style="'--steps:'+project.steps.length">
|
||||
<ol
|
||||
class="project-steps"
|
||||
:data-steps="project.steps.length"
|
||||
:style="'--steps:' + project.steps.length"
|
||||
>
|
||||
<li
|
||||
v-for="step in project.steps"
|
||||
class="project-step"
|
||||
|
|
@ -39,5 +45,5 @@ const frenchFormattedModified = dayjs(project.modified).format(
|
|||
"dddd D MMMM YYYY"
|
||||
);
|
||||
|
||||
const { stepsLabels, setStatus } = useProjectStore();
|
||||
const { stepsLabels, setStatus, isEmptyBrief } = useProjectStore();
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -26,9 +26,15 @@
|
|||
>
|
||||
<hgroup class="order-last">
|
||||
<h3 class="card__title | font-serif | text-lg">
|
||||
<router-link :to="'/' + step.uri" class="link-full">{{
|
||||
step.label
|
||||
}}</router-link>
|
||||
<router-link
|
||||
:to="
|
||||
step.id === 'clientBrief'
|
||||
? '/' + page.uri + '/client-brief'
|
||||
: '/' + step.uri
|
||||
"
|
||||
class="link-full"
|
||||
>{{ step.label }}</router-link
|
||||
>
|
||||
</h3>
|
||||
</hgroup>
|
||||
<div class="card__meta | flex">
|
||||
|
|
@ -42,17 +48,20 @@
|
|||
<figure
|
||||
v-if="step.id === 'clientBrief' && step.files[0]?.type === 'image'"
|
||||
class="card__images"
|
||||
:data-count="step.files.length"
|
||||
:data-count="
|
||||
step.files.filter((file) => file.type === 'image').length
|
||||
"
|
||||
:data-plus="
|
||||
step.files.length > 3 ? step.files.length - 3 : undefined
|
||||
"
|
||||
>
|
||||
<img
|
||||
v-for="image in step.files.slice(0, 3)"
|
||||
:key="image.uuid"
|
||||
:src="image.url"
|
||||
:alt="image.alt"
|
||||
/>
|
||||
<template v-for="image in step.files.slice(0, 3)" :key="image.uuid">
|
||||
<img
|
||||
v-if="image.type === 'image'"
|
||||
:src="image.url"
|
||||
:alt="image.alt"
|
||||
/>
|
||||
</template>
|
||||
</figure>
|
||||
<figure
|
||||
v-if="step.id === 'virtualSample'"
|
||||
|
|
@ -87,70 +96,93 @@
|
|||
</footer>
|
||||
</article>
|
||||
|
||||
<template v-if="step.id === 'clientBrief' && hasOneBriefType()">
|
||||
<button
|
||||
v-if="step.files[0].type === 'document'"
|
||||
class="btn | w-full"
|
||||
@click="toImagesBrief()"
|
||||
>
|
||||
Ajouter un brief via la plateforme
|
||||
</button>
|
||||
<div class="btn | w-full" v-else>
|
||||
<label for="upload-pdf">
|
||||
Ajouter brief PDF
|
||||
<input
|
||||
id="upload-pdf"
|
||||
type="file"
|
||||
@change="addPdf($event, step.uri)"
|
||||
accept="application/pdf"
|
||||
ref="pdfInput"
|
||||
hidden
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template
|
||||
v-if="
|
||||
(step.id == 'clientBrief' &&
|
||||
step.files.find((file) => file.type === 'document')) ||
|
||||
step.id == 'proposal' ||
|
||||
(step.id == 'industrialIdeation' && step.files.length)
|
||||
"
|
||||
>
|
||||
<article
|
||||
class="card"
|
||||
v-for="(file, index) in step.files"
|
||||
:key="file.name"
|
||||
>
|
||||
<hgroup class="order-last">
|
||||
<h3 class="card__title | font-serif | text-lg">
|
||||
<router-link
|
||||
:to="'/' + step.uri + '&fileIndex=' + index"
|
||||
class="link-full"
|
||||
<template v-for="(file, index) in step.files" :key="file.name">
|
||||
<article class="card" v-if="file.type === 'document'">
|
||||
<hgroup class="order-last">
|
||||
<h3 class="card__title | font-serif | text-lg">
|
||||
<router-link
|
||||
:to="'/' + step.uri + '&fileIndex=' + index"
|
||||
class="link-full"
|
||||
>
|
||||
{{
|
||||
file.label.length
|
||||
? file.label
|
||||
: file.name.replace(".pdf", "")
|
||||
}}
|
||||
</router-link>
|
||||
</h3>
|
||||
</hgroup>
|
||||
<div class="card__meta | flex">
|
||||
<time
|
||||
class="card__date | text-grey-700"
|
||||
:datetime="dayjs(file.modified).format('YYYY-M-DD')"
|
||||
>{{ dayjs(file.modified).format("DD MMMM YYYY") }}</time
|
||||
>
|
||||
{{
|
||||
file.label.length
|
||||
? file.label
|
||||
: file.name.replace(".pdf", "")
|
||||
}}
|
||||
</router-link>
|
||||
</h3>
|
||||
</hgroup>
|
||||
<div class="card__meta | flex">
|
||||
<time
|
||||
class="card__date | text-grey-700"
|
||||
:datetime="dayjs(file.modified).format('YYYY-M-DD')"
|
||||
>{{ dayjs(file.modified).format("DD MMMM YYYY") }}</time
|
||||
>
|
||||
</div>
|
||||
<template v-if="index === 0">
|
||||
<figure
|
||||
v-if="file.cover"
|
||||
class="card__images pdf-cover"
|
||||
style="aspect-ratio: unset"
|
||||
>
|
||||
<img :src="file.cover" alt="" />
|
||||
</figure>
|
||||
<div v-else class="card__images" data-icon="document"></div>
|
||||
</template>
|
||||
<footer
|
||||
v-if="file.comments?.length > 0"
|
||||
class="order-last | text-sm text-primary font-medium"
|
||||
>
|
||||
<template v-if="step.id === 'proposal'">
|
||||
<router-link
|
||||
:to="'/' + step.uri + '&fileIndex=' + index + '&comments'"
|
||||
</div>
|
||||
<template v-if="step.id === 'clientBrief' || index === 0">
|
||||
<figure
|
||||
v-if="file.cover"
|
||||
class="card__images pdf-cover"
|
||||
style="aspect-ratio: unset"
|
||||
>
|
||||
{{ file.comments.length }} commentaire{{
|
||||
file.comments.length > 1 ? "s" : ""
|
||||
}}
|
||||
</router-link>
|
||||
<img :src="file.cover" alt="" />
|
||||
</figure>
|
||||
<div v-else class="card__images" data-icon="document"></div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<router-link :to="'/' + step.uri + '&comments=true'">
|
||||
{{ file.comments.length }} commentaire{{
|
||||
file.comments.length > 1 ? "s" : ""
|
||||
}}
|
||||
</router-link>
|
||||
</template>
|
||||
</footer>
|
||||
</article>
|
||||
<footer
|
||||
v-if="file.comments?.length > 0"
|
||||
class="order-last | text-sm text-primary font-medium"
|
||||
>
|
||||
<template v-if="step.id === 'proposal'">
|
||||
<router-link
|
||||
:to="'/' + step.uri + '&fileIndex=' + index + '&comments'"
|
||||
>
|
||||
{{ file.comments.length }} commentaire{{
|
||||
file.comments.length > 1 ? "s" : ""
|
||||
}}
|
||||
</router-link>
|
||||
</template>
|
||||
<template v-else>
|
||||
<router-link :to="'/' + step.uri + '&comments=true'">
|
||||
{{ file.comments.length }} commentaire{{
|
||||
file.comments.length > 1 ? "s" : ""
|
||||
}}
|
||||
</router-link>
|
||||
</template>
|
||||
</footer>
|
||||
</article>
|
||||
</template>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
|
|
@ -189,16 +221,20 @@ import "dayjs/locale/fr";
|
|||
import { usePageStore } from "../../stores/page";
|
||||
import { computed } from "vue";
|
||||
import { useProjectStore } from "../../stores/project";
|
||||
import { useRouter } from "vue-router";
|
||||
import { useBriefStore } from "../../stores/brief";
|
||||
|
||||
const { step } = defineProps({
|
||||
step: Object,
|
||||
});
|
||||
|
||||
const emit = defineEmits(["update:file"]);
|
||||
const router = useRouter();
|
||||
|
||||
dayjs.locale("fr");
|
||||
|
||||
const { page } = usePageStore();
|
||||
const { addPdf } = useBriefStore();
|
||||
const { setStatus } = useProjectStore();
|
||||
|
||||
const steps = page.steps.map((item) => {
|
||||
|
|
@ -225,6 +261,16 @@ function getFrontView(track) {
|
|||
const frontView = track.files.find((file) => file.name === frontViewName);
|
||||
return frontView;
|
||||
}
|
||||
|
||||
function hasOneBriefType() {
|
||||
const hasImage = step.files.some((file) => file.type === "image");
|
||||
const hasDocument = step.files.some((file) => file.type === "document");
|
||||
return hasImage ^ hasDocument;
|
||||
}
|
||||
|
||||
function toImagesBrief() {
|
||||
router.push(location.pathname + "/client-brief?step=images");
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ watch(isOpen, (newValue) => {
|
|||
|
||||
openedFile.value = route.query.fileIndex
|
||||
? dialog.content.files[route.query.fileIndex]
|
||||
: dialog.content.files[0];
|
||||
: dialog.content.files.find((file) => file.type === "document");
|
||||
|
||||
// Functions
|
||||
async function validate() {
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@
|
|||
<input
|
||||
id="upload-pdf"
|
||||
type="file"
|
||||
@change="addPdf($event)"
|
||||
@change="addPdf($event, page.uri, true)"
|
||||
accept="application/pdf"
|
||||
ref="pdfInput"
|
||||
hidden
|
||||
|
|
@ -96,45 +96,13 @@
|
|||
import { ref } from "vue";
|
||||
import { usePageStore } from "../../../stores/page";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { useBriefStore } from "../../../stores/brief";
|
||||
|
||||
const emit = defineEmits("update:step");
|
||||
|
||||
const { page } = storeToRefs(usePageStore());
|
||||
const { addPdf } = useBriefStore();
|
||||
const pdfInput = ref(null);
|
||||
|
||||
async function addPdf(event) {
|
||||
const file = event.target.files[0];
|
||||
|
||||
if (file) {
|
||||
const formData = new FormData();
|
||||
formData.append("file", file);
|
||||
|
||||
try {
|
||||
const response = await fetch(
|
||||
"/upload-pdf.json?pageUri=" + page.value.uri,
|
||||
{
|
||||
method: "POST",
|
||||
body: formData,
|
||||
}
|
||||
);
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (response.ok) {
|
||||
console.log("File uploaded successfully.");
|
||||
page.value = result;
|
||||
location.href =
|
||||
location.origin + "/" + page.value.parent + "?dialog=client-brief";
|
||||
} else {
|
||||
console.error("Error uploading file:", result.error);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Request failed:", error);
|
||||
}
|
||||
} else {
|
||||
console.error("No file selected.");
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
|
|
|||
45
src/stores/brief.js
Normal file
45
src/stores/brief.js
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
import { defineStore } from "pinia";
|
||||
import { ref } from "vue";
|
||||
import { usePageStore } from "./page";
|
||||
|
||||
export const useBriefStore = defineStore("brief", () => {
|
||||
async function addPdf(event, briefUri, redirectToParent = false) {
|
||||
const file = event.target.files[0];
|
||||
const { page } = usePageStore();
|
||||
|
||||
if (file) {
|
||||
const formData = new FormData();
|
||||
formData.append("file", file);
|
||||
|
||||
try {
|
||||
const response = await fetch("/upload-pdf.json?pageUri=" + briefUri, {
|
||||
method: "POST",
|
||||
body: formData,
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (response.ok) {
|
||||
page.value = result;
|
||||
if (redirectToParent) {
|
||||
location.href =
|
||||
location.origin +
|
||||
"/" +
|
||||
page.value.parent +
|
||||
"?dialog=client-brief";
|
||||
} else {
|
||||
location.href = location.href + "?dialog=client-brief";
|
||||
}
|
||||
} else {
|
||||
console.error("Error uploading file:", result.error);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Request failed:", error);
|
||||
}
|
||||
} else {
|
||||
console.error("No file selected.");
|
||||
}
|
||||
}
|
||||
|
||||
return { addPdf };
|
||||
});
|
||||
|
|
@ -30,5 +30,12 @@ export const useProjectStore = defineStore("project", () => {
|
|||
}
|
||||
}
|
||||
|
||||
return { stepsLabels, setStatus };
|
||||
function isEmptyBrief(project) {
|
||||
return (
|
||||
project.currentStep === "clientBrief" &&
|
||||
project.steps[0].files.length === 0
|
||||
);
|
||||
}
|
||||
|
||||
return { stepsLabels, setStatus, isEmptyBrief };
|
||||
});
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
class="btn | ml-auto"
|
||||
@click="validate"
|
||||
v-if="page.content.isvalidated != 'true'"
|
||||
:disabled="page.files.length === 0"
|
||||
>
|
||||
Valider et envoyer le brief
|
||||
</button>
|
||||
|
|
@ -29,6 +30,7 @@ import TitledPdfWrapper from "../components/project/TitledPdfWrapper.vue";
|
|||
import { usePageStore } from "../stores/page";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { useApiStore } from "../stores/api";
|
||||
import { useRoute } from "vue-router";
|
||||
|
||||
const stepsComponents = {
|
||||
Intro,
|
||||
|
|
@ -47,6 +49,9 @@ function changeStep(stepName) {
|
|||
}
|
||||
|
||||
function setInitialStep() {
|
||||
if (useRoute().query.step === "images") {
|
||||
return "Images";
|
||||
}
|
||||
const hasPDF = page.value.content.pdf.length !== 0;
|
||||
const hasImages =
|
||||
page.value.content.moodboard.length !== 0 ||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue