mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-09-10 08:44:58 +00:00
Compare commits
6 Commits
58-birthda
...
upgrade-ph
Author | SHA1 | Date | |
---|---|---|---|
d1a4891b9d
|
|||
5749660760 | |||
b679dbe26c
|
|||
6c3fa5cb98
|
|||
6bdd1f31d3 | |||
ff3dab0934
|
@@ -2,11 +2,20 @@
|
||||
|
||||
<!-- https://phpunit.readthedocs.io/en/latest/configuration.html -->
|
||||
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="tests/app/vendor/phpunit/phpunit/phpunit.xsd"
|
||||
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.6/phpunit.xsd"
|
||||
backupGlobals="false"
|
||||
colors="true"
|
||||
bootstrap="tests/app/tests/bootstrap.php"
|
||||
>
|
||||
cacheResultFile=".phpunit.cache/test-results"
|
||||
executionOrder="depends,defects"
|
||||
forceCoversAnnotation="true"
|
||||
beStrictAboutCoversAnnotation="true"
|
||||
beStrictAboutOutputDuringTests="true"
|
||||
beStrictAboutTodoAnnotatedTests="true"
|
||||
convertDeprecationsToExceptions="true"
|
||||
failOnRisky="true"
|
||||
failOnWarning="true"
|
||||
verbose="true">
|
||||
<php>
|
||||
<ini name="error_reporting" value="-1" />
|
||||
<server name="APP_ENV" value="test" force="true" />
|
||||
|
@@ -1,52 +1,90 @@
|
||||
<template>
|
||||
<a :class="props.classes" @click="download_and_open($event)">
|
||||
<i class="fa fa-download"></i>
|
||||
Télécharger
|
||||
</a>
|
||||
<a v-if="!state.is_ready" :class="props.classes" @click="download_and_open($event)">
|
||||
<i class="fa fa-download"></i>
|
||||
Télécharger
|
||||
</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>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import {reactive} from "vue";
|
||||
import {reactive, ref, nextTick, onMounted} from "vue";
|
||||
import {build_download_info_link, download_and_decrypt_doc} from "./helpers";
|
||||
import mime from "mime";
|
||||
import {StoredObject} from "../../types";
|
||||
|
||||
interface DownloadButtonConfig {
|
||||
storedObject: StoredObject,
|
||||
classes: {[k: string]: boolean},
|
||||
filename?: string,
|
||||
storedObject: StoredObject,
|
||||
classes: { [k: string]: boolean },
|
||||
filename?: string,
|
||||
}
|
||||
|
||||
interface DownloadButtonState {
|
||||
is_ready: boolean
|
||||
is_ready: boolean,
|
||||
is_running: boolean,
|
||||
href_url: string,
|
||||
}
|
||||
|
||||
const props = defineProps<DownloadButtonConfig>();
|
||||
const state: DownloadButtonState = reactive({is_ready: false});
|
||||
const state: DownloadButtonState = reactive({is_ready: false, is_running: false, href_url: "#"});
|
||||
|
||||
async function download_and_open(event: Event): Promise<void> {
|
||||
const button = event.target as HTMLAnchorElement;
|
||||
|
||||
if (!state.is_ready) {
|
||||
event.preventDefault();
|
||||
const urlInfo = build_download_info_link(props.storedObject.filename);
|
||||
|
||||
const raw = await download_and_decrypt_doc(urlInfo, props.storedObject.keyInfos, new Uint8Array(props.storedObject.iv));
|
||||
|
||||
button.href = window.URL.createObjectURL(raw);
|
||||
button.target = '_blank';
|
||||
button.type = props.storedObject.type;
|
||||
|
||||
button.download = props.filename || 'document';
|
||||
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) {
|
||||
button.download = button.download + '.' + ext;
|
||||
return document_name + '.' + ext;
|
||||
}
|
||||
|
||||
state.is_ready = true;
|
||||
return document_name;
|
||||
}
|
||||
|
||||
button.click();
|
||||
}
|
||||
async function download_and_open(event: Event): Promise<void> {
|
||||
const button = event.target as HTMLAnchorElement;
|
||||
|
||||
if (state.is_running) {
|
||||
console.log('state is running, aborting');
|
||||
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);
|
||||
let raw;
|
||||
|
||||
try {
|
||||
raw = await download_and_decrypt_doc(urlInfo, props.storedObject.keyInfos, new Uint8Array(props.storedObject.iv));
|
||||
} catch (e) {
|
||||
console.error("error while downloading and decrypting document");
|
||||
console.error(e);
|
||||
throw e;
|
||||
}
|
||||
|
||||
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;
|
||||
console.log('new button marked as ready');
|
||||
console.log('will click on button');
|
||||
|
||||
console.log('openbutton is now', open_button.value);
|
||||
|
||||
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>
|
||||
|
@@ -149,16 +149,21 @@ async function download_and_decrypt_doc(urlGenerator: string, keyData: JsonWebKe
|
||||
}
|
||||
|
||||
if (iv.length === 0) {
|
||||
console.log('returning document immediatly');
|
||||
return rawResponse.blob();
|
||||
}
|
||||
|
||||
console.log('start decrypting doc');
|
||||
|
||||
const rawBuffer = await rawResponse.arrayBuffer();
|
||||
|
||||
try {
|
||||
const key = await window.crypto.subtle
|
||||
.importKey('jwk', keyData, { name: algo }, false, ['decrypt']);
|
||||
console.log('key created');
|
||||
const decrypted = await window.crypto.subtle
|
||||
.decrypt({ name: algo, iv: iv }, key, rawBuffer);
|
||||
console.log('doc decrypted');
|
||||
|
||||
return Promise.resolve(new Blob([decrypted]));
|
||||
} catch (e) {
|
||||
|
@@ -51,7 +51,10 @@ class UserRefEventSubscriber implements EventSubscriberInterface
|
||||
|
||||
public function onStateEntered(EnteredEvent $enteredEvent): void
|
||||
{
|
||||
if ($enteredEvent->getMarking()->has(AccompanyingPeriod::STEP_CONFIRMED)) {
|
||||
if (
|
||||
$enteredEvent->getMarking()->has(AccompanyingPeriod::STEP_CONFIRMED)
|
||||
and $enteredEvent->getTransition()->getName() === 'confirm'
|
||||
) {
|
||||
$this->onPeriodConfirmed($enteredEvent->getSubject());
|
||||
}
|
||||
}
|
||||
|
@@ -16,11 +16,13 @@
|
||||
</div>
|
||||
<div class="wh-col">
|
||||
{% if period.step == 'DRAFT' %}
|
||||
<span class="badge bg-secondary">{{- 'Draft'|trans|upper -}}</span>
|
||||
{% elseif period.step == 'CONFIRMED' %}
|
||||
<span class="badge bg-primary">{{- 'Confirmed'|trans|upper -}}</span>
|
||||
{% else %}
|
||||
<span class="badge bg-danger">{{- 'Closed'|trans|upper -}}</span>
|
||||
<span class="badge bg-secondary" style="font-size: 85%;" title="{{ 'course.draft'|trans|e('html_attr') }}">{{ 'course.draft'|trans }}</span>
|
||||
{% elseif period.step == 'CLOSED' %}
|
||||
<span class="badge bg-danger" style="font-size: 85%;" title="{{ 'course.closed'|trans|e('html_attr') }}">{{ 'course.closed'|trans }}</span>
|
||||
{% elseif period.step == 'CONFIRMED_INACTIVE_SHORT' %}
|
||||
<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>
|
||||
{% 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 %}
|
||||
</div>
|
||||
</div>
|
||||
|
Reference in New Issue
Block a user