mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-09-27 17:15:02 +00:00
Compare commits
3 Commits
710_vendee
...
58-birthda
Author | SHA1 | Date | |
---|---|---|---|
a136a278da
|
|||
9c85ad74ce | |||
fec2dd0f74 |
@@ -1,16 +1,12 @@
|
|||||||
<template>
|
<template>
|
||||||
<a v-if="!state.is_ready" :class="props.classes" @click="download_and_open($event)">
|
<a :class="props.classes" @click="download_and_open($event)">
|
||||||
<i class="fa fa-download"></i>
|
<i class="fa fa-download"></i>
|
||||||
Télécharger
|
Télécharger
|
||||||
</a>
|
</a>
|
||||||
<a v-else :class="props.classes" target="_blank" :type="props.storedObject.type" :download="buildDocumentName()" :href="state.href_url" ref="open_button">
|
|
||||||
<i class="fa fa-external-link"></i>
|
|
||||||
Ouvrir
|
|
||||||
</a>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import {reactive, ref, nextTick, onMounted} from "vue";
|
import {reactive} from "vue";
|
||||||
import {build_download_info_link, download_and_decrypt_doc} from "./helpers";
|
import {build_download_info_link, download_and_decrypt_doc} from "./helpers";
|
||||||
import mime from "mime";
|
import mime from "mime";
|
||||||
import {StoredObject} from "../../types";
|
import {StoredObject} from "../../types";
|
||||||
@@ -22,69 +18,35 @@ interface DownloadButtonConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface DownloadButtonState {
|
interface DownloadButtonState {
|
||||||
is_ready: boolean,
|
is_ready: boolean
|
||||||
is_running: boolean,
|
|
||||||
href_url: string,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = defineProps<DownloadButtonConfig>();
|
const props = defineProps<DownloadButtonConfig>();
|
||||||
const state: DownloadButtonState = reactive({is_ready: false, is_running: false, href_url: "#"});
|
const state: DownloadButtonState = reactive({is_ready: false});
|
||||||
|
|
||||||
const open_button = ref<HTMLAnchorElement | null>(null);
|
|
||||||
|
|
||||||
function buildDocumentName(): string {
|
|
||||||
const document_name = props.filename || 'document';
|
|
||||||
const ext = mime.getExtension(props.storedObject.type);
|
|
||||||
|
|
||||||
if (null !== ext) {
|
|
||||||
return document_name + '.' + ext;
|
|
||||||
}
|
|
||||||
|
|
||||||
return document_name;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function download_and_open(event: Event): Promise<void> {
|
async function download_and_open(event: Event): Promise<void> {
|
||||||
const button = event.target as HTMLAnchorElement;
|
const button = event.target as HTMLAnchorElement;
|
||||||
|
|
||||||
if (state.is_running) {
|
if (!state.is_ready) {
|
||||||
console.log('state is running, aborting');
|
event.preventDefault();
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
state.is_running = true;
|
|
||||||
|
|
||||||
if (state.is_ready) {
|
|
||||||
console.log('state is ready. This should not happens');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const urlInfo = build_download_info_link(props.storedObject.filename);
|
const urlInfo = build_download_info_link(props.storedObject.filename);
|
||||||
let raw;
|
|
||||||
|
|
||||||
try {
|
const raw = await download_and_decrypt_doc(urlInfo, props.storedObject.keyInfos, new Uint8Array(props.storedObject.iv));
|
||||||
raw = await download_and_decrypt_doc(urlInfo, props.storedObject.keyInfos, new Uint8Array(props.storedObject.iv));
|
|
||||||
} catch (e) {
|
button.href = window.URL.createObjectURL(raw);
|
||||||
console.error("error while downloading and decrypting document");
|
button.target = '_blank';
|
||||||
console.error(e);
|
button.type = props.storedObject.type;
|
||||||
throw e;
|
|
||||||
|
button.download = props.filename || 'document';
|
||||||
|
|
||||||
|
const ext = mime.getExtension(props.storedObject.type);
|
||||||
|
if (null !== ext) {
|
||||||
|
button.download = button.download + '.' + ext;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('document downloading (and decrypting) successfully');
|
|
||||||
|
|
||||||
console.log('creating the url')
|
|
||||||
state.href_url = window.URL.createObjectURL(raw);
|
|
||||||
console.log('url created', state.href_url);
|
|
||||||
state.is_running = false;
|
|
||||||
state.is_ready = true;
|
state.is_ready = true;
|
||||||
console.log('new button marked as ready');
|
|
||||||
console.log('will click on button');
|
|
||||||
|
|
||||||
console.log('openbutton is now', open_button.value);
|
button.click();
|
||||||
|
}
|
||||||
await nextTick();
|
|
||||||
console.log('next tick actions');
|
|
||||||
console.log('openbutton after next tick', open_button.value);
|
|
||||||
open_button.value?.click();
|
|
||||||
console.log('open button should have been clicked');
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@@ -149,21 +149,16 @@ async function download_and_decrypt_doc(urlGenerator: string, keyData: JsonWebKe
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (iv.length === 0) {
|
if (iv.length === 0) {
|
||||||
console.log('returning document immediatly');
|
|
||||||
return rawResponse.blob();
|
return rawResponse.blob();
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('start decrypting doc');
|
|
||||||
|
|
||||||
const rawBuffer = await rawResponse.arrayBuffer();
|
const rawBuffer = await rawResponse.arrayBuffer();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const key = await window.crypto.subtle
|
const key = await window.crypto.subtle
|
||||||
.importKey('jwk', keyData, { name: algo }, false, ['decrypt']);
|
.importKey('jwk', keyData, { name: algo }, false, ['decrypt']);
|
||||||
console.log('key created');
|
|
||||||
const decrypted = await window.crypto.subtle
|
const decrypted = await window.crypto.subtle
|
||||||
.decrypt({ name: algo, iv: iv }, key, rawBuffer);
|
.decrypt({ name: algo, iv: iv }, key, rawBuffer);
|
||||||
console.log('doc decrypted');
|
|
||||||
|
|
||||||
return Promise.resolve(new Blob([decrypted]));
|
return Promise.resolve(new Blob([decrypted]));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@@ -51,10 +51,7 @@ class UserRefEventSubscriber implements EventSubscriberInterface
|
|||||||
|
|
||||||
public function onStateEntered(EnteredEvent $enteredEvent): void
|
public function onStateEntered(EnteredEvent $enteredEvent): void
|
||||||
{
|
{
|
||||||
if (
|
if ($enteredEvent->getMarking()->has(AccompanyingPeriod::STEP_CONFIRMED)) {
|
||||||
$enteredEvent->getMarking()->has(AccompanyingPeriod::STEP_CONFIRMED)
|
|
||||||
and $enteredEvent->getTransition()->getName() === 'confirm'
|
|
||||||
) {
|
|
||||||
$this->onPeriodConfirmed($enteredEvent->getSubject());
|
$this->onPeriodConfirmed($enteredEvent->getSubject());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -122,8 +122,7 @@
|
|||||||
<add-evaluation
|
<add-evaluation
|
||||||
v-for="e in pickedEvaluations"
|
v-for="e in pickedEvaluations"
|
||||||
v-bind:key="e.key"
|
v-bind:key="e.key"
|
||||||
v-bind:evaluation="e"
|
v-bind:evaluation="e">
|
||||||
v-bind:docAnchorId="this.docAnchorId">
|
|
||||||
</add-evaluation>
|
</add-evaluation>
|
||||||
|
|
||||||
<!-- box to add new evaluation -->
|
<!-- box to add new evaluation -->
|
||||||
@@ -390,7 +389,6 @@ export default {
|
|||||||
i18n,
|
i18n,
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
docAnchorId: null,
|
|
||||||
isExpanded: false,
|
isExpanded: false,
|
||||||
editor: ClassicEditor,
|
editor: ClassicEditor,
|
||||||
showAddObjective: false,
|
showAddObjective: false,
|
||||||
@@ -430,13 +428,6 @@ export default {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
beforeMount() {
|
|
||||||
const urlParams = new URLSearchParams(window.location.search);
|
|
||||||
this.docAnchorId = urlParams.get('doc_id');
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.scrollToElement(this.docAnchorId);
|
|
||||||
},
|
|
||||||
computed: {
|
computed: {
|
||||||
...mapState([
|
...mapState([
|
||||||
'work',
|
'work',
|
||||||
@@ -568,7 +559,7 @@ export default {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
saveFormOnTheFly(payload) {
|
saveFormOnTheFly(payload) {
|
||||||
// console.log('saveFormOnTheFly: type', payload.type, ', data', payload.data);
|
console.log('saveFormOnTheFly: type', payload.type, ', data', payload.data);
|
||||||
|
|
||||||
let body = { type: payload.type };
|
let body = { type: payload.type };
|
||||||
body.name = payload.data.text;
|
body.name = payload.data.text;
|
||||||
@@ -590,12 +581,6 @@ export default {
|
|||||||
this.$toast.open({message: 'An error occurred'});
|
this.$toast.open({message: 'An error occurred'});
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
|
||||||
scrollToElement(docAnchorId) {
|
|
||||||
const documentEl = document.getElementById(`document_${docAnchorId}`);
|
|
||||||
if (documentEl) {
|
|
||||||
documentEl.scrollIntoView({behavior: 'smooth'});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@@ -11,7 +11,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<form-evaluation ref="FormEvaluation" :key="evaluation.key" :evaluation="evaluation" :docAnchorId="docAnchorId"></form-evaluation>
|
<form-evaluation ref="FormEvaluation" :key="evaluation.key" :evaluation="evaluation"></form-evaluation>
|
||||||
|
|
||||||
<ul class="record_actions">
|
<ul class="record_actions">
|
||||||
<li v-if="evaluation.workflows_availables.length > 0">
|
<li v-if="evaluation.workflows_availables.length > 0">
|
||||||
@@ -85,7 +85,7 @@ export default {
|
|||||||
Modal,
|
Modal,
|
||||||
ListWorkflowModal,
|
ListWorkflowModal,
|
||||||
},
|
},
|
||||||
props: ['evaluation', 'docAnchorId'],
|
props: ['evaluation'],
|
||||||
i18n,
|
i18n,
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
@@ -80,13 +80,12 @@
|
|||||||
|
|
||||||
<div class="flex-table">
|
<div class="flex-table">
|
||||||
<div class="item-bloc" v-for="(d, i) in evaluation.documents" :key="d.id">
|
<div class="item-bloc" v-for="(d, i) in evaluation.documents" :key="d.id">
|
||||||
<div :id="`document_${d.id}`" class="item-row">
|
<div class="item-row">
|
||||||
<div class="input-group input-group-lg mb-3 row">
|
<div class="input-group input-group-lg mb-3 row">
|
||||||
<label class="col-sm-3 col-form-label">Titre du document:</label>
|
<label class="col-sm-3 col-form-label">Titre du document:</label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<input
|
<input
|
||||||
class="form-control document-title"
|
class="form-control document-title"
|
||||||
:class="[parseInt(this.docAnchorId) === d.id ? 'bg-blink' : 'nothing']"
|
|
||||||
type="text"
|
type="text"
|
||||||
:value="d.title"
|
:value="d.title"
|
||||||
:id="d.id"
|
:id="d.id"
|
||||||
@@ -222,7 +221,7 @@ const i18n = {
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "FormEvaluation",
|
name: "FormEvaluation",
|
||||||
props: ['evaluation', 'docAnchorId'],
|
props: ['evaluation'],
|
||||||
components: {
|
components: {
|
||||||
ckeditor: CKEditor.component,
|
ckeditor: CKEditor.component,
|
||||||
PickTemplate,
|
PickTemplate,
|
||||||
@@ -403,19 +402,4 @@ export default {
|
|||||||
ul.document-upload {
|
ul.document-upload {
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bg-blink{
|
|
||||||
color: #050000;
|
|
||||||
padding: 10px;
|
|
||||||
display: inline-block;
|
|
||||||
border-radius: 5px;
|
|
||||||
animation: blinkingBackground 2.2s infinite;
|
|
||||||
animation-iteration-count: 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes blinkingBackground{
|
|
||||||
0% { background-color: #ed776d;}
|
|
||||||
50% { background-color: #ffffff;}
|
|
||||||
100% { background-color: #ed776d;}
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
@@ -207,7 +207,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import {dateToISO} from 'ChillMainAssets/chill/js/date';
|
import {dateToISO, ISOToDate} from 'ChillMainAssets/chill/js/date';
|
||||||
import AddressRenderBox from 'ChillMainAssets/vuejs/_components/Entity/AddressRenderBox.vue';
|
import AddressRenderBox from 'ChillMainAssets/vuejs/_components/Entity/AddressRenderBox.vue';
|
||||||
import Confidential from 'ChillMainAssets/vuejs/_components/Confidential.vue';
|
import Confidential from 'ChillMainAssets/vuejs/_components/Confidential.vue';
|
||||||
import BadgeEntity from 'ChillMainAssets/vuejs/_components/BadgeEntity.vue';
|
import BadgeEntity from 'ChillMainAssets/vuejs/_components/BadgeEntity.vue';
|
||||||
@@ -262,7 +262,7 @@ export default {
|
|||||||
},
|
},
|
||||||
birthdate: function () {
|
birthdate: function () {
|
||||||
if (this.person.birthdate !== null || this.person.birthdate === "undefined") {
|
if (this.person.birthdate !== null || this.person.birthdate === "undefined") {
|
||||||
return new Date(this.person.birthdate.datetime);
|
return ISOToDate(this.person.birthdate.datetime);
|
||||||
} else {
|
} else {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
@@ -16,13 +16,11 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="wh-col">
|
<div class="wh-col">
|
||||||
{% if period.step == 'DRAFT' %}
|
{% if period.step == 'DRAFT' %}
|
||||||
<span class="badge bg-secondary" style="font-size: 85%;" title="{{ 'course.draft'|trans|e('html_attr') }}">{{ 'course.draft'|trans }}</span>
|
<span class="badge bg-secondary">{{- 'Draft'|trans|upper -}}</span>
|
||||||
{% elseif period.step == 'CLOSED' %}
|
{% elseif period.step == 'CONFIRMED' %}
|
||||||
<span class="badge bg-danger" style="font-size: 85%;" title="{{ 'course.closed'|trans|e('html_attr') }}">{{ 'course.closed'|trans }}</span>
|
<span class="badge bg-primary">{{- 'Confirmed'|trans|upper -}}</span>
|
||||||
{% elseif period.step == 'CONFIRMED_INACTIVE_SHORT' %}
|
{% else %}
|
||||||
<span class="badge bg-chill-yellow text-primary" style="font-size: 85%;" title="{{ 'course.inactive_short'|trans|e('html_attr') }}">{{ 'course.inactive_short'|trans }}</span>
|
<span class="badge bg-danger">{{- 'Closed'|trans|upper -}}</span>
|
||||||
{% elseif period.step == 'CONFIRMED_INACTIVE_LONG' %}
|
|
||||||
<span class="badge bg-danger" style="font-size: 85%;" title="{{ 'course.inactive_long'|trans|e('html_attr') }}">{{ 'course.inactive_long'|trans }}</span>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -123,7 +123,7 @@
|
|||||||
<ul class="record_actions">
|
<ul class="record_actions">
|
||||||
<li>{{ doc.storedObject|chill_document_button_group(doc.title, is_granted('CHILL_MAIN_ACCOMPANYING_PERIOD_WORK_UPDATE', evaluation.accompanyingPeriodWork)) }}</li>
|
<li>{{ doc.storedObject|chill_document_button_group(doc.title, is_granted('CHILL_MAIN_ACCOMPANYING_PERIOD_WORK_UPDATE', evaluation.accompanyingPeriodWork)) }}</li>
|
||||||
<li>
|
<li>
|
||||||
<a class="btn btn-show" href="{{ path('chill_person_accompanying_period_work_edit', {'id': evaluation.accompanyingPeriodWork.id, 'doc_id': doc.id}) }}">
|
<a class="btn btn-show" href="{{ path('chill_person_accompanying_period_work_edit', {'id': evaluation.accompanyingPeriodWork.id}) }}">
|
||||||
{{ 'Show'|trans }}
|
{{ 'Show'|trans }}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
Reference in New Issue
Block a user