From bbbf5d75b83b66854be6dfab29d9f2f484a893ab Mon Sep 17 00:00:00 2001 From: Camille Dupont Date: Fri, 29 Oct 2021 00:15:37 +0200 Subject: [PATCH 01/12] Update README_INTERNAL and Dockerfile commands --- Dockerfile | 3 +-- README_INTERNAL.md | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index 4dfb491..0bcfaec 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,8 +15,7 @@ COPY server server COPY .logo-ascii .logo-ascii # Build frontend and install backend dependencies -RUN npm run installApp && npm run buildApp && npm install \ - && rm -rf src frontend +RUN npm i && cd frontend/ && npm i && npm run build && rm -rf src frontend && cd .. EXPOSE 3000 diff --git a/README_INTERNAL.md b/README_INTERNAL.md index 246b4a2..8b9f3d6 100644 --- a/README_INTERNAL.md +++ b/README_INTERNAL.md @@ -148,7 +148,7 @@ Transform the tag in github release (makes the last tag more visible and detaile sudo docker tag pixano/pixano-app:$VERSION pixano/pixano-app:latest # make sure it built correctly cd data-test/ - sudo docker run -it --rm -v "$PWD":/data --network host pixano/app:$VERSION + sudo docker run -it --rm -v "$PWD":/data --network host pixano/pixano-app:$VERSION cd ../ # push to docker hub sudo docker push pixano/pixano-app:$VERSION From fcd6479f4129d2e8d29bf42071d43657a9646d68 Mon Sep 17 00:00:00 2001 From: Brice Burger Date: Tue, 2 Nov 2021 10:05:38 +0000 Subject: [PATCH 02/12] Update TODO_INTERNAL.md --- TODO_INTERNAL.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/TODO_INTERNAL.md b/TODO_INTERNAL.md index 95a0a3f..0587274 100644 --- a/TODO_INTERNAL.md +++ b/TODO_INTERNAL.md @@ -9,6 +9,15 @@ Ce fichier contient la liste des modifications/corrections prévues dans ce code # AFAIRE : +- [ ] [#interface] manque pop-up erreur +- [ ] [#interface] aide affichée à la 1ère connexion +- [ ] [#interface] ajouter un bouton pour guider la fin de la création de tache +- [ ] [#doc] readme add 'cd ...' + add folder path in commands to make sure we run in the right folder +- [ ] [#feature] fichiers à supprimer si pb (compléter commande cleanall) +- [ ] [#doc] Manque README global qui explique comment est construit Pixano et ses dépôts, mettre des schémas pour montrer les utilisations (distribué, standalone facile, etc) +- [ ] [#doc] Getting started blog post +- [ ] [#doc] Ajouter des démos complètes sexy + ajouter un bouton ajouter une config pour tester ton projet facilelement +- [ ] [#feature] Ajouter un exécutable - [ ] [#doc] mise à jour de la procédure de livraison : idem elements - [ ] [#doc] ajouter un test d'import/export dans la procédure avant livraison - [ ] [#interface] quand on importe, il faudrait une boite de dialogue pour demander si on veut fusionner avec la base existante ou créer une nouvelle (actuellement, si on sélectionne une tâche il ajoute les imports avec des '-1', si on est sur "new task" il fusionne) From a10b78cbddcf05b1467adcda5280fd6e133f51fc Mon Sep 17 00:00:00 2001 From: Brice Burger Date: Tue, 2 Nov 2021 17:52:07 +0100 Subject: [PATCH 03/12] better password management: change password is now working + log without passwd --- frontend/src/views/app-user-manager.js | 67 ++++++++++++++------------ server/routes/users.js | 2 +- 2 files changed, 38 insertions(+), 31 deletions(-) diff --git a/frontend/src/views/app-user-manager.js b/frontend/src/views/app-user-manager.js index f14c258..0406d63 100644 --- a/frontend/src/views/app-user-manager.js +++ b/frontend/src/views/app-user-manager.js @@ -8,6 +8,7 @@ import { html, css } from 'lit-element'; import { connect } from 'pwa-helpers/connect-mixin.js'; import TemplatePage from '../templates/template-page'; import { store, getState } from '../store'; +import { getValue } from '../helpers/utils'; import { logout, signup, getUsers, deleteUser, @@ -90,10 +91,15 @@ class AppUserManager extends connect(store)(TemplatePage) { }); } - onSaveUser(user) { - store.dispatch(updateUser(user)); - this.enabledUsername = ''; - } + onPasswordChanged(e) { + this.passwordElement.value = getValue(e); + } + + onSaveUser(user) { + user.password = this.passwordElement.value; + store.dispatch(updateUser(user)); + this.enabledUsername = ''; + } onCancel() { this.enabledUsername = ''; @@ -227,32 +233,33 @@ class AppUserManager extends connect(store)(TemplatePage) { `; } - listitem(user) { - return html` -
-

${user.username}

-

- -

-
- user.role = this.dropdownValues['role'][e.detail.index]}> - ${this.dropdownValues['role'].map((v) => html`${v}`)} - -
-
- user.preferences.theme = this.dropdownValues['preferences.theme'][e.detail.index]}> - ${this.dropdownValues['preferences.theme'].map((v) => html`${v}`)} - -
- ${this.editionCell(user)} -
- `; - } + listitem(user) { + return html` +
+

${user.username}

+

+ +

+
+ user.role = this.dropdownValues['role'][e.detail.index]}> + ${this.dropdownValues['role'].map((v) => html`${v}`)} + +
+
+ user.preferences.theme = this.dropdownValues['preferences.theme'][e.detail.index]}> + ${this.dropdownValues['preferences.theme'].map((v) => html`${v}`)} + +
+ ${this.editionCell(user)} +
+ `; + } get userSection() { diff --git a/server/routes/users.js b/server/routes/users.js index c2e8bb1..91984d0 100644 --- a/server/routes/users.js +++ b/server/routes/users.js @@ -254,7 +254,7 @@ async function put_user(req, res) { const user = await db.get(dbkeys.keyForUser(username)); return user.password === password; } catch (err) { - console.log(username, password, 'does not exist.'); + console.log(username, 'does not exist.'); return false; } } From 53ff17587e1184984101d7b8b0af607863d1f7ba Mon Sep 17 00:00:00 2001 From: Brice Burger Date: Wed, 3 Nov 2021 16:13:38 +0100 Subject: [PATCH 04/12] really merge with 0d7252ab62100 --- TODO_INTERNAL.md | 5 + frontend/src/helpers/attribute-picker.js | 40 ++- frontend/src/plugins/cuboid.js | 4 +- frontend/src/plugins/segmentation.js | 230 +++++++++--------- .../src/templates/template-plugin-instance.js | 10 +- 5 files changed, 142 insertions(+), 147 deletions(-) diff --git a/TODO_INTERNAL.md b/TODO_INTERNAL.md index 0587274..d6c7570 100644 --- a/TODO_INTERNAL.md +++ b/TODO_INTERNAL.md @@ -59,3 +59,8 @@ Ce fichier contient la liste des modifications/corrections prévues dans ce code - [ ] [#feature] possibilité de sélectionner plusieurs éléments pour leur donner des caractéristiques communes ? - [ ] [#feature] passerelle Mturk / Amazon SageMaker +## plugin segmentation +- [ ] [#bogue] attributs non conservés arès submit +- [ ] [#bogue] add/substract désélectionne la zone + + diff --git a/frontend/src/helpers/attribute-picker.js b/frontend/src/helpers/attribute-picker.js index bd46be9..599f97e 100644 --- a/frontend/src/helpers/attribute-picker.js +++ b/frontend/src/helpers/attribute-picker.js @@ -112,6 +112,14 @@ export class AttributePicker extends LitElement { } static get properties () { + /** + * showDetail: Boolean, rendering mode for the selected category (showing all attributes or only the category) + * shortcuts : Array of strings, contains the list of all applicable keyboard shortcuts + * schema: shema for this annotation (i.e. category and attributes available for each category in this annotation) + * value: {categoryName, options }, contains the value of the current category and its options (i.e. attributes available for this category) + * numDone: Number, only used for keypoints-box + * numTotal: Number, only used for keypoints-box + */ return { showDetail: { type: Boolean }, shortcuts: { type: Array }, @@ -123,7 +131,7 @@ export class AttributePicker extends LitElement { } get selectedCategory() { - return this.schema.category.find((c) => c.name === this.value.category); + return this.schema.category.find((c) => c.name === this.value.categoryName); } getDefaultAttributesForCategory(schema, categoryName) { @@ -180,7 +188,7 @@ export class AttributePicker extends LitElement { this.mem = ''; this.schema = default_schema; const options = this.getDefaultAttributesForCategory(default_schema, default_schema.default); - this.value = {category: default_schema.default, options }; + this.value = {categoryName: default_schema.default, options }; this.mem = ''; this.onKeyDown = this.onKeyDown.bind(this); this.onKeyUp = this.onKeyUp.bind(this); @@ -217,13 +225,13 @@ export class AttributePicker extends LitElement { } get defaultValue() { - const options = this.getDefaultAttributesForCategory(this.schema, this.value.category); - return {category: this.value.category, options}; + const options = this.getDefaultAttributesForCategory(this.schema, this.value.categoryName); + return {categoryName: this.value.categoryName, options}; } setCategory(newCategory) { const options = this.getDefaultAttributesForCategory(this.schema, newCategory); - this.value = {category: newCategory, options }; + this.value = {categoryName: newCategory, options }; this._notifyUpdate(); } @@ -235,7 +243,7 @@ export class AttributePicker extends LitElement { setAttributes(entity) { if (entity) { entity.options = entity.options || {}; - const options = this.getDefaultAttributesForCategory(this.schema, entity.category); + const options = this.getDefaultAttributesForCategory(this.schema, entity.categoryName); Object.keys(options).forEach((key) => { if (entity.options.hasOwnProperty(key)) { options[key] = JSON.parse(JSON.stringify(entity.options[key])); @@ -244,7 +252,7 @@ export class AttributePicker extends LitElement { } }); // update property choices - this.value = {category: entity.category, options}; + this.value = {categoryName: entity.categoryName, options}; // update property values const childDivs = this.shadowRoot.getElementById('updateEditor').getElementsByTagName('mwc-select'); @@ -272,7 +280,7 @@ export class AttributePicker extends LitElement { reloadSchema(schema) { this.schema = schema; const options = this.getDefaultAttributesForCategory(schema, schema.default); - this.value = {category: schema.default, options }; + this.value = {categoryName: schema.default, options }; } _notifyUpdate() { @@ -361,10 +369,10 @@ export class AttributePicker extends LitElement { ${ this.schema.category.map((category, idx) => { return html` -
this.setCategory(category.name)}> +
this.setCategory(category.name)}> ${idx}

${category.name}

- ${category.properties && category.name === this.value.category ? html` + ${category.properties && category.name === this.value.categoryName ? html` ${category.properties.map((prop) => this.htmlProp(prop))} `: html``} ` @@ -380,7 +388,7 @@ export class AttributePicker extends LitElement { ${ this.schema.category.map((category, idx) => { return html` -
this.setCategory(category.name)}> +
this.setCategory(category.name)}> ${idx}

${category.name}

` }) @@ -400,16 +408,6 @@ export class AttributePicker extends LitElement { ${this.renderSimple} `; } - // render(){ - // return html` - // ${this.shortcutsDialog} - // - // ${this.renderDetail} - // ${this.renderSimple} - //
keypoints faits ${this.numDone} / ${this.numTotal}
- // `; - // } - } customElements.define('attribute-picker', AttributePicker); diff --git a/frontend/src/plugins/cuboid.js b/frontend/src/plugins/cuboid.js index 6915ddb..6d787cd 100644 --- a/frontend/src/plugins/cuboid.js +++ b/frontend/src/plugins/cuboid.js @@ -21,7 +21,7 @@ export class PluginCuboid extends TemplatePluginInstance { return; } const shapes = JSON.parse(JSON.stringify(this.annotations.map((l) => { - const color = this._colorFor(l.category); + const color = this._colorFor(l.categoryName); return { ...l, color: colorAnyToHexNumber(color) }; }))); this.element.editableCuboids = shapes; @@ -48,7 +48,7 @@ export class PluginCuboid extends TemplatePluginInstance { Object.keys(value).forEach((key) => { shape[key] = JSON.parse(JSON.stringify(value[key])); }); - shape.color = this._colorFor(shape.category); + shape.color = this._colorFor(shape.categoryName); this.collect(); }); } diff --git a/frontend/src/plugins/segmentation.js b/frontend/src/plugins/segmentation.js index 6c3b2cb..6592507 100644 --- a/frontend/src/plugins/segmentation.js +++ b/frontend/src/plugins/segmentation.js @@ -14,7 +14,8 @@ import { store, getState } from '../store'; import '../helpers/attribute-picker'; import { subtract, union } from '../my-icons'; import { setAnnotations } from '../actions/annotations'; -import { TemplatePlugin } from '../templates/template-plugin'; +import { TemplatePluginInstance } from '../templates/template-plugin-instance'; +import { commonJson } from '../helpers/utils'; const EditionMode = { ADD_TO_INSTANCE: 'add_to_instance', @@ -27,7 +28,7 @@ const EditionMode = { * Reads labels as: * { id: 0, mask: Base64 } */ -export class PluginSegmentation extends TemplatePlugin { +export class PluginSegmentation extends TemplatePluginInstance { static get properties() { return { @@ -39,16 +40,15 @@ export class PluginSegmentation extends TemplatePlugin { constructor() { super(); - this.mode = 'edit'; + this.mode = 'create'; this.maskVisuMode = 'SEMANTIC'; this.currentEditionMode = EditionMode.NEW_INSTANCE; - this.selectedIds = [0,0,0]; } get toolDrawer() { return html` @@ -87,7 +87,7 @@ export class PluginSegmentation extends TemplatePlugin { ` @@ -110,39 +110,105 @@ export class PluginSegmentation extends TemplatePlugin { this.element.targetClass = schema.category.find((c) => c.name === schema.default).idx; } - onUpdate() { - const frame = { mask: this.element.getMask()}; - store.dispatch(setAnnotations({annotations: frame})); - } - - onSelection(evt) { - this.selectedIds = evt.detail; - this.updateDisplayOfSelectedProperties(); - } - - updateDisplayOfSelectedProperties() { - if (this.selectedIds && this.selectedIds.length) { - this.attributePicker.setAttributesIdx(this.selectedIds[2]); - } else { - this.attributePicker.setAttributesIdx(); - } - } - - onAttributeChanged() { - const value = this.attributePicker.selectedCategory; - this.element.targetClass = value.idx; - if (this.selectedIds && this.selectedIds.length - && (this.selectedIds[0] != 0 || this.selectedIds[1] != 0 || this.selectedIds[2] != 0)) { - this.element.fillSelectionWithClass(value.idx); - this.onUpdate(); - } - } - - get propertyPanel() { - return html` - - ` - } + /** + * Invoked on instance selection in the canvas. + * @param {CustomEvent} evt + */ + onSelection(evt) { + this.selectedIds = evt.detail; + if (this.selectedIds) {//only one id at a time for segmentation + const annot = this.annotations.filter((a) => JSON.stringify(this.selectedIds)===(a.id));// search the corresponding id + const common = commonJson(annot); + this.attributePicker.setAttributes(common); + } else { + // if null, nothing is selected + this.selectedIds = []; + } + } + + /** + * Invoked when a new instance is updated (created = updated for segmentation) + * @param {CustomEvent} evt + */ + onUpdate(evt) { + const updatedIds = evt.detail; + let frame = this.annotations; + // 1) update the mask (always id 0) + let mask = frame.find((l) => l.id === 0); + let create = false; + if (!mask) create=true; + mask = {id: 0, mask: this.element.getMask()};//if the mask already exists => just overwrite the previous mask + if (create) frame.push(mask);//otherwise(first time), create it + // 2) update annotation info when needed + let label = frame.find((l) => l.id === JSON.stringify(updatedIds));// search the corresponding id + if (label) {//id exists in the database, update information + // nothing to do for annotation infos, only the mask has changed + } else {// this is a new id + // create the new label + label = {...this.attributePicker.defaultValue}; + // store the stringified values + const value = this.attributePicker.value; + Object.keys(label).forEach((key) => { + label[key] = JSON.parse(JSON.stringify(value[key])); + }); + label.id = JSON.stringify(updatedIds); + frame.push(label) + } + // 3) store the new annotation structure + store.dispatch(setAnnotations({annotations: frame})); + // selectedId has also changed, update it + this.selectedIds = updatedIds; + } + + /** + * Invoked on attribute change from property panel. + */ + onAttributeChanged() { + if (!this.selectedIds.length) {//nothing is selected + // only set the category acordingly to the selected attribute + const category = this.attributePicker.selectedCategory; + this.element.targetClass = category.idx; + return; + } + let frame = this.annotations; + // 1) update the mask (always id 0) + // change category in element + const category = this.attributePicker.selectedCategory; + this.element.targetClass = category.idx; + this.element.fillSelectionWithClass(category.idx); + // get the new mask and store it + let mask = frame.find((l) => l.id === 0); + mask = {id: 0, mask: this.element.getMask()};//just overwrite the previous mask + // 2) update annotation info from attributes + const value = this.attributePicker.value; + let label = frame.find((l) => l.id === JSON.stringify(this.selectedIds));// search the corresponding id + Object.keys(value).forEach((key) => { + label[key] = JSON.parse(JSON.stringify(value[key])); + }); + // category has changed => selectedId has also changed, update it + const updatedIds = this.element.selectedId; + label.id = JSON.stringify(updatedIds); + this.selectedIds = updatedIds; + // 3) store the new annotation structure + store.dispatch(setAnnotations({annotations: frame})); + } + + /** + * Invoked on instance removal + * @param {CustomEvent} evt + */ + onDelete(evt) { + const ids = evt.detail; + let frame = this.annotations; + // 1) update the mask (always id 0) + // get the new mask and store it + let mask = frame.find((l) => l.id === 0); + mask = {id: 0, mask: this.element.getMask()};//just overwrite the previous mask + // 2) update annotation info (= delete corresponding id) + frame = frame.filter((l) => l.id !== JSON.stringify(ids)) + // 3) store the new annotation structure + store.dispatch(setAnnotations({annotations: frame})); + } refresh() { if (!this.element) { @@ -173,87 +239,13 @@ export class PluginSegmentation extends TemplatePlugin { maskVisuMode=${this.maskVisuMode} @update=${this.onUpdate} @selection=${this.onSelection} - @mode=${this.onModeChange}>`; + @delete=${this.onDelete} + @mode=${this.onModeChange}>`;//onCreate never really called for segmentation : the mask is updated } + collect() { + console.log("should not be called") + } + } customElements.define('plugin-segmentation', PluginSegmentation); - - -// Code to handle attributes for segments -// /** -// * Invoked on instance selection in the canvas. -// * @param {CustomEvent} evt -// */ -// onSelection(evt) { -// this.selectedIds = evt.detail; -// if (this.selectedIds) {//only one id at a time for segmentation -// const annot = this.annotations.filter((a) => JSON.stringify(this.selectedIds)===(a.id));// search the corresponding id -// const common = commonJson(annot); -// this.attributePicker.setAttributes(common); -// } else { -// // if null, nothing is selected -// this.selectedIds = []; -// } -// } - -// /** -// * Invoked when a new instance is updated (created = updated for segmentation) -// * @param {CustomEvent} evt -// */ -// onUpdate(evt) { -// // 1) update annotation info when needed -// const updatedIds = evt.detail; -// const label = this.annotations.find((l) => l.id === JSON.stringify(updatedIds));// search the corresponding id -// if (label) {//id exists in the database, update information -// // nothing to do for annotation infos, only the mask has changed -// } else {// this is a new id -// // create the new label -// let label = {...this.attributePicker.defaultValue}; -// // store the stringified values -// const value = this.attributePicker.value; -// Object.keys(label).forEach((key) => { -// label[key] = JSON.parse(JSON.stringify(value[key])); -// }); -// label.id = JSON.stringify(updatedIds); -// store.dispatch(createAnnotation(label)); -// } -// // 2) update the mask (always id 0) -// const curr = this.annotations.find((l) => l.id === 0); -// const im = this.element.getMask(); -// const fn = curr ? updateAnnotation : createAnnotation; -// store.dispatch(fn({ id: 0, mask: im })); -// this.selectedIds = updatedIds; -// } - -// /** -// * Invoked on attribute change from property panel. -// */ -// onAttributeChanged() { -// if (!this.selectedIds.length) {//nothing is selected -// // only set the category acordingly to the selected attribute -// const category = this.attributePicker.selectedCategory; -// this.element.targetClass = category.idx; -// return; -// } -// // 2) update the mask (always id 0) -// // change category in element -// const category = this.attributePicker.selectedCategory; -// this.element.targetClass = category.idx; -// this.element.fillSelectionWithClass(category.idx); -// // get the new mask and store it -// const im = this.element.getMask(); -// store.dispatch(updateAnnotation({ id: 0, mask: im })); -// // 1) update annotation info from attributes -// const value = this.attributePicker.value; -// const label = this.annotations.find((l) => l.id === JSON.stringify(this.selectedIds));// search the corresponding id -// Object.keys(value).forEach((key) => { -// label[key] = JSON.parse(JSON.stringify(value[key])); -// }); -// // category has changed => selectedId has also changed, update it -// const updatedIds = this.element.selectedId; -// label.id = JSON.stringify(updatedIds); -// this.selectedIds = updatedIds; -// // update store -// store.dispatch(updateAnnotation(label)); -// } diff --git a/frontend/src/templates/template-plugin-instance.js b/frontend/src/templates/template-plugin-instance.js index 366d286..bba666a 100644 --- a/frontend/src/templates/template-plugin-instance.js +++ b/frontend/src/templates/template-plugin-instance.js @@ -25,7 +25,7 @@ export class TemplatePluginInstance extends TemplatePlugin { constructor(){ super(); - this.mode = 'edit'; + this.mode = 'create'; this.selectedIds = []; } @@ -41,7 +41,7 @@ export class TemplatePluginInstance extends TemplatePlugin { Object.keys(value).forEach((key) => { shape[key] = JSON.parse(JSON.stringify(value[key])); }); - shape.color = this._colorFor(shape.category); + shape.color = this._colorFor(shape.categoryName); this.collect(); }); } @@ -53,7 +53,7 @@ export class TemplatePluginInstance extends TemplatePlugin { // need to make immutable variable as not to change directly // the redux store this.element.shapes = JSON.parse(JSON.stringify(this.annotations.map((l) => { - return {...l, color: this._colorFor(l.category)} + return {...l, color: this._colorFor(l.categoryName)} }))); } @@ -93,7 +93,7 @@ export class TemplatePluginInstance extends TemplatePlugin { if (this.isSequence) { newObject.timestamp = this.targetFrameIdx; } - newObject.color = this._colorFor(newObject.category); + newObject.color = this._colorFor(newObject.categoryName); this.collect(); } @@ -138,7 +138,7 @@ export class TemplatePluginInstance extends TemplatePlugin { get toolDrawer() { return html` From 8a953516aa31216ef3568e9fd7a8ae85465910a4 Mon Sep 17 00:00:00 2001 From: Brice Burger Date: Wed, 3 Nov 2021 18:13:57 +0100 Subject: [PATCH 05/12] segmentation and smart-segmentation bug bix --- TODO_INTERNAL.md | 4 ++-- frontend/src/plugins/segmentation.js | 23 ++++++++++------------ frontend/src/plugins/smart-segmentation.js | 13 +++++------- 3 files changed, 17 insertions(+), 23 deletions(-) diff --git a/TODO_INTERNAL.md b/TODO_INTERNAL.md index d6c7570..31ec4ae 100644 --- a/TODO_INTERNAL.md +++ b/TODO_INTERNAL.md @@ -60,7 +60,7 @@ Ce fichier contient la liste des modifications/corrections prévues dans ce code - [ ] [#feature] passerelle Mturk / Amazon SageMaker ## plugin segmentation -- [ ] [#bogue] attributs non conservés arès submit -- [ ] [#bogue] add/substract désélectionne la zone +- [ ] [#bogue] setMask non entièrement fonctionnel : rien en s'affiche et on ne peut rien sélectionner +- [x] [#bogue] add/substract désélectionne la zone diff --git a/frontend/src/plugins/segmentation.js b/frontend/src/plugins/segmentation.js index 6592507..def4013 100644 --- a/frontend/src/plugins/segmentation.js +++ b/frontend/src/plugins/segmentation.js @@ -210,19 +210,16 @@ export class PluginSegmentation extends TemplatePluginInstance { store.dispatch(setAnnotations({annotations: frame})); } - refresh() { - if (!this.element) { - return; - } - if (!this.annotations.mask) { - this.element.setEmpty(); - return; - } - const mask = this.annotations.mask; - if (mask != this.element.getMask()) { - this.element.setMask(mask); - } - } + refresh() {//get back annotation into element + console.log("refresh") + if (!this.element) { + return; + } + // 1) get back the mask into element + let mask = this.annotations.find((l) => l.id === 0); + if (!mask) this.element.setEmpty(); + else this.element.setMask(mask).then(console.log("set ok")); + } getEditionMode() { if (this.element) return this.element.editionMode; diff --git a/frontend/src/plugins/smart-segmentation.js b/frontend/src/plugins/smart-segmentation.js index 81cc8a5..c212867 100644 --- a/frontend/src/plugins/smart-segmentation.js +++ b/frontend/src/plugins/smart-segmentation.js @@ -10,6 +10,7 @@ import '@material/mwc-icon-button'; import '@material/mwc-icon-button-toggle'; import '@material/mwc-icon'; import { PluginSegmentation } from './segmentation'; +import { getState } from '../store'; /** * Plugin segmentation. @@ -20,12 +21,8 @@ export class PluginSmartSegmentation extends PluginSegmentation { initDisplay() { super.initDisplay(); - const tasks = this.info.tasks; - const taskName = this.info.taskName; - const task = tasks.find((t) => t.name === taskName); - if (!task) { - return; - } + const taskName = getState('application').taskName; + const task = getState('application').tasks.find((t) => t.name === taskName); if (task.spec.settings && task.spec.settings.model) { this.element.model = task.spec.settings.model; } @@ -39,7 +36,6 @@ export class PluginSmartSegmentation extends PluginSegmentation { title="Smart create" @click="${() => this.mode = 'smart-create'}"> -
` } @@ -49,7 +45,8 @@ export class PluginSmartSegmentation extends PluginSegmentation { maskVisuMode=${this.maskVisuMode} @update=${this.onUpdate} @selection=${this.onSelection} - @mode=${this.onModeChange}>`; + @delete=${this.onDelete} + @mode=${this.onModeChange}>`;//onCreate never really called for segmentation : the mask is updated } } From a04aca189078650a12ed2f93e45d5b38bce2b795 Mon Sep 17 00:00:00 2001 From: Brice Burger Date: Thu, 4 Nov 2021 16:20:05 +0100 Subject: [PATCH 06/12] roll back : categoryName -> category (postponed until the export/import files have a versionning system) + bug fix in segmentation --- TODO_INTERNAL.md | 5 +++- frontend/src/helpers/attribute-picker.js | 24 +++++++++---------- frontend/src/plugins/cuboid.js | 4 ++-- frontend/src/plugins/keypoints-box.js | 4 ++-- frontend/src/plugins/segmentation.js | 16 +++++++------ .../src/templates/template-plugin-instance.js | 6 ++--- server/config/parser.js | 2 +- 7 files changed, 33 insertions(+), 28 deletions(-) diff --git a/TODO_INTERNAL.md b/TODO_INTERNAL.md index 31ec4ae..63e3691 100644 --- a/TODO_INTERNAL.md +++ b/TODO_INTERNAL.md @@ -9,6 +9,9 @@ Ce fichier contient la liste des modifications/corrections prévues dans ce code # AFAIRE : +- [ ] [#feature] ajouter un système de versionning dans les fichiers import/export +- [ ] [#feature] fichiers import/export : une fois le versionning en place, créer une v2 avec : category -> categoryName + ... +- [ ] [#doc] tabulation uniformisée - [ ] [#interface] manque pop-up erreur - [ ] [#interface] aide affichée à la 1ère connexion - [ ] [#interface] ajouter un bouton pour guider la fin de la création de tache @@ -60,7 +63,7 @@ Ce fichier contient la liste des modifications/corrections prévues dans ce code - [ ] [#feature] passerelle Mturk / Amazon SageMaker ## plugin segmentation -- [ ] [#bogue] setMask non entièrement fonctionnel : rien en s'affiche et on ne peut rien sélectionner +- [x] [#bogue] setMask non entièrement fonctionnel : rien en s'affiche et on ne peut rien sélectionner - [x] [#bogue] add/substract désélectionne la zone diff --git a/frontend/src/helpers/attribute-picker.js b/frontend/src/helpers/attribute-picker.js index 599f97e..33193c3 100644 --- a/frontend/src/helpers/attribute-picker.js +++ b/frontend/src/helpers/attribute-picker.js @@ -116,7 +116,7 @@ export class AttributePicker extends LitElement { * showDetail: Boolean, rendering mode for the selected category (showing all attributes or only the category) * shortcuts : Array of strings, contains the list of all applicable keyboard shortcuts * schema: shema for this annotation (i.e. category and attributes available for each category in this annotation) - * value: {categoryName, options }, contains the value of the current category and its options (i.e. attributes available for this category) + * value: {category, options }, contains the value of the current category and its options (i.e. attributes available for this category) * numDone: Number, only used for keypoints-box * numTotal: Number, only used for keypoints-box */ @@ -131,7 +131,7 @@ export class AttributePicker extends LitElement { } get selectedCategory() { - return this.schema.category.find((c) => c.name === this.value.categoryName); + return this.schema.category.find((c) => c.name === this.value.category); } getDefaultAttributesForCategory(schema, categoryName) { @@ -188,7 +188,7 @@ export class AttributePicker extends LitElement { this.mem = ''; this.schema = default_schema; const options = this.getDefaultAttributesForCategory(default_schema, default_schema.default); - this.value = {categoryName: default_schema.default, options }; + this.value = {category: default_schema.default, options }; this.mem = ''; this.onKeyDown = this.onKeyDown.bind(this); this.onKeyUp = this.onKeyUp.bind(this); @@ -225,13 +225,13 @@ export class AttributePicker extends LitElement { } get defaultValue() { - const options = this.getDefaultAttributesForCategory(this.schema, this.value.categoryName); - return {categoryName: this.value.categoryName, options}; + const options = this.getDefaultAttributesForCategory(this.schema, this.value.category); + return {category: this.value.category, options}; } setCategory(newCategory) { const options = this.getDefaultAttributesForCategory(this.schema, newCategory); - this.value = {categoryName: newCategory, options }; + this.value = {category: newCategory, options }; this._notifyUpdate(); } @@ -243,7 +243,7 @@ export class AttributePicker extends LitElement { setAttributes(entity) { if (entity) { entity.options = entity.options || {}; - const options = this.getDefaultAttributesForCategory(this.schema, entity.categoryName); + const options = this.getDefaultAttributesForCategory(this.schema, entity.category); Object.keys(options).forEach((key) => { if (entity.options.hasOwnProperty(key)) { options[key] = JSON.parse(JSON.stringify(entity.options[key])); @@ -252,7 +252,7 @@ export class AttributePicker extends LitElement { } }); // update property choices - this.value = {categoryName: entity.categoryName, options}; + this.value = {category: entity.category, options}; // update property values const childDivs = this.shadowRoot.getElementById('updateEditor').getElementsByTagName('mwc-select'); @@ -280,7 +280,7 @@ export class AttributePicker extends LitElement { reloadSchema(schema) { this.schema = schema; const options = this.getDefaultAttributesForCategory(schema, schema.default); - this.value = {categoryName: schema.default, options }; + this.value = {category: schema.default, options }; } _notifyUpdate() { @@ -369,10 +369,10 @@ export class AttributePicker extends LitElement { ${ this.schema.category.map((category, idx) => { return html` -
this.setCategory(category.name)}> +
this.setCategory(category.name)}> ${idx}

${category.name}

- ${category.properties && category.name === this.value.categoryName ? html` + ${category.properties && category.name === this.value.category ? html` ${category.properties.map((prop) => this.htmlProp(prop))} `: html``} ` @@ -388,7 +388,7 @@ export class AttributePicker extends LitElement { ${ this.schema.category.map((category, idx) => { return html` -
this.setCategory(category.name)}> +
this.setCategory(category.name)}> ${idx}

${category.name}

` }) diff --git a/frontend/src/plugins/cuboid.js b/frontend/src/plugins/cuboid.js index 6d787cd..6915ddb 100644 --- a/frontend/src/plugins/cuboid.js +++ b/frontend/src/plugins/cuboid.js @@ -21,7 +21,7 @@ export class PluginCuboid extends TemplatePluginInstance { return; } const shapes = JSON.parse(JSON.stringify(this.annotations.map((l) => { - const color = this._colorFor(l.categoryName); + const color = this._colorFor(l.category); return { ...l, color: colorAnyToHexNumber(color) }; }))); this.element.editableCuboids = shapes; @@ -48,7 +48,7 @@ export class PluginCuboid extends TemplatePluginInstance { Object.keys(value).forEach((key) => { shape[key] = JSON.parse(JSON.stringify(value[key])); }); - shape.color = this._colorFor(shape.categoryName); + shape.color = this._colorFor(shape.category); this.collect(); }); } diff --git a/frontend/src/plugins/keypoints-box.js b/frontend/src/plugins/keypoints-box.js index d6dbf2b..25aca4e 100644 --- a/frontend/src/plugins/keypoints-box.js +++ b/frontend/src/plugins/keypoints-box.js @@ -108,7 +108,7 @@ export class PluginKeypointsBox extends TemplatePluginInstance { freeBoxes.shift(); this.attributePicker.numDone = this.attributePicker.numTotal - freeBoxes.length; store.dispatch(createAnnotation(newAnnotation)); - this.element.shapes = freeBoxes.length ? [{...freeBoxes[0], color: this._colorFor(freeBoxes[0].categoryName) }] : []; + this.element.shapes = freeBoxes.length ? [{...freeBoxes[0], color: this._colorFor(freeBoxes[0].category) }] : []; } else { this.element.shapes = []; } @@ -138,7 +138,7 @@ export class PluginKeypointsBox extends TemplatePluginInstance { .filter((r) => !ids.includes(r.id)); if (freeBoxes.length) { - this.element.shapes = [{...freeBoxes[0], color: this._colorFor(freeBoxes[0].categoryName) }]; + this.element.shapes = [{...freeBoxes[0], color: this._colorFor(freeBoxes[0].category) }]; } } diff --git a/frontend/src/plugins/segmentation.js b/frontend/src/plugins/segmentation.js index def4013..c6b5209 100644 --- a/frontend/src/plugins/segmentation.js +++ b/frontend/src/plugins/segmentation.js @@ -135,10 +135,12 @@ export class PluginSegmentation extends TemplatePluginInstance { let frame = this.annotations; // 1) update the mask (always id 0) let mask = frame.find((l) => l.id === 0); - let create = false; - if (!mask) create=true; - mask = {id: 0, mask: this.element.getMask()};//if the mask already exists => just overwrite the previous mask - if (create) frame.push(mask);//otherwise(first time), create it + if (!mask) { + mask = {id: 0, mask: this.element.getMask()};//if the mask already exists => just overwrite the previous mask + frame.push(mask);//otherwise(first time), create it + } else { + mask.mask = this.element.getMask(); + } // 2) update annotation info when needed let label = frame.find((l) => l.id === JSON.stringify(updatedIds));// search the corresponding id if (label) {//id exists in the database, update information @@ -178,7 +180,7 @@ export class PluginSegmentation extends TemplatePluginInstance { this.element.fillSelectionWithClass(category.idx); // get the new mask and store it let mask = frame.find((l) => l.id === 0); - mask = {id: 0, mask: this.element.getMask()};//just overwrite the previous mask + mask.mask = this.element.getMask();//just overwrite the previous mask // 2) update annotation info from attributes const value = this.attributePicker.value; let label = frame.find((l) => l.id === JSON.stringify(this.selectedIds));// search the corresponding id @@ -203,7 +205,7 @@ export class PluginSegmentation extends TemplatePluginInstance { // 1) update the mask (always id 0) // get the new mask and store it let mask = frame.find((l) => l.id === 0); - mask = {id: 0, mask: this.element.getMask()};//just overwrite the previous mask + mask.mask = this.element.getMask();//just overwrite the previous mask // 2) update annotation info (= delete corresponding id) frame = frame.filter((l) => l.id !== JSON.stringify(ids)) // 3) store the new annotation structure @@ -218,7 +220,7 @@ export class PluginSegmentation extends TemplatePluginInstance { // 1) get back the mask into element let mask = this.annotations.find((l) => l.id === 0); if (!mask) this.element.setEmpty(); - else this.element.setMask(mask).then(console.log("set ok")); + else this.element.setMask(mask.mask); } getEditionMode() { diff --git a/frontend/src/templates/template-plugin-instance.js b/frontend/src/templates/template-plugin-instance.js index bba666a..621e7d8 100644 --- a/frontend/src/templates/template-plugin-instance.js +++ b/frontend/src/templates/template-plugin-instance.js @@ -41,7 +41,7 @@ export class TemplatePluginInstance extends TemplatePlugin { Object.keys(value).forEach((key) => { shape[key] = JSON.parse(JSON.stringify(value[key])); }); - shape.color = this._colorFor(shape.categoryName); + shape.color = this._colorFor(shape.category); this.collect(); }); } @@ -53,7 +53,7 @@ export class TemplatePluginInstance extends TemplatePlugin { // need to make immutable variable as not to change directly // the redux store this.element.shapes = JSON.parse(JSON.stringify(this.annotations.map((l) => { - return {...l, color: this._colorFor(l.categoryName)} + return {...l, color: this._colorFor(l.category)} }))); } @@ -93,7 +93,7 @@ export class TemplatePluginInstance extends TemplatePlugin { if (this.isSequence) { newObject.timestamp = this.targetFrameIdx; } - newObject.color = this._colorFor(newObject.categoryName); + newObject.color = this._colorFor(newObject.category); this.collect(); } diff --git a/server/config/parser.js b/server/config/parser.js index ee70274..48f6fcd 100644 --- a/server/config/parser.js +++ b/server/config/parser.js @@ -45,7 +45,7 @@ async function parse(databasePath) { return { id: a.id, name: a.name, - category: a.categoryName, + category: a.category, geometry: a.geometry, options: { ...a.options, From e0e693c4be7e7bdc1bc60479a96105fe3fa0c483 Mon Sep 17 00:00:00 2001 From: Brice Burger Date: Fri, 5 Nov 2021 12:51:27 +0100 Subject: [PATCH 07/12] minor: thumbnails fixedsize + missing dependency --- package.json | 3 ++- server/helpers/data-populator.js | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index aab2f46..10fac4d 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "path": "^0.12.7", "save": "^2.4.0", "short-uuid": "^3.1.1", - "tmp": "^0.1.0" + "tmp": "^0.1.0", + "semver": "^7.3.5" } } diff --git a/server/helpers/data-populator.js b/server/helpers/data-populator.js index 4d3bb57..43141b2 100644 --- a/server/helpers/data-populator.js +++ b/server/helpers/data-populator.js @@ -69,7 +69,7 @@ async function populateSimple(db, mediaRelativePath, hostWorkspacePath, datasetI for await (const f of files) { const id = generateKey(); const url = workspaceToMount(hostWorkspacePath, f); - const value = { id, dataset_id: datasetId, type: dataType, path: url, children: '', thumbnail: await imageThumbnail(f, {responseType: 'base64'})}; + const value = { id, dataset_id: datasetId, type: dataType, path: url, children: '', thumbnail: await imageThumbnail(f, {responseType: 'base64', height: 100})}; await bm.add({ type: 'put', key: dbkeys.keyForData(datasetId, id), value: value}); bar1.increment(); } From 6b122c6cf92293f431f09b080797bec77a7fbd55 Mon Sep 17 00:00:00 2001 From: Brice Burger Date: Mon, 8 Nov 2021 10:39:50 +0100 Subject: [PATCH 08/12] INTERNAL: update todo --- TODO_INTERNAL.md | 15 ++++++++++++--- frontend/package.json | 8 ++++---- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/TODO_INTERNAL.md b/TODO_INTERNAL.md index 63e3691..c0f174a 100644 --- a/TODO_INTERNAL.md +++ b/TODO_INTERNAL.md @@ -9,15 +9,24 @@ Ce fichier contient la liste des modifications/corrections prévues dans ce code # AFAIRE : + +## admin +- [ ] [#feature] posibilité de gérer séparément les données images et les tâches => implémentation du bouton création +- [ ] [#feature] implémentation de la navigation dans les fichiers lors de la création de tâches +- [ ] [#doc] afficher le numéro de version de pixano-app => https://www.npmjs.com/package/git-describe - [ ] [#feature] ajouter un système de versionning dans les fichiers import/export - [ ] [#feature] fichiers import/export : une fois le versionning en place, créer une v2 avec : category -> categoryName + ... -- [ ] [#doc] tabulation uniformisée + +## annotation +- [ ] [#doc] afficher le numéro de version de pixano-element et de pixano-app + afficher si element est local ou version npm +- [ ] [#interface] afficher la liste des objets étiquetés et revoir les interactions pour ne pas remodifier le dernier objet créé +- [ ] [#doc] tabulations/espaces uniformisée dans tous les fichiers - [ ] [#interface] manque pop-up erreur - [ ] [#interface] aide affichée à la 1ère connexion - [ ] [#interface] ajouter un bouton pour guider la fin de la création de tache -- [ ] [#doc] readme add 'cd ...' + add folder path in commands to make sure we run in the right folder +- [x] [#doc] readme add 'cd ...' + add folder path in commands to make sure we run in the right folder - [ ] [#feature] fichiers à supprimer si pb (compléter commande cleanall) -- [ ] [#doc] Manque README global qui explique comment est construit Pixano et ses dépôts, mettre des schémas pour montrer les utilisations (distribué, standalone facile, etc) +- [o] [#doc] Manque README global qui explique comment est construit Pixano et ses dépôts, mettre des schémas pour montrer les utilisations (distribué, standalone facile, etc) - [ ] [#doc] Getting started blog post - [ ] [#doc] Ajouter des démos complètes sexy + ajouter un bouton ajouter une config pour tester ton projet facilelement - [ ] [#feature] Ajouter un exécutable diff --git a/frontend/package.json b/frontend/package.json index 71d416c..9497e68 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -49,10 +49,10 @@ "@material/mwc-tab-bar": "0.19.1", "@material/mwc-textarea": "0.19.1", "@material/mwc-textfield": "0.19.1", - "@pixano/ai": "0.5.17", - "@pixano/core": "0.5.17", - "@pixano/graphics-2d": "0.5.17", - "@pixano/graphics-3d": "0.5.17", + "@pixano/ai": "file:../../pixano-elements/packages/ai", + "@pixano/core": "file:../../pixano-elements/packages/core", + "@pixano/graphics-2d": "file:../../pixano-elements/packages/graphics-2d", + "@pixano/graphics-3d": "file:../../pixano-elements/packages/graphics-3d", "@trystan2k/fleshy-jsoneditor": "3.0.0", "@webcomponents/webcomponentsjs": "^2.4.0", "babel-loader": "^8.0.6", From 26bcf49ebb99f7021ba509dbad240810fcae95f9 Mon Sep 17 00:00:00 2001 From: Brice Burger Date: Mon, 8 Nov 2021 12:06:34 +0100 Subject: [PATCH 09/12] update npm --- TODO_INTERNAL.md | 10 ++++++++-- frontend/package.json | 22 +++++++++++----------- package.json | 4 ++-- 3 files changed, 21 insertions(+), 15 deletions(-) diff --git a/TODO_INTERNAL.md b/TODO_INTERNAL.md index c0f174a..c2ce476 100644 --- a/TODO_INTERNAL.md +++ b/TODO_INTERNAL.md @@ -13,9 +13,12 @@ Ce fichier contient la liste des modifications/corrections prévues dans ce code ## admin - [ ] [#feature] posibilité de gérer séparément les données images et les tâches => implémentation du bouton création - [ ] [#feature] implémentation de la navigation dans les fichiers lors de la création de tâches -- [ ] [#doc] afficher le numéro de version de pixano-app => https://www.npmjs.com/package/git-describe +- [ ] [#doc] afficher le numéro de version de pixano-app + - sol 1: https://www.npmjs.com/package/git-describe : récupérer côté serveur et envoyer au client + - sol 2: inclure dans les scripts npm la création d'un fichier de version (https://www.npmjs.com/package/get-git-version), et l'inclure côté client - [ ] [#feature] ajouter un système de versionning dans les fichiers import/export - [ ] [#feature] fichiers import/export : une fois le versionning en place, créer une v2 avec : category -> categoryName + ... +- [ ] [#feature] séparer la gestion des tâches et des datasets ## annotation - [ ] [#doc] afficher le numéro de version de pixano-element et de pixano-app + afficher si element est local ou version npm @@ -59,7 +62,10 @@ Ce fichier contient la liste des modifications/corrections prévues dans ce code - [ ] [#feature] annotateurs à compétence différenciée, par ex : les annotateurs de niveau 1 font les BB autour des voitures, les annotateurs de niveau 2 complètent les marques et modèles - [ ] [#feature] avoir des tags test/train/validation et pouvoir segmenter la base en fonction (en lien avec l’intégration de Semfeat ?) -- [ ] [#feature] intégration Semfeat/Élise +- [ ] [#feature] intégration Semfeat/Élise (sur une branche Élise) + - [ ] ajouter Élise dans la génération du docker + - [ ] créer les interactions +- [ ] [#feature] nouveau module de classification - [ ] [#interface] à la création d'une nouvelle tâche, il faudrait pouvoir décider si on souhaite étiqueter en mode shuffle (par défaut) ou linéaire (en suivant le nom des fichiers) - [ ] [#interface] add an error message when creating task/dataset in a path which does not exist diff --git a/frontend/package.json b/frontend/package.json index 9497e68..8b00fce 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -23,11 +23,11 @@ "webpack-cli": "^3.3.10" }, "dependencies": { - "@babel/core": "^7.7.7", - "@babel/plugin-transform-runtime": "^7.7.6", + "@babel/core": "^7.16.0", + "@babel/plugin-transform-runtime": "^7.16.0", "@babel/polyfill": "^7.7.0", - "@babel/preset-env": "^7.7.7", - "@babel/runtime": "^7.7.7", + "@babel/preset-env": "^7.16.0", + "@babel/runtime": "^7.16.0", "@material/mwc-button": "0.19.1", "@material/mwc-checkbox": "0.19.1", "@material/mwc-circular-progress-four-color": "0.19.1", @@ -49,13 +49,13 @@ "@material/mwc-tab-bar": "0.19.1", "@material/mwc-textarea": "0.19.1", "@material/mwc-textfield": "0.19.1", - "@pixano/ai": "file:../../pixano-elements/packages/ai", - "@pixano/core": "file:../../pixano-elements/packages/core", - "@pixano/graphics-2d": "file:../../pixano-elements/packages/graphics-2d", - "@pixano/graphics-3d": "file:../../pixano-elements/packages/graphics-3d", + "@pixano/ai": "0.5.17", + "@pixano/core": "0.5.17", + "@pixano/graphics-2d": "0.5.17", + "@pixano/graphics-3d": "0.5.17", "@trystan2k/fleshy-jsoneditor": "3.0.0", "@webcomponents/webcomponentsjs": "^2.4.0", - "babel-loader": "^8.0.6", + "babel-loader": "^8.2.3", "copy-webpack-plugin": "^5.1.1", "css-loader": "^3.4.0", "file-loader": "^5.0.2", @@ -65,9 +65,9 @@ "material-design-icons": "^3.0.1", "node-sass": "^4.13.0", "pwa-helpers": "^0.9.1", - "redux": "^4.0.4", + "redux": "^4.1.2", "redux-devtools-extension": "^2.13.8", - "redux-thunk": "^2.3.0", + "redux-thunk": "^2.4.0", "redux-undo": "^1.0.0", "sass-loader": "^8.0.0", "source-map-loader": "^0.2.4", diff --git a/package.json b/package.json index 10fac4d..47fa101 100644 --- a/package.json +++ b/package.json @@ -29,8 +29,8 @@ "object-sizeof": "^1.5.3", "path": "^0.12.7", "save": "^2.4.0", + "semver": "^7.3.5", "short-uuid": "^3.1.1", - "tmp": "^0.1.0", - "semver": "^7.3.5" + "tmp": "^0.1.0" } } From 62bd226a1f796c6f59ff77a8d53bd98ade08a347 Mon Sep 17 00:00:00 2001 From: Brice Burger Date: Tue, 9 Nov 2021 10:26:27 +0100 Subject: [PATCH 10/12] thumbnails are not available for anything else then images for now --- TODO_INTERNAL.md | 6 ++++-- frontend/src/views/app-dashboard-admin.js | 7 +++++-- server/helpers/data-populator.js | 3 ++- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/TODO_INTERNAL.md b/TODO_INTERNAL.md index c2ce476..f38d05c 100644 --- a/TODO_INTERNAL.md +++ b/TODO_INTERNAL.md @@ -62,8 +62,10 @@ Ce fichier contient la liste des modifications/corrections prévues dans ce code - [ ] [#feature] annotateurs à compétence différenciée, par ex : les annotateurs de niveau 1 font les BB autour des voitures, les annotateurs de niveau 2 complètent les marques et modèles - [ ] [#feature] avoir des tags test/train/validation et pouvoir segmenter la base en fonction (en lien avec l’intégration de Semfeat ?) -- [ ] [#feature] intégration Semfeat/Élise (sur une branche Élise) - - [ ] ajouter Élise dans la génération du docker +- [o] [#feature] intégration Semfeat/Élise (sur une branche Élise) + - [x] ajouter Élise dans la génération du docker + - [ ] synchroniser la base de données image + - Q: comment gérer plusieurs datasets différents ? possible directement avec Élise ? ou il faudra créer plusieurs instances ? - [ ] créer les interactions - [ ] [#feature] nouveau module de classification diff --git a/frontend/src/views/app-dashboard-admin.js b/frontend/src/views/app-dashboard-admin.js index 1414d2d..03cae5a 100644 --- a/frontend/src/views/app-dashboard-admin.js +++ b/frontend/src/views/app-dashboard-admin.js @@ -467,7 +467,7 @@ class AppDashboardAdmin extends TemplatePage { /** * Display table row - * Status | Data Id | Annotator | Validator | State | Time | Launch + * Status | Data Id | Annotator | Validator | State | Time | Thumbnail | Launch */ listitem(item) { const v = this.statusMap.get(item.status); @@ -528,7 +528,10 @@ class AppDashboardAdmin extends TemplatePage {
Time
-
+
+ +
+
`; } diff --git a/server/helpers/data-populator.js b/server/helpers/data-populator.js index 43141b2..2be8d46 100644 --- a/server/helpers/data-populator.js +++ b/server/helpers/data-populator.js @@ -69,7 +69,8 @@ async function populateSimple(db, mediaRelativePath, hostWorkspacePath, datasetI for await (const f of files) { const id = generateKey(); const url = workspaceToMount(hostWorkspacePath, f); - const value = { id, dataset_id: datasetId, type: dataType, path: url, children: '', thumbnail: await imageThumbnail(f, {responseType: 'base64', height: 100})}; + let value = { id, dataset_id: datasetId, type: dataType, path: url, children: ''} + if (dataType=='image') value.thumbnail = await imageThumbnail(f, {responseType: 'base64', height: 100}); await bm.add({ type: 'put', key: dbkeys.keyForData(datasetId, id), value: value}); bar1.increment(); } From e2b644204054a7e26b13ce8bc54b3221f6e872a6 Mon Sep 17 00:00:00 2001 From: Brice Burger Date: Mon, 15 Nov 2021 18:05:29 +0100 Subject: [PATCH 11/12] release 0.4.9 --- frontend/package.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/package.json b/frontend/package.json index 8b00fce..6ff7d95 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,6 +1,6 @@ { "name": "pixano-app-frontend", - "version": "0.4.7", + "version": "0.4.9", "description": "This is a Pixano app.", "scripts": { "copyindex": "shx cp src/index.html ../build", diff --git a/package.json b/package.json index 47fa101..f8ec583 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pixano-app", - "version": "0.4.7", + "version": "0.4.9", "description": "This is a Pixano app.", "keywords": [], "license": "CECILL-C", From 72c2b125d5a266c02be71ceda2f1d8d0f5f6f73d Mon Sep 17 00:00:00 2001 From: Brice Burger Date: Mon, 15 Nov 2021 18:05:29 +0100 Subject: [PATCH 12/12] release 0.4.9 --- frontend/package.json | 10 +++++----- package.json | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/frontend/package.json b/frontend/package.json index 8b00fce..63664a0 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,6 +1,6 @@ { "name": "pixano-app-frontend", - "version": "0.4.7", + "version": "0.4.9", "description": "This is a Pixano app.", "scripts": { "copyindex": "shx cp src/index.html ../build", @@ -49,10 +49,10 @@ "@material/mwc-tab-bar": "0.19.1", "@material/mwc-textarea": "0.19.1", "@material/mwc-textfield": "0.19.1", - "@pixano/ai": "0.5.17", - "@pixano/core": "0.5.17", - "@pixano/graphics-2d": "0.5.17", - "@pixano/graphics-3d": "0.5.17", + "@pixano/ai": "0.6.0", + "@pixano/core": "0.6.0", + "@pixano/graphics-2d": "0.6.0", + "@pixano/graphics-3d": "0.6.0", "@trystan2k/fleshy-jsoneditor": "3.0.0", "@webcomponents/webcomponentsjs": "^2.4.0", "babel-loader": "^8.2.3", diff --git a/package.json b/package.json index 47fa101..f8ec583 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pixano-app", - "version": "0.4.7", + "version": "0.4.9", "description": "This is a Pixano app.", "keywords": [], "license": "CECILL-C",