From 6a96dbe948166037851209dc4c4f3c488a13ca69 Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 17 Sep 2018 13:08:48 +0200 Subject: [PATCH 1/8] made exp domain selection in task creation a SelectExperienceDomain component --- .../admin/task/task_create_form_view.js | 29 ++++++++-------- .../admin/user/experience_modal_view.js | 5 ++- .../components/select_experience_domain.js | 34 ++++++++++++++----- app/assets/javascripts/messages.js | 2 ++ 4 files changed, 45 insertions(+), 25 deletions(-) diff --git a/app/assets/javascripts/admin/task/task_create_form_view.js b/app/assets/javascripts/admin/task/task_create_form_view.js index 070412d12e5..6d4b9d8bbbc 100644 --- a/app/assets/javascripts/admin/task/task_create_form_view.js +++ b/app/assets/javascripts/admin/task/task_create_form_view.js @@ -2,19 +2,7 @@ import _ from "lodash"; import React from "react"; import { withRouter } from "react-router-dom"; -import { - Form, - Input, - Select, - Button, - Card, - Radio, - Upload, - Modal, - Icon, - InputNumber, - Spin, -} from "antd"; +import { Form, Select, Button, Card, Radio, Upload, Modal, Icon, InputNumber, Spin } from "antd"; import { getActiveDatasets, getProjects, @@ -26,6 +14,8 @@ import { updateTask, } from "admin/admin_rest_api"; import { Vector3Input, Vector6Input } from "libs/vector_input"; +import SelectExperienceDomain from "components/select_experience_domain"; +import messages from "messages"; import type { APIDatasetType, @@ -232,8 +222,17 @@ class TaskCreateFormView extends React.PureComponent { {getFieldDecorator("neededExperience.domain", { - rules: [{ required: true }, { min: 3 }], - })()} + rules: [{ required: true }], + })( + , + )} diff --git a/app/assets/javascripts/admin/user/experience_modal_view.js b/app/assets/javascripts/admin/user/experience_modal_view.js index 91581e51750..81461d8dbb7 100644 --- a/app/assets/javascripts/admin/user/experience_modal_view.js +++ b/app/assets/javascripts/admin/user/experience_modal_view.js @@ -388,10 +388,13 @@ class ExperienceModalView extends React.PureComponent { ) : null} {}} alreadyUsedDomains={this.getDomainsOfTable()} /> diff --git a/app/assets/javascripts/components/select_experience_domain.js b/app/assets/javascripts/components/select_experience_domain.js index e8d61bc05aa..9e095bbfcdb 100644 --- a/app/assets/javascripts/components/select_experience_domain.js +++ b/app/assets/javascripts/components/select_experience_domain.js @@ -1,3 +1,6 @@ +// @flow + +import _ from "lodash"; import * as React from "react"; import { Select } from "antd"; import type { ExperienceDomainListType } from "admin/api_flow_types"; @@ -6,10 +9,13 @@ import { getExistingExperienceDomains } from "admin/admin_rest_api"; const Option = Select.Option; type Props = { - value: string, + value: ?string, + placeholder: string, + notFoundContent: ?string, disabled: boolean, - onSelect: () => void, - onDeselect: () => void, + mode: string, + onSelect: ?() => void, + onChange: ?() => void, alreadyUsedDomains: ExperienceDomainListType, }; @@ -35,18 +41,28 @@ class SelectExperienceDomain extends React.PureComponent { } render() { + const options = this.getUnusedDomains().map(domain => ); + const notFoundContent = this.props.notFoundContent || "Not Found"; + const additionalProps = {}; + if (this.props.onChange) { + additionalProps.onChange = this.props.onChange; + } + if (this.props.onSelect) { + additionalProps.onSelect = this.props.onSelect; + } return ( ); } diff --git a/app/assets/javascripts/messages.js b/app/assets/javascripts/messages.js index 6fb1527fbd0..d15158edb29 100644 --- a/app/assets/javascripts/messages.js +++ b/app/assets/javascripts/messages.js @@ -68,6 +68,8 @@ In order to restore the current window, a reload is necessary.`, "The next task will most likely be part of project <%- projectName %>", ), "task.confirm_reset": "Do you really want to reset this task?", + "task.domain_does_not_exist": + "No matching experience domain. Assign this domain to a user to add it to the listed options.", "annotation.reset_success": "Annotation was successfully reset.", "task.bulk_create_invalid": "Can not parse task specification. It includes at least one invalid task.", From c3771369bfb3d5edeba9813dade6b5cb0688faac Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 17 Sep 2018 13:09:40 +0200 Subject: [PATCH 2/8] added check for at least 3 chars in exp domain in user modal --- app/assets/javascripts/admin/user/experience_modal_view.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/assets/javascripts/admin/user/experience_modal_view.js b/app/assets/javascripts/admin/user/experience_modal_view.js index 81461d8dbb7..f0e78dbe27f 100644 --- a/app/assets/javascripts/admin/user/experience_modal_view.js +++ b/app/assets/javascripts/admin/user/experience_modal_view.js @@ -7,6 +7,7 @@ import * as Utils from "libs/utils"; import { updateUser } from "admin/admin_rest_api"; import { handleGenericError } from "libs/error_handling"; import type { APIUserType, ExperienceDomainListType } from "admin/api_flow_types"; +import Toast from "libs/toast"; import SelectExperienceDomain from "components/select_experience_domain"; const { Column } = Table; @@ -203,6 +204,10 @@ class ExperienceModalView extends React.PureComponent { }; addEnteredExperience = (domain: string) => { + if (domain.length < 3) { + Toast.warning("A experience domain needs at least 3 letters."); + return; + } if (this.state.tableEntries.findIndex(entry => entry.domain === domain) > -1) { return; } From f5fb466700aa6129b45f7d9a4bc38de49b7fbb04 Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 17 Sep 2018 13:20:40 +0200 Subject: [PATCH 3/8] fixed linter and flow errors --- app/assets/javascripts/admin/task/task_create_form_view.js | 3 +++ app/assets/javascripts/admin/user/experience_modal_view.js | 3 ++- app/assets/javascripts/components/select_experience_domain.js | 4 ++-- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/app/assets/javascripts/admin/task/task_create_form_view.js b/app/assets/javascripts/admin/task/task_create_form_view.js index 6d4b9d8bbbc..9ecd66c1045 100644 --- a/app/assets/javascripts/admin/task/task_create_form_view.js +++ b/app/assets/javascripts/admin/task/task_create_form_view.js @@ -231,6 +231,9 @@ class TaskCreateFormView extends React.PureComponent { notFoundContent={messages["task.domain_does_not_exist"]} width={100} alreadyUsedDomains={[]} + onSelect={null} + onChange={null} + value={null} />, )} diff --git a/app/assets/javascripts/admin/user/experience_modal_view.js b/app/assets/javascripts/admin/user/experience_modal_view.js index f0e78dbe27f..be559d1f2dc 100644 --- a/app/assets/javascripts/admin/user/experience_modal_view.js +++ b/app/assets/javascripts/admin/user/experience_modal_view.js @@ -397,9 +397,10 @@ class ExperienceModalView extends React.PureComponent { placeholder="New Experience Domain" notFoundContent={null} hasFieldDecorator={false} - value={[]} + value="" width={50} onSelect={this.addEnteredExperience} + onChange={null} alreadyUsedDomains={this.getDomainsOfTable()} /> diff --git a/app/assets/javascripts/components/select_experience_domain.js b/app/assets/javascripts/components/select_experience_domain.js index 9e095bbfcdb..0f213a80d18 100644 --- a/app/assets/javascripts/components/select_experience_domain.js +++ b/app/assets/javascripts/components/select_experience_domain.js @@ -1,6 +1,5 @@ // @flow -import _ from "lodash"; import * as React from "react"; import { Select } from "antd"; import type { ExperienceDomainListType } from "admin/api_flow_types"; @@ -10,11 +9,12 @@ const Option = Select.Option; type Props = { value: ?string, + width: number, placeholder: string, notFoundContent: ?string, disabled: boolean, mode: string, - onSelect: ?() => void, + onSelect: ?(string) => void, onChange: ?() => void, alreadyUsedDomains: ExperienceDomainListType, }; From b2857c14e4f52fbdd76e4ca2e662554f1780febf Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 17 Sep 2018 13:24:01 +0200 Subject: [PATCH 4/8] fixed flow error --- app/assets/javascripts/admin/user/experience_modal_view.js | 2 +- app/assets/javascripts/components/select_experience_domain.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/assets/javascripts/admin/user/experience_modal_view.js b/app/assets/javascripts/admin/user/experience_modal_view.js index be559d1f2dc..1916b9ab904 100644 --- a/app/assets/javascripts/admin/user/experience_modal_view.js +++ b/app/assets/javascripts/admin/user/experience_modal_view.js @@ -397,7 +397,7 @@ class ExperienceModalView extends React.PureComponent { placeholder="New Experience Domain" notFoundContent={null} hasFieldDecorator={false} - value="" + value={[]} width={50} onSelect={this.addEnteredExperience} onChange={null} diff --git a/app/assets/javascripts/components/select_experience_domain.js b/app/assets/javascripts/components/select_experience_domain.js index 0f213a80d18..fe52937cc89 100644 --- a/app/assets/javascripts/components/select_experience_domain.js +++ b/app/assets/javascripts/components/select_experience_domain.js @@ -8,7 +8,7 @@ import { getExistingExperienceDomains } from "admin/admin_rest_api"; const Option = Select.Option; type Props = { - value: ?string, + value: ?string | ?Array, width: number, placeholder: string, notFoundContent: ?string, From 1000107e027c00532b0f3b7b83fabd3d61d1cd5b Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 18 Sep 2018 07:12:29 +0200 Subject: [PATCH 5/8] added defaults for many props in SelectExpDomain --- app/assets/javascripts/admin/task/task_create_form_view.js | 7 +------ .../javascripts/components/select_experience_domain.js | 7 +++++++ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/app/assets/javascripts/admin/task/task_create_form_view.js b/app/assets/javascripts/admin/task/task_create_form_view.js index 9ecd66c1045..fd054c29ef7 100644 --- a/app/assets/javascripts/admin/task/task_create_form_view.js +++ b/app/assets/javascripts/admin/task/task_create_form_view.js @@ -226,14 +226,9 @@ class TaskCreateFormView extends React.PureComponent { })( , )} diff --git a/app/assets/javascripts/components/select_experience_domain.js b/app/assets/javascripts/components/select_experience_domain.js index fe52937cc89..279abe7688d 100644 --- a/app/assets/javascripts/components/select_experience_domain.js +++ b/app/assets/javascripts/components/select_experience_domain.js @@ -24,6 +24,13 @@ type State = { }; class SelectExperienceDomain extends React.PureComponent { + static defaultProps = { + mode: "default", + alreadyUsedDomains: [], + onChange: () => {}, + onSelect: () => {}, + }; + state = { domains: [], }; From 15a16364e962a53417214e37de88a0698d59a3c2 Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 18 Sep 2018 07:22:00 +0200 Subject: [PATCH 6/8] applied requested changes --- .../admin/user/experience_modal_view.js | 6 +---- .../components/select_experience_domain.js | 23 ++++++++----------- 2 files changed, 10 insertions(+), 19 deletions(-) diff --git a/app/assets/javascripts/admin/user/experience_modal_view.js b/app/assets/javascripts/admin/user/experience_modal_view.js index 1916b9ab904..dbcef8d9e9f 100644 --- a/app/assets/javascripts/admin/user/experience_modal_view.js +++ b/app/assets/javascripts/admin/user/experience_modal_view.js @@ -205,7 +205,7 @@ class ExperienceModalView extends React.PureComponent { addEnteredExperience = (domain: string) => { if (domain.length < 3) { - Toast.warning("A experience domain needs at least 3 letters."); + Toast.warning("An experience domain needs at least 3 letters."); return; } if (this.state.tableEntries.findIndex(entry => entry.domain === domain) > -1) { @@ -392,15 +392,11 @@ class ExperienceModalView extends React.PureComponent { ) : null} diff --git a/app/assets/javascripts/components/select_experience_domain.js b/app/assets/javascripts/components/select_experience_domain.js index 279abe7688d..7ac22f05ba6 100644 --- a/app/assets/javascripts/components/select_experience_domain.js +++ b/app/assets/javascripts/components/select_experience_domain.js @@ -14,8 +14,8 @@ type Props = { notFoundContent: ?string, disabled: boolean, mode: string, - onSelect: ?(string) => void, - onChange: ?() => void, + onSelect: string => void, + onChange: () => void, alreadyUsedDomains: ExperienceDomainListType, }; @@ -29,6 +29,9 @@ class SelectExperienceDomain extends React.PureComponent { alreadyUsedDomains: [], onChange: () => {}, onSelect: () => {}, + value: null, + notFoundContent: null, + disabled: false, }; state = { @@ -48,28 +51,20 @@ class SelectExperienceDomain extends React.PureComponent { } render() { - const options = this.getUnusedDomains().map(domain => ); - const notFoundContent = this.props.notFoundContent || "Not Found"; - const additionalProps = {}; - if (this.props.onChange) { - additionalProps.onChange = this.props.onChange; - } - if (this.props.onSelect) { - additionalProps.onSelect = this.props.onSelect; - } return ( ); } From 09eb52f3b3ff9a47f2b989dcc63a7dae30074114 Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 18 Sep 2018 10:15:40 +0200 Subject: [PATCH 7/8] removed properties from defaultProps and made them to an eventual prop --- .../admin/user/experience_modal_view.js | 1 + .../components/select_experience_domain.js | 16 +++++----------- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/app/assets/javascripts/admin/user/experience_modal_view.js b/app/assets/javascripts/admin/user/experience_modal_view.js index dbcef8d9e9f..2ac1379de4c 100644 --- a/app/assets/javascripts/admin/user/experience_modal_view.js +++ b/app/assets/javascripts/admin/user/experience_modal_view.js @@ -392,6 +392,7 @@ class ExperienceModalView extends React.PureComponent { ) : null} , + value?: string | Array, width: number, placeholder: string, - notFoundContent: ?string, + notFoundContent?: string, disabled: boolean, - mode: string, - onSelect: string => void, - onChange: () => void, + mode?: string, + onSelect?: string => void, + onChange?: () => void, alreadyUsedDomains: ExperienceDomainListType, }; @@ -25,13 +25,7 @@ type State = { class SelectExperienceDomain extends React.PureComponent { static defaultProps = { - mode: "default", alreadyUsedDomains: [], - onChange: () => {}, - onSelect: () => {}, - value: null, - notFoundContent: null, - disabled: false, }; state = { From 3b3f30d676ba73bccc003bb874e243b7906618b4 Mon Sep 17 00:00:00 2001 From: MichaelBuessemeyer <39529669+MichaelBuessemeyer@users.noreply.github.com> Date: Wed, 19 Sep 2018 10:58:32 +0200 Subject: [PATCH 8/8] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 29ea977e641..a2e4f308f92 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,7 @@ For upgrade instructions, please check the [migration guide](MIGRATIONS.md). ### Changed - The modal used to change the experience of users by admins got a rework. [#3077](https://github.com/scalableminds/webknossos/pull/3077) +- During task creation, specifying an experience domain is now possible by choosing from existing domains. [#3233](https://github.com/scalableminds/webknossos/pull/3233) - Unified the search functionality within webKnossos to implement an AND logic everyhwere. [#3228](https://github.com/scalableminds/webknossos/pull/3228) - Renamed "Soma Clicking" to "Single-Node-Tree Mode". [#3141](https://github.com/scalableminds/webknossos/pull/3141/files) - The fallback segmentation layer attribute of volume tracings is now persisted to NML/ZIP files. Upon re-upload, only volume tracings with this attribute will show a fallback layer. Use `tools/volumeAddFallbackLayer.py` to add this attribute to existing volume tracings. [#3088](https://github.com/scalableminds/webknossos/pull/3088)