From 4798dbe8b0d9d6253e89e1129029d8443443a43e Mon Sep 17 00:00:00 2001 From: Brice Burger Date: Thu, 23 Dec 2021 10:09:21 +0100 Subject: [PATCH 01/16] SERVERLESS DEMO: first structure --- .gitignore | 1 + frontend/src/serverless_demo/README.md | 13 ++ .../src/serverless_demo/dashboard-demo.js | 164 ++++++++++++++++++ frontend/src/serverless_demo/image.jpg | Bin 0 -> 87586 bytes .../images/pixano-mono-grad.svg | 30 ++++ frontend/src/serverless_demo/index.html | 21 +++ frontend/src/serverless_demo/package.json | 27 +++ .../src/serverless_demo/webpack.config.js | 23 +++ 8 files changed, 279 insertions(+) create mode 100644 frontend/src/serverless_demo/README.md create mode 100644 frontend/src/serverless_demo/dashboard-demo.js create mode 100644 frontend/src/serverless_demo/image.jpg create mode 100644 frontend/src/serverless_demo/images/pixano-mono-grad.svg create mode 100644 frontend/src/serverless_demo/index.html create mode 100644 frontend/src/serverless_demo/package.json create mode 100644 frontend/src/serverless_demo/webpack.config.js diff --git a/.gitignore b/.gitignore index beea512..709fff9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ node_modules/ build/ package-lock.json +*-bundle.js diff --git a/frontend/src/serverless_demo/README.md b/frontend/src/serverless_demo/README.md new file mode 100644 index 0000000..a847ac9 --- /dev/null +++ b/frontend/src/serverless_demo/README.md @@ -0,0 +1,13 @@ +# `Serverless Demo` + +This demo serves all plugins available in Pixano in a serverless application. Choose the plugin you want to use, click on _START ANNOTATING_. + +... image url + +Run the following commands to build and run this demo as a standalone application: + +``` +npm install +npm run build +npx serve +``` diff --git a/frontend/src/serverless_demo/dashboard-demo.js b/frontend/src/serverless_demo/dashboard-demo.js new file mode 100644 index 0000000..7798567 --- /dev/null +++ b/frontend/src/serverless_demo/dashboard-demo.js @@ -0,0 +1,164 @@ +/** + * @copyright CEA-LIST/DIASI/SIALV/LVA (2021) + * @author CEA-LIST/DIASI/SIALV/LVA + * @license CECILL-C +*/ + +import { html, css } from 'lit-element'; +import TemplatePage from '@pixano-app/frontend/src/templates/template-page'; +import { store, getState } from '@pixano-app/frontend/src/store'; +import { updateTaskName } from '@pixano-app/frontend/src/actions/application'; + +import { pluginsList } from '@pixano-app/frontend/src/plugins/index'; + +import '@pixano-app/frontend/src/plugins/rectangle'; + +import '@material/mwc-select'; +import '@material/mwc-icon-button'; +import '@material/mwc-list/mwc-list-item.js'; + + +class DashboardDemo extends TemplatePage { + + constructor() { + super(); + console.log("constructor DashboardDemo"); + this.chosenPlugin = false; + this.isactive = true; + } + static get properties() { + return { + chosenPlugin: { type: Boolean }, + isactive: { type: Boolean } + }; + } + + onActivate() { + console.log("activate DashboardDemo"); + } + + startAnnotating() { + const taskName = getState('application').taskName; + console.log("startAnnotating"); + // this.element.input = "image.jpg"; + this.chosenPlugin = true; + // import('@pixano-app/frontend/src/plugins/rectangle.js').then(() => {console.log("fait ?");}).catch(() => {console.log("erruer!!");}); + + + // const jobObjective = 'to_annotate'; + // this.gotoPage(`/#label/${taskName}/${jobObjective}`); + } + + static get styles() { + return [super.styles, css` + .body { + flex-flow: wrap; + display: flex; + height: 100%; + width: 100%; + margin: auto; + } + .logo { + background: whitesmoke; + } + .section { + --mdc-theme-primary: var(--pixano-color); + } + #overview { + flex: 1; + margin: 0; + background: var(--mdc-theme-primary); + --mdc-select-hover-line-color: white; + color: white; + flex-direction: row; + } + #overview > mwc-select { + display: flex; + margin-right: 20px; + align-items: center; + } + #left-panel { + background: whitesmoke; + margin: 0; + width: 80px; + } + mwc-linear-progress { + transform: rotate(-90deg); + margin-top: calc(60vh + 50px); + padding-top: 50%; + width: 60vh; + transform-origin: left top; + } + `] + } + + get headerContent() { + if (!this.chosenPlugin) return html` +

Dashboard: choose your annotation plugin

+ this.startAnnotating()}>Start Annotating + + `; + else return html` +

Annotate

+ this.chosenPlugin=false} title="Back to plugin choice"> + this.element.input = "image.jpg"} title="Download your image"> + `; + } + + get topSection() { + const taskName = getState('application').taskName; + return html` +
+

Select a plugin:

+ { + if (pluginsList[e.detail.index] && pluginsList[e.detail.index] !== taskName) { + store.dispatch(updateTaskName(pluginsList[e.detail.index])); + } + }}> + ${pluginsList.map((p) => html`${p}`) + } + +
+ `; + } + + get body() { + if (!this.chosenPlugin) return html` +
+ ${this.topSection} +
+ ` + else return html` + + ` + // else return html` + // + // ` + } + // ... mwc-icon-button pas fonctionnels non plus ... +// voir la demo existante : charger directement un pxn-rectangle pour voir si çà change + voir comment et quand est chargée l'image + + get element() { + // return this.shadowRoot.getElementById('pxn-rectangle'); + // return this.shadowRoot.getElementById('plugin-rectangle'); + return this.shadowRoot.getElementById('main'); + } + + // render() { + // return html` + //
+ //
+ // + //
+ // ${this.headerContent} + //
+ //
+ // ${this.body} + //
+ // + // `; + // } +} +customElements.define('dashboard-demo', DashboardDemo); diff --git a/frontend/src/serverless_demo/image.jpg b/frontend/src/serverless_demo/image.jpg new file mode 100644 index 0000000000000000000000000000000000000000..7d09bc895269766e464d6c34215de3b88ad3f3c8 GIT binary patch literal 87586 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 pg7f + + + + + + + + + + + + + + + + + + + + + diff --git a/frontend/src/serverless_demo/index.html b/frontend/src/serverless_demo/index.html new file mode 100644 index 0000000..cd622e1 --- /dev/null +++ b/frontend/src/serverless_demo/index.html @@ -0,0 +1,21 @@ + + + + Serverless Demo + + + + + + + + + + + diff --git a/frontend/src/serverless_demo/package.json b/frontend/src/serverless_demo/package.json new file mode 100644 index 0000000..2dd3d86 --- /dev/null +++ b/frontend/src/serverless_demo/package.json @@ -0,0 +1,27 @@ +{ + "name": "serverless_demo", + "version": "0.6.0", + "private": true, + "description": "Serverless Demo", + "author": "Pixano Authors ", + "homepage": "https://pixano.cea.fr/", + "license": "CECILL-C", + "main": "dashboard-demo.js", + "scripts": { + "build": "webpack --config webpack.config.js", + "watch": "webpack --config webpack.config.js --watch" + }, + "devDependencies": { + "source-map-loader": "^0.2.4", + "webpack": "4.44.2", + "webpack-cli": "3.3.12" + }, + "dependencies": { + "copy-webpack-plugin": "^5.1.1", + "html-webpack-plugin": "^3.2.0", + "@material/mwc-icon": "0.19.1", + "@material/mwc-icon-button": "0.19.1", + "@material/mwc-icon-button-toggle": "0.19.1", + "@pixano-app/frontend": "file:../../" + } +} diff --git a/frontend/src/serverless_demo/webpack.config.js b/frontend/src/serverless_demo/webpack.config.js new file mode 100644 index 0000000..182ee79 --- /dev/null +++ b/frontend/src/serverless_demo/webpack.config.js @@ -0,0 +1,23 @@ +const path = require('path'); + +module.exports = { + mode: 'development', + entry: path.resolve(__dirname, './dashboard-demo.js'), + output: { + path: path.resolve(__dirname), + filename: 'dashboard-demo-bundle.js' + }, + resolve: { + extensions: ['.ts', '.tsx', '.js'] + }, + devtool: 'eval-source-map', + module: { + rules: [ + { + test: /\.(js|mjs|jsx|ts|tsx)$/, + use: ["source-map-loader"], + enforce: "pre" + } + ] + } +}; From b71605633f2b4a066d93dfcdeef8b3f460abfe33 Mon Sep 17 00:00:00 2001 From: Brice Burger Date: Thu, 23 Dec 2021 16:14:43 +0100 Subject: [PATCH 02/16] update publish process + fix in Dockerfile --- Dockerfile | 2 +- README_INTERNAL.md | 80 +++++++++++++++++++++++++++++++--------------- 2 files changed, 55 insertions(+), 27 deletions(-) diff --git a/Dockerfile b/Dockerfile index 77b826b..12db7de 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,7 +15,7 @@ COPY server server COPY .logo-ascii .logo-ascii # Build frontend and install backend dependencies -RUN npm deps && npm run build && rm -rf frontend +RUN npm run deps && npm run build && rm -rf frontend EXPOSE 3000 diff --git a/README_INTERNAL.md b/README_INTERNAL.md index 14dade4..36b75d9 100644 --- a/README_INTERNAL.md +++ b/README_INTERNAL.md @@ -68,7 +68,8 @@ master <------push------ github <--merge-- master <--merge--> p2 ## Publication ### 0) prepare gitlab version - VERSION=0.6.0 + LAST_VERSION=0.4.9 + VERSION=0.5.0 git fetch git checkout master git pull origin master @@ -83,24 +84,27 @@ master <------push------ github <--merge-- master <--merge--> p2 - on your fork github (on github.com), click on "Fetch upstream", then "Fetch and merge" 2. Locally: + 2.1 Merge with master + # make sure the repositories are up-to-date git fetch upstream git checkout github + git pull # integrate our modifications to the github branch # merge all commits without commit which lets you inspect (and modify) the result before committing # ensure that you `git rm --cached` every internal file/section git merge --no-commit master - # when everything is ok, commit the changes - git commit -m "release $VERSION" - -During the merge / before commiting, **do not include / delete files and internal/proprietary codes** : -- do not include the present file [README_INTERNAL.md](./README_INTERNAL.md), nor the .gitlab-ci.yml -- do not include the folder [doc_interne](./doc_interne) -- do not include the files with tag "proprietary" -- do not include with code blocks surrounded by tag "proprietary" + During the merge / before commiting, **do not include / delete files and internal/proprietary codes** : + - do not include the present file [README_INTERNAL.md](./README_INTERNAL.md) and [TODO_INTERNAL.md](./TODO_INTERNAL.md), nor the .gitlab-ci.yml + - do not include the files with tag "proprietary" + - do not include with code blocks surrounded by tag "proprietary" + + 2.2 Commit blacked out merge + + git commit ### 2) Verify and validate code #### clean and recompile "from scratch" @@ -108,8 +112,8 @@ During the merge / before commiting, **do not include / delete files and interna rm -rf node_modules frontend/node_modules rm package-lock.json frontend/package-lock.json # compilation - npm i - cd frontend ; npm i ; npm run build ; cd - + npm run deps + npm run build #### verify "by hand" node server/server.js data-test/ ## you can create tasks for images using the folder "images/" @@ -120,22 +124,35 @@ During the merge / before commiting, **do not include / delete files and interna git tag -m "v$VERSION" "v$VERSION" # push modifications on the fork git push upstream github:master --follow-tags - - # tag report on master - git checkout master - #OR git checkout f5f56daf if the reference commit is not the last one - git tag -m "vi$VERSION" "vi$VERSION" - git push origin master --follow-tags + #### 2. pull-request The rest is on [github](https://github.com) : -- on the fork $MYACCOUNT : onglet "Pull requests" => "New pull request" => "Create pull request" => "Create pull request" -- automatic verifications are made by github -- on the pixano account : got to "Merge pull request" => "Confirm merge" +- on the fork $MYACCOUNT : onglet "Pull requests" => "New pull request" => "Create pull request" +- complete the merge request message with: + - Tip: To easily list the commits and descriptions: ```git log v$LAST_VERSION..v$VERSION --oneline --pretty="format:%s"``` + - in Title: v$VERSION + - in Comment: write something like: +``` +## server +* file: modifications... +* file: modifications... +* ... +## frontend +* ... + +Co-authored-by: Camille Dupont camille.dupont@cea.fr +Co-authored-by: Brice Burger brice.burger@cea.fr +Co-authored-by: ... +``` +- click on "Create pull request" => automatic verifications are made by github +- at the bottom of the page: click on "Merge pull request" => "Confirm merge" + + #### 3. release Transform the tag in github release (makes the last tag more visible and detailed) : - + @@ -143,11 +160,9 @@ Transform the tag in github release (makes the last tag more visible and detaile - go to the page in [release](https://github.com/pixano/pixano-app/releases) - button "Draft a new release" - - "Tag version" vX.Y.Z - - in "Release title", put the version vX.Y.Z - - complete the comments - - To easily list the commits and descriptions : - git log v0.5.15..v0.5.16 --oneline + - click on "Tag version" button: vX.Y.Z => "create new tag" + - in "Release title": vX.Y.Z + - complete the comments with the same comment then the pull request - "Publish release" #### 4. push on docker hub @@ -164,4 +179,17 @@ Transform the tag in github release (makes the last tag more visible and detaile # push to docker hub sudo docker push pixano/pixano-app:$VERSION sudo docker push pixano/pixano-app:latest + +#### 5. report all to master + # tag report on master + git checkout master + #OR git checkout f5f56daf if the reference commit is not the last one + + # if some changes have to be reported back + git cherry-pick last_github_commit_hash + # push to origin + git tag -m "vi$VERSION" "vi$VERSION" + git push origin master --follow-tags + + From c6fb9af9ef338f329ea4066c3991d919a8ca60cb Mon Sep 17 00:00:00 2001 From: Camille Dupont Date: Thu, 6 Jan 2022 11:26:50 +0000 Subject: [PATCH 03/16] Update TODO_INTERNAL.md --- TODO_INTERNAL.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/TODO_INTERNAL.md b/TODO_INTERNAL.md index e7c8ceb..1544c56 100644 --- a/TODO_INTERNAL.md +++ b/TODO_INTERNAL.md @@ -11,7 +11,7 @@ Ce fichier contient la liste des modifications/corrections prévues dans ce code # AFAIRE : ## général -- [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) +- [x] [#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 @@ -41,7 +41,7 @@ Ce fichier contient la liste des modifications/corrections prévues dans ce code - [x] [#bogue] le REJECT ne fonctionne pas (firefox sur rectangle sans annotation dans l'image) ### gestion des jeux de données - [ ] [#feature] séparer la gestion des tâches et des datasets => implémentation du bouton création -- [ ] [#feature] possibilité de prendre en compte une modification de la base de données images => bouton "refresh database" ? +- [ ] [#feature] possibilité de prendre en compte une modification de la datasets => bouton "refresh database" ? - [ ] [#feature] avoir des tags test/train/validation et pouvoir segmenter la base en fonction (en lien avec l’intégration de Semfeat ?) - [ ] [#feature] possibilité de gérer des "sélections" au lieu d'annoter systématiquement l'ensemble d'une base de données (supprime le point précédent ?) - [x] [#feature] intégration Semfeat/Élise (sur une branche Élise) @@ -53,7 +53,7 @@ Ce fichier contient la liste des modifications/corrections prévues dans ce code ### visualisation / sélection des données - [ ] [#feature] commencer par mettre les images en visu et ne plus mettre nécessairement toutes les images en to_annotate par défaut => il faut pouvoir sélectionner une partie de la base de donnée facilement pour l'étiquetage - [ ] [#feature] passerelle Mturk / Amazon SageMaker -- [ ] [#bogue] l'affichage n'est pas le même (boutons manquants) quand on appuie sur le bouton image dans la liste par rapport à un appui sur les "start *" +- [ ] [#bogue] l'affichage n'est pas le même (boutons manquants) quand on appuie sur le bouton image dans la liste par rapport à un appui sur les "start *" ??? - [o] [#feature] affichage sous forme d’imagettes plutôt qu’une liste - [x] [#feature] création des imagettes et intégration dans la liste de fichiers - [ ] [#feature] généralisation des imagettes à toutes les formes de fichiers en entrée @@ -61,7 +61,7 @@ Ce fichier contient la liste des modifications/corrections prévues dans ce code - [ ] [#feature] possibilité de n'afficher dans ce mur qu'une sous-sélection grâce aux filtres dans la liste - [ ] [#feature] visualisation des annotations existantes/de résultats importés dans ces imagettes => recalculer les thumbnails après chaque submit ? - [ ] [#bogue] après une sélection via un filtre, on reste sur la même page d'affichage, mais s'il n'y a plus autant d'images à afficher => il faudrait revenir à 0 -- [ ] [#bogue] quand on clique sur l'affichage d'image après avoir filtré une partie du contenu, il ne fait rien (image vide ou image précédente s'il y en avait une +- [ ] [#bogue] quand on clique sur l'affichage d'image après avoir filtré une partie du contenu, il ne fait rien (image vide ou image précédente s'il y en avait une ??? ## annotation - [ ] [#bogue] supprimer les plugins inutilisés ? : tracking-point, keypoints-box, sequence-point-rectangle @@ -80,9 +80,9 @@ Ce fichier contient la liste des modifications/corrections prévues dans ce code - ils reprennent la valeur par défaut si on passe à une annotation de classe différente puis qu'on y revient - si on modifie la valeur sur une boite, c'est propagé à toutes les autres boites de même classe sur lesquelles on clique - [x] [#bogue #firefox] quand on édite les annotations, puis qu'on crée de nouveau sur la même image, les propriétés restent celles de la dernière annotation modifiée (et on la modifie donc) (uniquement sous firefox) -- [ ] [#feature] possibilité de sélectionner plusieurs éléments pour leur donner des caractéristiques communes ? +- [x] [#feature] possibilité de sélectionner plusieurs éléments pour leur donner des caractéristiques communes ? ### plugin keypoints -- [ ] [#feature] possibilité de ne pas annoter tous les keypoints (non visibles) ? +- [ ] [#feature] possibilité de ne pas annoter tous les keypoints (non visibles) ? => elements ### plugin segmentation - [x] [#bogue] segmentation : mes modifs union/substract ne fonctionnent pas dans l'app - [x] [#bogue] setMask non entièrement fonctionnel : rien en s'affiche et on ne peut rien sélectionner From 941db74947ed52f996e92a5de30d42e84c703ae6 Mon Sep 17 00:00:00 2001 From: Brice Burger Date: Fri, 7 Jan 2022 17:18:49 +0100 Subject: [PATCH 04/16] pxn-graph => pxn-keypoints --- frontend/src/plugins/keypoints-box.js | 6 +++--- frontend/src/plugins/keypoints.js | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/frontend/src/plugins/keypoints-box.js b/frontend/src/plugins/keypoints-box.js index 25aca4e..211b59e 100644 --- a/frontend/src/plugins/keypoints-box.js +++ b/frontend/src/plugins/keypoints-box.js @@ -5,7 +5,7 @@ */ import { html } from 'lit-element'; -import { settings } from '@pixano/graphics-2d/lib/pxn-graph'; +import { settings } from '@pixano/graphics-2d/lib/pxn-keypoints'; import '@material/mwc-icon-button'; import { colorNames, shuffle } from '@pixano/core/lib/utils' import { TemplatePluginInstance } from '../templates/template-plugin-instance'; @@ -160,13 +160,13 @@ export class PluginKeypointsBox extends TemplatePluginInstance { } get editor() { - return html``; + @selection=${this.onSelection}>`; } } customElements.define('plugin-keypoints-box', PluginKeypointsBox); diff --git a/frontend/src/plugins/keypoints.js b/frontend/src/plugins/keypoints.js index ba233f3..f029221 100644 --- a/frontend/src/plugins/keypoints.js +++ b/frontend/src/plugins/keypoints.js @@ -78,13 +78,13 @@ export class PluginKeypoints extends TemplatePluginInstance { } get editor() { - return html``; + @mode=${this.onModeChange}>`; } } customElements.define('plugin-keypoints', PluginKeypoints); From 470722a556a64389f7f41c70267199630a1dc811 Mon Sep 17 00:00:00 2001 From: Brice Burger Date: Thu, 13 Jan 2022 10:22:24 +0100 Subject: [PATCH 05/16] serverless-demo has been moved to pixano-elements --- frontend/src/serverless_demo/README.md | 13 -- .../src/serverless_demo/dashboard-demo.js | 164 ------------------ frontend/src/serverless_demo/image.jpg | Bin 87586 -> 0 bytes .../images/pixano-mono-grad.svg | 30 ---- frontend/src/serverless_demo/index.html | 21 --- frontend/src/serverless_demo/package.json | 27 --- .../src/serverless_demo/webpack.config.js | 23 --- 7 files changed, 278 deletions(-) delete mode 100644 frontend/src/serverless_demo/README.md delete mode 100644 frontend/src/serverless_demo/dashboard-demo.js delete mode 100644 frontend/src/serverless_demo/image.jpg delete mode 100644 frontend/src/serverless_demo/images/pixano-mono-grad.svg delete mode 100644 frontend/src/serverless_demo/index.html delete mode 100644 frontend/src/serverless_demo/package.json delete mode 100644 frontend/src/serverless_demo/webpack.config.js diff --git a/frontend/src/serverless_demo/README.md b/frontend/src/serverless_demo/README.md deleted file mode 100644 index a847ac9..0000000 --- a/frontend/src/serverless_demo/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# `Serverless Demo` - -This demo serves all plugins available in Pixano in a serverless application. Choose the plugin you want to use, click on _START ANNOTATING_. - -... image url - -Run the following commands to build and run this demo as a standalone application: - -``` -npm install -npm run build -npx serve -``` diff --git a/frontend/src/serverless_demo/dashboard-demo.js b/frontend/src/serverless_demo/dashboard-demo.js deleted file mode 100644 index 7798567..0000000 --- a/frontend/src/serverless_demo/dashboard-demo.js +++ /dev/null @@ -1,164 +0,0 @@ -/** - * @copyright CEA-LIST/DIASI/SIALV/LVA (2021) - * @author CEA-LIST/DIASI/SIALV/LVA - * @license CECILL-C -*/ - -import { html, css } from 'lit-element'; -import TemplatePage from '@pixano-app/frontend/src/templates/template-page'; -import { store, getState } from '@pixano-app/frontend/src/store'; -import { updateTaskName } from '@pixano-app/frontend/src/actions/application'; - -import { pluginsList } from '@pixano-app/frontend/src/plugins/index'; - -import '@pixano-app/frontend/src/plugins/rectangle'; - -import '@material/mwc-select'; -import '@material/mwc-icon-button'; -import '@material/mwc-list/mwc-list-item.js'; - - -class DashboardDemo extends TemplatePage { - - constructor() { - super(); - console.log("constructor DashboardDemo"); - this.chosenPlugin = false; - this.isactive = true; - } - static get properties() { - return { - chosenPlugin: { type: Boolean }, - isactive: { type: Boolean } - }; - } - - onActivate() { - console.log("activate DashboardDemo"); - } - - startAnnotating() { - const taskName = getState('application').taskName; - console.log("startAnnotating"); - // this.element.input = "image.jpg"; - this.chosenPlugin = true; - // import('@pixano-app/frontend/src/plugins/rectangle.js').then(() => {console.log("fait ?");}).catch(() => {console.log("erruer!!");}); - - - // const jobObjective = 'to_annotate'; - // this.gotoPage(`/#label/${taskName}/${jobObjective}`); - } - - static get styles() { - return [super.styles, css` - .body { - flex-flow: wrap; - display: flex; - height: 100%; - width: 100%; - margin: auto; - } - .logo { - background: whitesmoke; - } - .section { - --mdc-theme-primary: var(--pixano-color); - } - #overview { - flex: 1; - margin: 0; - background: var(--mdc-theme-primary); - --mdc-select-hover-line-color: white; - color: white; - flex-direction: row; - } - #overview > mwc-select { - display: flex; - margin-right: 20px; - align-items: center; - } - #left-panel { - background: whitesmoke; - margin: 0; - width: 80px; - } - mwc-linear-progress { - transform: rotate(-90deg); - margin-top: calc(60vh + 50px); - padding-top: 50%; - width: 60vh; - transform-origin: left top; - } - `] - } - - get headerContent() { - if (!this.chosenPlugin) return html` -

Dashboard: choose your annotation plugin

- this.startAnnotating()}>Start Annotating - - `; - else return html` -

Annotate

- this.chosenPlugin=false} title="Back to plugin choice"> - this.element.input = "image.jpg"} title="Download your image"> - `; - } - - get topSection() { - const taskName = getState('application').taskName; - return html` -
-

Select a plugin:

- { - if (pluginsList[e.detail.index] && pluginsList[e.detail.index] !== taskName) { - store.dispatch(updateTaskName(pluginsList[e.detail.index])); - } - }}> - ${pluginsList.map((p) => html`${p}`) - } - -
- `; - } - - get body() { - if (!this.chosenPlugin) return html` -
- ${this.topSection} -
- ` - else return html` - - ` - // else return html` - // - // ` - } - // ... mwc-icon-button pas fonctionnels non plus ... -// voir la demo existante : charger directement un pxn-rectangle pour voir si çà change + voir comment et quand est chargée l'image - - get element() { - // return this.shadowRoot.getElementById('pxn-rectangle'); - // return this.shadowRoot.getElementById('plugin-rectangle'); - return this.shadowRoot.getElementById('main'); - } - - // render() { - // return html` - //
- //
- // - //
- // ${this.headerContent} - //
- //
- // ${this.body} - //
- // - // `; - // } -} -customElements.define('dashboard-demo', DashboardDemo); diff --git a/frontend/src/serverless_demo/image.jpg b/frontend/src/serverless_demo/image.jpg deleted file mode 100644 index 7d09bc895269766e464d6c34215de3b88ad3f3c8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 87586 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 pg7f - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/src/serverless_demo/index.html b/frontend/src/serverless_demo/index.html deleted file mode 100644 index cd622e1..0000000 --- a/frontend/src/serverless_demo/index.html +++ /dev/null @@ -1,21 +0,0 @@ - - - - Serverless Demo - - - - - - - - - - - diff --git a/frontend/src/serverless_demo/package.json b/frontend/src/serverless_demo/package.json deleted file mode 100644 index 2dd3d86..0000000 --- a/frontend/src/serverless_demo/package.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "name": "serverless_demo", - "version": "0.6.0", - "private": true, - "description": "Serverless Demo", - "author": "Pixano Authors ", - "homepage": "https://pixano.cea.fr/", - "license": "CECILL-C", - "main": "dashboard-demo.js", - "scripts": { - "build": "webpack --config webpack.config.js", - "watch": "webpack --config webpack.config.js --watch" - }, - "devDependencies": { - "source-map-loader": "^0.2.4", - "webpack": "4.44.2", - "webpack-cli": "3.3.12" - }, - "dependencies": { - "copy-webpack-plugin": "^5.1.1", - "html-webpack-plugin": "^3.2.0", - "@material/mwc-icon": "0.19.1", - "@material/mwc-icon-button": "0.19.1", - "@material/mwc-icon-button-toggle": "0.19.1", - "@pixano-app/frontend": "file:../../" - } -} diff --git a/frontend/src/serverless_demo/webpack.config.js b/frontend/src/serverless_demo/webpack.config.js deleted file mode 100644 index 182ee79..0000000 --- a/frontend/src/serverless_demo/webpack.config.js +++ /dev/null @@ -1,23 +0,0 @@ -const path = require('path'); - -module.exports = { - mode: 'development', - entry: path.resolve(__dirname, './dashboard-demo.js'), - output: { - path: path.resolve(__dirname), - filename: 'dashboard-demo-bundle.js' - }, - resolve: { - extensions: ['.ts', '.tsx', '.js'] - }, - devtool: 'eval-source-map', - module: { - rules: [ - { - test: /\.(js|mjs|jsx|ts|tsx)$/, - use: ["source-map-loader"], - enforce: "pre" - } - ] - } -}; From 3d612f0d93448b90631026ce40cfac93c0e71c80 Mon Sep 17 00:00:00 2001 From: Brice Burger Date: Fri, 21 Jan 2022 14:43:53 +0100 Subject: [PATCH 06/16] transfer labels and some utils to elements --- frontend/src/helpers/attribute-picker.js | 407 ------------------ frontend/src/helpers/utils.js | 163 ------- frontend/src/plugins/classification.js | 2 +- frontend/src/plugins/index.js | 3 - frontend/src/plugins/segmentation.js | 5 +- .../src/templates/template-plugin-instance.js | 4 +- 6 files changed, 5 insertions(+), 579 deletions(-) delete mode 100644 frontend/src/helpers/attribute-picker.js diff --git a/frontend/src/helpers/attribute-picker.js b/frontend/src/helpers/attribute-picker.js deleted file mode 100644 index eadeaf2..0000000 --- a/frontend/src/helpers/attribute-picker.js +++ /dev/null @@ -1,407 +0,0 @@ -/** - * Utility class to pick labels in a panel - * @copyright CEA-LIST/DIASI/SIALV/LVA (2019) - * @author CEA-LIST/DIASI/SIALV/LVA - * @license CECILL-C -*/ - -import { LitElement, html, css } from 'lit-element'; -import '@material/mwc-dialog'; -import '@material/mwc-checkbox'; -import '@material/mwc-formfield'; -import '@material/mwc-select'; -import '@material/mwc-list/mwc-list-item'; -import { getValue } from '../helpers/utils'; - - -// TODO: move to pixano-elements -export class AttributePicker extends LitElement { - - static get styles() { - return [ - css` - :host { - -webkit-touch-callout: none; /* iOS Safari */ - -webkit-user-select: none; /* Safari */ - -khtml-user-select: none; /* Konqueror HTML */ - -moz-user-select: none; /* Old versions of Firefox */ - -ms-user-select: none; /* Internet Explorer/Edge */ - user-select: none; /* Non-prefixed version, currently - supported by Chrome, Opera and Firefox */ - } - h3 { - font-size: 14px; - margin-left: 10px; - } - .category { - height: 40px; - display: flex; - align-items: center; - padding-left: 10px; - } - .category:hover { - background-color: #ececec; - cursor: pointer; - } - .selected { - background-color: rgb(230, 230, 230); - color: var(--secondary-color); - } - span.step { - background: red; - border-radius: 0.8em; - -moz-border-radius: 0.8em; - -webkit-border-radius: 0.8em; - color: #ffffff; - display: inline-block; - line-height: 1.6em; - margin-right: 15px; - text-align: center; - width: 1.6em; - margin-left: 10px; - } - .category > p { - margin: 0; - padding-left: 10px; - } - .shortcut { - position: absolute; - right: 0px; - z-index: 1; - } - #shortcut-table { - font-family: "Trebuchet MS", Arial, Helvetica, sans-serif; - border-collapse: collapse; - width: 100%; - } - - #shortcut-table td, #shortcut-table th { - border: 1px solid #ddd; - padding: 8px; - } - - #shortcut-table tr:nth-child(even){background-color: #f2f2f2;} - - #shortcut-table tr:hover {background-color: #ddd;} - - #shortcut-table th { - padding-top: 12px; - padding-bottom: 12px; - text-align: left; - background-color: #4CAF50; - color: white; - } - mwc-select { - width: 100%; - } - mwc-formfield { - margin: auto; - width: 70%; - display: flex; - } - ` - ] - } - - 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: {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 - */ - return { - showDetail: { type: Boolean }, - shortcuts: { type: Array }, - schema: { type: Object }, - value: { type: Object }, - numDone: { type: Number }, - numTotal: { type: Number } - } - } - - get selectedCategory() { - return this.schema.category.find((c) => c.name === this.value.category); - } - - getDefaultAttributesForCategory(schema, categoryName) { - let category = schema.category.find((c) => c.name === categoryName); - if (!category && schema.category.length) { - category = schema.category[0]; - } - if (category && category.properties) { - const d = {}; - category.properties.forEach((p) => { - d[p.name] = p.default; - }); - return d; - } - return {} - } - - onKeyDown(event) { - if (event.ctrlKey) { - event.preventDefault(); - } - } - - onKeyUp(event) { - const isNumber = event.code.replace('Digit', '').replace('Numpad', '') - if (Number(isNumber) >= 0 && Number(isNumber) <= 9 && event.ctrlKey) { - event.preventDefault(); - this.mem += isNumber; - - } - if (event.key === 'Control' && this.mem !== '') { - event.preventDefault(); - const c = this.schema.category[Number(this.mem)]; - if (c) { - this.setCategory(c.name); - } - this.mem = ''; - } - } - - constructor() { - super(); - this.shortcuts = [ - ['ALT', 'Switch create/update mode'], - ['CTRL + [0-9]', 'Select category by index'], - ['TAB', 'Navigate through objects'], - ['SHIFT + Tab', 'Navigate through objects (inverse)'], - ['SHIFT + Click', 'Multiple selection'], - ['CTRL + z', 'Undo'], - ['CTRL + SHIFT + z', 'Redo'], - ['CTRL + s', 'Save'] - ]; - this.showDetail = false; - this.mem = ''; - this.schema = {}; - this.schema.category = []; - const options = {}; - this.value = {category: '', options }; - this.onKeyDown = this.onKeyDown.bind(this); - this.onKeyUp = this.onKeyUp.bind(this); - } - - connectedCallback() { - super.connectedCallback(); - window.addEventListener('keydown', this.onKeyDown); - window.addEventListener('keyup', this.onKeyUp); - } - - disconnectedCallback() { - super.disconnectedCallback(); - window.removeEventListener('keydown', this.onKeyDown); - window.removeEventListener('keyup', this.onKeyUp); - } - - openShortcuts() { - const d = this.shadowRoot.querySelector('mwc-dialog'); - d.open = true; - } - - _getList() { - try { - return this.schema.category.map((c)=> c.name); - } catch { - return []; - } - } - - _colorFor(categoryName) { - const category = this.schema.category.find((c) => c.name === categoryName); - return category ? category.color || 'rgb(0,0,0)' : 'rgb(0,0,0)'; - } - - get defaultValue() { - 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 = {category: newCategory, options }; - this._notifyUpdate(); - } - - /** - * Triggered when exterior/non-user-triggered - * edition of edition label schema - * @param {*} entity - */ - setAttributes(entity) { - if (entity) { - entity.options = entity.options || {}; - 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])); - } else { - options[key] = ""; - } - }); - // update property choices - this.value = {category: entity.category, options}; - - // update property values - const childDivs = this.shadowRoot.getElementById('updateEditor').getElementsByTagName('mwc-select'); - const childContent = this.schema.category.find((c) => c.name === this.value.category); - const propList = childContent ? childContent.properties : []; - [ ...childDivs].forEach((c) => { - const subprop = propList.find((p) => p.name == c.label); - const enumList = subprop ? subprop.enum : []; - // cast to number - const val = isNaN(options[c.label]) ? options[c.label] : parseInt(options[c.label]); - c.select(enumList.findIndex((e) => e === val)) - }); - } - } - - setAttributesIdx(idx) { - if (idx != undefined) { - this.value = {category: this.schema.category.find((c) => c.idx === idx).name}; - } else { - const options = this.getDefaultAttributesForCategory(this.schema, this.schema.default); - this.value = {category: this.schema.default, options }; - } - } - - reloadSchema(schema) { - this.schema = schema; - const options = this.getDefaultAttributesForCategory(schema, schema.default); - this.value = {category: schema.default, options }; - } - - _notifyUpdate() { - this.dispatchEvent(new Event('update')); - } - - get shortcutsDialog() { - return html` - -

Shortcut list

-
- - - - - - ${ - this.shortcuts.map(([k,v]) => { - return html` - - `; - }) - } -
ShortcutDescription
${k}${v}
-
- OK -
- ` - } - - firstUpdated() { - this.reloadSchema(this.schema); - } - - htmlProp(prop) { - if (prop.type === 'dropdown') { - // list of attribute choices - return html` - { - const idx = e.detail.index; - if (this.value.options[prop.name] != prop.enum[idx]) { - this.value.options[prop.name] = prop.enum[idx]; - this._notifyUpdate(); - } - }}> - ${prop.enum.map((sub) => { - return html`${sub}` - })} - - ` - } else if (prop.type === 'checkbox') { - const checked = JSON.parse(JSON.parse(JSON.stringify(this.value.options[prop.name]).toLowerCase()));// if the initial value was a string like "false" or "False", we want it to be interpreted as a boolean - return html` - - { - const path = evt.composedPath(); - const input = path[0]; - if (checked != input.checked) { - this.value.options[prop.name] = !checked; - this.value = {...this.value}; - this._notifyUpdate(); - } - } - }> - - ` - } else if (prop.type === 'textfield') { - const textval = this.value.options[prop.name]; - return html` - { - this.value.options[prop.name] = getValue(evt); - this.value = {...this.value}; - this._notifyUpdate(); - } - }> - ` - } - return html``; - } - - get renderDetail() { - return html` -
-

- ${ - this.schema.category.map((category, idx) => { - return html` -
this.setCategory(category.name)}> - ${idx}

${category.name}

-
- ${category.properties && category.name === this.value.category ? html` - ${category.properties.map((prop) => this.htmlProp(prop))} - `: html``} - ` - }) - } -
` - } - - get renderSimple() { - return html` -
-

- ${ - this.schema.category.map((category, idx) => { - return html` -
this.setCategory(category.name)}> - ${idx}

${category.name}

-
` - }) - } -
- `; - } - - /** - * Render the element template. - */ - render(){ - return html` - ${this.shortcutsDialog} - - ${this.renderDetail} - ${this.renderSimple} - `; - } -} - -customElements.define('attribute-picker', AttributePicker); diff --git a/frontend/src/helpers/utils.js b/frontend/src/helpers/utils.js index 2886331..0a25e2a 100644 --- a/frontend/src/helpers/utils.js +++ b/frontend/src/helpers/utils.js @@ -4,169 +4,6 @@ * @license CECILL-C */ -export function commonJson(entities) { - if (entities.length == 0) { - return; - } else if (entities.length == 1) { - return entities[0]; - } - function getKeys(object) { - function iter(o, p) { - if (Array.isArray(o)) { - result.push(p.join('.')); - return; - } - if (o && typeof o === 'object') { - var keys = Object.keys(o); - if (keys.length) { - keys.forEach((k) => { iter(o[k], p.concat(k)); }); - } - return; - } - result.push(p.join('.')); - } - var result = []; - iter(object, []); - return result; - } - const commonEntity = JSON.parse(JSON.stringify(entities)).shift(); - const keys = getKeys(commonEntity); - keys.forEach((key) => { - const commonAttr = key.split('.').reduce((o, p) => (o && o.hasOwnProperty(p)) ? o[p] : null, commonEntity); - for (const e of entities) { - const entityAttr = key.split('.').reduce((o, p) => (o && o.hasOwnProperty(p)) ? o[p] : null, e); - if (!entityAttr || JSON.stringify(entityAttr) != JSON.stringify(commonAttr)) { - // remove from commonEntity - deleteObjProp(commonEntity, key); - break; - } - } - }); - return commonEntity; -} - -function deleteObjProp(obj, path) { - if (!obj || !path) { - return; - } - if (typeof path === 'string') { - path = path.split('.'); - } - for (var i = 0; i < path.length - 1; i++) { - obj = obj[path[i]]; - if (typeof obj === 'undefined') { - return; - } - } - delete obj[path.pop()]; -}; - -export function colorToRGBA(color) { - // Returns the color as an array of [r, g, b, a] -- all range from 0 - 255 - // color must be a valid canvas fillStyle. This will cover most anything - // you'd want to use. - // Examples: - // colorToRGBA('red') # [255, 0, 0, 255] - // colorToRGBA('#f00') # [255, 0, 0, 255] - var cvs, ctx; - cvs = document.createElement('canvas'); - cvs.height = 1; - cvs.width = 1; - ctx = cvs.getContext('2d'); - ctx.fillStyle = color; - ctx.fillRect(0, 0, 1, 1); - return ctx.getImageData(0, 0, 1, 1).data; -} - -function byteToHex(num) { - // Turns a number (0-255) into a 2-character hex number (00-ff) - return ('0'+num.toString(16)).slice(-2); -} - -export function colorToHex(color) { - // Convert any CSS color to a hex representation - // Examples: - // colorToHex('red') # '#ff0000' - // colorToHex('rgb(255, 0, 0)') # '#ff0000' - var rgba, hex; - rgba = colorToRGBA(color); - hex = [0,1,2].map( - function(idx) { return byteToHex(rgba[idx]); } - ).join(''); - return "#"+hex; -} - -export const isEqual = (value, other) => { - - // Get the value type - var type = Object.prototype.toString.call(value); - - // If the two objects are not the same type, return false - if (type !== Object.prototype.toString.call(other)) return false; - - // If items are not an object or array, return false - if (['[object Array]', '[object Object]'].indexOf(type) < 0) return false; - - // Compare the length of the length of the two items - var valueLen = type === '[object Array]' ? value.length : Object.keys(value).length; - var otherLen = type === '[object Array]' ? other.length : Object.keys(other).length; - if (valueLen !== otherLen) return false; - - // Compare two items - var compare = function (item1, item2) { - - // Get the object type - var itemType = Object.prototype.toString.call(item1); - - // If an object or array, compare recursively - if (['[object Array]', '[object Object]'].indexOf(itemType) >= 0) { - if (!isEqual(item1, item2)) return false; - } - - // Otherwise, do a simple comparison - else { - - // If the two items are not the same type, return false - if (itemType !== Object.prototype.toString.call(item2)) return false; - - // Else if it's a function, convert to a string and compare - // Otherwise, just compare - if (itemType === '[object Function]') { - if (item1.toString() !== item2.toString()) return false; - } else { - if (item1 !== item2) return false; - } - - } - }; - - // Compare properties - if (type === '[object Array]') { - for (var i = 0; i < valueLen; i++) { - if (compare(value[i], other[i]) === false) return false; - } - } else { - for (var key in value) { - if (value.hasOwnProperty(key)) { - if (compare(value[key], other[key]) === false) return false; - } - } - } - - // If nothing failed, return true - return true; - -}; - -export function getProperty(obj, path) { - return path.split('.').reduce((p,c)=>p&&p[c]||null, obj); -} - -export function setProperty(obj, path, value) { - path.split('.') - .reduce((o,p,i) => o[p] = path.split('.').length === ++i ? value : o[p] || {}, obj) -} - /** * Retrieve input text value from change event * @param {Event} e diff --git a/frontend/src/plugins/classification.js b/frontend/src/plugins/classification.js index 22af5b1..0df4d57 100644 --- a/frontend/src/plugins/classification.js +++ b/frontend/src/plugins/classification.js @@ -6,8 +6,8 @@ import { html } from 'lit-element'; import '@pixano/graphics-2d/lib/pxn-classification'; +import '@pixano/core/lib/attribute-picker'; import { TemplatePlugin } from '../templates/template-plugin'; -import '../helpers/attribute-picker'; import { store } from '../store'; import { setAnnotations } from '../actions/annotations'; diff --git a/frontend/src/plugins/index.js b/frontend/src/plugins/index.js index 671b534..7ed6cf3 100644 --- a/frontend/src/plugins/index.js +++ b/frontend/src/plugins/index.js @@ -7,9 +7,6 @@ * @license CECILL-C */ -import '../helpers/attribute-picker'; - - /** * List of all plugin names */ diff --git a/frontend/src/plugins/segmentation.js b/frontend/src/plugins/segmentation.js index 3aec0d1..21d475a 100644 --- a/frontend/src/plugins/segmentation.js +++ b/frontend/src/plugins/segmentation.js @@ -6,16 +6,15 @@ import { html } from 'lit-element'; import '@pixano/graphics-2d/lib/pxn-segmentation'; +import '@pixano/core/lib/attribute-picker'; import '@material/mwc-icon-button'; import '@material/mwc-icon-button-toggle'; import '@material/mwc-icon'; -import { colorToRGBA } from '@pixano/core/lib/utils'; +import { colorToRGBA, commonJson } from '@pixano/core/lib/utils'; import { store, getState } from '../store'; -import '../helpers/attribute-picker'; import { subtract, union } from '../my-icons'; import { setAnnotations } from '../actions/annotations'; import { TemplatePluginInstance } from '../templates/template-plugin-instance'; -import { commonJson } from '../helpers/utils'; const EditionMode = { ADD_TO_INSTANCE: 'add_to_instance', diff --git a/frontend/src/templates/template-plugin-instance.js b/frontend/src/templates/template-plugin-instance.js index 621e7d8..eac494c 100644 --- a/frontend/src/templates/template-plugin-instance.js +++ b/frontend/src/templates/template-plugin-instance.js @@ -9,10 +9,10 @@ import { html } from 'lit-element'; import '@material/mwc-icon-button'; import '@material/mwc-icon-button-toggle'; import '@material/mwc-icon'; -import { commonJson } from '../helpers/utils'; +import { commonJson } from '@pixano/core/lib/utils'; import { store } from '../store'; import { setAnnotations } from '../actions/annotations'; -import '../helpers/attribute-picker'; +import '@pixano/core/lib/attribute-picker'; import { TemplatePlugin } from './template-plugin'; export class TemplatePluginInstance extends TemplatePlugin { From bd296e71576b0a2627aeab8cc1bdb8dca608252a Mon Sep 17 00:00:00 2001 From: Brice Burger Date: Sun, 16 Jan 2022 18:22:06 +0100 Subject: [PATCH 07/16] tasks can now have spaces or special characters in their name --- frontend/src/actions/requests.js | 2 +- frontend/src/app.js | 4 ++-- frontend/src/templates/template-page.js | 4 ++-- frontend/src/views/app-explore.js | 5 +++-- frontend/src/views/app-label.js | 2 +- frontend/src/views/app-login.js | 2 +- frontend/src/views/app-project-manager.js | 12 ++++++------ 7 files changed, 16 insertions(+), 15 deletions(-) diff --git a/frontend/src/actions/requests.js b/frontend/src/actions/requests.js index 74dedef..2760526 100644 --- a/frontend/src/actions/requests.js +++ b/frontend/src/actions/requests.js @@ -29,7 +29,7 @@ const _requestHelper = (method, url = "/api/v1/", body = undefined, dispatch = n dispatch(updateWaiting(true)); } return new Promise((resolve, reject) => { - return fetch(url, messageContent).then((response) => { + return fetch(encodeURI(url), messageContent).then((response) => { if (dispatch) { dispatch(updateWaiting(false)); } diff --git a/frontend/src/app.js b/frontend/src/app.js index 6764c57..2d8ebed 100644 --- a/frontend/src/app.js +++ b/frontend/src/app.js @@ -68,13 +68,13 @@ class MyApp extends connect(store)(LitElement) { goHome() { const user = getState('user'); const page = user.currentUser.role === 'admin' ? '/#dashboard-admin': '/#dashboard-user'; - window.history.pushState({}, '', page); + window.history.pushState({}, '', encodeURI(page)); store.dispatch(navigate(page)); } goLogin() { const page = '/#login'; - window.history.pushState({}, '', page); + window.history.pushState({}, '', encodeURI(page)); store.dispatch(navigate(page)); } diff --git a/frontend/src/templates/template-page.js b/frontend/src/templates/template-page.js index 5356f92..984d4cf 100644 --- a/frontend/src/templates/template-page.js +++ b/frontend/src/templates/template-page.js @@ -87,7 +87,7 @@ export default class TemplatePage extends LitElement { * @param {string} page e.g. /#dashboard-admin or / */ gotoPage(page) { - window.history.pushState({}, '', page); + window.history.pushState({}, '', encodeURI(page)); store.dispatch(navigate(page)); } @@ -106,7 +106,7 @@ export default class TemplatePage extends LitElement { } else { return; } - window.history.pushState({}, '', page); + window.history.pushState({}, '', encodeURI(page)); store.dispatch(navigate(page)); } diff --git a/frontend/src/views/app-explore.js b/frontend/src/views/app-explore.js index 38792c5..5190235 100644 --- a/frontend/src/views/app-explore.js +++ b/frontend/src/views/app-explore.js @@ -39,7 +39,7 @@ export class AppExplore extends TemplatePage { onActivate() { const paths = window.location.hash.split('/'); - const taskName = paths[1]; + const taskName = decodeURI(paths[1]); const dataId = paths[2]; store.dispatch(updateTaskName(taskName)); const task = getState('application').tasks.find((t) => t.name === taskName); @@ -102,7 +102,8 @@ export class AppExplore extends TemplatePage { const appState = getState('application'); const nextDataId = appState.dataId; if (nextDataId !== currentDataId) { - window.history.pushState({}, '', `/#explore/${appState.taskName}/${nextDataId}`); + const page = '/#explore/'+appState.taskName+'/'+nextDataId; + window.history.pushState({}, '', encodeURI(page)); this.dataPath = this.path; } }); diff --git a/frontend/src/views/app-label.js b/frontend/src/views/app-label.js index d3d4a45..08979db 100644 --- a/frontend/src/views/app-label.js +++ b/frontend/src/views/app-label.js @@ -52,7 +52,7 @@ class AppLabel extends AppExplore { onActivate() { const paths = window.location.hash.split('/'); - const taskName = paths[1]; + const taskName = decodeURI(paths[1]); this.jobObjective = paths[2] || this.jobDefaultObjective; store.dispatch(updateTaskName(taskName)); const task = getState('application').tasks.find((t) => t.name === taskName); diff --git a/frontend/src/views/app-login.js b/frontend/src/views/app-login.js index 70e5bb6..a02c570 100644 --- a/frontend/src/views/app-login.js +++ b/frontend/src/views/app-login.js @@ -37,7 +37,7 @@ class AppLogin extends LitElement { goHome() { const user = getState('user'); const page = user.currentUser.role === 'admin' ? '/#dashboard-admin': '/#dashboard-user'; - window.history.pushState({}, '', page); + window.history.pushState({}, '', encodeURI(page)); store.dispatch(navigate(page)); } diff --git a/frontend/src/views/app-project-manager.js b/frontend/src/views/app-project-manager.js index 0150694..ef89b03 100644 --- a/frontend/src/views/app-project-manager.js +++ b/frontend/src/views/app-project-manager.js @@ -204,12 +204,12 @@ class AppProjectManager extends connect(store)(TemplatePage) { */ SaveOrCreateTask() { let task = { ...this.tasks[this.taskIdx] }; - const reg = new RegExp('[^=a-zA-Z0-9-_]+',); - const isWrongContained = reg.test(task.name); - if (!task.name || isWrongContained) { - this.errorPopup("Enter a correct task name"); - return; - } + // const reg = new RegExp('[^=a-zA-Z0-9-_]+',); + // const isWrongContained = reg.test(task.name); + // if (!task.name || isWrongContained) { + // this.errorPopup("Enter a correct task name"); + // return; + // } task.spec.label_schema = this.taskSettings.json; task.spec.settings = this.pluginSettings.json; const fn = this.creatingTask ? postTask : putTask; From 48cec33d50460adc0158cb31bc2b2de09b3ef8e9 Mon Sep 17 00:00:00 2001 From: Brice Burger Date: Fri, 21 Jan 2022 16:29:28 +0100 Subject: [PATCH 08/16] exported format and files: remove thumbnail + add versioning --- server/routes/tasks.js | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/server/routes/tasks.js b/server/routes/tasks.js index db6cab4..8280861 100644 --- a/server/routes/tasks.js +++ b/server/routes/tasks.js @@ -15,6 +15,8 @@ const { getAllDataFromDataset, getAllPathsFromDataset, getDataDetails } = require('./datasets'); +const annotation_format_version = "0.9"; + /** * @api {get} /tasks Get list of tasks details * @apiName GetTasks @@ -126,6 +128,15 @@ async function import_tasks(req, res) { const importedTasks = []; for await (const jsonf of taskJsonFiles) { const taskData = utils.readJSON(path.join(importPath, jsonf)); + let version = taskData.version; + // check annotation format version + if (!version) version = "0.9";//0.9 is the first versioned format + if (parseFloat(version) < parseFloat(annotation_format_version)) { + // TO BE DETERMINED when new version will arrise: solve compatibility issues + } + console.info("Annotation format version:",annotation_format_version); + + const dataset = await getOrcreateDataset({...taskData.dataset, data_type: taskData.spec.data_type}, workspace); const spec = await getOrcreateSpec(taskData.spec); @@ -267,12 +278,15 @@ async function export_tasks(req, res) { const dataset = await db.get(dbkeys.keyForDataset(task.dataset_id)); const datasetId = dataset.id; delete dataset.id; - const taskJson = {name: task.name, spec, dataset}; + const taskJson = {name: task.name, version: annotation_format_version, spec, dataset}; // Write task json const err = utils.writeJSON(taskJson, `${exportPath}/${task.name}.json`); if (err) { - return; + return res.status(400).json({ + error: 'cannot_write', + message: `Cannot write json file ${exportPath}/${task.name}.json` + }); } // Write annotations for each task in a specific folder @@ -282,8 +296,11 @@ async function export_tasks(req, res) { // Recreate it fs.mkdirSync(taskFolder, function(err){ if(err){ - console.log(err); - response.send(`ERROR! Can't create directory ${taskFolder}`); + console.log(err); + return res.status(400).json({ + error: 'cannot_create', + message: `ERROR! Can't create directory ${taskFolder}` + }); } }); @@ -293,6 +310,7 @@ async function export_tasks(req, res) { const data = await getDataDetails(datasetId, labels.data_id, true); delete data.id; delete data.dataset_id; + delete data.thumbnail; let path = data.path; path = Array.isArray(path) ? path[0] : path; path = path.replace(dataset.path, '') @@ -303,7 +321,10 @@ async function export_tasks(req, res) { const err = utils.writeJSON(labelsJson, `${taskFolder}/${filename}.json`); if (err) { - return; + return res.status(400).json({ + error: 'cannot_write', + message: `Cannot write json file ${taskFolder}/${filename}.json` + }); } } } From 4e1b9bbb14efd68be0f845f6b5b0b39122cb7020 Mon Sep 17 00:00:00 2001 From: Brice Burger Date: Fri, 11 Feb 2022 15:45:09 +0100 Subject: [PATCH 09/16] minor : update README + add clearall script --- README.md | 9 +++++++-- package.json | 1 + 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index fb4c670..3f4e15c 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,7 @@ pixano ./data-test --port 3001 #### Install global dependencies -- NodeJS (>=12) +- NodeJS (10, 12 or 14) To install on ubuntu: ```bash @@ -78,6 +78,8 @@ nodejs --version npm install -g npm@6.10.0 ``` You can read this nice [introduction](https://codeburst.io/the-only-nodejs-introduction-youll-ever-need-d969a47ef219) to NodeJS in case you're curious on how it works. + +> ATTENTION: node version 16 is not compatible for now #### Install application dependencies @@ -187,10 +189,13 @@ The `task1.json` file contains global task settings (task type, task categories, ### Build docker from sources -To create a docker image of the application, build the application (step 1.b) and then run: +To create a docker image of the application, you can use the standard docker command: ```bash # You can change `pixano` by your choosen image name sudo docker build -t pixano/pixano-app:my-tag . +``` +If you used a local pixano-element, build the application (step 1.b) and then run: +```bash # You can use the local Dockerfile if the build folder already exists sudo docker build -t pixano/pixano-app:my-tag -f Dockerfile-local . ``` diff --git a/package.json b/package.json index 06278f5..fdd6c80 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ }, "scripts": { "deps": "rm -f package-lock.json && npm i && cd frontend && rm -f package-lock.json && npm i", + "clearall": "rm -rf node_modules/ package-lock.json frontend/node_modules/ frontend/package-lock.json", "build": "cd frontend && npm run build", "installLocalElements": "cd frontend && npm run installLocalElements" }, From fa4906f406d702ecb70f05518b91154e33f73edb Mon Sep 17 00:00:00 2001 From: Brice Burger Date: Wed, 16 Feb 2022 11:16:21 +0100 Subject: [PATCH 10/16] correct showdetails + update README --- README.md | 8 +++++++- frontend/src/plugins/classification.js | 3 ++- frontend/src/templates/template-plugin-instance.js | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 3f4e15c..653cec9 100644 --- a/README.md +++ b/README.md @@ -92,10 +92,16 @@ If you want to use custom `pixano-element` modules from local path instead of th ```bash # Install application dependencies and local pixano-elements -npm run installLocalElements --path=../../pixano-elements +npm run installLocalElements --path=$PIXANO_ELEMENTS_PATH ``` *NB: Make sure you have the git repository of pixano-elements next to the pixano-app folder and that you have followed the pixano-elements build instructions before running the above commands.* +If this command breaks your local pixano-elements demo, this command will repear it: +```bash +cd $PIXANO_ELEMENTS_PATH +npm run bootstrap +``` + #### Build the application ```bash diff --git a/frontend/src/plugins/classification.js b/frontend/src/plugins/classification.js index 0df4d57..2e9e207 100644 --- a/frontend/src/plugins/classification.js +++ b/frontend/src/plugins/classification.js @@ -24,6 +24,7 @@ export class PluginClassification extends TemplatePlugin { refresh() { if (!this.element) return; + this.attributePicker.showDetail = true;// exception for classification: always show details if (this.annotations.length===0) this.attributePicker.setAttributes(this.attributePicker.defaultValue);// initialize to default else { this.element.annotations = JSON.parse(JSON.stringify(this.annotations)); @@ -44,7 +45,7 @@ export class PluginClassification extends TemplatePlugin { * Implement property panel content, details always visible */ get propertyPanel() { - return html`` + return html`` } get editor() { diff --git a/frontend/src/templates/template-plugin-instance.js b/frontend/src/templates/template-plugin-instance.js index eac494c..dfb88be 100644 --- a/frontend/src/templates/template-plugin-instance.js +++ b/frontend/src/templates/template-plugin-instance.js @@ -127,7 +127,7 @@ export class TemplatePluginInstance extends TemplatePlugin { */ get propertyPanel() { return html` - ` } From 95f645d33ed3bc1229d3058053d033d7e91a9712 Mon Sep 17 00:00:00 2001 From: Brice Burger Date: Wed, 9 Mar 2022 12:13:38 +0100 Subject: [PATCH 11/16] cherry-pick: classification : take directly initialization into account in redux --- frontend/src/plugins/classification.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/frontend/src/plugins/classification.js b/frontend/src/plugins/classification.js index 2e9e207..a2d7dec 100644 --- a/frontend/src/plugins/classification.js +++ b/frontend/src/plugins/classification.js @@ -25,8 +25,10 @@ export class PluginClassification extends TemplatePlugin { refresh() { if (!this.element) return; this.attributePicker.showDetail = true;// exception for classification: always show details - if (this.annotations.length===0) this.attributePicker.setAttributes(this.attributePicker.defaultValue);// initialize to default - else { + if (this.annotations.length===0) {// initialize to default + this.attributePicker.setAttributes(this.attributePicker.defaultValue); + store.dispatch(setAnnotations({annotations: [this.attributePicker.value]}));//Save current state to redux database (to keep history) + } else { this.element.annotations = JSON.parse(JSON.stringify(this.annotations)); this.attributePicker.setAttributes(this.element.annotations[0]); } From b5799e9f74a77464398bf242650c8ed09ccdd052 Mon Sep 17 00:00:00 2001 From: Brice Burger Date: Thu, 24 Mar 2022 11:16:00 +0100 Subject: [PATCH 12/16] cherry-pick: add possibility to discard some data + add status to import/export + fix get_next_job (go to next job, when job is dead) --- documentation/rest-api.md | 2 +- frontend/src/views/app-dashboard-admin.js | 2 +- server/routes/jobs.js | 26 +-- server/routes/tasks.js | 213 ++++++++++++++-------- 4 files changed, 154 insertions(+), 89 deletions(-) diff --git a/documentation/rest-api.md b/documentation/rest-api.md index 96a9e65..37c2b98 100644 --- a/documentation/rest-api.md +++ b/documentation/rest-api.md @@ -57,7 +57,7 @@ This document lists the API of the Pixano server that enable the creation of new type Objective = 'to_annotate' | 'to_validate' | 'to_correct'; // possible status a data item can have -type LabellingStatus = Objective | 'done'; +type LabellingStatus = Objective | 'done' | 'discard'; // possible types a data item can have type DataType = 'image' | 'pcl' | 'pcl_image' | 'sequence_pcl' | 'sequence_image' | 'sequence_pcl_image'; diff --git a/frontend/src/views/app-dashboard-admin.js b/frontend/src/views/app-dashboard-admin.js index f9fe7b7..fe4e745 100644 --- a/frontend/src/views/app-dashboard-admin.js +++ b/frontend/src/views/app-dashboard-admin.js @@ -58,8 +58,8 @@ class AppDashboardAdmin extends TemplatePage { ['to_annotate', ['to annotate', 'create', 'blue']], ['to_validate', ['to validate', 'youtube_searched_for', 'orange']], ['to_correct', ['to correct', 'thumb_down', 'red']], + ['discard', ['do NOT annotate', 'highlight_off', 'red']], ['done', ['done', 'done', 'green']]]); - this.assignedMap = new Map([['', ''], ['true', 'in progress'], ['false', 'idle']]); diff --git a/server/routes/jobs.js b/server/routes/jobs.js index 29b5cb1..6452ae5 100644 --- a/server/routes/jobs.js +++ b/server/routes/jobs.js @@ -47,12 +47,13 @@ async function get_next_job(req, res) { const assignedJob = user.curr_assigned_jobs[oKey]; if (assignedJob) { let job, result; + var error=false; try { job = await db.get(dbkeys.keyForJob(taskName, assignedJob)); result = await db.get(dbkeys.keyForResult(taskName, job.data_id)); } - catch (err) { console.log('\tjob no longer exist', err);} - if (isJobValid(job, result) && await isJobAvailableForUser(job, user)) { + catch (err) { error=true; console.log('\tjob no longer exist', err);} + if (!error && isJobValid(job, result) && await isJobAvailableForUser(job, user)) { await _assignJob(job, user); return res.send({...job, annotator: result.annotator, validator: result.validator}); } @@ -68,12 +69,13 @@ async function get_next_job(req, res) { if (queuedJobs.length) { for (const q of queuedJobs) { let job, result; + var error=false; try { job = await db.get(dbkeys.keyForJob(taskName, q)); result = await db.get(dbkeys.keyForResult(taskName, job.data_id)); } - catch (err) { console.log('\tjob no longer exist', err); } - if (isJobValid(job, result) && await isJobAvailableForUser(job, user)) { + catch (err) { error=true; console.log('\tjob no longer exist', err); } + if (!error && isJobValid(job, result) && await isJobAvailableForUser(job, user)) { await _assignJob(job, user); return res.send({...job, annotator: result.annotator, validator: result.validator}); } @@ -90,9 +92,10 @@ async function get_next_job(req, res) { for await(const result of streamA) { if (objectiveList.includes(result.status) && !result.in_progress) { let job; + var error=false; try { job = await db.get(dbkeys.keyForJob(taskName, result.current_job_id)); } - catch (err) { console.log('\tjob no longer exist', err); } - if (isJobValid(job, result) && await isJobAvailableForUser(job, user)) { + catch (err) { error=true; console.log('\tjob no longer exist', err); } + if (!error && isJobValid(job, result) && await isJobAvailableForUser(job, user)) { await _assignJob(job, user); return res.send({...job, annotator: result.annotator, validator: result.validator}); } @@ -103,9 +106,10 @@ async function get_next_job(req, res) { for await(const result of streamB) { if (objectiveList.includes(result.status) && !result.in_progress) { let job; + var error=false; try { job = await db.get(dbkeys.keyForJob(taskName, result.current_job_id)); } - catch (err) { console.log('\tjob no longer exist', err); } - if (isJobValid(job, result) && await isJobAvailableForUser(job, user, true)) { + catch (err) { error=true; console.log('\tjob no longer exist', err); } + if (!error && isJobValid(job, result) && await isJobAvailableForUser(job, user, true)) { await _assignJob(job, user); return res.send({...job, annotator: result.annotator, validator: result.validator}); } @@ -205,17 +209,17 @@ async function put_job(req, res) { // Update result resultData.in_progress = false; - resultData.status = ['to_annotate', 'to_validate', 'to_correct', 'done'].includes(newObjective) ? newObjective : 'to_annotate'; + resultData.status = ['to_annotate', 'to_validate', 'to_correct', 'discard', 'done'].includes(newObjective) ? newObjective : 'to_annotate'; resultData.finished_job_ids.push(resultData.current_job_id); - if (newObjective === 'done') { + if (newObjective === 'done' || newObjective === 'discard') { resultData.current_job_id = ''; ops.push({ type: 'put', key: dbkeys.keyForResult(taskName, jobData.data_id), value: resultData}); await db.batch(ops); return res.status(204).json({}); } - // Create new Job if not 'done' + // Create new Job if not 'done' or 'discard' const newJob = createJob(jobData.task_name, jobData.data_id, newObjective); resultData.current_job_id = newJob.id; diff --git a/server/routes/tasks.js b/server/routes/tasks.js index 8280861..dc43e5a 100644 --- a/server/routes/tasks.js +++ b/server/routes/tasks.js @@ -91,6 +91,12 @@ async function post_tasks(req, res) { */ async function import_tasks(req, res) { checkAdmin(req, async () => { + if (req.body.url) { + return res.status(400).json({ + error: 'url_not_implemented', + message: 'Import tasks from URL is not yet implemented.' + }); + } if (!req.body.path) { return res.status(400).json({ error: 'wrong_path', @@ -126,7 +132,7 @@ async function import_tasks(req, res) { // dataset: { path: string, data_type: string } // } const importedTasks = []; - for await (const jsonf of taskJsonFiles) { + for await (const jsonf of taskJsonFiles) { const taskData = utils.readJSON(path.join(importPath, jsonf)); let version = taskData.version; // check annotation format version @@ -173,7 +179,7 @@ async function import_tasks(req, res) { // annotations: any[], // data: { type: string, path: string | string[], children: array<{path, timestamp}>} // } - for await (const jsonFile of annJsonFiles) { + for await (const jsonFile of annJsonFiles) { // Create data const fullPath = path.join(importPath, taskFolder, jsonFile); const ann = utils.readJSON(fullPath); @@ -216,6 +222,11 @@ async function import_tasks(req, res) { }; await bm.add({ type: 'put', key: dbkeys.keyForLabels(newTask.name, newLabels.data_id), value: newLabels}); + if (ann.data.status) {//if existing, get status back + resultData = await db.get(dbkeys.keyForResult(newTask.name, newLabels.data_id));//get the status for this data + resultData.status = ann.data.status;//add the status + await bm.add({ type: 'put', key: dbkeys.keyForResult(newTask.name, newLabels.data_id), value: resultData}); + } // Mark result as done // const resultData = await db.get(dbkeys.keyForResult(newTask.name, dataId)); @@ -242,7 +253,7 @@ async function import_tasks(req, res) { * @apiGroup Tasks * @apiPermission admin * - * @apiParam {string} [path] Relative path to tasks folder + * @apiParam {string} [path] Relative path to tasks folder OR [url] destination URL for online export * * @apiSuccessExample Success-Response: * HTTP/1.1 200 OK @@ -251,85 +262,135 @@ async function import_tasks(req, res) { * HTTP/1.1 400 Failed to create export folder */ async function export_tasks(req, res) { - checkAdmin(req, async () => { - if (!req.body.path) { - return res.status(400).json({ - error: 'wrong_path', - message: 'Invalid path.' - }); - } - const exportPath = path.join(workspace, req.body.path); - console.log('##### Exporting to ', exportPath); - if(!utils.isSubFolder(workspace, exportPath)) { - return res.status(400).json({ - error: 'wrong_folder', - message: 'Export folder should be a sub folder of the working space.' - }); - } - // If path does not exist create it - if (!fs.existsSync(exportPath)) { - fs.mkdirSync(exportPath, {recursive: true}); - } - - const streamTask = utils.iterateOnDB(db, dbkeys.keyForTask(), false, true); - for await (const task of streamTask) { - const spec = await db.get(dbkeys.keyForSpec(task.spec_id)); - delete spec.id; - const dataset = await db.get(dbkeys.keyForDataset(task.dataset_id)); - const datasetId = dataset.id; - delete dataset.id; - const taskJson = {name: task.name, version: annotation_format_version, spec, dataset}; - - // Write task json - const err = utils.writeJSON(taskJson, `${exportPath}/${task.name}.json`); - if (err) { + checkAdmin(req, async () => { + if (!req.body.path && !req.body.url) { + return res.status(400).json({ + error: 'wrong_path', + message: 'Invalid path.' + }); + } + if (req.body.path) {//export to local file system + var exportPath = path.join(workspace, req.body.path); + console.log('##### Exporting to ', exportPath); + if (!utils.isSubFolder(workspace, exportPath)) { return res.status(400).json({ - error: 'cannot_write', - message: `Cannot write json file ${exportPath}/${task.name}.json` + error: 'wrong_folder', + message: 'Export folder should be a sub folder of the working space.' }); - } - - // Write annotations for each task in a specific folder - const taskFolder = `${exportPath}/${task.name}`; - // Remove existing folder - utils.removeDir(taskFolder); - // Recreate it - fs.mkdirSync(taskFolder, function(err){ - if(err){ - console.log(err); + } + // If path does not exist create it + if (!fs.existsSync(exportPath)) { + fs.mkdirSync(exportPath, { recursive: true }); + } + } + + const streamTask = utils.iterateOnDB(db, dbkeys.keyForTask(), false, true); + for await (const task of streamTask) { + const spec = await db.get(dbkeys.keyForSpec(task.spec_id)); + delete spec.id; + const dataset = await db.get(dbkeys.keyForDataset(task.dataset_id)); + const datasetId = dataset.id; + delete dataset.id; + const taskJson = { name: task.name, version: annotation_format_version, spec, dataset }; + + // EXPORT task json + if (req.body.path) {//export to local file system + const err = utils.writeJSON(taskJson, `${exportPath}/${task.name}.json`); + if (err) { return res.status(400).json({ - error: 'cannot_create', - message: `ERROR! Can't create directory ${taskFolder}` + error: 'cannot_write', + message: `Cannot write json file ${exportPath}/${task.name}.json` }); - } - }); - - // Write annotations - const streamLabels = utils.iterateOnDB(db, dbkeys.keyForLabels(task.name), false, true); - for await (const labels of streamLabels) { - const data = await getDataDetails(datasetId, labels.data_id, true); - delete data.id; - delete data.dataset_id; - delete data.thumbnail; - let path = data.path; - path = Array.isArray(path) ? path[0] : path; - path = path.replace(dataset.path, '') - const filename = utils.pathToFilename(path); + } + } else {//export to destination URL + /// TODO: the task is not exported in Confiance + // var err = ''; + // const url = req.body.url.endsWith('/') ? req.body.url+'_doc' : req.body.url+'/_doc'; + // await fetch(url+`/_doc`, { + // method: 'post', + // headers: { 'Content-Type': 'application/json' }, + // body: JSON.stringify( taskJson ) + // })// send POST request + // .then(res => { + // if (res.statusText=='OK') return res.json(); + // else console.log("KO :\n",res); + // }) + // .then(res => { console.log(res); + // }).catch((e) => { err = e; }); + // if (err) { + // return res.status(400).json({ + // error: 'cannot_write', + // message: `Cannot write json file '${task.name}.json'.\n\nERROR while calling ELASTIC:${err}` + // }); + // } + } - const labelsJson = {...labels, data}; - delete labelsJson.data_id; + if (req.body.path) { + // Write annotations for each task in a specific folder + var taskFolder = `${exportPath}/${task.name}`; + // Remove existing folder + utils.removeDir(taskFolder); + // Recreate it + fs.mkdirSync(taskFolder, function (err) { + if (err) { + console.log(err); + return res.status(400).json({ + error: 'cannot_create', + message: `ERROR! Can't create directory ${taskFolder}` + }); + } + }); + } - const err = utils.writeJSON(labelsJson, `${taskFolder}/${filename}.json`); - if (err) { - return res.status(400).json({ - error: 'cannot_write', - message: `Cannot write json file ${taskFolder}/${filename}.json` - }); - } - } - } - res.send(); - }); + // Write annotations + const streamLabels = utils.iterateOnDB(db, dbkeys.keyForLabels(task.name), false, true); + for await (const labels of streamLabels) { + resultData = await db.get(dbkeys.keyForResult(task.name, labels.data_id));//get the status for this data + const data = await getDataDetails(datasetId, labels.data_id, true); + delete data.id; + delete data.dataset_id; + delete data.thumbnail; + data.status = resultData.status;//add the status + let path = data.path; + path = Array.isArray(path) ? path[0] : path; + path = path.replace(dataset.path, '') + const filename = utils.pathToFilename(path); + + const labelsJson = { ...labels, data }; + + // EXPORT task json + if (req.body.path) {//export to local file system + const err = utils.writeJSON(labelsJson, `${taskFolder}/${filename}.json`); + if (err) { + return res.status(400).json({ + error: 'cannot_write', + message: `Cannot write json file ${taskFolder}/${filename}.json` + }); + } + } else {//export to destination URL + var err = ''; + const url = req.body.url.endsWith('/') ? req.body.url+'_doc' : req.body.url+'/_doc'; + + await fetch(url, { + method: 'PUT', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify( labelsJson ) + })// send POST request + .then(res => { + if (res.ok) return res.json(); + else throw new Error(res);//we have to trow ourself because fetch only throw on network errors, not on 4xx or 5xx errors + }).catch((e) => { err = e; }); + if (err) { + return res.status(400).json({ + error: 'cannot_write', + message: `Cannot write json file '${filename}.json'.\n\nERROR while calling ELASTIC:${err}` + }); + } + } + } + } + res.send(); + }); } /** From c671ca80edfc9170e0ab46e24d4a4301207d82f2 Mon Sep 17 00:00:00 2001 From: Brice Burger Date: Wed, 30 Mar 2022 10:52:48 +0200 Subject: [PATCH 13/16] add Dockerfile-local-minimal : size of generated images shrink from 3.4Go to 1.7Go --- Dockerfile-local-minimal | 60 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 Dockerfile-local-minimal diff --git a/Dockerfile-local-minimal b/Dockerfile-local-minimal new file mode 100644 index 0000000..895c0f2 --- /dev/null +++ b/Dockerfile-local-minimal @@ -0,0 +1,60 @@ +FROM ubuntu:20.04 + +# Install Node.js +ENV DEBIAN_FRONTEND=noninteractive +RUN apt-get update +RUN apt-get install -y nodejs +RUN node --version +#RUN apt-get install -y npm +#RUN npm --version +#RUN npm install -g npm@6.10.0 +#RUN npm --version + + +###### Élise (this image can only be created into the CEA network) (version WITH_MYSQL=NO) + +# prérequis +RUN apt-get install -y libpoco-dev libopencv-dev libatlas-base-dev +RUN apt-get install libssh2-1 +# définition des variables d'environnement +ENV ELISE_BASE=$pwd/ELISE +ENV ELISE_EXTERNALS=$ELISE_BASE/elise_ext +ENV OPENCV_DIST=$ELISE_EXTERNALS +ENV JULIET_DIST=$ELISE_EXTERNALS +ENV OPENCV_DIST=$ELISE_EXTERNALS +ENV ELISE_DIST=$ELISE_EXTERNALS +ENV ELISE_CONFIG=$ELISE_BASE/elise/ +ENV LD_LIBRARY_PATH=$ELISE_DIST/lib +# préparation / copy libs +RUN mkdir -p $ELISE_BASE $ELISE_EXTERNALS $ELISE_CONFIG $ELISE_DIST/lib +COPY ELISE/eliseCfg $ELISE_BASE/eliseCfg +COPY ELISE/elise_ext/bin $ELISE_EXTERNALS/bin +COPY ELISE/elise_ext/lib $ELISE_EXTERNALS/lib +RUN mkdir -p $ELISE_EXTERNALS/data/idx/ + +EXPOSE 8081 +###### fin Élise + + +# Copy bundled frontend and backend dependencies +COPY build build +COPY node_modules node_modules + +# Copy files for the backend +COPY package.json package.json +COPY server server +COPY .logo-ascii .logo-ascii + +EXPOSE 3000 + + +# default files and folders (usefull when no volume can be mounted with this image) +COPY config config +RUN mkdir -p /data +COPY data-test /data/data-test + +# ENTRYPOINT ["node", "server/server.js"] +# RUN echo 'cat .logo-ascii && node server/server.js "$@"' > entrypoint.sh +RUN echo 'bash -c "$ELISE_DIST/bin/run_search_server --param=$ELISE_BASE/eliseCfg/elise_search_FSF_config.xml -tSEARCHER_FSF &" && bash -c "$ELISE_DIST/bin/run_elise_server --param=$ELISE_BASE/eliseCfg/elise_server_config_sqlite.xml &" && cat .logo-ascii && node server/server.js "$@" > pixano_logs 2>&1' > entrypoint.sh +ENTRYPOINT ["sh", "entrypoint.sh"] +CMD [] From cd760dede52dda23c5d1ce24894da755a5d22c24 Mon Sep 17 00:00:00 2001 From: Brice Burger Date: Tue, 5 Apr 2022 09:42:14 +0200 Subject: [PATCH 14/16] use clickable image instead of button to open visualisation --- frontend/src/views/app-dashboard-admin.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/frontend/src/views/app-dashboard-admin.js b/frontend/src/views/app-dashboard-admin.js index fe4e745..a92254e 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 | Thumbnail | Launch + * Status | Data Id | Annotator | Validator | State | Time | Thumbnail */ listitem(item) { const v = this.statusMap.get(item.status); @@ -483,8 +483,8 @@ class AppDashboardAdmin extends TemplatePage {

${item.validator}

${this.assignedMap.get(item.in_progress.toString())}

${format(item.cumulated_time)}

-

-

this.onExplore(evt, item.data_id)}>

+

this.onExplore(evt, item.data_id)}>

+

  • From 67dac968bc08132716b0c2d750939e6d3811601d Mon Sep 17 00:00:00 2001 From: Brice Burger Date: Thu, 7 Apr 2022 09:42:11 +0200 Subject: [PATCH 15/16] minor : integrate min in Dockerfile-local --- Dockerfile-local | 13 ++++----- Dockerfile-local-minimal | 60 ---------------------------------------- 2 files changed, 6 insertions(+), 67 deletions(-) delete mode 100644 Dockerfile-local-minimal diff --git a/Dockerfile-local b/Dockerfile-local index c35b71c..255e91c 100644 --- a/Dockerfile-local +++ b/Dockerfile-local @@ -1,26 +1,25 @@ FROM ubuntu:20.04 # Install Node.js -RUN apt-get update && apt-get install -y --reinstall ca-certificates curl build-essential -RUN curl --silent --location https://deb.nodesource.com/setup_12.x | bash - +ENV DEBIAN_FRONTEND=noninteractive +RUN apt-get update RUN apt-get install -y nodejs -RUN npm install -g npm@6.10.0 +RUN node --version -# Copy bundled frontend +# Copy bundled frontend and backend dependencies COPY build build +COPY node_modules node_modules # Copy files for the backend COPY package.json package.json COPY server server COPY .logo-ascii .logo-ascii -# Install backend dependencies -RUN npm install EXPOSE 3000 # default files and folders (usefull when no volume can be mounted with this image) RUN mkdir -p /data - +COPY data-test /data/data-test # ENTRYPOINT ["node", "server/server.js"] RUN echo 'cat .logo-ascii && node server/server.js "$@"' > entrypoint.sh diff --git a/Dockerfile-local-minimal b/Dockerfile-local-minimal deleted file mode 100644 index 895c0f2..0000000 --- a/Dockerfile-local-minimal +++ /dev/null @@ -1,60 +0,0 @@ -FROM ubuntu:20.04 - -# Install Node.js -ENV DEBIAN_FRONTEND=noninteractive -RUN apt-get update -RUN apt-get install -y nodejs -RUN node --version -#RUN apt-get install -y npm -#RUN npm --version -#RUN npm install -g npm@6.10.0 -#RUN npm --version - - -###### Élise (this image can only be created into the CEA network) (version WITH_MYSQL=NO) - -# prérequis -RUN apt-get install -y libpoco-dev libopencv-dev libatlas-base-dev -RUN apt-get install libssh2-1 -# définition des variables d'environnement -ENV ELISE_BASE=$pwd/ELISE -ENV ELISE_EXTERNALS=$ELISE_BASE/elise_ext -ENV OPENCV_DIST=$ELISE_EXTERNALS -ENV JULIET_DIST=$ELISE_EXTERNALS -ENV OPENCV_DIST=$ELISE_EXTERNALS -ENV ELISE_DIST=$ELISE_EXTERNALS -ENV ELISE_CONFIG=$ELISE_BASE/elise/ -ENV LD_LIBRARY_PATH=$ELISE_DIST/lib -# préparation / copy libs -RUN mkdir -p $ELISE_BASE $ELISE_EXTERNALS $ELISE_CONFIG $ELISE_DIST/lib -COPY ELISE/eliseCfg $ELISE_BASE/eliseCfg -COPY ELISE/elise_ext/bin $ELISE_EXTERNALS/bin -COPY ELISE/elise_ext/lib $ELISE_EXTERNALS/lib -RUN mkdir -p $ELISE_EXTERNALS/data/idx/ - -EXPOSE 8081 -###### fin Élise - - -# Copy bundled frontend and backend dependencies -COPY build build -COPY node_modules node_modules - -# Copy files for the backend -COPY package.json package.json -COPY server server -COPY .logo-ascii .logo-ascii - -EXPOSE 3000 - - -# default files and folders (usefull when no volume can be mounted with this image) -COPY config config -RUN mkdir -p /data -COPY data-test /data/data-test - -# ENTRYPOINT ["node", "server/server.js"] -# RUN echo 'cat .logo-ascii && node server/server.js "$@"' > entrypoint.sh -RUN echo 'bash -c "$ELISE_DIST/bin/run_search_server --param=$ELISE_BASE/eliseCfg/elise_search_FSF_config.xml -tSEARCHER_FSF &" && bash -c "$ELISE_DIST/bin/run_elise_server --param=$ELISE_BASE/eliseCfg/elise_server_config_sqlite.xml &" && cat .logo-ascii && node server/server.js "$@" > pixano_logs 2>&1' > entrypoint.sh -ENTRYPOINT ["sh", "entrypoint.sh"] -CMD [] From cf42784c3e2043634019065315d3b5fe4fba1f7c Mon Sep 17 00:00:00 2001 From: Brice Burger Date: Thu, 7 Apr 2022 09:55:39 +0200 Subject: [PATCH 16/16] release 0.6.0 --- README_INTERNAL.md | 6 +++--- frontend/package.json | 10 +++++----- package.json | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/README_INTERNAL.md b/README_INTERNAL.md index 36b75d9..d7dc936 100644 --- a/README_INTERNAL.md +++ b/README_INTERNAL.md @@ -68,8 +68,8 @@ master <------push------ github <--merge-- master <--merge--> p2 ## Publication ### 0) prepare gitlab version - LAST_VERSION=0.4.9 - VERSION=0.5.0 + LAST_VERSION=0.5.0 + VERSION=0.6.0 git fetch git checkout master git pull origin master @@ -77,7 +77,7 @@ master <------push------ github <--merge-- master <--merge--> p2 gedit package.json frontend/package.json ## change version to $VERSION ## in frontend : if necessary, change version of elements - git add package.json frontend/package.json + git add README_INTERNAL.md package.json frontend/package.json git commit -m "release $VERSION" ### 1) Prepate the publication 1. On github : Update your fork diff --git a/frontend/package.json b/frontend/package.json index d823233..780816a 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,6 +1,6 @@ { "name": "pixano-app-frontend", - "version": "0.5.0", + "version": "0.6.0", "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.6.1", - "@pixano/core": "0.6.1", - "@pixano/graphics-2d": "0.6.1", - "@pixano/graphics-3d": "0.6.1", + "@pixano/ai": "0.7.0", + "@pixano/core": "0.7.0", + "@pixano/graphics-2d": "0.7.0", + "@pixano/graphics-3d": "0.7.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 fdd6c80..93fa3b6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pixano-app", - "version": "0.5.0", + "version": "0.6.0", "description": "This is a Pixano app.", "keywords": [], "license": "CECILL-C",