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 2021/02/22 21:34:22 UTC

[airavata-django-portal] branch develop updated: Adding search options to the experiment list

This is an automated email from the ASF dual-hosted git repository.

machristie pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/airavata-django-portal.git


The following commit(s) were added to refs/heads/develop by this push:
     new ff9996b  Adding search options to the experiment list
     new 9df1b54  Merge pull request #53 from akbranam/develop
ff9996b is described below

commit ff9996b49961ed338702ef7763b1a92891755434
Author: akbranam <ak...@gmail.com>
AuthorDate: Mon Feb 15 21:04:13 2021 -0500

    Adding search options to the experiment list
---
 django_airavata/apps/workspace/package.json        |   1 +
 .../js/containers/ExperimentListContainer.vue      | 195 ++++++++++++++++++++-
 .../js/entry-experiment-list.js                    |   3 +
 django_airavata/apps/workspace/yarn.lock           |  12 ++
 4 files changed, 210 insertions(+), 1 deletion(-)

diff --git a/django_airavata/apps/workspace/package.json b/django_airavata/apps/workspace/package.json
index 077cd21..8d53566 100644
--- a/django_airavata/apps/workspace/package.json
+++ b/django_airavata/apps/workspace/package.json
@@ -25,6 +25,7 @@
     "moment": "^2.21.0",
     "terser": "^4.1.2",
     "vue": "^2.5.22",
+    "vue-flatpickr-component": "^8.1.2",
     "vue-router": "^3.0.6",
     "vue-slider-component": "^3.2.9-1"
   },
diff --git a/django_airavata/apps/workspace/static/django_airavata_workspace/js/containers/ExperimentListContainer.vue b/django_airavata/apps/workspace/static/django_airavata_workspace/js/containers/ExperimentListContainer.vue
index 6e177c2..b282125 100644
--- a/django_airavata/apps/workspace/static/django_airavata_workspace/js/containers/ExperimentListContainer.vue
+++ b/django_airavata/apps/workspace/static/django_airavata_workspace/js/containers/ExperimentListContainer.vue
@@ -8,6 +8,80 @@
     <div class="row">
       <div class="col">
         <div class="card">
+          <div class = "card-body">
+            <b-input-group class="w-100 mb-2">
+              <b-form-input v-if="defaultOptionSelected" v-model="search" 
+                placeholder="Search Experiments"
+                @keydown.native.enter="searchExperiments"
+              />
+              <b-form-select v-if="applicationSelected" v-model="applicationSelect" 
+              :options="applicationNameOptions"
+              >
+                <template slot="first">
+                  <option :value="null" disabled>Select an application to search by</option>
+                </template>
+              </b-form-select>
+              <b-form-select v-if="projectSelected" v-model="projectSelect" 
+              :options="projectNameOptions"
+              >
+                <template slot="first">
+                  <option :value="null" disabled>Select a project to search by</option>
+                </template>
+              </b-form-select>
+              <b-form-select v-model="experimentAttributeSelect" 
+              @input="checkSearchOptions"
+              >
+                <template slot="first">
+                  <option :value="null" disabled>Select an attribute to search by</option>
+                </template>
+                <option value="USER_NAME">User Name</option>
+                <option value="EXPERIMENT_NAME">Experiment Name</option>
+                <option value="EXPERIMENT_DESC">Experiment Description</option>
+                <option value="APPLICATION_ID">Application</option>
+                <option value="PROJECT_ID">Project</option>
+              </b-form-select>
+              <b-form-select v-model="experimentStatusSelect">
+                <template slot="first">
+                  <option :value="null" disabled>Select an experiment status to filter by</option>
+                </template>
+                <option value="CREATED">Created</option>
+                <option value="VALIDATED">Validated</option>
+                <option value="SCHEDULED">Scheduled</option>
+                <option value="LAUNCHED">Launched</option>
+                <option value="EXECUTING">Executing</option>
+                <option value="CANCELED">Cancled</option>
+                <option value="COMPLETED">Completed</option>
+                <option value="FAILED">Failed</option>
+              </b-form-select>
+              <b-input-group-append>
+                <b-button @click="resetSearch">Reset</b-button>
+                <b-button
+                  variant="primary"
+                  @click="searchExperiments"
+                >Search</b-button>
+              </b-input-group-append>
+            </b-input-group>
+            <b-input-group class="w-100 mb-2">
+            <b-input-group-prepend is-text >
+                    <i
+                      class="fa fa-calendar-week"
+                      aria-hidden="true"
+                    ></i>
+                  </b-input-group-prepend>
+                  <flat-pickr v-model="dateSelect"          
+                    :config="dateConfig"
+                    placeholder="Select a date range to filter by"
+                    @on-change="dateRangeChanged"
+                    class="form-control"
+                  />            
+            </b-input-group>
+          </div>
+        </div>
+      </div>
+    </div>
+    <div class="row">
+      <div class="col">
+        <div class="card">
           <div class="card-body">
             <table class="table table-hover">
               <thead>
@@ -84,7 +158,7 @@
 </template>
 
 <script>
-import { models, services } from "django-airavata-api";
+import { models, services, utils } from "django-airavata-api";
 import { components as comps } from "django-airavata-common-ui";
 
 import moment from "moment";
@@ -97,6 +171,25 @@ export default {
     return {
       experimentsPaginator: null,
       applicationInterfaces: {},
+      search: null, 
+      applicationSelect: null, 
+      projectSelect: null,
+      dateSelect : null,
+      experimentAttributeSelect: null, 
+      experimentStatusSelect: null, 
+      appInterfaces: null,
+      projectInterfaces: null,
+      fromDate: null,
+      toDate: null,
+      applicationSelected: false,
+      projectSelected: false, 
+      defaultOptionSelected: true,
+      dateConfig: {
+        mode: "range",
+        wrap: true,
+        dateFormat: "Y-m-d",
+        maxDate: new Date().fp_incr(1),
+      },
     };
   },
   components: {
@@ -104,6 +197,78 @@ export default {
     "experiment-status-badge": comps.ExperimentStatusBadge,
   },
   methods: {
+    searchExperiments: function(){
+      this.experimentsPaginator = null;
+      this.reloadExperiments();
+    },
+    resetSearch: function(){
+      this.experimentsPaginator = null;
+      this.search = null;
+      this.experimentAttributeSelect = null;
+      this.experimentStatusSelect = null;
+      this.applicationSelect = null;
+      this.projectSelect = null;
+      this.dateSelect = null;
+      this.toDate = null;
+      this.fromDate = null;
+      this.checkSearchOptions();
+      this.reloadExperiments();
+    },
+    reloadExperiments: function(){
+      const searchParams = {};
+      if (this.experimentAttributeSelect) {
+        if (this.experimentAttributeSelect=="APPLICATION_ID"&& this.applicationSelect){
+          searchParams["APPLICATION_ID"] = this.applicationSelect;
+        }
+        else if (this.experimentAttributeSelect=="PROJECT_ID"&& this.projectSelect){
+          searchParams["PROJECT_ID"] = this.projectSelect;
+        }
+        else if (this.search){
+          searchParams[this.experimentAttributeSelect] = this.search;
+        }
+      }
+      if (this.experimentStatusSelect){
+        searchParams["STATUS"]= this.experimentStatusSelect;
+      }
+      if (this.fromDate && this.toDate){
+        searchParams["FROM_DATE"] = this.fromDate.getTime();
+        searchParams["TO_DATE"] = this.toDate.getTime();
+      }
+
+      services.ExperimentSearchService.list(searchParams).then(
+        result => (this.experimentsPaginator = result)
+        );
+    },
+    checkSearchOptions: function(){
+      this.applicationSelected = false;
+      this.projectSelected = false;
+      this.defaultOptionSelected = false;
+      if(this.experimentAttributeSelect == "APPLICATION_ID"){
+        this.applicationSelected = true;
+      }
+      else if( this.experimentAttributeSelect == "PROJECT_ID"){
+        this.projectSelected=true;
+      }
+      else{
+        this.defaultOptionSelected = true;
+      }
+    },
+    loadApplicationInterfaces: function() {
+      return services.ApplicationInterfaceService.list().then(
+        (appInterfaces) => (this.appInterfaces = appInterfaces)
+      );
+    },
+    loadProjectInterfaces: function(){
+      return services.ProjectService.listAll().then(
+        (projectInterfaces) => (this.projectInterfaces = projectInterfaces)
+      );
+    },
+    dateRangeChanged: function(selectedDates) {
+      [this.fromDate, this.toDate] = selectedDates;
+      if (this.fromDate && this.toDate) {
+        this.reloadExperiments();
+      }
+    },
     nextExperiments: function () {
       this.experimentsPaginator.next();
     },
@@ -170,8 +335,36 @@ export default {
         ? this.experimentsPaginator.results
         : null;
     },
+    applicationNameOptions() {
+      if (this.appInterfaces) {
+        const options = this.appInterfaces.map((appInterface) => {
+          return {
+            value: appInterface.applicationInterfaceId,
+            text: appInterface.applicationName,
+          };
+        });
+        return utils.StringUtils.sortIgnoreCase(options, (o) => o.text);
+      } else {
+        return [];
+      }
+    },
+    projectNameOptions() {
+      if (this.projectInterfaces){
+        const options = this.projectInterfaces.map((projectInterface) => {
+          return {
+            value: projectInterface.projectID,
+            text: projectInterface.name,
+          };
+        });
+        return utils.StringUtils.sortIgnoreCase(options, (o) => o.text);
+      } else{
+        return [];
+      }
+    },
   },
   beforeMount: function () {
+    this.loadApplicationInterfaces();
+    this.loadProjectInterfaces();
     services.ExperimentSearchService.list({
       initialData: this.initialExperimentsData,
     }).then((result) => (this.experimentsPaginator = result));
diff --git a/django_airavata/apps/workspace/static/django_airavata_workspace/js/entry-experiment-list.js b/django_airavata/apps/workspace/static/django_airavata_workspace/js/entry-experiment-list.js
index d7452f1..4c0c325 100644
--- a/django_airavata/apps/workspace/static/django_airavata_workspace/js/entry-experiment-list.js
+++ b/django_airavata/apps/workspace/static/django_airavata_workspace/js/entry-experiment-list.js
@@ -1,7 +1,10 @@
 import { components, entry } from "django-airavata-common-ui";
 import ExperimentListContainer from "./containers/ExperimentListContainer.vue";
+import VueFlatPickr from "vue-flatpickr-component";
+import "flatpickr/dist/flatpickr.css";
 
 entry((Vue) => {
+  Vue.use(VueFlatPickr);
   new Vue({
     render(h) {
       return h(components.MainLayout, [
diff --git a/django_airavata/apps/workspace/yarn.lock b/django_airavata/apps/workspace/yarn.lock
index 141512e..7fc2a41 100644
--- a/django_airavata/apps/workspace/yarn.lock
+++ b/django_airavata/apps/workspace/yarn.lock
@@ -4354,6 +4354,11 @@ flat-cache@^2.0.1:
     rimraf "2.6.3"
     write "1.0.3"
 
+flatpickr@^4.6.6:
+  version "4.6.9"
+  resolved "https://registry.yarnpkg.com/flatpickr/-/flatpickr-4.6.9.tgz#9a13383e8a6814bda5d232eae3fcdccb97dc1499"
+  integrity sha512-F0azNNi8foVWKSF+8X+ZJzz8r9sE1G4hl06RyceIaLvyltKvDl6vqk9Lm/6AUUCi5HWaIjiUbk7UpeE/fOXOpw==
+
 flatted@^2.0.0:
   version "2.0.1"
   resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.1.tgz#69e57caa8f0eacbc281d2e2cb458d46fdb449e08"
@@ -10305,6 +10310,13 @@ vue-eslint-parser@^5.0.0:
     esquery "^1.0.1"
     lodash "^4.17.11"
 
+vue-flatpickr-component@^8.1.2:
+  version "8.1.6"
+  resolved "https://registry.yarnpkg.com/vue-flatpickr-component/-/vue-flatpickr-component-8.1.6.tgz#8fb25dc72946ceb1ab005b871a8151461c0883f6"
+  integrity sha512-RUu/M/1lbuzQT+U3yP7O5/M2EIizr9vXLXqSc1eFOvCT3AHurQg8+iO02rjW+2l78Kit8pCNAUvHw7eexws6hw==
+  dependencies:
+    flatpickr "^4.6.6"
+
 vue-functional-data-merge@^3.1.0:
   version "3.1.0"
   resolved "https://registry.yarnpkg.com/vue-functional-data-merge/-/vue-functional-data-merge-3.1.0.tgz#08a7797583b7f35680587f8a1d51d729aa1dc657"