Repository: incubator-atlas Updated Branches: refs/heads/master 1620284e4 -> b305ba505
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/edc4786b/dashboardv2/public/js/external_lib/datetimepicker/bootstrap-datetimepicker.min.css ---------------------------------------------------------------------- diff --git a/dashboardv2/public/js/external_lib/datetimepicker/bootstrap-datetimepicker.min.css b/dashboardv2/public/js/external_lib/datetimepicker/bootstrap-datetimepicker.min.css new file mode 100644 index 0000000..e9ec816 --- /dev/null +++ b/dashboardv2/public/js/external_lib/datetimepicker/bootstrap-datetimepicker.min.css @@ -0,0 +1,5 @@ +/*! + * Datetimepicker for Bootstrap 3 + * version : 4.14.30 + * https://github.com/Eonasdan/bootstrap-datetimepicker/ + */.bootstrap-datetimepicker-widget{list-style:none}.bootstrap-datetimepicker-widget.dropdown-menu{margin:2px 0;padding:4px;width:19em}@media (min-width:768px){.bootstrap-datetimepicker-widget.dropdown-menu.timepicker-sbs{width:38em}}@media (min-width:992px){.bootstrap-datetimepicker-widget.dropdown-menu.timepicker-sbs{width:38em}}@media (min-width:1200px){.bootstrap-datetimepicker-widget.dropdown-menu.timepicker-sbs{width:38em}}.bootstrap-datetimepicker-widget.dropdown-menu:after,.bootstrap-datetimepicker-widget.dropdown-menu:before{content:'';display:inline-block;position:absolute}.bootstrap-datetimepicker-widget.dropdown-menu.bottom:before{border-left:7px solid transparent;border-right:7px solid transparent;border-bottom:7px solid #ccc;border-bottom-color:rgba(0,0,0,.2);top:-7px;left:7px}.bootstrap-datetimepicker-widget.dropdown-menu.bottom:after{border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:6px solid #fff;top:-6px;left:8px}.bootstrap-datetime picker-widget.dropdown-menu.top:before{border-left:7px solid transparent;border-right:7px solid transparent;border-top:7px solid #ccc;border-top-color:rgba(0,0,0,.2);bottom:-7px;left:6px}.bootstrap-datetimepicker-widget.dropdown-menu.top:after{border-left:6px solid transparent;border-right:6px solid transparent;border-top:6px solid #fff;bottom:-6px;left:7px}.bootstrap-datetimepicker-widget.dropdown-menu.pull-right:before{left:auto;right:6px}.bootstrap-datetimepicker-widget.dropdown-menu.pull-right:after{left:auto;right:7px}.bootstrap-datetimepicker-widget .list-unstyled{margin:0}.bootstrap-datetimepicker-widget a[data-action]{padding:6px 0}.bootstrap-datetimepicker-widget a[data-action]:active{box-shadow:none}.bootstrap-datetimepicker-widget .timepicker-hour,.bootstrap-datetimepicker-widget .timepicker-minute,.bootstrap-datetimepicker-widget .timepicker-second{width:54px;font-weight:700;font-size:1.2em;margin:0}.bootstrap-datetimepicker-widget button[data-action]{padding:6px}.bootst rap-datetimepicker-widget .btn[data-action=incrementHours]::after{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);border:0;content:"Increment Hours"}.bootstrap-datetimepicker-widget .btn[data-action=incrementMinutes]::after{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);border:0;content:"Increment Minutes"}.bootstrap-datetimepicker-widget .btn[data-action=decrementHours]::after{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);border:0;content:"Decrement Hours"}.bootstrap-datetimepicker-widget .btn[data-action=decrementMinutes]::after{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);border:0;content:"Decrement Minutes"}.bootstrap-datetimepicker-widget .btn[data-action=showHours]::after{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);border:0;content :"Show Hours"}.bootstrap-datetimepicker-widget .btn[data-action=showMinutes]::after{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);border:0;content:"Show Minutes"}.bootstrap-datetimepicker-widget .btn[data-action=togglePeriod]::after{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);border:0;content:"Toggle AM/PM"}.bootstrap-datetimepicker-widget .btn[data-action=clear]::after{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);border:0;content:"Clear the picker"}.bootstrap-datetimepicker-widget .btn[data-action=today]::after{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);border:0;content:"Set the date to today"}.bootstrap-datetimepicker-widget .picker-switch{text-align:center}.bootstrap-datetimepicker-widget .picker-switch::after{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflo w:hidden;clip:rect(0,0,0,0);border:0;content:"Toggle Date and Time Screens"}.bootstrap-datetimepicker-widget .picker-switch td{padding:0;margin:0;height:auto;width:auto;line-height:inherit}.bootstrap-datetimepicker-widget .picker-switch td span{line-height:2.5;height:2.5em;width:100%}.bootstrap-datetimepicker-widget table{width:100%;margin:0}.bootstrap-datetimepicker-widget table td,.bootstrap-datetimepicker-widget table th{text-align:center;border-radius:4px}.bootstrap-datetimepicker-widget table th{height:20px;line-height:20px;width:20px}.bootstrap-datetimepicker-widget table th.picker-switch{width:145px}.bootstrap-datetimepicker-widget table th.disabled,.bootstrap-datetimepicker-widget table th.disabled:hover{background:0 0;color:#777;cursor:not-allowed}.bootstrap-datetimepicker-widget table th.prev::after{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);border:0;content:"Previous Month"}.bootstrap-datetimepicker-widget table th.next ::after{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);border:0;content:"Next Month"}.bootstrap-datetimepicker-widget table thead tr:first-child th{cursor:pointer}.bootstrap-datetimepicker-widget table thead tr:first-child th:hover{background:#eee}.bootstrap-datetimepicker-widget table td{height:54px;line-height:54px;width:54px}.bootstrap-datetimepicker-widget table td.cw{font-size:.8em;height:20px;line-height:20px;color:#777}.bootstrap-datetimepicker-widget table td.day{height:20px;line-height:20px;width:20px}.bootstrap-datetimepicker-widget table td.day:hover,.bootstrap-datetimepicker-widget table td.hour:hover,.bootstrap-datetimepicker-widget table td.minute:hover,.bootstrap-datetimepicker-widget table td.second:hover{background:#eee;cursor:pointer}.bootstrap-datetimepicker-widget table td.new,.bootstrap-datetimepicker-widget table td.old{color:#777}.bootstrap-datetimepicker-widget table td.today{position:relative}.bootstrap-dateti mepicker-widget table td.today:before{content:'';display:inline-block;border:0 solid transparent;border-bottom-color:#337ab7;border-top-color:rgba(0,0,0,.2);position:absolute;bottom:4px;right:4px}.bootstrap-datetimepicker-widget table td.active,.bootstrap-datetimepicker-widget table td.active:hover{background-color:#337ab7;color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,.25)}.bootstrap-datetimepicker-widget table td.active.today:before{border-bottom-color:#fff}.bootstrap-datetimepicker-widget table td.disabled,.bootstrap-datetimepicker-widget table td.disabled:hover{background:0 0;color:#777;cursor:not-allowed}.bootstrap-datetimepicker-widget table td span{display:inline-block;width:54px;height:54px;line-height:54px;margin:2px 1.5px;cursor:pointer;border-radius:4px}.bootstrap-datetimepicker-widget table td span:hover{background:#eee}.bootstrap-datetimepicker-widget table td span.active{background-color:#337ab7;color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,.25)}.bootstrap-datetimepicker-widg et table td span.old{color:#777}.bootstrap-datetimepicker-widget table td span.disabled,.bootstrap-datetimepicker-widget table td span.disabled:hover{background:0 0;color:#777;cursor:not-allowed}.bootstrap-datetimepicker-widget.usetwentyfour td.hour{height:27px;line-height:27px}.bootstrap-datetimepicker-widget.wider{width:21em}.bootstrap-datetimepicker-widget .datepicker-decades .decade{line-height:1.8em!important}.input-group.date .input-group-addon{cursor:pointer}.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);border:0} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/edc4786b/dashboardv2/public/js/main.js ---------------------------------------------------------------------- diff --git a/dashboardv2/public/js/main.js b/dashboardv2/public/js/main.js index 772d3d4..fe08754 100644 --- a/dashboardv2/public/js/main.js +++ b/dashboardv2/public/js/main.js @@ -94,6 +94,10 @@ require.config({ 'deps': ['d3'], 'exports': ['d3-tip'] }, + 'datetimepicker': { + 'deps': ['jquery'], + 'exports': 'datetimepicker' + }, 'dagreD3': { 'deps': ['d3'], 'exports': ['dagreD3'] @@ -130,10 +134,11 @@ require.config({ 'hbs': 'external_lib/require-handlebars-plugin/js/hbs', 'i18nprecompile': 'external_lib/require-handlebars-plugin/js/i18nprecompile', 'dagreD3': 'libs/dagre-d3/dagre-d3.min', - 'select2': 'libs/select2/select2.min', + 'select2': 'libs/select2/select2.full.min', 'backgrid-select-all': 'libs/backgrid-select-all/backgrid-select-all.min', 'moment': 'libs/moment/js/moment.min', 'jquery-ui': 'external_lib/jquery-ui/jquery-ui.min', + 'datetimepicker': 'external_lib/datetimepicker/bootstrap-datetimepicker', 'pnotify': 'external_lib/pnotify.custom.min', 'jquery-placeholder': 'libs/jquery-placeholder/js/jquery.placeholder', 'platform': 'libs/platform/platform' @@ -156,7 +161,7 @@ require(['App', 'utils/Overrides', 'bootstrap', 'd3', - 'select2' + 'select2' ], function(App, Router, CommonViewFunction, Globals, UrlLinks) { App.appRouter = new Router(); CommonViewFunction.userDataFetch({ http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/edc4786b/dashboardv2/public/js/models/VEntity.js ---------------------------------------------------------------------- diff --git a/dashboardv2/public/js/models/VEntity.js b/dashboardv2/public/js/models/VEntity.js index 4347b62..2173534 100644 --- a/dashboardv2/public/js/models/VEntity.js +++ b/dashboardv2/public/js/models/VEntity.js @@ -70,8 +70,20 @@ define(['require', }, options); return this.constructor.nonCrudOperation.call(this, url, 'GET', options); + }, + createOreditEntity: function(guid, options) { + var url; + if (guid) { + url = UrlLinks.entitiesApiUrl(guid); + } else { + url = UrlLinks.entitiesApiUrl(); + } + options = _.extend({ + contentType: 'application/json', + dataType: 'json' + }, options); + return this.constructor.nonCrudOperation.call(this, url, "", options); } - }, {}); return VEntity; }); http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/edc4786b/dashboardv2/public/js/templates/detail_page/DetailPageLayoutView_tmpl.html ---------------------------------------------------------------------- diff --git a/dashboardv2/public/js/templates/detail_page/DetailPageLayoutView_tmpl.html b/dashboardv2/public/js/templates/detail_page/DetailPageLayoutView_tmpl.html index f34bcea..e89555a 100644 --- a/dashboardv2/public/js/templates/detail_page/DetailPageLayoutView_tmpl.html +++ b/dashboardv2/public/js/templates/detail_page/DetailPageLayoutView_tmpl.html @@ -19,6 +19,7 @@ <a href="javascript:void(0);" class="backButton" data-id="backButton"><i class="fa fa-chevron-left"></i> Back To Results</a> </div> <h1><span data-id="title"></span></h1> + <button data-id="editButton" class="btn btn-default pull-right editbutton" id="editText"><i class="fa fa-pencil"></i></button> <div data-id="editBox" style="margin-bottom:10px;"> <textarea class="well well-sm col-sm-12" data-id="descriptionTextArea"></textarea> <div class="clearfix" align="right"> http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/edc4786b/dashboardv2/public/js/templates/entity/CreateEntityLayoutView_tmpl.html ---------------------------------------------------------------------- diff --git a/dashboardv2/public/js/templates/entity/CreateEntityLayoutView_tmpl.html b/dashboardv2/public/js/templates/entity/CreateEntityLayoutView_tmpl.html new file mode 100644 index 0000000..01f2aa0 --- /dev/null +++ b/dashboardv2/public/js/templates/entity/CreateEntityLayoutView_tmpl.html @@ -0,0 +1,46 @@ +<!-- + * 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="entityDefinitionform" class="css-form"> + <!-- <h4 style="margin-bottom:30px"></h4> --> + <div class="form-group"> + <div class="col-sm-12"> + <div class="row"> + {{#if guid}} + <div class="col-md-8"> + <label class="col-md-6 row-margin-bottom" data-id="assetName"></label> + </div> + {{else}} + <div class="col-md-8"> + <select class="form-control col-md-6 row-margin-bottom" data-id="entityList"></select> + </div> + {{/if}} + <div class="col-md-4"> + <span class="pull-left">Required</span> + <label class="switch pull-left"> + <input type="checkbox" class="switch-input" name="toggleRequired" value="text"> + <div class="switch-slider"></div> + </label> + <span class="pull-left">All</span> + </div> + </div> + </div> + <div class="entityLoader" style="display:none"> + <i class="fa fa-refresh fa-spin-custom"></i> + </div> + <div class="control-group entityInputData" data-id="entityInputData"></div> + </div> +</form> http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/edc4786b/dashboardv2/public/js/templates/search/SearchLayoutView_tmpl.html ---------------------------------------------------------------------- diff --git a/dashboardv2/public/js/templates/search/SearchLayoutView_tmpl.html b/dashboardv2/public/js/templates/search/SearchLayoutView_tmpl.html index db31046..8d7f874 100644 --- a/dashboardv2/public/js/templates/search/SearchLayoutView_tmpl.html +++ b/dashboardv2/public/js/templates/search/SearchLayoutView_tmpl.html @@ -15,6 +15,9 @@ * limitations under the License. --> <div class="row row-margin-bottom"> + <div class="col-sm-12"> + <button class="btn btn-atlasAction btn-atlas pull-left" data-id="createEntity"><i class="fa fa-plus"></i> Create Entity</button> + </div> <div class="col-sm-12" style="margin:15px 0px;"> <div class="row"> <div class="col-md-6"> http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/edc4786b/dashboardv2/public/js/utils/UrlLinks.js ---------------------------------------------------------------------- diff --git a/dashboardv2/public/js/utils/UrlLinks.js b/dashboardv2/public/js/utils/UrlLinks.js index a5288be..4071b07 100644 --- a/dashboardv2/public/js/utils/UrlLinks.js +++ b/dashboardv2/public/js/utils/UrlLinks.js @@ -29,11 +29,11 @@ define(['require', 'utils/Enums'], function(require, Enums) { return this.baseUrl + '/v1/taxonomies' + '/' + name + '/terms'; }, entitiesApiUrl: function(guid, name) { - var entitiesUrl = this.baseUrlV2 + '/entity/guid'; + var entitiesUrl = this.baseUrlV2 + '/entity'; if (guid && name) { - return entitiesUrl + '/' + guid + '/classification/' + name; + return entitiesUrl + '/guid/' + guid + '/classification/' + name; } else if (guid && !name) { - return entitiesUrl + '/' + guid; + return entitiesUrl + '/guid/' + guid; } else { return entitiesUrl; } http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/edc4786b/dashboardv2/public/js/views/detail_page/DetailPageLayoutView.js ---------------------------------------------------------------------- diff --git a/dashboardv2/public/js/views/detail_page/DetailPageLayoutView.js b/dashboardv2/public/js/views/detail_page/DetailPageLayoutView.js index b2d2c7b..041204f 100644 --- a/dashboardv2/public/js/views/detail_page/DetailPageLayoutView.js +++ b/dashboardv2/public/js/views/detail_page/DetailPageLayoutView.js @@ -75,6 +75,7 @@ define(['require', /** ui events hash */ events: function() { var events = {}; + events["click " + this.ui.editButton] = 'onClickEditEntity'; events["click " + this.ui.tagClick] = function(e) { if (e.target.nodeName.toLocaleLowerCase() != "i") { var scope = $(e.currentTarget); @@ -358,6 +359,21 @@ define(['require', term: true })); }); + }, + onClickEditEntity: function(e) { + var that = this; + $(e.currentTarget).blur(); + require([ + 'views/entity/CreateEntityLayoutView' + ], function(CreateEntityLayoutView) { + var view = new CreateEntityLayoutView({ + guid: that.id, + callback: function() { + that.fetchCollection(); + } + }); + + }); } }); return DetailPageLayoutView; http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/edc4786b/dashboardv2/public/js/views/entity/CreateEntityLayoutView.js ---------------------------------------------------------------------- diff --git a/dashboardv2/public/js/views/entity/CreateEntityLayoutView.js b/dashboardv2/public/js/views/entity/CreateEntityLayoutView.js new file mode 100644 index 0000000..a3e0389 --- /dev/null +++ b/dashboardv2/public/js/views/entity/CreateEntityLayoutView.js @@ -0,0 +1,613 @@ +/** + * 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. + */ + +define(['require', + 'backbone', + 'hbs!tmpl/entity/CreateEntityLayoutView_tmpl', + 'utils/Utils', + 'collection/VTagList', + 'collection/VCommonList', + 'collection/VEntityList', + 'models/VEntity', + 'modules/Modal', + 'utils/Messages', + 'datetimepicker', + 'moment', + 'utils/UrlLinks', + 'collection/VSearchList', + 'utils/Enums' +], function(require, Backbone, CreateEntityLayoutViewTmpl, Utils, VTagList, VCommonList, VEntityList, VEntity, Modal, Messages, datepicker, moment, UrlLinks, VSearchList, Enums) { + + var CreateEntityLayoutView = Backbone.Marionette.LayoutView.extend( + /** @lends CreateEntityLayoutView */ + { + _viewName: 'CreateEntityLayoutView', + + template: CreateEntityLayoutViewTmpl, + + templateHelpers: function() { + return { + guid: this.guid + }; + }, + + /** Layout sub regions */ + regions: {}, + + /** ui selector cache */ + ui: { + entityName: "[data-id='entityName']", + entityList: "[data-id='entityList']", + description: "[data-id='description']", + entityInputData: "[data-id='entityInputData']", + entityLegend: "[data-id='entityLegend']", + toggleRequired: 'input[name="toggleRequired"]', + assetName: "[data-id='assetName']", + entityInput: "[data-id='entityInput']" + }, + /** ui events hash */ + events: function() { + var events = {}; + events["change " + this.ui.entityList] = "onEntityChange"; + events["change " + this.ui.toggleRequired] = function(e) { + this.requiredAllToggle(e.currentTarget.checked) + }; + return events; + }, + /** + * intialize a new CreateEntityLayoutView Layout + * @constructs + */ + initialize: function(options) { + _.extend(this, _.pick(options, 'guid', 'callback', 'showLoader')); + var that = this, + entityTitle, okLabel; + this.entityDetailCollection = new VCommonList(); + this.searchCollection = new VSearchList(); + this.searchCollection.url = UrlLinks.searchApiUrl(Enums.searchUrlType.DSL); + this.selectStoreCollection = new Backbone.Collection(); + this.entityModel = new VEntity(); + if (this.guid) { + this.collection = new VEntityList(); + this.collection.modelAttrName = "createEntity" + } else { + this.collection = new VTagList(); + } + this.asyncFetchCounter = 0; + this.required = true; + if (this.guid) { + entityTitle = 'Edit entity'; + okLabel = 'Update'; + } else { + entityTitle = 'Create entity'; + okLabel = 'Create'; + } + this.modal = new Modal({ + title: entityTitle, + content: this, + cancelText: "Cancel", + okText: okLabel, + allowCancel: true, + okCloses: false, + resizable: true, + resizableOpts: { + minWidth: 600, + minHeight: 284, + handles: "n, e, s, w", + resize: function(event, ui) { + that.modal.$el.find('.modal-body').css('min-height', ui.size.height - 134 + 'px'); + that.modal.$el.find('.modal-body').css('max-height', ui.size.height - 134 + 'px'); + } + } + }).open(); + var enable = false; + this.ui.entityList.val(""); + $(this.ui.entityInputData).on('keyup change dp.change', that.modal.$el.find('input select textarea'), function(e) { + that.ui.entityInputData.find("input,select,textarea").each(function() { + if (this.value !== "") { + if ($(this).data('select2')) { + $(this).data('select2').$container.removeClass("errorClass") + } else { + $(this).removeClass('errorClass'); + } + } + }); + }); + this.modal.on('ok', function(e) { + that.okButton(); + }); + this.modal.on('closeModal', function() { + that.modal.trigger('cancel'); + }); + }, + bindEvents: function() { + var that = this; + this.listenTo(this.collection, "reset", function() { + --this.asyncFetchCounter; + this.entityCollectionList(); + }, this); + this.listenTo(this.collection, 'error', function() { + --this.asyncFetchCounter + this.hideLoader(); + }, this); + this.listenTo(this.searchCollection, "reset", function() { + this.addJsonSearchData(); + }, this); + this.listenTo(this.searchCollection, 'error', function(data, key) { + this.addJsonSearchData(key); + this.hideLoader(); + }, this); + }, + onRender: function() { + this.bindEvents(); + this.fetchCollections(); + }, + fetchCollections: function() { + this.asyncFetchCounter++; + if (this.guid) { + this.collection.url = UrlLinks.entitiesApiUrl(this.guid); + this.collection.fetch({ reset: true }); + } else { + this.collection.url = UrlLinks.entitiesDefApiUrl() + this.collection.modelAttrName = 'list'; + this.collection.fetch({ reset: true }); + } + + }, + entityCollectionList: function() { + this.ui.entityList.empty(); + var that = this, + name = "", + value; + if (this.guid) { + this.collection.each(function(val) { + name += val.get("attributes").name || val.get("attributes").qualifiedName || val.get("attributes").id; + that.entityData = val; + }); + this.ui.assetName.html(name); + this.onEntityChange(null, this.entityData); + } else { + var str = '<option selected="selected" disabled="disabled">--Select entity-type--</option>'; + this.collection.fullCollection.comparator = function(model) { + return model.get('name'); + } + this.collection.fullCollection.sort().each(function(val) { + str += '<option>' + val.get("name") + '</option>'; + }); + this.ui.entityList.html(str); + } + }, + capitalize: function(string) { + return string.charAt(0).toUpperCase() + string.slice(1); + }, + requiredAllToggle: function(checked) { + if (checked) { + this.ui.entityInputData.find('div.true').show(); + this.ui.entityInputData.find('fieldset div.true').show(); + this.required = false; + } else { + this.ui.entityInputData.find('div.true').hide(); + this.ui.entityInputData.find('fieldset div.true').hide(); + this.required = true; + } + + }, + onEntityChange: function(e, value) { + var that = this, + typeName; + this.showLoader(); + this.ui.entityInputData.empty(); + if (value) { + typeName = value.get("typeName"); + } + if (typeName) { + this.collection.url = UrlLinks.entitiesDefApiUrl(typeName); + } else { + this.collection.url = UrlLinks.entitiesDefApiUrl(e.target.value); + this.collection.modelAttrName = 'attributeDefs'; + } + this.collection.fetch({ + success: function(model, data) { + that.subAttributeData(data) + }, + complete: function() { + var _self = that; + that.$('input[data-type="date"]').each(function() { + if (!$(this).data('datepicker')) { + $(this).datetimepicker({ + format: 'DD MMMM YYYY' + }); + } + }); + that.$('input[data-type="long"]').each(function() { + if (!$(this).data('datepicker')) { + $(this).datetimepicker({ + format: 'DD MMMM YYYY, HH:mm', + showTodayButton: true, + showClose: true + }); + } + }); + // IE9 allow input type number + that.$('input[data-type="int"]').on('keydown', function(e) { + var regex = /^[0-9]*([.](?=[^.]|$))*(?:\.\d{1,2})?$/; // allow only numbers [0-9] + if (!regex.test(e.currentTarget.value)) { + return false; + } + }); + if (that.ui.entityInputData.find('select.true,input.true').length === 0) { + that.requiredAllToggle(that.ui.entityInputData.find('select.true,input.true').length === 0); + that.ui.toggleRequired.prop('checked', true); + + } + // IE9 allow input type number + that.$('input[data-type="int"]').on('keyup click', function(e) { + e.currentTarget.value = e.currentTarget.value; + var regex = /^[0-9]*([.](?=[^.]|$))*(?:\.\d{1,2})?$/; // allow only numbers [0-9] + if (!regex.test(e.currentTarget.value)) { + var txtfld = e.currentTarget; + var newtxt = txtfld.value.slice(0, txtfld.value.length - 1); + txtfld.value = newtxt; + } + }); + }, + silent: true + }); + }, + subAttributeData: function(data) { + var that = this, + attributeInput = "", + alloptional = false; + _.each(data.attributeDefs, function(value) { + if (value.isOptional == true) { + alloptional = true; + } + + attributeInput += that.getContainer(value); + }); + if (attributeInput !== "") { + entityTitle = that.getFieldSet(data, alloptional, attributeInput); + that.ui.entityInputData.prepend(entityTitle); + } + if (data.superTypes && data.superTypes.length > 0) { + for (var j = 0; j < data.superTypes.length; j++) { + var superTypeAttr = data.superTypes[j]; + that.fetchTagSubData(superTypeAttr); + } + } else { + this.hideLoader(); + } + if (this.required) { + this.ui.entityInputData.find('fieldset div.true').hide() + this.ui.entityInputData.find('div.true').hide(); + } + if (!('placeholder' in HTMLInputElement.prototype)) { + this.ui.entityInputData.find('input,select,textarea').placeholder(); + } + }, + getContainer: function(value) { + var entityLabel = this.capitalize(value.name); + return '<div class="row row-margin-bottom ' + value.isOptional + '"><span class="col-md-3">' + + '<label class="' + value.isOptional + '">' + entityLabel + (value.isOptional == true ? '' : ' <span class="requiredInput">*</span>') + '</label></span>' + + '<span class="col-md-9 position-relative">' + + (value.typeName === "boolean" ? this.getSelect(value) : this.getInput(value)) + + '<span class="spanEntityType" title="Data Type : ' + value.typeName + '">' + '(' + Utils.escapeHtml(value.typeName) + ')' + '</span></input></span></div>'; + }, + getFieldSet: function(data, alloptional, attributeInput) { + return '<fieldset class="scheduler-border' + (alloptional ? " alloptional" : "") + '"><legend class="scheduler-border">' + data.name + '</legend>' + attributeInput + '</fieldset>'; + }, + getInput: function(value) { + var that = this; + var entityValue = ""; + if (this.guid) { + var dataValue = this.entityData.get("attributes")[value.name]; + if (_.isObject(dataValue)) { + entityValue = JSON.stringify(dataValue); + } else { + if (dataValue) { + entityValue = dataValue; + } + if (value.typeName === "date" && dataValue) { + entityValue = moment(dataValue).format("DD MMMM YYYY"); + } + if (value.typeName === "long") { + entityValue = moment(dataValue).format("DD MMMM YYYY, HH:mm"); + } + } + } + if (value.typeName === "string" || value.typeName === "long" || value.typeName === "int" || value.typeName === "boolean" || value.typeName === "date") { + return '<input class="form-control entityInputBox ' + (value.isOptional === true ? "false" : "true") + '"' + + ' data-type="' + value.typeName + '"' + + ' value="' + entityValue + '"' + + ' data-key="' + value.name + '"' + + ' placeholder="' + value.name + '"' + + ' data-id="entityInput">'; + } else if (value.typeName === "map<string,string>") { + return '<textarea class="form-control entityInputBox ' + (value.isOptional === true ? "false" : "true") + '"' + + ' data-type="' + value.typeName + '"' + + ' data-key="' + value.name + '"' + + ' placeholder="' + value.name + '"' + + ' data-id="entityInput">' + entityValue + '</textarea>'; + } else { + var changeDatatype; + if (value.typeName.indexOf("array") == -1) { + changeDatatype = value.typeName; + } else { + if (value.typeName === "array<string>") { + changeDatatype = value.typeName; + } else { + changeDatatype = value.typeName.split('<')[1].split('>')[0]; + } + } + $.extend(that.searchCollection.queryParams, { query: changeDatatype }); + that.searchCollection.fetch({ reset: true }); + return '<select class="form-control row-margin-bottom entityInputBox ' + (value.isOptional === true ? "false" : "true") + '" data-type="' + value.typeName + + '" data-key="' + value.name + '"data-id="entitySelectData" data-queryData="' + changeDatatype + '">' + (this.guid ? entityValue : "") + '</select>'; + } + }, + getSelect: function(value) { + return '<select class="form-control row-margin-bottom ' + (value.isOptional === true ? "false" : "true") + '" data-type="' + value.typeName + '" data-key="' + value.name + '" data-id="entityInput">' + + '<option disabled="disabled">--Select true or false--</option><option>true</option>' + + '<option>false</option></select>'; + }, + fetchTagSubData: function(entityName) { + var that = this; + this.collection.url = UrlLinks.entitiesDefApiUrl(entityName); + this.collection.modelAttrName = 'attributeDefs'; + this.asyncFetchCounter++; + this.collection.fetch({ + success: function(model, data) { + that.subAttributeData(data); + }, + complete: function() { + --that.asyncFetchCounter; + if (that.asyncFetchCounter === 0) { + that.$('input[data-type="date"]').each(function() { + if (!$(this).data('datepicker')) { + $(this).datetimepicker({ + format: 'DD MMMM YYYY' + }); + } + }); + that.$('input[data-type="long"]').each(function() { + if (!$(this).data('datepicker')) { + $(this).datetimepicker({ + format: 'DD MMMM YYYY, HH:mm', + showTodayButton: true, + showClose: true + }); + } + }); + that.hideLoader(); + } + that.$('select[data-type="boolean"]').each(function(value, key) { + var dataKey = $(key).data('key'); + if (that.entityData) { + var setValue = that.entityData.get("attributes")[dataKey]; + this.value = setValue; + } + }); + + }, + silent: true + }); + }, + + okButton: function() { + var that = this; + this.showLoader(); + this.parentEntity = this.ui.entityList.val(); + var entityAttribute = {}; + that.validateError = false; + that.validateMessage = false; + this.ui.entityInputData.find("input,select,textarea").each(function() { + var value = $(this).val(); + if ($(this).val() && $(this).val().trim) { + value = $(this).val().trim(); + } + if ($(this).hasClass("true")) { + if (value == "" || value == undefined) { + if ($(this).data('select2')) { + $(this).data('select2').$container.addClass("errorClass") + } else { + $(this).addClass('errorClass'); + } + that.hideLoader(); + that.validateError = true; + that.validateMessage = true; + return; + } + } + var dataTypeEnitity = $(this).data('type'); + var datakeyEntity = $(this).data('key'); + var selectDataType = $(this).data('querydata'); + var pickKey = $(this).data('pickkey'); + if (typeof datakeyEntity === 'string' && datakeyEntity.indexOf("Time") > -1) { + entityAttribute[datakeyEntity] = Date.parse($(this).val()); + } else if (dataTypeEnitity == "string" || dataTypeEnitity === "long" || dataTypeEnitity === "int" || dataTypeEnitity === "boolean" || dataTypeEnitity == "date") { + entityAttribute[datakeyEntity] = $(this).val(); + } else { + try { + if (value !== undefined && value !== null && value !== "") { + if (_.isArray(value)) { + var arrayEmptyValueCheck = value.join("") + if (arrayEmptyValueCheck === "") { + return; + } + if (dataTypeEnitity === "array<string>" || dataTypeEnitity === "map<string,string>") { + parseData = value; + } else { + if (that.selectStoreCollection.length) { + var parseData = value.map(function(val) { + var temp = {} // I9 support; + temp[pickKey] = val; + var valueData = that.selectStoreCollection.findWhere(temp).toJSON(); + valueData['guid'] = valueData.id; + return valueData; + }) + } + } + } else { + if (that.selectStoreCollection.length && pickKey) { + var temp = {} // I9 support; + temp[pickKey] = $(this).val(); + var parseData = that.selectStoreCollection.findWhere(temp).toJSON(); + parseData['guid'] = parseData.id || parseData['$id$'].id; + } + // Object but maptype + if (!pickKey) { + parseData = JSON.parse($(this).val()); + } + } + entityAttribute[datakeyEntity] = parseData + $(this).removeClass('errorClass'); + } + } catch (e) { + $(this).addClass('errorClass'); + that.validateError = e; + that.hideLoader(); + } + } + }); + var entityJson = { + "typeName": this.guid ? this.entityData.get("typeName") : this.parentEntity, + "attributes": entityAttribute + }; + if (this.guid) { + entityJson["guid"] = this.entityData.get("guid"); + }; + if (that.validateError) { + if (that.validateMessage) { + Utils.notifyError({ + content: "Please fill the required fields" + }); + } else { + Utils.notifyError({ + content: that.validateError.message + }); + } + that.validateError = null; + that.hideLoader(); + } else { + this.entityModel.createOreditEntity(this.guid, { + data: JSON.stringify(entityJson), + type: this.guid ? "PUT" : "POST", + success: function(model, response) { + that.callback(); + that.modal.close(); + Utils.notifySuccess({ + content: "entity " + Messages[that.guid ? 'editSuccessMessage' : 'addSuccessMessage'] + }); + }, + error: function(response) { + if (response.responseJSON) { + Utils.notifyError({ + content: response.responseJSON.error || response.responseJSON.errorMessage + }); + } + }, + complete: function() { + that.hideLoader(); + } + }); + } + }, + showLoader: function() { + this.$('.entityLoader').show(); + this.$('.entityInputData').hide(); + }, + hideLoader: function() { + this.$('.entityLoader').hide(); + this.$('.entityInputData').show(); + }, + addJsonSearchData: function(isError) { + var that = this, + typename, + str = ''; + if (isError) { + typename = isError.responseJSON.error.split(": ")[1]; + } else { + if (this.searchCollection.length) { + typename = this.searchCollection.first().get("$typeName$"); + this.selectStoreCollection.push(this.searchCollection.fullCollection.models); + var labelName = ""; + _.each(this.searchCollection.fullCollection.models, function(value, key) { + if (value.get("qualifiedName")) { + labelName = "qualifiedName"; + } else if (value.get("name")) { + labelName = "name"; + } else if (value.get("id")) { + labelName = "id"; + } + str += '<option>' + value.get(labelName) + '</option>'; + }); + } + } + this.$('select[data-queryData="' + typename + '"]').html(str); + this.$('select[data-queryData="' + typename + '"]').attr('data-pickkey', labelName); + this.$('select[data-queryData="' + typename + '"]').each(function(value, key) { + var keyData = $(this).data("key"); + var typeData = $(this).data("type"); + var placeholderName = "Select a " + typename + " from the dropdown list"; + var $this = $(this); + $this.attr("multiple", ($this.data('type').indexOf("array") === -1 ? false : true)) + if (that.guid) { + if (that.selectStoreCollection.length) { + var selectedValue = []; + } + var dataValue = that.entityData.get("attributes")[keyData]; + that.selectStoreCollection.each(function(value) { + if (dataValue !== null && _.isArray(dataValue)) { + _.each(dataValue, function(obj) { + if (obj.guid === value.get("id")) { + selectedValue.push(value.get("qualifiedName") || value.get("name") || value.get("id")); + } + }); + } else if (dataValue !== null) { + if (dataValue.guid === value.get("id")) { + selectedValue.push(value.get("qualifiedName") || value.get("name") || value.get("id")); + } + } + }); + if (selectedValue) { + $this.val(selectedValue); + } else { + if (that.guid) { + var dataValue = that.entityData.get("attributes")[keyData]; + if (dataValue !== null) { + _.each(dataValue, function(obj) { + str += '<option>' + obj + '</option>'; + }); + $this.html(str); + } + } + $this.val(dataValue); + } + } else { + $this.val(""); + } + $this.select2({ + placeholder: placeholderName, + allowClear: true, + tags: true + }); + }); + } + }); + return CreateEntityLayoutView; +}); http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/edc4786b/dashboardv2/public/js/views/search/SearchLayoutView.js ---------------------------------------------------------------------- diff --git a/dashboardv2/public/js/views/search/SearchLayoutView.js b/dashboardv2/public/js/views/search/SearchLayoutView.js index d652aa4..2dd2549 100644 --- a/dashboardv2/public/js/views/search/SearchLayoutView.js +++ b/dashboardv2/public/js/views/search/SearchLayoutView.js @@ -42,7 +42,8 @@ define(['require', searchBtn: '[data-id="searchBtn"]', clearSearch: '[data-id="clearSearch"]', typeLov: '[data-id="typeLOV"]', - refreshBtn: '[data-id="refreshBtn"]' + refreshBtn: '[data-id="refreshBtn"]', + createEntity: "[data-id='createEntity']", }, /** ui events hash */ events: function() { @@ -63,6 +64,7 @@ define(['require', events["click " + this.ui.clearSearch] = 'clearSearchData'; events["change " + this.ui.typeLov] = 'onChangeTypeList'; events["click " + this.ui.refreshBtn] = 'onRefreshButton'; + events["click " + this.ui.createEntity] = 'onClickCreateEntity'; return events; }, /** @@ -247,7 +249,20 @@ define(['require', mergeBrowserUrl: false, trigger: true }); - } + }, + onClickCreateEntity: function(e) { + var that = this; + $(e.currentTarget).blur(); + require([ + 'views/entity/CreateEntityLayoutView' + ], function(CreateEntityLayoutView) { + var view = new CreateEntityLayoutView({ + callback: function() { + that.fetchCollection(); + } + }); + }); + }, }); return SearchLayoutView; }); http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/edc4786b/dashboardv2/public/js/views/search/SearchResultLayoutView.js ---------------------------------------------------------------------- diff --git a/dashboardv2/public/js/views/search/SearchResultLayoutView.js b/dashboardv2/public/js/views/search/SearchResultLayoutView.js index 0a37834..ded4e38 100644 --- a/dashboardv2/public/js/views/search/SearchResultLayoutView.js +++ b/dashboardv2/public/js/views/search/SearchResultLayoutView.js @@ -57,7 +57,8 @@ define(['require', previousData: "[data-id='previousData']", nextData: "[data-id='nextData']", pageRecordText: "[data-id='pageRecordText']", - addAssignTag: "[data-id='addAssignTag']" + addAssignTag: "[data-id='addAssignTag']", + editEntityButton: "[data-id='editEntityButton']" }, /** ui events hash */ @@ -107,6 +108,7 @@ define(['require', }; events["click " + this.ui.nextData] = "onClicknextData"; events["click " + this.ui.previousData] = "onClickpreviousData"; + events["click " + this.ui.editEntityButton] = "onClickEditEntity"; return events; }, /** @@ -450,6 +452,7 @@ define(['require', nameHtml += '<button type="button" title="Deleted" class="btn btn-atlasAction btn-atlas deleteBtn"><i class="fa fa-trash"></i></button>'; return '<div class="readOnly readOnlyLink">' + nameHtml + '</div>'; } else { + nameHtml += '<button title="Edit" data-id="editEntityButton" data-giud= "' + (model.get('$id$').id || model.get('$id$')) + '" class="btn btn-atlasAction btn-atlas editBtn"><i class="fa fa-pencil"></i></button>' return nameHtml; } } @@ -485,6 +488,7 @@ define(['require', nameHtml += '<button type="button" title="Deleted" class="btn btn-atlasAction btn-atlas deleteBtn"><i class="fa fa-trash"></i></button>'; return '<div class="readOnly readOnlyLink">' + nameHtml + '</div>'; } else { + nameHtml += '<button title="Edit" data-giud= "' +(model.get('$id$').id || model.get('$id$')) + '" class="btn btn-atlasAction btn-atlas editBtn"><i class="fa fa-pencil"></i></button>' return nameHtml; } } @@ -667,6 +671,22 @@ define(['require', }); this.previousClick = true; this.fetchCollection(); + }, + + onClickEditEntity: function(e) { + var that = this; + $(e.currentTarget).blur(); + var guid = $(e.currentTarget).data('giud'); + require([ + 'views/entity/CreateEntityLayoutView' + ], function(CreateEntityLayoutView) { + var view = new CreateEntityLayoutView({ + guid: guid, + callback: function() { + that.fetchCollection(); + } + }); + }); } }); return SearchResultLayoutView;
