airavata-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From machris...@apache.org
Subject [airavata-django-portal] 01/02: AIRAVATA-2598 Simplified JS model creation
Date Sun, 10 Dec 2017 19:14:11 GMT
This is an automated email from the ASF dual-hosted git repository.

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

commit e6f5c4c36d6b3920338e1d9c0b82a1f4e51f86f9
Author: Marcus Christie <machrist@iu.edu>
AuthorDate: Thu Dec 7 14:03:59 2017 -0500

    AIRAVATA-2598 Simplified JS model creation
---
 django_airavata/apps/api/package.json              |  3 +-
 django_airavata/apps/api/serializers.py            |  9 ++-
 .../api/static/django_airavata_api/js/index.js     |  8 +++
 .../js/models/ApplicationInterfaceDefinition.js    | 34 ++++++++++++
 .../js/models/ApplicationModule.js                 | 32 +++--------
 .../django_airavata_api/js/models/BaseModel.js     | 64 ++++++++++++++++++++--
 .../django_airavata_api/js/models/Experiment.js    | 32 ++++-------
 .../js/models/InputDataObjectType.js               | 24 ++++++++
 .../js/models/OutputDataTypeObject.js              | 22 ++++++++
 .../django_airavata_api/js/models/Project.js       | 33 +++++------
 .../js/services/ApplicationInterfaceService.js     | 29 ++++++++++
 .../js/services/ApplicationModuleService.js        |  2 +-
 .../js/services/ProjectService.js                  |  2 +-
 .../js/views/ProjectButtonNew.vue                  |  2 +-
 14 files changed, 221 insertions(+), 75 deletions(-)

diff --git a/django_airavata/apps/api/package.json b/django_airavata/apps/api/package.json
index ba3df2c..b31e3c8 100644
--- a/django_airavata/apps/api/package.json
+++ b/django_airavata/apps/api/package.json
@@ -6,7 +6,8 @@
   "private": true,
   "main": "./static/django_airavata_api/dist/index.js",
   "scripts": {
-    "build": "babel static/django_airavata_api/js -d static/django_airavata_api/dist"
+    "build": "babel static/django_airavata_api/js -d static/django_airavata_api/dist",
+    "watch": "babel static/django_airavata_api/js --watch -d static/django_airavata_api/dist"
   },
   "dependencies": {},
   "devDependencies": {
diff --git a/django_airavata/apps/api/serializers.py b/django_airavata/apps/api/serializers.py
index 6e5c63e..7f10532 100644
--- a/django_airavata/apps/api/serializers.py
+++ b/django_airavata/apps/api/serializers.py
@@ -1,4 +1,3 @@
-from abc import ABC
 
 from airavata.model.experiment.ttypes import ExperimentModel
 from airavata.model.workspace.ttypes import Project
@@ -15,6 +14,10 @@ from rest_framework import serializers
 import datetime
 import copy
 from urllib.parse import quote
+import logging
+
+
+log = logging.getLogger(__name__)
 
 
 class FullyEncodedHyperlinkedIdentityField(serializers.HyperlinkedIdentityField):
@@ -80,13 +83,13 @@ class GatewayIdDefaultField(serializers.CharField):
 
 class ProjectSerializer(serializers.Serializer):
     url = FullyEncodedHyperlinkedIdentityField(view_name='django_airavata_api:project-detail',
lookup_field='projectID', lookup_url_kwarg='project_id')
-    projectID = serializers.CharField(default=Project.thrift_spec[1][4])
+    projectID = serializers.CharField(default=Project.thrift_spec[1][4], read_only=True)
     name = serializers.CharField(required=True)
     description = serializers.CharField(allow_null=True)
     owner = GatewayUsernameDefaultField()
     gatewayId = GatewayIdDefaultField()
     experiments = FullyEncodedHyperlinkedIdentityField(view_name='django_airavata_api:project-experiments',
lookup_field='projectID', lookup_url_kwarg='project_id')
-    creationTime = UTCPosixTimestampDateTimeField()
+    creationTime = UTCPosixTimestampDateTimeField(allow_null=True)
 
     def create(self, validated_data):
         return Project(**validated_data)
diff --git a/django_airavata/apps/api/static/django_airavata_api/js/index.js b/django_airavata/apps/api/static/django_airavata_api/js/index.js
index 77bb393..2e74456 100644
--- a/django_airavata/apps/api/static/django_airavata_api/js/index.js
+++ b/django_airavata/apps/api/static/django_airavata_api/js/index.js
@@ -1,8 +1,12 @@
 
+import ApplicationInterfaceDefinition from './models/ApplicationInterfaceDefinition'
 import ApplicationModule from './models/ApplicationModule'
 import Experiment from './models/Experiment'
+import InputDataObjectType from './models/InputDataObjectType'
+import OutputDataTypeObject from './models/OutputDataTypeObject'
 import Project from './models/Project'
 
+import ApplicationInterfaceService from './services/ApplicationInterfaceService'
 import ApplicationModuleService from './services/ApplicationModuleService'
 import ProjectService from './services/ProjectService'
 
@@ -10,12 +14,16 @@ import FetchUtils from './utils/FetchUtils'
 import PaginationIterator from './utils/PaginationIterator'
 
 exports.models = {
+    ApplicationInterfaceDefinition,
     ApplicationModule,
     Experiment,
+    InputDataObjectType,
+    OutputDataTypeObject,
     Project,
 }
 
 exports.services = {
+    ApplicationInterfaceService,
     ApplicationModuleService,
     ProjectService,
 }
diff --git a/django_airavata/apps/api/static/django_airavata_api/js/models/ApplicationInterfaceDefinition.js
b/django_airavata/apps/api/static/django_airavata_api/js/models/ApplicationInterfaceDefinition.js
new file mode 100644
index 0000000..086ba2c
--- /dev/null
+++ b/django_airavata/apps/api/static/django_airavata_api/js/models/ApplicationInterfaceDefinition.js
@@ -0,0 +1,34 @@
+import BaseModel from './BaseModel'
+import InputDataObjectType from './InputDataObjectType'
+import OutputDataObjectType from './OutputDataTypeObject'
+
+
+const FIELDS = [
+    'applicationInterfaceId',
+    'applicationName',
+    'applicationDescription',
+    {
+        name: 'applicationModules',
+        type: 'string',
+        list: true,
+    },
+    {
+        name: 'applicationInputs',
+        type: InputDataObjectType,
+        list: true,
+    },
+    {
+        name: 'applicationOutputs',
+        type: OutputDataObjectType,
+        list: true,
+    },
+    'archiveWorkingDirectory',
+    'hasOptionalFileInputs',
+];
+
+export default class ApplicationInterfaceDefinition extends BaseModel {
+
+    constructor(data = {}) {
+        super(FIELDS, data);
+    }
+}
diff --git a/django_airavata/apps/api/static/django_airavata_api/js/models/ApplicationModule.js
b/django_airavata/apps/api/static/django_airavata_api/js/models/ApplicationModule.js
index 9c93db7..5ea8e35 100644
--- a/django_airavata/apps/api/static/django_airavata_api/js/models/ApplicationModule.js
+++ b/django_airavata/apps/api/static/django_airavata_api/js/models/ApplicationModule.js
@@ -1,30 +1,14 @@
 import BaseModel from './BaseModel';
 
+const FIELDS = [
+    'appModuleId',
+    'appModuleName',
+    'appModuleVersion',
+    'appModuleDescription',
+];
+
 export default class ApplicationModule extends BaseModel {
     constructor(data = {}) {
-        super(data);
-        this.appModuleId = null;
-        this.appModuleName = null;
-        this.appModuleVersion = null;
-        this.appModuleDescription = null;
-        this.copyData(data);
-    }
-
-    validateForCreate() {
-        if (this.appModuleName === null || this.appModuleName.trim() === "") {
-            return {
-                name: ["Please provide a name."]
-            }
-        }
-        return null;
-    }
-
-    toJSONForCreate() {
-        // Remaining fields just get defaulted
-        return JSON.stringify(this, ["appModuleName", "appModuleVersion", "appModuleDescription"]);
-    }
-
-    toJSONForUpdate() {
-        return JSON.stringify(this, ["appModuleId", "appModuleName", "appModuleVersion",
"appModuleDescription"]);
+        super(FIELDS, data);
     }
 }
diff --git a/django_airavata/apps/api/static/django_airavata_api/js/models/BaseModel.js b/django_airavata/apps/api/static/django_airavata_api/js/models/BaseModel.js
index f34365d..49afcb9 100644
--- a/django_airavata/apps/api/static/django_airavata_api/js/models/BaseModel.js
+++ b/django_airavata/apps/api/static/django_airavata_api/js/models/BaseModel.js
@@ -1,10 +1,66 @@
 
+// TODO: document
 export default class BaseModel {
-    constructor(data = {}) {
+
+    /**
+     * Create and optionally populate fields of a model instance.
+     * - fields: an Array of field definitions. Each field definition can either
+     *   be just the name of the field as a string, or an object with the
+     *   following properties:
+     *   - name (required)
+     *   - type (required: one of 'string', 'boolean', 'number', 'date', or a class reference)
+     *   - list (optional, boolean)
+     *   - default (optional, the default value to be used, if not specified then null is
used)
+     * - data: a data object, typically a deserialized JSON response
+     */
+    constructor(fields, data={}){
+        fields.forEach(fieldDefinition => {
+            if (typeof fieldDefinition === 'string') {
+                this[fieldDefinition] = this.convertSimpleField(data[fieldDefinition], null);
+            } else { // fieldDefinition must be an object
+                let fieldName = fieldDefinition.name;
+                let fieldType = fieldDefinition.type;
+                let fieldIsList = typeof fieldDefinition.list !== 'undefined' ? fieldDefinition.list
: false;
+                let fieldDefault = typeof fieldDefinition.default !== 'undefined' ? fieldDefinition.default
: null;
+                let fieldValue = data[fieldName];
+                if (fieldIsList) {
+                    this[fieldName] = fieldValue ? fieldValue.map(item => this.convertField(fieldType,
item, fieldDefault)) : fieldDefault;
+                } else {
+                    this[fieldName] = this.convertField(fieldType, fieldValue, fieldDefault);
+                }
+            }
+        });
     }
-    copyData(data) {
-        for (let prop in this) {
-            this[prop] = data[prop] || null;
+
+    convertField(fieldType, fieldValue, fieldDefault) {
+        if (fieldType === 'string' || fieldType === 'boolean' || fieldType === 'number')
{
+            return this.convertSimpleField(fieldValue, fieldDefault);
+        } else if (fieldType === 'date') {
+            return this.convertDateField(fieldValue, fieldDefault);
+        } else if (typeof fieldType === 'function') {
+            // Assume that it is another BaseModel class
+            return this.convertModelField(fieldType, fieldValue, fieldDefault);
         }
     }
+
+    convertSimpleField(fieldValue, fieldDefault) {
+        return typeof fieldValue !== 'undefined' ? fieldValue : fieldDefault;
+    }
+
+    convertDateField(fieldValue, fieldDefault) {
+        return typeof fieldValue !== 'undefined' ? new Date(fieldValue) : fieldDefault;
+    }
+
+    convertModelField(modelClass, fieldValue, fieldDefault) {
+        return typeof fieldValue !== 'undefined' ? new modelClass(fieldValue) : fieldDefault;
+    }
+
+    /**
+     * Override to provide validation. If there are validation errors this
+     * method should return a dictionary where keys are property names and
+     * values are an array of error messages.
+     */
+    validate() {
+        return null;
+    }
 }
diff --git a/django_airavata/apps/api/static/django_airavata_api/js/models/Experiment.js b/django_airavata/apps/api/static/django_airavata_api/js/models/Experiment.js
index db85395..b47e7a6 100644
--- a/django_airavata/apps/api/static/django_airavata_api/js/models/Experiment.js
+++ b/django_airavata/apps/api/static/django_airavata_api/js/models/Experiment.js
@@ -1,27 +1,17 @@
 import BaseModel from './BaseModel';
 
+const FIELDS = [
+    'experimentId',
+    'projectId',
+    'gatewayId',
+    'experimentType',
+    'userName',
+    'experimentName',
+    'description',
+];
+
 export default class Experiment extends BaseModel {
     constructor(data = {}) {
-        super(data);
-        this.experimentId = null;
-        this.projectId = null;
-        this.gatewayId = null;
-        this.experimentType = null;
-        this.userName = null;
-        this.experimentName = null;
-        this.description = null;
-        this.copyData(data);
-    }
-
-    validateForCreate() {
-    }
-
-    validateForUpdate() {
-    }
-
-    toJSONForCreate() {
-    }
-
-    toJSONForUpdate() {
+        super(FIELDS, data);
     }
 }
diff --git a/django_airavata/apps/api/static/django_airavata_api/js/models/InputDataObjectType.js
b/django_airavata/apps/api/static/django_airavata_api/js/models/InputDataObjectType.js
new file mode 100644
index 0000000..601fdd0
--- /dev/null
+++ b/django_airavata/apps/api/static/django_airavata_api/js/models/InputDataObjectType.js
@@ -0,0 +1,24 @@
+
+import BaseModel from './BaseModel';
+
+const FIELDS = [
+    'name',
+    'value',
+    'type',
+    'applicationArgument',
+    'standardInput',
+    'userFriendlyDescription',
+    'metaData',
+    'inputOrder',
+    'isRequired',
+    'requiredToAddedToCommandLine',
+    'dataStaged',
+    'storageResourceId',
+    'isReadOnly',
+];
+
+export default class InputDataObjectType extends BaseModel {
+    constructor(data = {}) {
+        super(FIELDS, data);
+    }
+}
diff --git a/django_airavata/apps/api/static/django_airavata_api/js/models/OutputDataTypeObject.js
b/django_airavata/apps/api/static/django_airavata_api/js/models/OutputDataTypeObject.js
new file mode 100644
index 0000000..f4d6d6b
--- /dev/null
+++ b/django_airavata/apps/api/static/django_airavata_api/js/models/OutputDataTypeObject.js
@@ -0,0 +1,22 @@
+
+import BaseModel from './BaseModel';
+
+const FIELDS = [
+    'name',
+    'value',
+    'type',
+    'applicationArgument',
+    'isRequired',
+    'requiredToAddedToCommandLine',
+    'dataMovement',
+    'location',
+    'searchQuery',
+    'outputStreaming',
+    'storageResourceId',
+];
+
+export default class OutputDataObjectType extends BaseModel {
+    constructor(data = {}) {
+        super(FIELDS, data);
+    }
+}
diff --git a/django_airavata/apps/api/static/django_airavata_api/js/models/Project.js b/django_airavata/apps/api/static/django_airavata_api/js/models/Project.js
index 447b59e..d6e9c99 100644
--- a/django_airavata/apps/api/static/django_airavata_api/js/models/Project.js
+++ b/django_airavata/apps/api/static/django_airavata_api/js/models/Project.js
@@ -1,19 +1,23 @@
 import BaseModel from './BaseModel';
 
+const FIELDS = [
+    'projectID',
+    'name',
+    'description',
+    'owner',
+    'gatewayId',
+    {
+        name: 'creationTime',
+        type: 'date'
+    },
+];
+
 export default class Project extends BaseModel {
     constructor(data = {}) {
-        super(data);
-        this.projectID = null;
-        this.name = null;
-        this.description = null;
-        this.owner = null;
-        this.gatewayId = null;
-        // TODO: convert to Date object here instead of doing this in views
-        this.creationTime = null;
-        this.copyData(data);
+        super(FIELDS, data);
     }
 
-    validateForCreate() {
+    validate() {
         if (this.name === null || this.name.trim() === "") {
             return {
                 name: ["Please provide a name."]
@@ -21,13 +25,4 @@ export default class Project extends BaseModel {
         }
         return null;
     }
-
-    toJSONForCreate() {
-        // Remaining fields just get defaulted
-        return JSON.stringify(this, ["name", "description"]);
-    }
-
-    toJSONForUpdate() {
-        return JSON.stringify(this, ["projectID", "name", "description"]);
-    }
 }
\ No newline at end of file
diff --git a/django_airavata/apps/api/static/django_airavata_api/js/services/ApplicationInterfaceService.js
b/django_airavata/apps/api/static/django_airavata_api/js/services/ApplicationInterfaceService.js
new file mode 100644
index 0000000..9c83752
--- /dev/null
+++ b/django_airavata/apps/api/static/django_airavata_api/js/services/ApplicationInterfaceService.js
@@ -0,0 +1,29 @@
+
+import ApplicationInterfaceDefinition from '../models/ApplicationInterfaceDefinition'
+import FetchUtils from '../utils/FetchUtils'
+
+class ApplicationIterfaceService {
+    list(data = null) {
+        // TODO
+    }
+
+    create(project) {
+        // TODO
+    }
+
+    update() {
+        // TODO
+    }
+
+    get(appInterfaceId) {
+        // TODO
+    }
+
+    getForAppModuleId(appModuleId) {
+        return FetchUtils.get('/api/applications/' + encodeURIComponent(appModuleId) + '/application_interface/')
+            .then(json => new ApplicationInterfaceDefinition(json))
+    }
+}
+
+// Export as a singleton
+export default new ApplicationIterfaceService();
diff --git a/django_airavata/apps/api/static/django_airavata_api/js/services/ApplicationModuleService.js
b/django_airavata/apps/api/static/django_airavata_api/js/services/ApplicationModuleService.js
index f433412..a3ab350 100644
--- a/django_airavata/apps/api/static/django_airavata_api/js/services/ApplicationModuleService.js
+++ b/django_airavata/apps/api/static/django_airavata_api/js/services/ApplicationModuleService.js
@@ -21,7 +21,7 @@ class ApplicationModuleService {
     }
 
     get(appModuleId) {
-        return FetchUtils.get('/api/applications/' + encodeURIComponent(appModuleId))
+        return FetchUtils.get('/api/applications/' + encodeURIComponent(appModuleId) + '/')
             .then(json => new ApplicationModule(json))
     }
 }
diff --git a/django_airavata/apps/api/static/django_airavata_api/js/services/ProjectService.js
b/django_airavata/apps/api/static/django_airavata_api/js/services/ProjectService.js
index 598e4d6..c78c5a5 100644
--- a/django_airavata/apps/api/static/django_airavata_api/js/services/ProjectService.js
+++ b/django_airavata/apps/api/static/django_airavata_api/js/services/ProjectService.js
@@ -25,7 +25,7 @@ class ProjectService {
     }
 
     create(project) {
-        return FetchUtils.post('/api/projects/', project.toJSONForCreate())
+        return FetchUtils.post('/api/projects/', JSON.stringify(project))
             .then(result => new Project(result));
     }
 
diff --git a/django_airavata/apps/workspace/static/django_airavata_workspace/js/views/ProjectButtonNew.vue
b/django_airavata/apps/workspace/static/django_airavata_workspace/js/views/ProjectButtonNew.vue
index 6a2fb18..9fb7fa9 100644
--- a/django_airavata/apps/workspace/static/django_airavata_workspace/js/views/ProjectButtonNew.vue
+++ b/django_airavata/apps/workspace/static/django_airavata_workspace/js/views/ProjectButtonNew.vue
@@ -69,7 +69,7 @@ export default {
     },
     computed: {
         newProjectValidationData: function() {
-            return this.userBeginsInput ? this.newProject.validateForCreate() : null;
+            return this.userBeginsInput ? this.newProject.validate() : null;
         },
         newProjectNameState: function() {
             if (this.newProjectServerValidationData && 'name' in this.newProjectServerValidationData)
{

-- 
To stop receiving notification emails like this one, please contact
"commits@airavata.apache.org" <commits@airavata.apache.org>.

Mime
View raw message