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 2466120a64d6fc68350747536776f1f0a2184e1a Author: Marcus Christie <[email protected]> AuthorDate: Thu Aug 30 20:05:43 2018 -0400 AIRAVATA-2876 app input field editor --- .../applications/ApplicationInputFieldEditor.vue | 86 +++++++++++++++++++ .../applications/ApplicationInterfaceEditor.vue | 49 ++++++----- .../src/components/commons/vmodel_mixin.js | 29 ++++++- .../api/static/django_airavata_api/js/index.js | 96 +++++++++++----------- .../django_airavata_api/js/models/DataType.js | 14 ++-- 5 files changed, 195 insertions(+), 79 deletions(-) diff --git a/django_airavata/apps/admin/static/django_airavata_admin/src/components/applications/ApplicationInputFieldEditor.vue b/django_airavata/apps/admin/static/django_airavata_admin/src/components/applications/ApplicationInputFieldEditor.vue new file mode 100644 index 0000000..085fa8b --- /dev/null +++ b/django_airavata/apps/admin/static/django_airavata_admin/src/components/applications/ApplicationInputFieldEditor.vue @@ -0,0 +1,86 @@ +<template> + <b-card header="Input Field"> + <b-form-group label="Name" :label-for="id+'-name'"> + <b-form-input :id="id+'-name'" type="text" v-model="data.name" required></b-form-input> + </b-form-group> + <b-form-group label="Initial Value" :label-for="id+'-value'"> + <b-form-input :id="id+'-value'" type="text" v-model="data.value"></b-form-input> + </b-form-group> + <b-form-group label="Type" :label-for="id+'-type'"> + <b-form-select :id="id+'-type'" v-model="data.type" :options="inputTypeOptions" /> + </b-form-group> + <b-form-group label="Application Argument" :label-for="id+'-argument'"> + <b-form-input :id="id+'-argument'" type="text" v-model="data.applicationArgument"></b-form-input> + </b-form-group> + <div class="d-flex"> + <b-form-group class="flex-fill" label="Standard Input" :label-for="id+'-standard-input'"> + <b-form-radio-group :id="id+'-standard-input'" v-model="data.standardInput" :options="trueFalseOptions"> + </b-form-radio-group> + </b-form-group> + <b-form-group class="flex-fill" label="Read Only" :label-for="id+'-read-only'"> + <b-form-radio-group :id="id+'-read-only'" v-model="data.isReadOnly" :options="trueFalseOptions"> + </b-form-radio-group> + </b-form-group> + </div> + <b-form-group label="User Friendly Description" :label-for="id+'-user-friendly-description'"> + <b-form-textarea :id="id+'-user-friendly-description'" v-model="data.userFriendlyDescription" :rows="3" /> + </b-form-group> + <div class="d-flex"> + <b-form-group class="flex-fill" label="Data is staged" :label-for="id+'-data-staged'"> + <b-form-radio-group :id="id+'-data-staged'" v-model="data.dataStaged" :options="trueFalseOptions"> + </b-form-radio-group> + </b-form-group> + <b-form-group class="flex-fill" label="Required" :label-for="id+'-required'"> + <b-form-radio-group :id="id+'-required'" v-model="data.isRequired" :options="trueFalseOptions"> + </b-form-radio-group> + </b-form-group> + </div> + <b-form-group class="flex-fill" label="Required on Command Line" :label-for="id+'-required-command-line'"> + <b-form-radio-group :id="id+'-required-command-line'" v-model="data.requiredToAddedToCommandLine" :options="trueFalseOptions"> + </b-form-radio-group> + </b-form-group> + </b-card> +</template> + +<script> +import { models } from "django-airavata-api"; +import vmodel_mixin from "../commons/vmodel_mixin"; + +export default { + name: "application-input-field-editor", + mixins: [vmodel_mixin], + props: { + value: { + type: models.InputDataObjectType + }, + id: { + required: true + } + }, + computed: { + inputTypeOptions() { + return models.DataType.values.map(dataType => { + return { + value: dataType, + text: dataType.name + }; + }); + }, + trueFalseOptions() { + return [{ text: "True", value: true }, { text: "False", value: false }]; + } + }, + methods: { + copyValue() { + return this.value.clone(); + } + } +}; +</script> + +<style scoped> +.flex-fill { + flex: 1; +} +</style> + diff --git a/django_airavata/apps/admin/static/django_airavata_admin/src/components/applications/ApplicationInterfaceEditor.vue b/django_airavata/apps/admin/static/django_airavata_admin/src/components/applications/ApplicationInterfaceEditor.vue index 1618c0c..be490ba 100644 --- a/django_airavata/apps/admin/static/django_airavata_admin/src/components/applications/ApplicationInterfaceEditor.vue +++ b/django_airavata/apps/admin/static/django_airavata_admin/src/components/applications/ApplicationInterfaceEditor.vue @@ -10,21 +10,32 @@ <div class="row"> <div class="col"> <b-form-group label="Enable Archiving Working Directory" label-for="archive-directory"> - <b-form-radio-group id="archive-directory" - v-model="appInterface.archiveWorkingDirectory" - :options="archiveWorkingDirectoryOptions" - @input="emitChanged"> + <b-form-radio-group id="archive-directory" v-model="data.archiveWorkingDirectory" :options="trueFalseOptions"> + </b-form-radio-group> + </b-form-group> + </div> + <div class="col"> + <b-form-group label="Enable Optional File Inputs" label-for="optional-file-inputs"> + <b-form-radio-group id="optional-file-inputs" v-model="data.hasOptionalFileInputs" :options="trueFalseOptions"> </b-form-radio-group> </b-form-group> </div> </div> <div class="row"> <div class="col"> + <h1 class="h5 mb-4"> + Input Fields + </h1> + <application-input-field-editor v-for="(input, index) in data.applicationInputs" :value="input" :key="index" :id="'app-input-'+index" @input="updatedInput($event, index)" /> + </div> + </div> + <div class="row"> + <div class="col"> <b-button variant="primary" @click="save"> - Save + Save </b-button> <b-button variant="secondary" @click="cancel"> - Cancel + Cancel </b-button> </div> </div> @@ -33,39 +44,35 @@ <script> import { models } from "django-airavata-api"; +import vmodel_mixin from "../commons/vmodel_mixin"; +import ApplicationInputFieldEditor from "./ApplicationInputFieldEditor.vue"; export default { name: "application-interface-editor", + mixins: [vmodel_mixin], props: { value: { - type: models.ApplicationInterfaceDefinition, - required: true + type: models.ApplicationInterfaceDefinition } }, - data: function() { - return { - appInterface: this.value.clone() - }; + components: { + ApplicationInputFieldEditor }, computed: { - archiveWorkingDirectoryOptions() { + trueFalseOptions() { return [{ text: "True", value: true }, { text: "False", value: false }]; } }, methods: { - emitChanged() { - this.$emit("input", this.appInterface); - }, save() { this.$emit("save"); }, cancel() { this.$emit("cancel"); - } - }, - watch: { - value: function(newValue) { - this.appInterface = newValue.clone(); + }, + updatedInput(newValue, index) { + Object.assign(this.data.applicationInputs[index], newValue); + this.$emit("input", this.data); } } }; diff --git a/django_airavata/apps/admin/static/django_airavata_admin/src/components/commons/vmodel_mixin.js b/django_airavata/apps/admin/static/django_airavata_admin/src/components/commons/vmodel_mixin.js index 00a29ad..94e6834 100644 --- a/django_airavata/apps/admin/static/django_airavata_admin/src/components/commons/vmodel_mixin.js +++ b/django_airavata/apps/admin/static/django_airavata_admin/src/components/commons/vmodel_mixin.js @@ -1,15 +1,36 @@ +import { models } from "django-airavata-api"; + export default { watch: { data: { - handler: function (newValue) { - this.$emit('input', newValue) + handler: function (newValue, oldValue) { + // Only emit 'input' for objects when one of their deep properties has + // changed to prevent infinite loop since 'data' is recloned whenever + // 'value' changes + if (typeof this.value === 'object' && newValue === oldValue) { + this.$emit('input', newValue) + } else if (typeof this.value !== 'object' && newValue !== oldValue) { + this.$emit('input', newValue) + } }, - deep:true + deep: true + }, + value: function (newValue) { + this.data = this.copyValue(newValue); + } + }, + methods: { + copyValue() { + if (this.value instanceof models.BaseModel) { + return this.value.clone(); + } else if (typeof this.value === 'object') { + return JSON.parse(JSON.stringify(this.value)); + } } }, data: function () { return { - data: this.value + data: this.copyValue(this.value), } }, props: { 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 324cdd9..3d00054 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 @@ -4,6 +4,7 @@ import UnhandledErrorDisplayList from './errors/UnhandledErrorDisplayList' import ApplicationInterfaceDefinition from './models/ApplicationInterfaceDefinition' import ApplicationModule from './models/ApplicationModule' +import BaseModel from './models/BaseModel' import BatchQueue from './models/BatchQueue' import BatchQueueResourcePolicy from './models/BatchQueueResourcePolicy' import ComputeResourcePolicy from './models/ComputeResourcePolicy' @@ -46,60 +47,61 @@ import PaginationIterator from './utils/PaginationIterator' import StringUtils from './utils/StringUtils' exports.errors = { - UnhandledError, - UnhandledErrorDispatcher, - UnhandledErrorDisplayList, + UnhandledError, + UnhandledErrorDispatcher, + UnhandledErrorDisplayList, } exports.models = { - ApplicationInterfaceDefinition, - ApplicationModule, - BatchQueue, - BatchQueueResourcePolicy, - ComputeResourcePolicy, - DataType, - Experiment, - ExperimentState, - FullExperiment, - Group, - GroupComputeResourcePreference, - GroupPermission, - GroupResourceProfile, - InputDataObjectType, - OutputDataObjectType, - Project, - ResourcePermissionType, - SharedEntity, - SummaryType, - UserPermission, + ApplicationInterfaceDefinition, + ApplicationModule, + BaseModel, + BatchQueue, + BatchQueueResourcePolicy, + ComputeResourcePolicy, + DataType, + Experiment, + ExperimentState, + FullExperiment, + Group, + GroupComputeResourcePreference, + GroupPermission, + GroupResourceProfile, + InputDataObjectType, + OutputDataObjectType, + Project, + ResourcePermissionType, + SharedEntity, + SummaryType, + UserPermission, } exports.services = { - ApplicationDeploymentService, - ApplicationInterfaceService: ServiceFactory.service("ApplicationInterfaces"), - ApplicationModuleService: ServiceFactory.service("ApplicationModules"), - CredentialSummaryService: ServiceFactory.service("CredentialSummaries"), - ExperimentService, - ExperimentSearchService, - FullExperimentService, - ProjectService, - GroupService, - GroupResourceProfileService: ServiceFactory.service("GroupResourceProfiles"), - UserProfileService, - ComputeResourceService: ServiceFactory.service("ComputeResources"), - CloudJobSubmissionService, - GlobusJobSubmissionService, - LocaJobSubmissionService, - SshJobSubmissionService, - UnicoreJobSubmissionService, - GridFTPDataMovementService, - SCPDataMovementService, - UnicoreDataMovementService, - ServiceFactory, + ApplicationDeploymentService, + ApplicationInterfaceService: ServiceFactory.service("ApplicationInterfaces"), + ApplicationModuleService: ServiceFactory.service("ApplicationModules"), + CredentialSummaryService: ServiceFactory.service("CredentialSummaries"), + ExperimentService, + ExperimentSearchService, + FullExperimentService, + ProjectService, + GroupService, + GroupResourceProfileService: ServiceFactory.service("GroupResourceProfiles"), + UserProfileService, + ComputeResourceService: ServiceFactory.service("ComputeResources"), + CloudJobSubmissionService, + GlobusJobSubmissionService, + LocaJobSubmissionService, + SshJobSubmissionService, + UnicoreJobSubmissionService, + GridFTPDataMovementService, + SCPDataMovementService, + UnicoreDataMovementService, + ServiceFactory, } exports.utils = { - FetchUtils, - PaginationIterator, - StringUtils, + FetchUtils, + PaginationIterator, + StringUtils, } diff --git a/django_airavata/apps/api/static/django_airavata_api/js/models/DataType.js b/django_airavata/apps/api/static/django_airavata_api/js/models/DataType.js index f8c229d..c981b3c 100644 --- a/django_airavata/apps/api/static/django_airavata_api/js/models/DataType.js +++ b/django_airavata/apps/api/static/django_airavata_api/js/models/DataType.js @@ -3,11 +3,11 @@ import BaseEnum from './BaseEnum' export default class DataType extends BaseEnum { } DataType.init([ - "STRING", - "INTEGER", - "FLOAT", - "URI", - "URI_COLLECTION", - "STDOUT", - "STDERR", + "STRING", + "INTEGER", + "FLOAT", + "URI", + "URI_COLLECTION", + "STDOUT", + "STDERR", ]);
