| <!-- |
| /** |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| --> |
| <form name="processForm" class="mt10" novalidate id="processFormGeneralStep"> |
| |
| <div class="col-xs-24"> |
| <label class="light" tooltip="process.name">Process Name<mandatory-field></mandatory-field></label> |
| </div> |
| |
| <div class="col-xs-6"> |
| <input type="text" class="form-control" ng-keydown="validations.acceptNoSpaces($event)" |
| check-name="{type:'process', check:!editingMode}" ng-class="{fakeInvalid:!validations.nameAvailable}" |
| ng-disabled="editingMode" id="entityNameField" ng-model="process.name" |
| ng-required="true" ng-maxlength="100" ng-pattern="validations.patterns.name"/> |
| </div> |
| |
| <div class="col-xs-24"> |
| <label class="light">Tags</label> |
| </div> |
| |
| <div id="tagsSection" class="col-xs-12"> |
| <div ng-repeat="tag in process.tags track by $index"> |
| <div class="row dynamic-table-spacer"> |
| <div class="col-xs-8"> |
| <input type="text" class="form-control" ng-model="tag.key" placeholder="key" |
| validation-optional-message="{{validations.messages.key}}" |
| ng-pattern="validations.patterns.alpha" ng-required="tag.value"/> |
| </div> |
| <div class="col-xs-8"> |
| <input type="text" class="form-control" ng-model="tag.value" placeholder="value" |
| validation-optional-message="{{validations.messages.value}}" |
| ng-pattern="validations.patterns.alpha" ng-required="tag.key"/> |
| </div> |
| <div class="col-xs-8"> |
| <button type="button" class="btn btn-default btn-xs" ng-click="removeTag($index)" ng-if="!$first || !$last"> |
| <span class="entypo minus"></span> delete |
| </button> |
| <button type="button" class="btn btn-default btn-xs" ng-click="addTag()" ng-if="$last"> |
| <span class="entypo plus"></span> ADD |
| </button> |
| </div> |
| </div> |
| </div> |
| </div> |
| |
| <div class="col-xs-24"> |
| <label>Details</label> |
| </div> |
| |
| <div class="col-xs-5 plr0px"> |
| <div class="col-xs-24"> |
| <label class="light" tooltip="process.workflow.engine">Engine<mandatory-field></mandatory-field></label> |
| <select ng-model="process.workflow.engine" |
| class="form-control padding0" |
| ng-required="true" |
| validation-message="{{validations.messages.engine}}"> |
| <option value="" disabled selected style='display:none;'>-Select engine-</option> |
| <option value="spark">Spark</option> |
| <option value="oozie">Oozie</option> |
| <option value="pig">Pig</option> |
| <option value="hive">Hive</option> |
| </select> |
| </div> |
| |
| <div class="col-xs-24" ng-show="process.workflow.engine !== 'spark'"> |
| <label class="light" tooltip="process.workflow.name">Workflow Name<mandatory-field></mandatory-field></label> |
| <input type="text" class="form-control" |
| id="workflowNameField" |
| ng-model="process.workflow.name" |
| ng-required="process.workflow.engine !== 'spark'" |
| ng-maxlength="100" |
| ng-pattern="validations.patterns.workflowName" |
| validation-optional-message="{{validations.messages.name}}" /> |
| </div> |
| |
| <div class="col-xs-24"> |
| <label class="light" tooltip="process.workflow.path">Workflow Path<mandatory-field></mandatory-field></label> |
| <input type="text" class="form-control" |
| id="pathField" |
| ng-model="process.workflow.path" |
| ng-required="true" |
| ng-maxlength="200" |
| validation-message="{{validations.messages.path}}" |
| ng-pattern="validations.patterns.path"/> |
| </div> |
| |
| <div class="col-xs-24"> |
| <label class="light">Cluster<mandatory-field></mandatory-field></label> |
| <div ng-repeat="cluster in process.clusters track by $index"> |
| <select ng-model="cluster.name" |
| ng-required="true" |
| ng-change="getSourceDefinition(cluster.name)" |
| class="form-control padding0" |
| validation-message="{{validations.messages.cluster}}"> |
| <option value="" disabled selected style='display:none;'>-Select cluster-</option> |
| <option ng-repeat="clusterItem in clusterList track by $index">{{clusterItem.name}}</option> |
| </select> |
| </div> |
| </div> |
| </div> |
| <div class="col-xs-offset-1 col-xs-6 plr0px" ng-show="process.workflow.engine==='spark'"> |
| <div class="col-xs-24"> |
| <label class="light" tooltip="process.workflow.spark.name">Name<mandatory-field></mandatory-field></label> |
| <input type="text" class="form-control" |
| ng-model="process.workflow.spark.name" |
| ng-required="process.workflow.engine==='spark'" |
| ng-maxlength="100" |
| ng-pattern="validations.patterns.name" |
| validation-optional-message="{{validations.messages.name}}" /> |
| </div> |
| |
| <div class="col-xs-24"> |
| <label class="light" tooltip="process.workflow.spark.application">Application<mandatory-field></mandatory-field></label> |
| <input type="text" class="form-control" |
| ng-model="process.workflow.spark.jar" |
| ng-required="process.workflow.engine==='spark'" /> |
| </div> |
| |
| <div class="col-xs-24"> |
| <label class="light" tooltip="process.workflow.spark.class">Main Class</label> |
| <input type="text" class="form-control" |
| ng-model="process.workflow.spark.class" |
| ng-required="process.workflow.engine==='spark' && !isPython" ng-disabled='isPython'/> |
| </div> |
| |
| <div class="col-xs-12"> |
| <label class="light" tooltip="process.workflow.spark.master">Runs On</label> |
| <select ng-model="process.workflow.spark.master" |
| class="form-control padding0" |
| ng-required="process.workflow.engine==='spark'"> |
| <option value="" disabled selected style='display:none;'>-Select Runs On-</option> |
| <option value="yarn">Yarn</option> |
| <option value="local">Local</option> |
| </select> |
| </div> |
| |
| <div class="col-xs-12 plr0px" ng-if="process.workflow.spark.master === 'yarn'"> |
| <div class="col-xs-24"> |
| <label class="light" tooltip="process.workflow.spark.mode">Mode<mandatory-field></mandatory-field></label> |
| </div> |
| <div class="col-xs-24 pt3px"> |
| <input type="radio" name="sparkMode" value="cluster" ng-model="process.workflow.spark.mode" /> |
| Cluster |
| <input type="radio" name="sparkMode" value="client" ng-model="process.workflow.spark.mode" /> |
| Client |
| </div> |
| </div> |
| |
| <div class="col-xs-24"> |
| <label class="light">Spark Options</label> |
| <input type="text" class="form-control" ng-model="process.workflow.spark.sparkOptions"/> |
| </div> |
| |
| <div class="col-xs-24"> |
| <label class="light">Spark Arguments</label> |
| <input type="text" class="form-control" ng-model="process.workflow.spark.arg"/> |
| </div> |
| </div> |
| |
| <div class="col-xs-offset-1 col-xs-5 plr0px"> |
| <div><label>INPUT(S)</label></div> |
| |
| <div ng-repeat="input in process.inputs track by $index"> |
| <div class="col-xs-24 detailsBox processCluster"> |
| <div class="row"> |
| <div class="col-xs-24"> |
| <label class="light">Name<mandatory-field></mandatory-field></label> |
| <input type="text" class="form-control" |
| ng-class="{firstInput: $index === 0}" |
| validation-message="{{validations.messages.name}}" |
| ng-model="input.name" |
| ng-required="true" |
| ng-maxlength="39" |
| ng-pattern="validations.patterns.inputName"/> |
| </div> |
| </div> |
| |
| <div class="row"> |
| <div class="col-xs-24"> |
| <label class="light">Feed<mandatory-field></mandatory-field></label> |
| <select ng-model="input.feed" ng-required="true" class="col-sm-24 form-control padding0" |
| validation-message="{{validations.messages.feed}}"> |
| <option value="" disabled selected style='display:none;'>-Select feed-</option> |
| <option ng-repeat="feedItem in feedsList track by $index">{{feedItem.name}}</option> |
| </select> |
| </div> |
| </div> |
| |
| <div><label>INSTANCE</label></div> |
| <div class="row"> |
| <div class="col-xs-12"> |
| <label class="light">Start<mandatory-field></mandatory-field></label> |
| <input type="text" class="form-control" validation-message="{{validations.messages.value}}" |
| ng-model="input.start" |
| ng-required="true" |
| ng-maxlength="39"/> |
| </div> |
| <div class="col-xs-12"> |
| <label class="light">End<mandatory-field></mandatory-field></label> |
| <input type="text" class="form-control {{invalidEndDate}}" validation-message="{{validations.messages.value}}" |
| ng-model="input.end" |
| ng-required="true" |
| ng-maxlength="100" |
| on-blur="validateStartEndDate"/> |
| <label ng-show="invalidEndDate" class="custom-danger nameValidationMessage">End should be equal or greater than Start</label> |
| </div> |
| </div> |
| <div class="col-xs-24 mt10"> |
| <button type="button" class="btn btn-default pull-right btn-xs" ng-click="removeInput($index)"> |
| <span class="entypo minus"></span> delete |
| </button> |
| </div> |
| </div> |
| </div> |
| |
| <button type="button" class="btn btn-default btn-xs mt10 mb10 addInputButton" ng-click="addInput()"> |
| <span class="entypo plus"></span> ADD |
| </button> |
| </div> |
| |
| <div class="col-xs-offset-1 col-xs-5 plr0px"> |
| <div><label>OUTPUT(S)</label></div> |
| <div ng-repeat="output in process.outputs track by $index"> |
| <div class="col-xs-24 detailsBox processCluster"> |
| <div class="row"> |
| <div class="col-xs-24"> |
| <label class="light">Name<mandatory-field></mandatory-field></label> |
| <input type="text" |
| ng-class="{firstOutput: $index === 0}" |
| class="form-control" |
| validation-message="{{validations.messages.name}}" |
| ng-model="output.name" |
| ng-required="true" |
| ng-maxlength="39" |
| ng-pattern="validations.patterns.id"/> |
| </div> |
| </div> |
| <div class="row"> |
| <div class="col-xs-24"> |
| <label class="light">Feed<mandatory-field></mandatory-field></label> |
| <select ng-model="output.feed" ng-required="true" class="col-sm-24 form-control padding0" |
| validation-message="{{validations.messages.feed}}" > |
| <option value="" disabled selected style='display:none;'>-Select feed-</option> |
| <option ng-repeat="feedItem in feedsList track by $index">{{feedItem.name}}</option> |
| </select> |
| </div> |
| </div> |
| <div><label class="mt15">INSTANCE</label></div> |
| <div class="row"> |
| <div class="col-xs-24"> |
| <label class="light">Instance<mandatory-field></mandatory-field></label> |
| <input type="text" class="form-control" validation-message="{{validations.messages.value}}" |
| ng-model="output.outputInstance" ng-required="true" ng-maxlength="39"/> |
| </div> |
| </div> |
| <div class="row mt10"> |
| <button type="button" class="btn btn-default pull-right btn-xs" ng-click="removeOutput($index)"> |
| <span class="entypo minus"></span> delete |
| </button> |
| </div> |
| </div> |
| </div> |
| |
| <button type="button" class="btn btn-default btn-xs mb10 mt10" ng-click="addOutput()"> |
| <span class="entypo plus"></span> ADD |
| </button> |
| </div> |
| |
| <div class="col-xs-24"> |
| <label>Run Duration<mandatory-field></mandatory-field></label> |
| </div> |
| <div class="col-xs-24" ng-repeat="cluster in process.clusters track by $index" class="validityBox"> |
| <div class="col-xs-24 plr0px validityBox"> |
| <div class="col-xs-24 plr0px"> |
| <label class="light">Start</label> |
| </div> |
| <div class="plr0px col-xs-2 startDateBox"> |
| <input type="text" |
| name="startDateInput" |
| class="form-control dateInput" |
| placeholder="{{dateFormat | lowercase}}" |
| ng-model="cluster.validity.start.date" |
| simple-date-picker /> |
| </div> |
| <div class="col-xs-3 startTimeBox"> |
| <timepicker ng-change="constructDate()" |
| ng-model="cluster.validity.start.time" |
| hour-step="1" |
| minute-step="1" |
| show-meridian="true"> |
| </timepicker> |
| </div> |
| <label class="col-xs-24 custom-danger validationMessageGral" |
| ng-if="!cluster.validity.start.date"> |
| {{validations.messages.date.empty}} |
| </label> |
| </div> |
| <div class="col-xs-24 plr0px validityBox"> |
| <div class="col-xs-24 plr0px"> |
| <label class="light">End</label> |
| </div> |
| <div class="plr0px col-xs-2 endDateBox"> |
| <input type="text" |
| name="startDateInput" |
| class="form-control dateInput" |
| placeholder="{{dateFormat | lowercase}}" |
| ng-model="cluster.validity.end.date" |
| simple-date-picker /> |
| </div> |
| <div class="col-xs-3 endTimeBox"> |
| <timepicker ng-change="constructDate()" |
| ng-model="cluster.validity.end.time" |
| hour-step="1" |
| minute-step="1" |
| show-meridian="true"> |
| </timepicker> |
| </div> |
| <label class="col-xs-24 custom-danger validationMessageGral" |
| ng-if="!cluster.validity.end.date"> |
| {{validations.messages.date.empty}} |
| </label> |
| </div> |
| </div> |
| |
| <div class="col-xs-24"> |
| <label>Frequency</label> |
| </div> |
| |
| <div class="col-xs-12 plr0px"> |
| <div class="col-xs-24"> |
| <label class="light">Repeat Every<mandatory-field></mandatory-field></label> |
| </div> |
| <div class="col-xs-24 inlineInputsGroup"> |
| <input type="text" class="form-control" validation-message="{{validations.messages.number}}" name="frequencyQuantity" |
| ng-model="process.frequency.quantity" ng-keydown="validations.acceptOnlyNumber($event)" |
| ng-keyup="checkMininumFrequency(process.frequency.quantity,process.frequency.unit, processForm.frequencyQuantity)" |
| id="frequencyQuantity" |
| ng-required="true" |
| ng-pattern="validations.patterns.twoDigits"/> |
| |
| <select ng-model="process.frequency.unit" ng-required="true" |
| ng-change="checkMininumFrequency(process.frequency.quantity,process.frequency.unit, processForm.frequencyQuantity)" |
| validation-message="{{validations.messages.number}}"> |
| <option selected value="minutes">minutes</option> |
| <option value="hours">hours</option> |
| <option value="days">days</option> |
| <option value="months">months</option> |
| </select> |
| <div class="col-xs-24 custom-danger" ng-if="!isFrequencyValid">{{validations.messages.frequency.minimum}}</div> |
| </div> |
| <div class="col-xs-24"> |
| <label class="light" tooltip="process.properties.timezone">Timezone<mandatory-field></mandatory-field></label> |
| </div> |
| <div class="col-xs-18"> |
| <time-zone-select ng-model="process.timezone" id="timeZoneSelect" required="true"> |
| </time-zone-select> |
| </div> |
| </div> |
| |
| <div class="col-xs-24 advancedOption" ng-click="expandOptions = !expandOptions" id="processAdvancedOption"> |
| <label class="mt15 pointer blink-success">ADVANCED OPTIONS</label> |
| <i class="glyphicon glyphicon-chevron-down mt15" ng-if="!expandOptions"></i> |
| <i class="glyphicon glyphicon-chevron-up mt15" ng-if="expandOptions"></i> |
| </div> |
| |
| <div id="advancedOptionsBox" class="col-xs-24 plr0px" ng-class="{expanded:expandOptions}"> |
| <div class="col-xs-24"><label>Retry Policy</label></div> |
| <div class="col-xs-24 plr0px"> |
| <div class="col-xs-4 plr0px"> |
| <div class="col-xs-24"> |
| <label class="light" tooltip="process.properties.retryPolicy" tooltip-position="up"> |
| Type |
| </label> |
| </div> |
| <div class="col-xs-24"> |
| <select ng-model="process.retry.policy" ng-required="true" validation-message="{{validations.messages.option}}" ng-change="policyChange()"> |
| <option value="" disabled selected style='display:none;'>-Select policy-</option> |
| <option value="periodic">Periodic</option> |
| <option value="exp-backoff">Exponential Backup</option> |
| <option value="final">None</option> |
| </select> |
| </div> |
| </div> |
| <div class="col-xs-offset-1 col-xs-5 plr0px"> |
| <div class="col-xs-24"> |
| <label class="light">Delay Up to</label> |
| </div> |
| <div class="col-xs-24 inlineInputsGroup"> |
| <input type="text" class="form-control" |
| ng-model="process.retry.delay.quantity" validation-message="{{validations.messages.number}}" |
| id="delayQuantity" ng-keydown="validations.acceptOnlyNumber($event)" |
| ng-disabled = "process.retry.policy === 'final'" |
| ng-required="true" |
| ng-pattern="validations.patterns.twoDigits"/> |
| |
| <select ng-model="process.retry.delay.unit" ng-required="true" ng-disabled = "process.retry.policy === 'final'" validation-message="{{validations.messages.option}}"> |
| <option value="" disabled selected style='display:none;'>-Select delay-</option> |
| <option value="minutes">minutes</option> |
| <option value="hours">hours</option> |
| <option value="days">days</option> |
| <option value="months">months</option> |
| </select> |
| </div> |
| </div> |
| <div class="col-xs-4 plr0px"> |
| <div class="col-xs-24"> |
| <label class="light">Attempts</label> |
| </div> |
| <div class="col-xs-24"> |
| <input type="text" class="form-control" validation-message="{{validations.messages.number}}" |
| ng-model="process.retry.attempts" ng-keydown="validations.acceptOnlyNumber($event)" |
| id="attemptsField" |
| ng-required="true" |
| ng-disabled = "process.retry.policy === 'final'" |
| ng-pattern="validations.patterns.twoDigits"/> |
| </div> |
| </div> |
| </div> |
| |
| <div class="col-xs-24"><label>Performance & Ordering</label></div> |
| <div class="col-xs-24 plr0px"> |
| <div class="col-xs-4 plr0px"> |
| <div class="col-xs-24"> |
| <label class="light">Max Parallel Instances</label> |
| </div> |
| <div class="col-xs-24"> |
| <select ng-model="process.parallel" ng-required="true"> |
| <option ng-repeat="value in [1,2,3,4,5,6,7,8,9,10,11,12] track by $index">{{value}}</option> |
| </select> |
| </div> |
| </div> |
| <div class="col-xs-offset-1 col-xs-4 plr0px"> |
| <div class="col-xs-24"> |
| <label class="light" tooltip="process.properties.order">Order</label> |
| </div> |
| <div class="col-xs-24"> |
| <select ng-model="process.order" ng-required="true" validation-message="{{validations.messages.option}}"> |
| <option value="" disabled selected style='display:none;'>-Select order-</option> |
| <option ng-repeat="value in ['FIFO', 'LIFO', 'LAST_ONLY'] track by $index">{{value}}</option> |
| </select> |
| </div> |
| </div> |
| </div> |
| |
| <div class="col-xs-24"> |
| <label>Properties</label> |
| </div> |
| <div ng-repeat="property in process.properties track by $index" class="col-xs-24 plr0px"> |
| <div class="col-xs-6 dynamic-table-spacer"> |
| <input type="text" class="form-control" ng-model="property.name" |
| ng-pattern="validations.patterns.propertyName" |
| validation-optional-message="{{validations.messages.name}}" |
| ng-disabled="xmlPreview.edit" |
| ng-required="property.value" placeholder="name" /> |
| </div> |
| <div class="col-xs-6 dynamic-table-spacer"> |
| <input type="text" class="form-control" ng-model="property.value" |
| validation-optional-message="{{validations.messages.value}}" |
| ng-disabled="xmlPreview.edit" |
| ng-required="property.name" placeholder="value" /> |
| </div> |
| <div class="dynamic-table-spacer"> |
| <button type="button" class="btn btn-default btn-xs" ng-click="removeProperty($index)" ng-if="!$first || !$last" |
| ng-disabled="xmlPreview.edit"> |
| <span class="entypo minus"></span> delete |
| </button> |
| <button type="button" class="btn btn-default btn-xs" ng-click="addProperty()" |
| ng-disabled="xmlPreview.edit" ng-if="$last"> |
| <span class="entypo plus"></span> ADD |
| </button> |
| </div> |
| </div> |
| |
| |
| <div class="col-xs-24"><label class="mt15">Access Control List</label></div> |
| <div class="col-xs-24 plr0px"> |
| <div class="col-xs-4"> |
| <label class="light">Owner<mandatory-field></mandatory-field></label> |
| <input type="text" |
| name="aclOwnerInput" |
| ng-model="process.ACL.owner" |
| ng-pattern="validations.patterns.unixId" |
| ng-required="true" |
| class="form-control" |
| validation-message="{{validations.messages.acl.owner}}"/> |
| </div> |
| <div class="col-xs-4"> |
| <label class="light">Group<mandatory-field></mandatory-field></label> |
| <input type="text" |
| name="aclGroupInput" |
| ng-model="process.ACL.group" |
| ng-pattern="validations.patterns.unixId" |
| ng-required="true" |
| class="form-control" |
| validation-message="{{validations.messages.acl.group}}" /> |
| </div> |
| <div class="col-xs-24"> |
| <div class="col-xs-8 plr0px"> |
| <label class="light">Permissions<mandatory-field></mandatory-field></label> |
| <acl-permissions acl-model="process.ACL.permission"></acl-permissions> |
| </div> |
| </div> |
| </div> |
| </div> |
| |
| <div class="col-xs-24 pb15px mt35"> |
| <div class="pull-right"> |
| <a class="btn cnclBtn" ui-sref="main"> |
| CANCEL |
| </a> |
| <button id="nextButton" class="btn nextBtn" |
| ng-disabled="buttonSpinners.show" |
| ng-click="goNext(processForm.$invalid)" scroll-to-error> |
| NEXT <img src="css/img/ajax-loader.gif" ng-if="buttonSpinners.show" /> |
| </button> |
| <button class="btn nextBtn" |
| ng-disabled="processForm.$invalid || buttonSpinners.saveShow" |
| ng-click="saveEntity(processForm.$invalid)" scroll-to-error> |
| SAVE <img src="css/img/ajax-loader.gif" ng-if="buttonSpinners.saveShow" /> |
| </button> |
| </div> |
| </div> |
| |
| </form> |