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/03/11 17:56:21 UTC

[airavata-django-portal] 01/02: AIRAVATA-3562 Mocked up UI for admins to edit 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 8ce0bb667173656db21ba6571d4d7eb52c99e846
Author: Marcus Christie <ma...@apache.org>
AuthorDate: Fri Mar 11 12:47:12 2022 -0500

    AIRAVATA-3562 Mocked up UI for admins to edit extended user profile fields
---
 django_airavata/apps/admin/apps.py                 |   2 +-
 .../users/ExtendedUserProfileContainer.vue         | 181 +++++++++++++++++++++
 .../static/django_airavata_admin/src/router.js     |   6 +
 django_airavata/apps/admin/urls.py                 |   1 +
 django_airavata/apps/admin/views.py                |   6 +
 5 files changed, 195 insertions(+), 1 deletion(-)

diff --git a/django_airavata/apps/admin/apps.py b/django_airavata/apps/admin/apps.py
index 82876b9..a9a6642 100644
--- a/django_airavata/apps/admin/apps.py
+++ b/django_airavata/apps/admin/apps.py
@@ -25,7 +25,7 @@ class AdminConfig(AiravataAppConfig):
             'label': 'Manage Users',
             'icon': 'fa fa-users',
             'url': 'django_airavata_admin:users',
-            'active_prefixes': ['users'],
+            'active_prefixes': ['users', 'extended-user-profile'],
             'enabled': lambda req: (req.is_gateway_admin or
                                     req.is_read_only_gateway_admin),
         },
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
new file mode 100644
index 0000000..faaba0b
--- /dev/null
+++ b/django_airavata/apps/admin/static/django_airavata_admin/src/components/users/ExtendedUserProfileContainer.vue
@@ -0,0 +1,181 @@
+<template>
+  <div>
+    <div class="row">
+      <div class="col-auto mr-auto">
+        <h1 class="h4 mb-4">Extended User Profile Editor</h1>
+      </div>
+    </div>
+    <div v-for="field in fields" 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="Description">
+            <b-form-input v-model="field.description" />
+          </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.type" :options="fieldTypeOptions" />
+          </b-form-group>
+          <b-card
+            title="Options"
+            v-if="
+              field.type === 'single-select' || field.type === 'multi-select'
+            "
+          >
+            <template v-for="option in field.options">
+              <b-input-group :key="option.id">
+                <b-form-input v-model="option.name" />
+                <b-input-group-append>
+                  <b-button @click="deleteOption(field, option)"
+                    >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="Title">
+                <b-form-input v-model="link.title" />
+              </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
+          >
+          <template v-if="field.conditional">
+            <b-card title="Conditional">
+              When
+              <br />
+              <template v-for="condition in field.conditional.conditions">
+                <div :key="condition.id">
+                  <b-form-select
+                    :options="getConditionFieldOptions(field)"
+                    v-model="condition.field"
+                  />
+                  =
+                  <b-form-select
+                    v-if="
+                      (condition.field &&
+                        condition.field.type === 'multi-select') ||
+                      condition.field.type === 'single-select' ||
+                      condition.field.type === 'user-agreement'
+                    "
+                    :disabled="condition.field"
+                    :options="getConditionFieldValueOptions(condition.field)"
+                    v-model="condition.value"
+                  />
+                  <b-form-input
+                    v-else-if="
+                      condition.field && condition.field.type === 'text'
+                    "
+                    v-model="condition.value"
+                  />
+                </div>
+              </template>
+            </b-card>
+          </template>
+          <b-button v-if="!field.conditional" @click="addConditional(field)"
+            >Add Conditional</b-button
+          >
+        </b-card>
+      </div>
+    </div>
+    <div class="row">
+      <div class="col">
+        <b-button variant="primary" @click="addField"> Add Field </b-button>
+      </div>
+    </div>
+    <div class="row mt-4">
+      <div class="col">
+        <b-button variant="primary" @click="save">Save</b-button>
+      </div>
+    </div>
+    <pre>{{ JSON.stringify(fields, null, 4) }}</pre>
+  </div>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      fields: [],
+    };
+  },
+  methods: {
+    addField() {
+      // TODO: post an empty field to the API
+      this.fields.push({
+        id: null,
+        name: "",
+        description: "",
+        type: "text",
+        required: false,
+        options: null,
+        links: null,
+      });
+    },
+    addOption(field) {
+      if (!field.options) {
+        field.options = [];
+      }
+      field.options.push({ id: null, name: "" });
+    },
+    deleteOption(field, option) {
+      const i = field.options.indexOf(option);
+      field.options.splice(i, 1);
+    },
+    addLink(field) {
+      if (!field.links) {
+        field.links = [];
+      }
+      field.links.push({
+        id: null,
+        url: "",
+        title: "",
+        display_link: true,
+        display_inline: false,
+      });
+    },
+    addConditional(field) {
+      if (!field.conditional) {
+        field.conditional = {
+          id: null,
+          conditions: [],
+          require_when: true,
+          show_when: true,
+        };
+      }
+    },
+    deleteLink(field, link) {
+      const i = field.links.indexOf(link);
+      field.links.splice(i, 1);
+    },
+    save() {},
+  },
+  computed: {
+    fieldTypeOptions() {
+      return [
+        { value: "text", text: "Text" },
+        { value: "single-select", text: "Single Select" },
+        { value: "multi-select", text: "Multi Select" },
+        { value: "user-agreement", text: "User Agreement" },
+      ];
+    },
+  },
+};
+</script>
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/src/router.js b/django_airavata/apps/admin/static/django_airavata_admin/src/router.js
index de0c0d4..b5e722e 100644
--- a/django_airavata/apps/admin/static/django_airavata_admin/src/router.js
+++ b/django_airavata/apps/admin/static/django_airavata_admin/src/router.js
@@ -9,6 +9,7 @@ import ComputeResourcePreferenceDashboard from "./components/dashboards/ComputeR
 import CredentialStoreDashboard from "./components/dashboards/CredentialStoreDashboard";
 import DevelopersContainer from "./components/developers//DevelopersContainer.vue";
 import ExperimentStatisticsContainer from "./components/statistics/ExperimentStatisticsContainer";
+import ExtendedUserProfileContainer from "./components/users/ExtendedUserProfileContainer";
 import GatewayResourceProfileEditorContainer from "./components/gatewayprofile/GatewayResourceProfileEditorContainer.vue";
 import GroupComputeResourcePreference from "./components/admin/group_resource_preferences/GroupComputeResourcePreference";
 import IdentityServiceUserManagementContainer from "./components/users/IdentityServiceUserManagementContainer.vue";
@@ -141,6 +142,11 @@ const routes = [
     ],
   },
   {
+    path: "/extended-user-profile",
+    component: ExtendedUserProfileContainer,
+    name: "extended-user-profile",
+  },
+  {
     path: "/notices",
     component: NoticesManagementContainer,
     name: "notices",
diff --git a/django_airavata/apps/admin/urls.py b/django_airavata/apps/admin/urls.py
index 24a4b90..f526727 100644
--- a/django_airavata/apps/admin/urls.py
+++ b/django_airavata/apps/admin/urls.py
@@ -15,5 +15,6 @@ urlpatterns = [
             name='gateway_resource_profile'),
     re_path(r'^notices/', views.notices, name='notices'),
     re_path(r'^users/', views.users, name='users'),
+    path('extended-user-profile/', views.extended_user_profile, name="extended_user_profile"),
     path('developers/', views.developers, name='developers'),
 ]
diff --git a/django_airavata/apps/admin/views.py b/django_airavata/apps/admin/views.py
index caca63a..e8be104 100644
--- a/django_airavata/apps/admin/views.py
+++ b/django_airavata/apps/admin/views.py
@@ -54,6 +54,12 @@ def users(request):
 
 
 @login_required
+def extended_user_profile(request):
+    request.active_nav_item = 'users'
+    return render(request, 'admin/admin_base.html')
+
+
+@login_required
 def experiment_statistics(request):
     request.active_nav_item = 'experiment-statistics'
     return render(request, 'admin/admin_base.html')