Skip to content

Commit

Permalink
Ajoute l'upload de fichiers associés à du matériel (partie client) (#92)
Browse files Browse the repository at this point in the history
  • Loading branch information
polosson committed Feb 11, 2021
1 parent c0a0cf2 commit 06ed7af
Show file tree
Hide file tree
Showing 28 changed files with 796 additions and 17 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Ce projet adhère au principe du [Semantic Versioning](https://semver.org/spec/v
- Améliore le calcul du matériel restant dans les événements.
- Ajoute la possibilité de limiter les caractéristiques spéciales du matériel par catégorie (#91).
- Ajoute le type "date" aux caractéristiques spéciales du matériel (#90).
- Permet l'envoi de documents (fichiers PDF, images JPEG ou PNG) associés à du matériel (#92).

## 0.11.0 (2021-01-14)

Expand Down
16 changes: 11 additions & 5 deletions client/src/components/Alert/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,23 @@ const ConfirmDelete = ($t, entityName, isSoft = true) => Swal.fire({
text: isSoft
? $t(`page-${entityName}.confirm-delete`)
: $t(`page-${entityName}.confirm-permanently-delete`),
type: 'warning',
icon: 'warning',
showCancelButton: true,
confirmButtonClass: isSoft ? 'swal2-confirm--trash' : 'swal2-confirm--delete',
customClass: {
confirmButton: isSoft ? 'swal2-confirm--trash' : 'swal2-confirm--delete',
},
confirmButtonText: isSoft ? $t('yes-delete') : $t('yes-permanently-delete'),
cancelButtonText: $t('cancel'),
});

const ConfirmRestore = ($t, entityName) => Swal.fire({
title: $t('please-confirm'),
text: $t(`page-${entityName}.confirm-restore`),
type: 'warning',
icon: 'warning',
showCancelButton: true,
confirmButtonClass: 'swal2-confirm--restore',
customClass: {
confirmButton: 'swal2-confirm--restore',
},
confirmButtonText: $t('yes-restore'),
cancelButtonText: $t('cancel'),
});
Expand All @@ -28,7 +32,9 @@ const Prompt = ($t, title, placeholder, confirmText, inputValue = '') => Swal.fi
inputPlaceholder: $t(placeholder),
inputValue,
showCancelButton: true,
confirmButtonClass: 'swal2-confirm--success',
customClass: {
confirmButton: 'swal2-confirm--success',
},
confirmButtonText: $t(confirmText),
cancelButtonText: $t('cancel'),
});
Expand Down
18 changes: 18 additions & 0 deletions client/src/components/Progressbar/Progressbar.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
.Progressbar {
position: relative;
height: 20px;
width: 100%;
background: $bg-color-tooltip;
border-radius: $input-border-radius;

&__progress {
position: absolute;
left: 0;
top: 0;
bottom: 0;
background: $bg-color-button-info;
border-radius: $input-border-radius;
text-align: center;
overflow: hidden;
}
}
27 changes: 27 additions & 0 deletions client/src/components/Progressbar/Progressbar.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<template>
<div class="Progressbar">
<div class="Progressbar__progress" :style="{ width: `${percent}%` }">
<span v-if="percent < 100">{{ humanPercent }}%</span>
<span v-if="percent === 100">{{ $t('almost-done') }}</span>
</div>
</div>
</template>

<style lang="scss">
@import '../../themes/default/index';
@import './Progressbar';
</style>

<script>
export default {
name: 'Progressbar',
props: {
percent: { type: Number, required: true },
},
computed: {
humanPercent() {
return Math.round(this.percent);
},
},
};
</script>
26 changes: 25 additions & 1 deletion client/src/config/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,28 @@ const DATE_DB_FORMAT = 'YYYY-MM-DD HH:mm:ss';
const DATE_QUERY_FORMAT = 'YYYY-MM-DD';
const DEBOUNCE_WAIT = 500; // - in miliseconds

export { DATE_DB_FORMAT, DATE_QUERY_FORMAT, DEBOUNCE_WAIT };
const AUTHORIZED_FILE_TYPES = [
'application/pdf',
'application/zip',
'application/x-rar-compressed',
'image/jpeg',
'image/png',
'image/webp',
'text/plain',
'application/vnd.oasis.opendocument.spreadsheet',
'application/vnd.ms-excel',
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'application/vnd.oasis.opendocument.text',
'application/msword',
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
];

const MAX_FILE_SIZE = 10 * 1024 * 1024; // 10 MB

export {
DATE_DB_FORMAT,
DATE_QUERY_FORMAT,
DEBOUNCE_WAIT,
AUTHORIZED_FILE_TYPES,
MAX_FILE_SIZE,
};
2 changes: 2 additions & 0 deletions client/src/locale/en/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export default {
'close': "Close",
'copy-to-clipboard': "Copy to clipboard",
'copied-in-clipboard': "Copied in clipboard!",
'almost-done': "Almost done...",

'please-choose': "Please choose...",
'start-typing-to-search': "Start typing to search...",
Expand All @@ -53,6 +54,7 @@ export default {
'personnal-infos': "Personnal informations",
'minimal-infos': "Minimal informations",
'billing-infos': "Billing informations",
'documents': "Documents",
'billing': "Billing",
'extra-infos': "Extra informations",
'special-attributes': "Special attributes",
Expand Down
4 changes: 4 additions & 0 deletions client/src/locale/en/errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ export default {
'details-message': "Error message",
'details-file': "File:",
'details-stacktrace': "Stack trace:",

'file-type-not-allowed': "Type '{type}' not supported.",
'file-size-exceeded': "File too large. Maximum {max}.",
'file-already-exists': "This file already exists in the list.",
},
};
/* eslint-enable quotes */
Expand Down
16 changes: 16 additions & 0 deletions client/src/locale/en/pages.js
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,22 @@ export default {
'clear-filters': "Clear filters",
},

'page-materials-view': {
'documents': {
'no-document': "No document yet.",
'drag-and-drop-files-here': "Drag and drop files here ↓ to add them.",
'choose-files': "Or click here to choose files to add",
'send-files': [
"Send file",
"Send {count} files",
],
'click-to-open': "Click to open / download file",
'confirm-permanently-delete': "Do you really want to permanently delete this document?",
'saved': "Documents saved.",
'deleted': "Document deleted.",
},
},

'page-attributes': {
'title': "Material special attributes",
'help': "Here you can check, and add fields that allows you to describe your material according to your own criteria.",
Expand Down
2 changes: 2 additions & 0 deletions client/src/locale/fr/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export default {
'close': "Fermer",
'copy-to-clipboard': "Copier dans le presse-papier",
'copied-in-clipboard': "Copié dans le presse-papier\u00a0!",
'almost-done': "Presque terminé...",

'please-choose': "Veuillez choisir...",
'start-typing-to-search': "Commencez à écrire pour rechercher...",
Expand All @@ -54,6 +55,7 @@ export default {
'minimal-infos': "Informations minimales",
'extra-infos': "Informations supplémentaires",
'billing-infos': "Informations de facturation",
'documents': "Documents",
'billing': "Facturation",
'special-attributes': "Caractéristiques spéciales",
'pseudo': "Pseudo",
Expand Down
4 changes: 4 additions & 0 deletions client/src/locale/fr/errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ export default {
'details-message': "Message de l'erreur",
'details-file': "Fichier\u00a0:",
'details-stacktrace': "Trace de la pile\u00a0:",

'file-type-not-allowed': "Le type '{type}' n'est pas pris en charge.",
'file-size-exceeded': "Fichier trop gros. Maximum {max}.",
'file-already-exists': "Ce fichier est déjà présent dans la liste.",
},
};
/* eslint-enable quotes */
Expand Down
16 changes: 16 additions & 0 deletions client/src/locale/fr/pages.js
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,22 @@ export default {
'clear-filters': "Réinitialiser les filtres",
},

'page-materials-view': {
'documents': {
'no-document': "Aucun document pour le moment.",
'drag-and-drop-files-here': "Glissez-déposez des fichiers ici ↓ pour les ajouter.",
'choose-files': "Ou cliquez ici pour choisir des fichiers à ajouter",
'send-files': [
"Envoyer le fichier",
"Envoyer {count} fichiers",
],
'click-to-open': "Cliquez pour ouvrir / télécharger le fichier",
'confirm-permanently-delete': "Voulez-vous vraiment supprimer définitivement ce document\u00a0?",
'saved': "Documents sauvegardés.",
'deleted': "Document supprimé.",
},
},

'page-attributes': {
'title': "Caractéristiques spéciales du matériel",
'help': "Ici vous pouvez consulter, et ajouter les champs qui permettent de décrire votre matériel selon vos propres critères.",
Expand Down
32 changes: 32 additions & 0 deletions client/src/pages/MaterialView/Documents/Documents.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
.MaterialViewDocuments {
height: calc(100% - 10px);
display: flex;
flex-wrap: wrap;

&__main {
flex: 1;
min-width: 300px;

.Help {
margin-top: $content-padding-large-vertical;
text-align: center;
}
}

&__no-document {
margin: 30px 0 0;
text-align: center;
font-size: 1.2rem;
color: $text-light-color;
font-style: italic;
}

&__list {
margin: 0;
padding: 0 $content-padding-small-vertical 0 0;
}

.MaterialViewDocumentsUpload {
flex: 1;
}
}
30 changes: 30 additions & 0 deletions client/src/pages/MaterialView/Documents/Documents.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<template>
<div class="MaterialViewDocuments">
<section class="MaterialViewDocuments__main">
<p v-if="documents.length === 0" class="MaterialViewDocuments__no-document">
{{ $t('page-materials-view.documents.no-document') }}
</p>
<ul v-if="documents.length > 0" class="MaterialViewDocuments__list">
<DocumentItem
v-for="document in documents"
:key="document.id"
:file="document"
@remove="removeDocument"
/>
</ul>
<Help
:message="help"
:error="error"
:isLoading="isLoading"
/>
</section>
<DocumentUpload :materialId="materialId" @uploadSuccess="handleUploadSuccess" />
</div>
</template>

<style lang="scss">
@import '../../../themes/default/index';
@import './Documents';
</style>

<script src="./index.js"></script>
61 changes: 61 additions & 0 deletions client/src/pages/MaterialView/Documents/Item/Item.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
.MaterialViewDocumentsItem {
display: flex;
align-items: center;
list-style: none;
margin: 0 0 10px;
padding: 0;
background: $bg-color-emphasis;
color: $text-base-color;
border-radius: $input-border-radius;

&__link,
&__no-link {
display: block;
padding: $content-padding-small-vertical;
}

&__icon {
flex: 0 0 auto;
font-size: 1.8rem;

.MaterialViewDocumentsItem__link,
.MaterialViewDocumentsItem__no-link {
margin-left: $content-padding-small-vertical;
}
}

&__name {
flex: 1;
}

&__size {
flex: 0 0 auto;
color: $text-light-color;
margin-right: $content-padding-small-vertical;
}

&__actions {
flex: 0 0 auto;
padding-right: $content-padding-small-vertical;
}

&--with-link {
.MaterialViewDocumentsItem {
&__link,
&__no-link {
color: $text-base-color;
}
}

&:hover {
background-color: lighten($bg-color-emphasis, 5%);

.MaterialViewDocumentsItem {
&__link,
&__no-link {
color: $link-hover-color;
}
}
}
}
}
46 changes: 46 additions & 0 deletions client/src/pages/MaterialView/Documents/Item/Item.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<template>
<li
class="MaterialViewDocumentsItem"
:class="{ 'MaterialViewDocumentsItem--with-link': !!file.id }"
>
<div class="MaterialViewDocumentsItem__icon">
<a
v-if="file.id"
:href="fileUrl"
target="_blank" class="MaterialViewDocumentsItem__link"
:title="$t('page-materials-view.documents.click-to-open')"
>
<i class="fas" :class="iconName" />
</a>
<span v-else class="MaterialViewDocumentsItem__no-link">
<i class="fas" :class="iconName" />
</span>
</div>
<div class="MaterialViewDocumentsItem__name">
<a
v-if="file.id"
:href="fileUrl"
target="_blank" class="MaterialViewDocumentsItem__link"
:title="$t('page-materials-view.documents.click-to-open')"
>
{{ file.name }}
</a>
<span v-else class="MaterialViewDocumentsItem__no-link">
{{ file.name }}
</span>
</div>
<div class="MaterialViewDocumentsItem__size">
{{ fileSize }}
</div>
<div class="MaterialViewDocumentsItem__actions">
<button class="danger" @click="handleClickRemove"><i class="fas fa-trash" /></button>
</div>
</li>
</template>

<style lang="scss">
@import '../../../../themes/default/index';
@import './Item';
</style>

<script src="./index.js"></script>
Loading

0 comments on commit 06ed7af

Please sign in to comment.