Commit a02a25e8 authored by Quentin David's avatar Quentin David
Browse files

Update of server & client

parent 76415a20
INPUT:
article1.txt
article2.txt
article3.txt
Collection corpus:
[Documents][3]
Documents 1:
documentid
INPUT : C'est possible d'avoir plusieurs fichiers
PROCESSUS/ PIPELINE : C'est mieux de rassembler en un unique fichier texte "corpus"
( fusion + concatenation, perte de l'arborescence )
VISUALISATION: Il faut retrouver l'arborescence et un format de lecture pour chaque fichier
( retour vers le source décrit lors de la création du corpus, ou division des documents à partir du conllu )
Corpus public:
type: public
createdBy: jojo
creationDate: osef
metadata: osef
documents[]
Où est contenu le texte de ce corpus ?
MetaCollection PipelineXCorpus:
pipelineId
corpusId
conllu
outputs[]
annotations[]
Documents:
documentid
source1 (path vers un fichier)
source2 (dérivation du conllu)
conlluBuffer (tokenization) [1 COLONNE: FORME, avec indexligne = token ()]
Source1 peut etre de différent types : XML, HTML, txt, pdf
Pour passer au conllu, on passe par un format String
Input:
article1.txt
article2.txt
article3.txt
Pipeline: p1
Validate
-> Creation de Corpus:
corpusId: _c1_
createdBy: moi
creationDate: now
type: private
{metadata } : null
documents:[
{
documentid: _d1_,
source: article1.txt,
conlluBuffer: null
},
{
documentid: _d2_,
source: article2.txt,
conlluBuffer: null
},
{
documentid: _d3_,
source: article3.txt,
conlluBuffer: null
}
]
-> Creation de pipeline: pipelineId: _p1_
-> Construction de conlluBuffer
À partir des fichiers sources on construit ConlluBuffer qui n'est d'autre que le fichier source tokenisé.
Donc une seule colonne qui correspond au token/forme
_c1_.documents[0].conlluBuffer= translatedAsConllu(article1.txt)
-> Construction de CorpusProcess
CorpusProcess est l'assemblage d'un corpus & d'une pipeline, lancé par un utilisateur.
Durant l'initialisation, il y a concaténation des différents conlluBuffer de chaque document du corpus afin
de créer un unique fichier conllu.
corpusProcessId: _cp1_
corpusId: _c1_
pipelineId: _p1_
userId: moi
conllu: { // On concatène les conllu buffer des différents Documents pour créer cette propriété
[{
columnId: _conllu1_,
columnTitle: FORM
columnContent: .... // tokenization de l'ensemble des documents du corpus
}],
annotatedDocuments: [{
documentId: _d1_,
corpusProcessId: _cp1_,
annotations: []
},
{
documentId: _d2_,
corpusProcessId: _cp1_,
annotations: []
},
{
documentId: _d3_,
corpusProcessId: _cp1_,
annotations: []
}],
outputs: [],
currentProcessingModule: null,
status: Not started yet
}
-> Démarrage de la chaine de traitement
En suivant les instructions de la pipeline _p1_, on démarre le premier module avec les paramètres correspondant.
_cp1_ est mis à jour
currentProcessingModule: _m1_,
status: Started
conllu: ajouter à la liste
{
columnId: _conllu2_,
columnTitle: Module1,
columnContent: Annotations du Module1
}
outputs: ajouter à la liste
{
processId: _process1_,
moduleName: Module1,
content: Output éventuellement retourné par Module1
}
-> Prochain module... & fin de la pipeline
Une fois un process terminé, on peut démarrer le suivant et updater _cp1_.currentProcessingModule.
Quand la pipeline est terminée sans erreur, _cp1_.status est mis à jour: Finished
-> Construction des annotations
À partir de la propriété conllu de _cp1_, on peut construire pour chaque colonne les annotations.
On sépare donc la colonne conllu en documents, puis on construit le format annotation.
On l'ajoute ensuite aux documents respectifs:
Ajout à _cp1_.annotatedDocuments[0].annotations:
{
processId: _process1_,
columnId: _conllu2_,
moduleName: Module1,
content: {
title: Annotation du Module1,
description: Voicil'annotation.,
data: annotationData du Module1
},
color: blue
}
......@@ -27,27 +27,37 @@ See [Configuration Reference](https://cli.vuejs.org/config/).
### Define corpus
* Prévoir une taille maximum pour les fichiers en input
* Réfléchir comment enregistrer les documents et éviter les doublons (id ?)
* Pouvoir supprimer les fichiers selons certains conditions (utilisateur n'apas été jusqu'au bout de l'UX, au bout de X jours pour un utilisateur anonyme)
* Option du corpus devrait apparaître uniquement lorsque "depuis un fichier local" ou "depuis un champ de texte" ?
* Faire le formulaire qui sera stocké lors de l'appuie de suivant
* Checkez pour mieux aligner les différents
-> Il apparaîtra à chaque fois, cependant, il sera prérempli dans le cas de corpora déjà précréés
### Define treatment
### Define pipeline
* Faire le formulaire des paramètres
* Faire le lien avec la timeline
* Ajouter l'option delete dans la timeline
* Enlever un module quand il est déjà selectionné dans la timeline ?
* Prévoir les modules affichés en fonction de la langue du corpus
### Display Results
### Prevalidation
* Revoir la présentation globale
### Validation
* Checker si utilisateur connecté ou non
* Si non connecté, donner un lien à consulter pour ses résultats.
### Display Results (Visualization tool)
* Voir comment mieux gérer le redimensionnement -> Check ?
* Regarder comment avoir un treeview clickable (possible ? ) -> DOne
* Regarder comment avoir un treeview clickable (possible ? ) -> Done
* Faire une transition pour afficher ou cacher le paneau de droite
* Checker pour faire des titres (Paneau d'annotation, Panneau de document...)
- Panneau de droite : Chaque étiquette doit avoir une couleur
### Others
* Implementer Vuex ?
* Implementer Vuex ? Fait mais non utilisé
* Implementer i18n pour la localization
* Detecting user locale
......
......@@ -12,28 +12,31 @@
<v-tabs-items v-model="tab" class="my-4" vertical>
<v-tab-item>
<!-- Local files -->
<LocalFilesTab :isSelectedTab="isSelectedTab(0)"/>
<!-- File input -->
<FileInputTab
:isSelectedTab="isSelectedTab(0)"
@file-input-update="updateChosenSelection(0, $event)"
/>
</v-tab-item>
<v-tab-item>
<!-- Input text -->
<InputTextTab
<!-- Text input -->
<TextInputTab
:isSelectedTab="isSelectedTab(1)"
@input-text-update="updateChosenCorpus(1, $event)"
@text-input-update="updateChosenSelection(1, $event)"
/>
</v-tab-item>
<v-tab-item>
<!-- Profile text -->
<ProfileCorporaTab
:isSelectedTab="isSelectedTab(2)"
@profile-corpora-update="updateChosenCorpus(2, $event)"
@profile-corpora-update="updateChosenSelection(2, $event)"
/>
</v-tab-item>
<v-tab-item>
<!-- Shared corpus -->
<PublicCorporaTab
:isSelectedTab="isSelectedTab(3)"
@public-corpora-update="updateChosenCorpus(3,$event)"
@public-corpora-update="updateChosenSelection(3,$event)"
/>
</v-tab-item>
</v-tabs-items>
......@@ -41,29 +44,32 @@
</v-container>
</template>
<script>
import InputTextTab from '@/components/DefineCorpus/CorpusTabs/InputTextTab';
import LocalFilesTab from '@/components/DefineCorpus/CorpusTabs/LocalFilesTab';
import TextInputTab from '@/components/DefineCorpus/CorpusTabs/TextInputTab';
import FileInputTab from '@/components/DefineCorpus/CorpusTabs/FileInputTab';
import ProfileCorporaTab from '@/components/DefineCorpus/CorpusTabs/ProfileCorporaTab';
import PublicCorporaTab from '@/components/DefineCorpus/CorpusTabs/PublicCorporaTab';
const FILE_INPUT = 0, TEXT_INPUT = 1, PROFILE_CORPUS = 2, PUBLIC_CORPUS = 3;
export default {
data: () => ({
tab: null,
tab_items: [
{ tab: 'local-file', content: 'Fichier local'},
{ tab: 'input-text', content: 'Champ de texte'},
{ tab: 'file-input', content: 'Fichier local'},
{ tab: 'text-input', content: 'Champ de texte'},
{ tab: 'profile-corpus', content: 'Corpora du profil'},
{ tab: 'public-corpus', content: 'Corpora publics'},
],
selected: null,
test: { "fr": false, "en": false},
inputText: '',
profileCorpus : null,
publicCorpus: null
fileInput: null,
textInput: '',
profileCorpusId : null,
publicCorpusId: null
}),
components: {
InputTextTab,
LocalFilesTab,
TextInputTab,
FileInputTab,
ProfileCorporaTab,
PublicCorporaTab
},
......@@ -73,34 +79,33 @@ export default {
},
// emit here ?
// { activeTab: tabName, corpus: corpus}
updateChosenCorpus(tabNumber, corpus) {
updateChosenSelection(tabNumber, selection) {
switch (tabNumber) {
case 0:
this.localFile = corpus;
case FILE_INPUT:
this.fileInput = selection;
break;
case 1:
this.inputText = corpus;
case TEXT_INPUT:
this.textInput = selection;
break;
case 2:
this.profileCorpus = corpus;
case PROFILE_CORPUS:
this.profileCorpusId = selection;
break;
case 3:
this.publicCorpus = corpus;
case PUBLIC_CORPUS:
this.publicCorpusId = selection;
break;
}
this.emitUpdate(tabNumber, corpus);
this.emitUpdate(tabNumber, selection);
},
emitUpdate(tabNumber, corpus) {
const tabNumberToString = { 0: 'local-file', 1: 'input-text', 2: 'profile-corpus', 3: 'public-corpus'};
emitUpdate(tabNumber, selection) {
// If this function is called when tabNumber !== this.tab
// this means that we asked for a reset of 'tabNumber'
// So we can emit corpus null
// So we can emit selection null
if (!this.isSelectedTab(tabNumber)) {
this.$emit('chosen-corpus-update', { activeTab: tabNumberToString[this.tab], corpus: null});
this.$emit('chosen-selection-update', { activeTab: this.tab, selection: null});
}
// Else it means the user has just modified in the same tab its input
else {
this.$emit('chosen-corpus-update', { activeTab: tabNumberToString[tabNumber], corpus: corpus });
this.$emit('chosen-selection-update', { activeTab: tabNumber, selection: selection });
}
}
}
......@@ -109,14 +114,14 @@ export default {
<i18n>
{
"fr":{
"local-file":"Depuis un fichier local",
"input-text":"Depuis un champ de texte",
"file-input":"Depuis un fichier local",
"text-input":"Depuis un champ de texte",
"profile-corpus":"Depuis un corpus du profil",
"public-corpus":"Depuis un corpus partagé"
},
"en":{
"local-file":"From a local file",
"input-text":"From a text field",
"file-input":"From a local file",
"text-input":"From a text field",
"profile-corpus":"From a profile corpus",
"public-corpus":"From a shared corpus"
}
......
......@@ -107,15 +107,7 @@
</v-card>
</v-col>
</v-row>
<v-btn
:disabled="!valid"
color="success"
@click="validate"
>Validate
</v-btn>
</v-form>
{{ formData }}
{{ valid }}
</v-card>
</template>
<script>
......
<template>
<v-card outlined height=8em>
<v-card-text
class="justify-center text-center"
>
<v-file-input
@change="updateValue()"
multiple
persistent-hint
small-chips
show-size
:rules="rules"
accept=".txt"
v-model="files"
:label="$t('file-input-label')"
:hint="$t('file-input-hint')"
>
</v-file-input>
</v-card-text>
</v-card>
</template>
<script>
/* Documentations:
/ Restrict file extensions: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#accept
/ Nice output for number of files and stuff, we might copy it: https://vuetifyjs.com/en/components/file-inputs/#complex-selection-slot
*/
// IDEAS:
// Persistent file input, clearable with the cross
// Total file size printed
const MAX_SIZE = 20000000;
export default {
data: () => ({
files: [],
rules: [
values => {
var totalSize = 0;
values.forEach(
(value) => {
totalSize += value.size;
});
return !values || totalSize < MAX_SIZE || 'MAX SIZE dépassée'
}
]
}),
props: ['isSelectedTab'],
watch: {
isSelectedTab: function() {
if (!this.isSelectedTab) {
this.files = [];
this.updateValue();
}
}
},
computed: {
totalSize() {
var totalSize = 0;
this.files.forEach(
file => totalSize += file.size
);
return totalSize;
}
},
methods: {
printFiles() {
this.files.forEach((e) => {
console.log(e);
})
},
updateValue() {
this.$emit('file-input-update',this.files);
}
}
}
</script>
<i18n>
{
"fr":{
"file-input-label":"Choisissez un ou plusieurs fichiers",
"file-input-hint":"Formats acceptés: PDF, TXT, ..."
},
"en":{
"file-input-label":"Chose one or multiple files",
"file-input-hint":"Accepted formats: PDF, TXT, ..."
}
}
</i18n>
\ No newline at end of file
<template>
<v-card outlined height=8em>
<v-card-text
class="justify-center text-center"
>
<v-file-input
:label="$t('local-file-label')"
multiple
:hint="$t('local-file-hint')"
persistent-hint
small-chips
>
</v-file-input>
</v-card-text>
</v-card>
</template>
<script>
export default {
props: ['isSelectedTab']
}
</script>
<i18n>
{
"fr":{
"local-file-label":"Choisissez un ou plusieurs fichiers",
"local-file-hint":"Formats acceptés: PDF, TXT, ..."
},
"en":{
"local-file-label":"Chose one or multiple files",
"local-file-hint":"Accepted formats: PDF, TXT, ..."
}
}
</i18n>
\ No newline at end of file
......@@ -5,6 +5,7 @@
>
<v-select
:items="test_common_corpus"
:item-text="name"
v-model="publicCorpus"
:label="$t('shared-corpus-label')"
outlined
......@@ -18,7 +19,12 @@
export default {
data: () => ({
publicCorpus: null,
test_common_corpus: ["CommonCorpus1", "LIPN_Articles", "Sequoia","LaVoixDuNord_Solr"],
test_common_corpus: [
{ text: "CommonCorpus1", value:1 },
{ text: "LIPN_Articles", value:2 },
{ text: "Sequoia", value:3 },
{ text: "LaVoixDuNord_Solr", value: 4}
],
}),
props: ['isSelectedTab'],
watch: {
......
......@@ -6,27 +6,27 @@
height=8em
auto-grow
clearable
v-model="inputText"
:label="$t('input-text')"
v-model="textInput"
:label="$t('text-input')"
></v-textarea>
</template>
<script>
export default {
data: () => ({
inputText: ''
textInput: ''
}),
props: ['isSelectedTab'],
watch: {
isSelectedTab: function() {
if (!this.isSelectedTab) {
this.inputText = '';
this.textInput = '';
this.updateValue();
}
}
},
methods: {
updateValue: function() {
this.$emit('input-text-update', this.inputText);
this.$emit('text-input-update', this.textInput);
}
}
}
......@@ -34,9 +34,9 @@ export default {
<i18n>
{
"fr":{
"input-text":"Entrez ou collez votre texte ici"
"text-input":"Entrez ou collez votre texte ici"
},
"en":{
"input-text":"Type or paste your text here"
"text-input":"Type or paste your text here"
}
}
\ No newline at end of file
......@@ -5,14 +5,14 @@
<h1 class="display-3"> {{ $t('corpus-choice' )}}</h1>
</v-card-title>
<AddCorpus
@chosen-corpus-update="updateChosenCorpus($event)"
@chosen-selection-update="updateSelection($event)"
/>
<CorpusParameters
v-show="showParameters"
:corpusId="corpusId"
@corpus-parameters-update="updateCorpusParameters($event)"
/>
</v-card>
Corpus: {{ corpus }}
<!-- Alerts -->
<div>
<v-alert type="info" v-if="!valid"> {{ buttonMessage }}
......@@ -30,6 +30,8 @@ import axios from '@/plugins/axios';
import AddCorpus from '@/components/DefineCorpus/AddCorpus';
import CorpusParameters from '@/components/DefineCorpus/CorpusParameters';
const FILE_INPUT = 0, TEXT_INPUT = 1, PROFILE_CORPUS = 2, PUBLIC_CORPUS = 3;
export default {
name: 'Corpus',
components: {
......@@ -37,85 +39,213 @@ export default {
CorpusParameters,
},
data: () => ({
showParameters: false,
corpus: null,
activeTab : 'local-file',
// showParameters: false,
corpusId: null,
textInput: null,
fileInput: null,
activeTab : FILE_INPUT,
corpusParameters: null,
corpusParametersValid: false,
areParametersValid: false,