You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airavata.apache.org by ma...@apache.org on 2022/06/03 20:11:54 UTC
[airavata-django-portal] 01/08: AIRAVATA-3564 Save common extended user profile fields
This is an automated email from the ASF dual-hosted git repository.
machristie pushed a commit to branch AIRAVATA-3562
in repository https://gitbox.apache.org/repos/asf/airavata-django-portal.git
commit 5b7b9b712265108e86f1ab58d371a45986be27f4
Author: Marcus Christie <ma...@apache.org>
AuthorDate: Tue May 24 12:33:25 2022 -0400
AIRAVATA-3564 Save common extended user profile fields
---
.../users/ExtendedUserProfileContainer.vue | 75 +++--------------
.../ExtendedUserProfileFieldEditor.vue | 98 ++++++++++++++++++++++
.../src/store/modules/extendedUserProfile.js | 35 ++++++++
.../js/models/ExtendedUserProfileField.js | 24 ++++++
.../js/components/ExtendedUserProfileEditor.vue | 16 ++--
... ExtendedUserProfileMultiChoiceValueEditor.vue} | 8 +-
...ExtendedUserProfileSingleChoiceValueEditor.vue} | 8 +-
....vue => ExtendedUserProfileTextValueEditor.vue} | 8 +-
...xtendedUserProfileUserAgreementValueEditor.vue} | 8 +-
...itor.vue => ExtendedUserProfileValueEditor.vue} | 0
.../js/store/modules/extendedUserProfile.js | 2 +-
11 files changed, 192 insertions(+), 90 deletions(-)
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/src/components/users/ExtendedUserProfileContainer.vue b/django_airavata/apps/admin/static/django_airavata_admin/src/components/users/ExtendedUserProfileContainer.vue
index e813f737..2bd39ae6 100644
--- a/django_airavata/apps/admin/static/django_airavata_admin/src/components/users/ExtendedUserProfileContainer.vue
+++ b/django_airavata/apps/admin/static/django_airavata_admin/src/components/users/ExtendedUserProfileContainer.vue
@@ -7,61 +7,7 @@
</div>
<div v-for="field in extendedUserProfileFields" class="row" :key="field.id">
<div class="col">
- <b-card :title="'Field: ' + field.name">
- <b-form-group label="Name">
- <b-form-input v-model="field.name" />
- </b-form-group>
- <b-form-group label="Help text">
- <b-form-input v-model="field.help_text" />
- </b-form-group>
- <b-form-group label="Required">
- <b-form-checkbox v-model="field.required" />
- </b-form-group>
- <b-form-group label="Type">
- <b-form-select
- v-model="field.field_type"
- :options="fieldTypeOptions"
- />
- </b-form-group>
- <b-card
- title="Options"
- v-if="
- field.field_type === 'single_choice' ||
- field.field_type === 'multi_choice'
- "
- >
- <template v-for="choice in field.choices">
- <b-input-group :key="choice.id">
- <b-form-input v-model="choice.display_text" />
- <b-input-group-append>
- <b-button @click="deleteOption(field, choice)"
- >Delete</b-button
- >
- </b-input-group-append>
- </b-input-group>
- </template>
- <b-button @click="addOption(field)">Add Option</b-button>
- </b-card>
- <template v-if="field.links && field.links.length > 0">
- <b-card title="Links" v-for="link in field.links" :key="link.id">
- <b-form-group label="Label">
- <b-form-input v-model="link.label" />
- </b-form-group>
- <b-form-group label="URL">
- <b-form-input v-model="link.url" />
- </b-form-group>
- <b-form-group label="Show as link?">
- <b-form-checkbox v-model="link.display_link" />
- </b-form-group>
- <b-form-group label="Show inline?">
- <b-form-checkbox v-model="link.display_inline" />
- </b-form-group>
- </b-card>
- </template>
- <b-button v-if="!field.links" @click="addLink(field)"
- >Add Link</b-button
- >
- </b-card>
+ <extended-user-profile-field-editor :extendedUserProfileField="field" />
</div>
</div>
<div class="row">
@@ -79,7 +25,9 @@
<script>
import { mapActions, mapGetters } from "vuex";
+import ExtendedUserProfileFieldEditor from "./field-editors/ExtendedUserProfileFieldEditor.vue";
export default {
+ components: { ExtendedUserProfileFieldEditor },
data() {
return {
fields: [],
@@ -89,7 +37,10 @@ export default {
this.loadExtendedUserProfileFields();
},
methods: {
- ...mapActions("extendedUserProfile", ["loadExtendedUserProfileFields"]),
+ ...mapActions("extendedUserProfile", [
+ "loadExtendedUserProfileFields",
+ "saveExtendedUserProfileFields",
+ ]),
addField() {
// TODO: post an empty field to the API
this.fields.push({
@@ -138,18 +89,12 @@ export default {
const i = field.links.indexOf(link);
field.links.splice(i, 1);
},
- save() {},
+ save() {
+ this.saveExtendedUserProfileFields();
+ },
},
computed: {
...mapGetters("extendedUserProfile", ["extendedUserProfileFields"]),
- fieldTypeOptions() {
- return [
- { value: "text", text: "Text" },
- { value: "single_choice", text: "Single Choice" },
- { value: "multi_choice", text: "Multi Choice" },
- { value: "user_agreement", text: "User Agreement" },
- ];
- },
},
};
</script>
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/src/components/users/field-editors/ExtendedUserProfileFieldEditor.vue b/django_airavata/apps/admin/static/django_airavata_admin/src/components/users/field-editors/ExtendedUserProfileFieldEditor.vue
new file mode 100644
index 00000000..5b19426b
--- /dev/null
+++ b/django_airavata/apps/admin/static/django_airavata_admin/src/components/users/field-editors/ExtendedUserProfileFieldEditor.vue
@@ -0,0 +1,98 @@
+<template>
+ <b-card :title="'Field: ' + name">
+ <b-form-group label="Name">
+ <b-form-input v-model="name" />
+ </b-form-group>
+ <b-form-group label="Help text">
+ <b-form-input v-model="help_text" />
+ </b-form-group>
+ <b-form-group label="Required">
+ <b-form-checkbox v-model="required" />
+ </b-form-group>
+ <!-- <b-card
+ title="Options"
+ v-if="
+ field.field_type === 'single_choice' ||
+ field.field_type === 'multi_choice'
+ "
+ >
+ <template v-for="choice in field.choices">
+ <b-input-group :key="choice.id">
+ <b-form-input v-model="choice.display_text" />
+ <b-input-group-append>
+ <b-button @click="deleteOption(field, choice)"
+ >Delete</b-button
+ >
+ </b-input-group-append>
+ </b-input-group>
+ </template>
+ <b-button @click="addOption(field)">Add Option</b-button>
+ </b-card>
+ <template v-if="field.links && field.links.length > 0">
+ <b-card title="Links" v-for="link in field.links" :key="link.id">
+ <b-form-group label="Label">
+ <b-form-input v-model="link.label" />
+ </b-form-group>
+ <b-form-group label="URL">
+ <b-form-input v-model="link.url" />
+ </b-form-group>
+ <b-form-group label="Show as link?">
+ <b-form-checkbox v-model="link.display_link" />
+ </b-form-group>
+ <b-form-group label="Show inline?">
+ <b-form-checkbox v-model="link.display_inline" />
+ </b-form-group>
+ </b-card>
+ </template>
+ <b-button v-if="!field.links" @click="addLink(field)"
+ >Add Link</b-button
+ > -->
+ </b-card>
+</template>
+
+<script>
+import { mapMutations } from "vuex";
+export default {
+ props: ["extendedUserProfileField"],
+ computed: {
+ name: {
+ get() {
+ return this.extendedUserProfileField.name;
+ },
+ set(value) {
+ this.setName({ value, field: this.extendedUserProfileField });
+ },
+ },
+ help_text: {
+ get() {
+ return this.extendedUserProfileField.help_text;
+ },
+ set(value) {
+ this.setHelpText({ value, field: this.extendedUserProfileField });
+ },
+ },
+ required: {
+ get() {
+ return this.extendedUserProfileField.required;
+ },
+ set(value) {
+ this.setRequired({ value, field: this.extendedUserProfileField });
+ },
+ },
+ // TODO: probably don't need these
+ fieldTypeOptions() {
+ return [
+ { value: "text", text: "Text" },
+ { value: "single_choice", text: "Single Choice" },
+ { value: "multi_choice", text: "Multi Choice" },
+ { value: "user_agreement", text: "User Agreement" },
+ ];
+ },
+ },
+ methods: {
+ ...mapMutations("extendedUserProfile", ["setName", "setHelpText", "setRequired"]),
+ },
+};
+</script>
+
+<style></style>
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/src/store/modules/extendedUserProfile.js b/django_airavata/apps/admin/static/django_airavata_admin/src/store/modules/extendedUserProfile.js
index 2e3eefc2..decd3d89 100644
--- a/django_airavata/apps/admin/static/django_airavata_admin/src/store/modules/extendedUserProfile.js
+++ b/django_airavata/apps/admin/static/django_airavata_admin/src/store/modules/extendedUserProfile.js
@@ -13,12 +13,47 @@ const actions = {
const extendedUserProfileFields = await services.ExtendedUserProfileFieldService.list();
commit("setExtendedUserProfileFields", { extendedUserProfileFields });
},
+ async saveExtendedUserProfileFields({ dispatch, state }) {
+ for (const field of state.extendedUserProfileFields) {
+ // Create or update each field
+ if (field.id) {
+ await services.ExtendedUserProfileFieldService.update({
+ lookup: field.id,
+ data: field,
+ });
+ } else {
+ await services.ExtendedUserProfileFieldService.create({ data: field });
+ }
+ }
+ // Reload the fields
+ dispatch("loadExtendedUserProfileFields");
+ },
};
+function getField(state, field) {
+ const extendedUserProfileField = state.extendedUserProfileFields.find(
+ (f) => f === field
+ );
+ return extendedUserProfileField;
+}
+function setFieldProp(state, field, prop, value) {
+ const extendedUserProfileField = getField(state, field);
+ extendedUserProfileField[prop] = value;
+}
+
const mutations = {
setExtendedUserProfileFields(state, { extendedUserProfileFields }) {
state.extendedUserProfileFields = extendedUserProfileFields;
},
+ setName(state, { value, field }) {
+ setFieldProp(state, field, "name", value);
+ },
+ setHelpText(state, { value, field }) {
+ setFieldProp(state, field, "help_text", value);
+ },
+ setRequired(state, { value, field }) {
+ setFieldProp(state, field, "required", value);
+ },
};
export default {
diff --git a/django_airavata/apps/api/static/django_airavata_api/js/models/ExtendedUserProfileField.js b/django_airavata/apps/api/static/django_airavata_api/js/models/ExtendedUserProfileField.js
index 2eec7ac8..bef33e41 100644
--- a/django_airavata/apps/api/static/django_airavata_api/js/models/ExtendedUserProfileField.js
+++ b/django_airavata/apps/api/static/django_airavata_api/js/models/ExtendedUserProfileField.js
@@ -37,4 +37,28 @@ export default class ExtendedUserProfileField extends BaseModel {
constructor(data = {}) {
super(FIELDS, data);
}
+ toJSON() {
+ const copy = Object.assign({}, this);
+ // Remove unnecessary properties
+ switch (this.field_type) {
+ case "text":
+ delete copy["other"];
+ delete copy["choices"];
+ delete copy["checkbox_label"];
+ break;
+ case "single_choice":
+ case "multi_choice":
+ delete copy["checkbox_label"];
+ break;
+ case "user_agreement":
+ delete copy["other"];
+ delete copy["choices"];
+ break;
+ default:
+ // eslint-disable-next-line no-console
+ console.error("Unrecognized field type", this.field_type);
+ break;
+ }
+ return copy;
+ }
}
diff --git a/django_airavata/apps/auth/static/django_airavata_auth/js/components/ExtendedUserProfileEditor.vue b/django_airavata/apps/auth/static/django_airavata_auth/js/components/ExtendedUserProfileEditor.vue
index 0b0b08d8..aaf9fc7f 100644
--- a/django_airavata/apps/auth/static/django_airavata_auth/js/components/ExtendedUserProfileEditor.vue
+++ b/django_airavata/apps/auth/static/django_airavata_auth/js/components/ExtendedUserProfileEditor.vue
@@ -15,10 +15,10 @@
<script>
import { mapGetters } from "vuex";
-import ExtendedUserProfileMultiChoiceFieldEditor from "./ExtendedUserProfileMultiChoiceFieldEditor.vue";
-import ExtendedUserProfileSingleChoiceFieldEditor from "./ExtendedUserProfileSingleChoiceFieldEditor.vue";
-import ExtendedUserProfileTextFieldEditor from "./ExtendedUserProfileTextFieldEditor.vue";
-import ExtendedUserProfileUserAgreementFieldEditor from "./ExtendedUserProfileUserAgreementFieldEditor.vue";
+import ExtendedUserProfileMultiChoiceValueEditor from "./ExtendedUserProfileMultiChoiceValueEditor.vue";
+import ExtendedUserProfileSingleChoiceValueEditor from "./ExtendedUserProfileSingleChoiceValueEditor.vue";
+import ExtendedUserProfileTextValueEditor from "./ExtendedUserProfileTextValueEditor.vue";
+import ExtendedUserProfileUserAgreementValueEditor from "./ExtendedUserProfileUserAgreementValueEditor.vue";
import { mixins } from "django-airavata-common-ui";
export default {
mixins: [mixins.ValidationParent],
@@ -31,10 +31,10 @@ export default {
methods: {
getEditor(extendedUserProfileField) {
const fieldTypeEditors = {
- text: ExtendedUserProfileTextFieldEditor,
- single_choice: ExtendedUserProfileSingleChoiceFieldEditor,
- multi_choice: ExtendedUserProfileMultiChoiceFieldEditor,
- user_agreement: ExtendedUserProfileUserAgreementFieldEditor,
+ text: ExtendedUserProfileTextValueEditor,
+ single_choice: ExtendedUserProfileSingleChoiceValueEditor,
+ multi_choice: ExtendedUserProfileMultiChoiceValueEditor,
+ user_agreement: ExtendedUserProfileUserAgreementValueEditor,
};
if (extendedUserProfileField.field_type in fieldTypeEditors) {
diff --git a/django_airavata/apps/auth/static/django_airavata_auth/js/components/ExtendedUserProfileMultiChoiceFieldEditor.vue b/django_airavata/apps/auth/static/django_airavata_auth/js/components/ExtendedUserProfileMultiChoiceValueEditor.vue
similarity index 94%
rename from django_airavata/apps/auth/static/django_airavata_auth/js/components/ExtendedUserProfileMultiChoiceFieldEditor.vue
rename to django_airavata/apps/auth/static/django_airavata_auth/js/components/ExtendedUserProfileMultiChoiceValueEditor.vue
index 9e99fb7f..9905c89f 100644
--- a/django_airavata/apps/auth/static/django_airavata_auth/js/components/ExtendedUserProfileMultiChoiceFieldEditor.vue
+++ b/django_airavata/apps/auth/static/django_airavata_auth/js/components/ExtendedUserProfileMultiChoiceValueEditor.vue
@@ -1,5 +1,5 @@
<template>
- <extended-user-profile-field-editor v-bind="$props">
+ <extended-user-profile-value-editor v-bind="$props">
<b-form-checkbox-group
v-model="value"
:options="options"
@@ -29,7 +29,7 @@
>Please specify a value for 'Other'.</b-form-invalid-feedback
>
</template>
- </extended-user-profile-field-editor>
+ </extended-user-profile-value-editor>
</template>
<script>
@@ -37,11 +37,11 @@ import { mapGetters, mapMutations } from "vuex";
import { validationMixin } from "vuelidate";
import { required, requiredIf } from "vuelidate/lib/validators";
import { errors } from "django-airavata-common-ui";
-import ExtendedUserProfileFieldEditor from "./ExtendedUserProfileFieldEditor.vue";
+import ExtendedUserProfileValueEditor from "./ExtendedUserProfileValueEditor.vue";
const OTHER_OPTION = new Object(); // sentinel value
export default {
mixins: [validationMixin],
- components: { ExtendedUserProfileFieldEditor },
+ components: { ExtendedUserProfileValueEditor },
props: ["extendedUserProfileField"],
data() {
return {
diff --git a/django_airavata/apps/auth/static/django_airavata_auth/js/components/ExtendedUserProfileSingleChoiceFieldEditor.vue b/django_airavata/apps/auth/static/django_airavata_auth/js/components/ExtendedUserProfileSingleChoiceValueEditor.vue
similarity index 94%
rename from django_airavata/apps/auth/static/django_airavata_auth/js/components/ExtendedUserProfileSingleChoiceFieldEditor.vue
rename to django_airavata/apps/auth/static/django_airavata_auth/js/components/ExtendedUserProfileSingleChoiceValueEditor.vue
index 7bc1f26d..1ca3ef48 100644
--- a/django_airavata/apps/auth/static/django_airavata_auth/js/components/ExtendedUserProfileSingleChoiceFieldEditor.vue
+++ b/django_airavata/apps/auth/static/django_airavata_auth/js/components/ExtendedUserProfileSingleChoiceValueEditor.vue
@@ -1,5 +1,5 @@
<template>
- <extended-user-profile-field-editor v-bind="$props">
+ <extended-user-profile-value-editor v-bind="$props">
<b-form-select
v-model="value"
:options="options"
@@ -33,7 +33,7 @@
>Please specify a value for 'Other'.</b-form-invalid-feedback
>
</template>
- </extended-user-profile-field-editor>
+ </extended-user-profile-value-editor>
</template>
<script>
@@ -41,12 +41,12 @@ import { mapGetters, mapMutations } from "vuex";
import { validationMixin } from "vuelidate";
import { required, requiredIf } from "vuelidate/lib/validators";
import { errors } from "django-airavata-common-ui";
-import ExtendedUserProfileFieldEditor from "./ExtendedUserProfileFieldEditor.vue";
+import ExtendedUserProfileValueEditor from "./ExtendedUserProfileValueEditor.vue";
const OTHER_OPTION = new Object(); // sentinel value
export default {
mixins: [validationMixin],
- components: { ExtendedUserProfileFieldEditor },
+ components: { ExtendedUserProfileValueEditor },
props: ["extendedUserProfileField"],
data() {
return {
diff --git a/django_airavata/apps/auth/static/django_airavata_auth/js/components/ExtendedUserProfileTextFieldEditor.vue b/django_airavata/apps/auth/static/django_airavata_auth/js/components/ExtendedUserProfileTextValueEditor.vue
similarity index 86%
rename from django_airavata/apps/auth/static/django_airavata_auth/js/components/ExtendedUserProfileTextFieldEditor.vue
rename to django_airavata/apps/auth/static/django_airavata_auth/js/components/ExtendedUserProfileTextValueEditor.vue
index 3e2a8e69..644ed825 100644
--- a/django_airavata/apps/auth/static/django_airavata_auth/js/components/ExtendedUserProfileTextFieldEditor.vue
+++ b/django_airavata/apps/auth/static/django_airavata_auth/js/components/ExtendedUserProfileTextValueEditor.vue
@@ -1,10 +1,10 @@
<template>
- <extended-user-profile-field-editor v-bind="$props">
+ <extended-user-profile-value-editor v-bind="$props">
<b-form-input v-model="value" :state="validateState($v.value)" />
<b-form-invalid-feedback :state="validateState($v.value)"
>This field is required.</b-form-invalid-feedback
>
- </extended-user-profile-field-editor>
+ </extended-user-profile-value-editor>
</template>
<script>
@@ -12,10 +12,10 @@ import { mapGetters, mapMutations } from "vuex";
import { validationMixin } from "vuelidate";
import { requiredIf } from "vuelidate/lib/validators";
import { errors } from "django-airavata-common-ui";
-import ExtendedUserProfileFieldEditor from "./ExtendedUserProfileFieldEditor.vue";
+import ExtendedUserProfileValueEditor from "./ExtendedUserProfileValueEditor.vue";
export default {
mixins: [validationMixin],
- components: { ExtendedUserProfileFieldEditor },
+ components: { ExtendedUserProfileValueEditor },
props: ["extendedUserProfileField"],
computed: {
...mapGetters("extendedUserProfile", ["getTextValue"]),
diff --git a/django_airavata/apps/auth/static/django_airavata_auth/js/components/ExtendedUserProfileUserAgreementFieldEditor.vue b/django_airavata/apps/auth/static/django_airavata_auth/js/components/ExtendedUserProfileUserAgreementValueEditor.vue
similarity index 89%
rename from django_airavata/apps/auth/static/django_airavata_auth/js/components/ExtendedUserProfileUserAgreementFieldEditor.vue
rename to django_airavata/apps/auth/static/django_airavata_auth/js/components/ExtendedUserProfileUserAgreementValueEditor.vue
index d0fe40a4..035044d0 100644
--- a/django_airavata/apps/auth/static/django_airavata_auth/js/components/ExtendedUserProfileUserAgreementFieldEditor.vue
+++ b/django_airavata/apps/auth/static/django_airavata_auth/js/components/ExtendedUserProfileUserAgreementValueEditor.vue
@@ -1,5 +1,5 @@
<template>
- <extended-user-profile-field-editor v-bind="$props">
+ <extended-user-profile-value-editor v-bind="$props">
<b-form-checkbox
v-model="value"
:unchecked-value="false"
@@ -11,18 +11,18 @@
<b-form-invalid-feedback :state="validateState($v.value)"
>This field is required.</b-form-invalid-feedback
>
- </extended-user-profile-field-editor>
+ </extended-user-profile-value-editor>
</template>
<script>
import { mapGetters, mapMutations } from "vuex";
import { validationMixin } from "vuelidate";
import { errors } from "django-airavata-common-ui";
-import ExtendedUserProfileFieldEditor from "./ExtendedUserProfileFieldEditor.vue";
+import ExtendedUserProfileValueEditor from "./ExtendedUserProfileValueEditor.vue";
export default {
mixins: [validationMixin],
- components: { ExtendedUserProfileFieldEditor },
+ components: { ExtendedUserProfileValueEditor },
props: ["extendedUserProfileField"],
computed: {
...mapGetters("extendedUserProfile", ["getUserAgreementValue"]),
diff --git a/django_airavata/apps/auth/static/django_airavata_auth/js/components/ExtendedUserProfileFieldEditor.vue b/django_airavata/apps/auth/static/django_airavata_auth/js/components/ExtendedUserProfileValueEditor.vue
similarity index 100%
rename from django_airavata/apps/auth/static/django_airavata_auth/js/components/ExtendedUserProfileFieldEditor.vue
rename to django_airavata/apps/auth/static/django_airavata_auth/js/components/ExtendedUserProfileValueEditor.vue
diff --git a/django_airavata/apps/auth/static/django_airavata_auth/js/store/modules/extendedUserProfile.js b/django_airavata/apps/auth/static/django_airavata_auth/js/store/modules/extendedUserProfile.js
index 6e264490..9fef5c74 100644
--- a/django_airavata/apps/auth/static/django_airavata_auth/js/store/modules/extendedUserProfile.js
+++ b/django_airavata/apps/auth/static/django_airavata_auth/js/store/modules/extendedUserProfile.js
@@ -176,7 +176,7 @@ const mutations = {
});
}
},
- updateExperimentInputValue(state, { extendedUserProfileValue }) {
+ updateExtendedUserProfileValue(state, { extendedUserProfileValue }) {
const index = state.extendedUserProfileValues.findIndex(
(v) =>
v.ext_user_profile_field ===