diff --git a/platform/commonUI/edit/bundle.js b/platform/commonUI/edit/bundle.js index 748e835d19..b0bede1f1f 100644 --- a/platform/commonUI/edit/bundle.js +++ b/platform/commonUI/edit/bundle.js @@ -23,7 +23,6 @@ define([ "./src/controllers/EditActionController", "./src/controllers/EditPanesController", - "./src/controllers/ElementsController", "./src/controllers/EditObjectController", "./src/actions/EditAndComposeAction", "./src/actions/EditAction", @@ -47,7 +46,6 @@ define([ "./src/creation/LocatorController", "./src/creation/CreationPolicy", "./src/creation/CreateActionProvider", - "./src/creation/AddActionProvider", "./src/creation/CreationService", "./res/templates/create/locator.html", "./res/templates/create/create-button.html", @@ -55,13 +53,11 @@ define([ "./res/templates/library.html", "./res/templates/edit-object.html", "./res/templates/edit-action-buttons.html", - "./res/templates/elements.html", "./res/templates/topbar-edit.html", 'legacyRegistry' ], function ( EditActionController, EditPanesController, - ElementsController, EditObjectController, EditAndComposeAction, EditAction, @@ -85,7 +81,6 @@ define([ LocatorController, CreationPolicy, CreateActionProvider, - AddActionProvider, CreationService, locatorTemplate, createButtonTemplate, @@ -93,7 +88,6 @@ define([ libraryTemplate, editObjectTemplate, editActionButtonsTemplate, - elementsTemplate, topbarEditTemplate, legacyRegistry ) { @@ -115,14 +109,6 @@ define([ "$scope" ] }, - { - "key": "ElementsController", - "implementation": ElementsController, - "depends": [ - "$scope", - "openmct" - ] - }, { "key": "EditObjectController", "implementation": EditObjectController, @@ -225,10 +211,10 @@ define([ "description": "Save changes made to these objects.", "depends": [ "$injector", - "policyService", "dialogService", "copyService", - "notificationService" + "notificationService", + "openmct" ], "priority": "mandatory" }, @@ -296,13 +282,6 @@ define([ "action" ] }, - { - "key": "edit-elements", - "template": elementsTemplate, - "gestures": [ - "drop" - ] - }, { "key": "topbar-edit", "template": topbarEditTemplate @@ -319,12 +298,6 @@ define([ ] } ], - "templates": [ - { - key: "elementsPool", - template: elementsTemplate - } - ], "components": [ { "type": "decorator", @@ -356,18 +329,6 @@ define([ "policyService" ] }, - { - "key": "AddActionProvider", - "provides": "actionService", - "type": "provider", - "implementation": AddActionProvider, - "depends": [ - "$q", - "typeService", - "dialogService", - "policyService" - ] - }, { "key": "CreationService", "provides": "creationService", diff --git a/platform/commonUI/edit/res/templates/elements.html b/platform/commonUI/edit/res/templates/elements.html deleted file mode 100644 index 80a35d00be..0000000000 --- a/platform/commonUI/edit/res/templates/elements.html +++ /dev/null @@ -1,49 +0,0 @@ - -
- - -
- -
No contained elements
-
-
diff --git a/platform/commonUI/edit/src/actions/SaveAsAction.js b/platform/commonUI/edit/src/actions/SaveAsAction.js index 642672cd8a..a00869eedb 100644 --- a/platform/commonUI/edit/src/actions/SaveAsAction.js +++ b/platform/commonUI/edit/src/actions/SaveAsAction.js @@ -40,20 +40,20 @@ function ( */ function SaveAsAction( $injector, - policyService, dialogService, copyService, notificationService, + openmct, context ) { this.domainObject = (context || {}).domainObject; this.injectObjectService = function () { this.objectService = $injector.get("objectService"); }; - this.policyService = policyService; this.dialogService = dialogService; this.copyService = copyService; this.notificationService = notificationService; + this.openmct = openmct; } /** @@ -63,7 +63,7 @@ function ( return new CreateWizard( this.domainObject, parent, - this.policyService + this.openmct ); }; diff --git a/platform/commonUI/edit/src/capabilities/EditorCapability.js b/platform/commonUI/edit/src/capabilities/EditorCapability.js index 614a17ea2e..c3a050e958 100644 --- a/platform/commonUI/edit/src/capabilities/EditorCapability.js +++ b/platform/commonUI/edit/src/capabilities/EditorCapability.js @@ -51,8 +51,11 @@ define( */ EditorCapability.prototype.edit = function () { console.warn('DEPRECATED: cannot edit via edit capability, use openmct.editor instead.'); - this.openmct.editor.edit(); - this.domainObject.getCapability('status').set('editing', true); + + if (!this.openmct.editor.isEditing()) { + this.openmct.editor.edit(); + this.domainObject.getCapability('status').set('editing', true); + } }; /** diff --git a/platform/commonUI/edit/src/controllers/ElementsController.js b/platform/commonUI/edit/src/controllers/ElementsController.js deleted file mode 100644 index ef041b4972..0000000000 --- a/platform/commonUI/edit/src/controllers/ElementsController.js +++ /dev/null @@ -1,197 +0,0 @@ -/***************************************************************************** - * Open MCT, Copyright (c) 2014-2018, United States Government - * as represented by the Administrator of the National Aeronautics and Space - * Administration. All rights reserved. - * - * Open MCT is licensed 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. - * - * Open MCT includes source code licensed under additional open source - * licenses. See the Open Source Licenses file (LICENSES.md) included with - * this source code distribution or the Licensing information page available - * at runtime from the About dialog for additional information. - *****************************************************************************/ - -define( - ['zepto'], - function ($) { - - /** - * The ElementsController prepares the elements view for display - * - * @constructor - */ - function ElementsController($scope, openmct) { - this.scope = $scope; - this.scope.composition = []; - this.openmct = openmct; - this.dragDown = this.dragDown.bind(this); - this.dragUp = this.dragUp.bind(this); - - var self = this; - - function filterBy(text) { - if (typeof text === 'undefined') { - return $scope.searchText; - } else { - $scope.searchText = text; - } - } - - function searchElements(value) { - if ($scope.searchText) { - return value.getModel().name.toLowerCase().search( - $scope.searchText.toLowerCase()) !== -1; - } else { - return true; - } - } - - function setSelection(selection) { - if (!selection[0]) { - return; - } - - if (self.mutationListener) { - self.mutationListener(); - delete self.mutationListener; - } - - var domainObject = selection[0].context.oldItem; - self.refreshComposition(domainObject); - - if (domainObject) { - - self.mutationListener = domainObject.getCapability('mutation') - .listen(self.refreshComposition.bind(self, domainObject)); - } - } - - $scope.filterBy = filterBy; - $scope.searchElements = searchElements; - - openmct.selection.on('change', setSelection); - setSelection(openmct.selection.get()); - - $scope.dragDown = this.dragDown; - $scope.drag = this.drag; - $scope.dragUp = this.dragUp; - - $scope.$on("$destroy", function () { - openmct.selection.off("change", setSelection); - }); - } - - /** - * Invoked on DragStart - Adds reordering class to parent UL element - * Sets selected object ID, to be used on Drag End - * - * @param {object} event | Mouse Event - */ - ElementsController.prototype.dragDown = function (event) { - if (!this.parentUL) { - this.parentUL = $(document).find('#inspector-elements-tree'); - } - - this.selectedTreeItem = $(event.target).parent(); - this.selectedObjectId = event.target.getAttribute('data-id'); - - this.parentUL.addClass('reordering'); - this.selectedTreeItem.addClass('reorder-actor'); - }; - - /** - * Invoked on dragEnd - Removes selected object from position in composition - * and replaces it at the target position. Composition is then updated with current - * scope - * - * @param {object} event - Mouse Event - */ - ElementsController.prototype.dragUp = function (event) { - this.targetObjectId = event.target.getAttribute('data-id'); - - if (this.targetObjectId && this.selectedObjectId) { - var selectedObjectPosition, - targetObjectPosition; - - selectedObjectPosition = findObjectInCompositionFromId(this.selectedObjectId, this.scope.composition); - targetObjectPosition = findObjectInCompositionFromId(this.targetObjectId, this.scope.composition); - - if ((selectedObjectPosition !== -1) && (targetObjectPosition !== -1)) { - var selectedObject = this.scope.composition.splice(selectedObjectPosition, 1), - selection = this.openmct.selection.get(), - domainObject = selection ? selection[0].context.oldItem : undefined; - - this.scope.composition.splice(targetObjectPosition, 0, selectedObject[0]); - - if (domainObject) { - domainObject.getCapability('mutation').mutate(function (model) { - model.composition = this.scope.composition.map(function (dObject) { - return dObject.id; - }); - }.bind(this)); - } - } - } - - if (this.parentUL) { - this.parentUL.removeClass('reordering'); - } - - if (this.selectedTreeItem) { - this.selectedTreeItem.removeClass('reorder-actor'); - } - }; - - ElementsController.prototype.drag = function (event) { - - }; - - /** - * Gets the composition for the selected object and populates the scope with it. - * - * @param domainObject the selected object - * @private - */ - ElementsController.prototype.refreshComposition = function (domainObject) { - var refreshTracker = {}; - this.currentRefresh = refreshTracker; - - var selectedObjectComposition = domainObject && domainObject.useCapability('composition'); - if (selectedObjectComposition) { - selectedObjectComposition.then(function (composition) { - if (this.currentRefresh === refreshTracker) { - this.scope.composition = composition; - } - }.bind(this)); - } else { - this.scope.composition = []; - } - }; - - /** - * Finds position of object with given ID in Composition - * - * @param {String} id - * @param {Array} composition - * @private - */ - function findObjectInCompositionFromId(id, composition) { - var mapped = composition.map(function (element) { - return element.id; - }); - - return mapped.indexOf(id); - } - - return ElementsController; - } -); diff --git a/platform/commonUI/edit/src/creation/AddAction.js b/platform/commonUI/edit/src/creation/AddAction.js deleted file mode 100644 index 06608f38e8..0000000000 --- a/platform/commonUI/edit/src/creation/AddAction.js +++ /dev/null @@ -1,133 +0,0 @@ -/***************************************************************************** - * Open MCT, Copyright (c) 2014-2018, United States Government - * as represented by the Administrator of the National Aeronautics and Space - * Administration. All rights reserved. - * - * Open MCT is licensed 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. - * - * Open MCT includes source code licensed under additional open source - * licenses. See the Open Source Licenses file (LICENSES.md) included with - * this source code distribution or the Licensing information page available - * at runtime from the About dialog for additional information. - *****************************************************************************/ - -/** - * Module defining AddAction. Created by ahenry on 01/21/16. - */ -define( - [ - './CreateWizard' - ], - function (CreateWizard) { - - /** - * The Add Action is performed to create new instances of - * domain objects of a specific type that are subobjects of an - * object being edited. This is the action that is performed when a - * user uses the Add menu option. - * - * @memberof platform/commonUI/browse - * @implements {Action} - * @constructor - * - * @param {Type} type the type of domain object to create - * @param {DomainObject} parent the domain object that should - * act as a container for the newly-created object - * (note that the user will have an opportunity to - * override this) - * @param {ActionContext} context the context in which the - * action is being performed - * @param {DialogService} dialogService - */ - function AddAction(type, parent, context, $q, dialogService, policyService) { - this.metadata = { - key: 'add', - cssClass: type.getCssClass(), - name: type.getName(), - type: type.getKey(), - description: type.getDescription(), - context: context - }; - - this.type = type; - this.parent = parent; - this.$q = $q; - this.dialogService = dialogService; - this.policyService = policyService; - } - - /** - * - * Create a new object of the given type. - * This will prompt for user input first. - * - * @returns {Promise} that will be resolved with the object that the - * action was originally invoked on (ie. the 'parent') - */ - AddAction.prototype.perform = function () { - var newModel = this.type.getInitialModel(), - newObject, - parentObject = this.parent, - wizard; - - newModel.type = this.type.getKey(); - newObject = parentObject.getCapability('instantiation').instantiate(newModel); - newObject.useCapability('mutation', function (model) { - model.location = parentObject.getId(); - }); - - wizard = new CreateWizard(newObject, this.parent, this.policyService); - - function populateObjectFromInput(formValue) { - return wizard.populateObjectFromInput(formValue, newObject); - } - - function persistAndReturn(domainObject) { - return domainObject.getCapability('persistence') - .persist() - .then(function () { - return domainObject; - }); - } - - function addToParent(populatedObject) { - parentObject.getCapability('composition').add(populatedObject); - return persistAndReturn(parentObject); - } - - return this.dialogService - .getUserInput(wizard.getFormStructure(false), wizard.getInitialFormValue()) - .then(populateObjectFromInput) - .then(persistAndReturn) - .then(addToParent); - - }; - - - /** - * Metadata associated with a Add action. - * @typedef {ActionMetadata} AddActionMetadata - * @property {string} type the key for the type of domain object - * to be created - */ - - /** - * Get metadata about this action. - * @returns {AddActionMetadata} metadata about this action - */ - AddAction.prototype.getMetadata = function () { - return this.metadata; - }; - - return AddAction; - } -); diff --git a/platform/commonUI/edit/src/creation/AddActionProvider.js b/platform/commonUI/edit/src/creation/AddActionProvider.js deleted file mode 100644 index 86891586a9..0000000000 --- a/platform/commonUI/edit/src/creation/AddActionProvider.js +++ /dev/null @@ -1,82 +0,0 @@ -/***************************************************************************** - * Open MCT, Copyright (c) 2014-2018, United States Government - * as represented by the Administrator of the National Aeronautics and Space - * Administration. All rights reserved. - * - * Open MCT is licensed 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. - * - * Open MCT includes source code licensed under additional open source - * licenses. See the Open Source Licenses file (LICENSES.md) included with - * this source code distribution or the Licensing information page available - * at runtime from the About dialog for additional information. - *****************************************************************************/ - -/** - * Module defining AddActionProvider.js. Created by ahenry on 01/21/16. - */ -define( - ["./AddAction"], - function (AddAction) { - - /** - * The AddActionProvider is an ActionProvider which introduces - * an Add action for creating sub objects. - * - * @memberof platform/commonUI/browse - * @constructor - * @implements {ActionService} - * - * @param {TypeService} typeService the type service, used to discover - * available types - * @param {DialogService} dialogService the dialog service, used by - * specific Create actions to get user input to populate the - * model of the newly-created domain object. - * @param {CreationService} creationService the creation service (also - * introduced in this bundle), responsible for handling actual - * object creation. - */ - function AddActionProvider($q, typeService, dialogService, policyService) { - this.typeService = typeService; - this.dialogService = dialogService; - this.$q = $q; - this.policyService = policyService; - } - - AddActionProvider.prototype.getActions = function (actionContext) { - var context = actionContext || {}, - key = context.key, - destination = context.domainObject; - - // We only provide Add actions, and we need a - // domain object to serve as the container for the - // newly-created object (although the user may later - // make a different selection) - if (key !== 'add' || !destination) { - return []; - } - - // Introduce one create action per type - return ['timeline', 'activity'].map(function (type) { - return new AddAction( - this.typeService.getType(type), - destination, - context, - this.$q, - this.dialogService, - this.policyService - ); - }, this); - }; - - return AddActionProvider; - } -); diff --git a/platform/commonUI/edit/src/creation/CreateWizard.js b/platform/commonUI/edit/src/creation/CreateWizard.js index 1a00361d91..46314c3d28 100644 --- a/platform/commonUI/edit/src/creation/CreateWizard.js +++ b/platform/commonUI/edit/src/creation/CreateWizard.js @@ -34,13 +34,13 @@ define( * @memberof platform/commonUI/browse * @constructor */ - function CreateWizard(domainObject, parent, policyService) { + function CreateWizard(domainObject, parent, openmct) { this.type = domainObject.getCapability('type'); this.model = domainObject.getModel(); this.domainObject = domainObject; this.properties = this.type.getProperties(); this.parent = parent; - this.policyService = policyService; + this.openmct = openmct; } /** @@ -56,15 +56,10 @@ define( */ CreateWizard.prototype.getFormStructure = function (includeLocation) { var sections = [], - domainObject = this.domainObject, - policyService = this.policyService; + domainObject = this.domainObject; function validateLocation(parent) { - return parent && policyService.allow( - "composition", - parent, - domainObject - ); + return parent && this.openmct.composition.checkPolicy(parent.useCapability('adapter'), domainObject.useCapability('adapter')); } sections.push({ @@ -93,7 +88,7 @@ define( rows: [{ name: "Save In", control: "locator", - validate: validateLocation, + validate: validateLocation.bind(this), key: "createParent" }] }); diff --git a/platform/commonUI/edit/test/controllers/ElementsControllerSpec.js b/platform/commonUI/edit/test/controllers/ElementsControllerSpec.js deleted file mode 100644 index 9a46941080..0000000000 --- a/platform/commonUI/edit/test/controllers/ElementsControllerSpec.js +++ /dev/null @@ -1,184 +0,0 @@ -/***************************************************************************** - * Open MCT, Copyright (c) 2014-2018, United States Government - * as represented by the Administrator of the National Aeronautics and Space - * Administration. All rights reserved. - * - * Open MCT is licensed 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. - * - * Open MCT includes source code licensed under additional open source - * licenses. See the Open Source Licenses file (LICENSES.md) included with - * this source code distribution or the Licensing information page available - * at runtime from the About dialog for additional information. - *****************************************************************************/ -/*global describe,it,expect,beforeEach,jasmine*/ - -define( - ["../../src/controllers/ElementsController"], - function (ElementsController) { - - describe("The Elements Pane controller", function () { - var mockScope, - mockOpenMCT, - mockSelection, - mockDomainObject, - mockMutationCapability, - mockCompositionCapability, - mockCompositionObjects, - mockComposition, - mockUnlisten, - selectable = [], - controller; - - function mockPromise(value) { - return { - then: function (thenFunc) { - return mockPromise(thenFunc(value)); - } - }; - } - - function createDomainObject() { - return { - useCapability: function () { - return mockCompositionCapability; - } - }; - } - - beforeEach(function () { - mockComposition = ["a", "b"]; - mockCompositionObjects = mockComposition.map(createDomainObject); - mockCompositionCapability = mockPromise(mockCompositionObjects); - - mockUnlisten = jasmine.createSpy('unlisten'); - mockMutationCapability = jasmine.createSpyObj("mutationCapability", [ - "listen" - ]); - mockMutationCapability.listen.and.returnValue(mockUnlisten); - mockDomainObject = jasmine.createSpyObj("domainObject", [ - "getCapability", - "useCapability" - ]); - mockDomainObject.useCapability.and.returnValue(mockCompositionCapability); - mockDomainObject.getCapability.and.returnValue(mockMutationCapability); - - mockScope = jasmine.createSpyObj("$scope", ['$on']); - mockSelection = jasmine.createSpyObj("selection", [ - 'on', - 'off', - 'get' - ]); - mockSelection.get.and.returnValue([]); - mockOpenMCT = { - selection: mockSelection - }; - - selectable[0] = { - context: { - oldItem: mockDomainObject - } - }; - - spyOn(ElementsController.prototype, 'refreshComposition').and.callThrough(); - - controller = new ElementsController(mockScope, mockOpenMCT); - }); - - function getModel(model) { - return function () { - return model; - }; - } - - it("filters objects in elements pool based on input text and" + - " object name", function () { - var objects = [ - { - getModel: getModel({name: "first element"}) - }, - { - getModel: getModel({name: "second element"}) - }, - { - getModel: getModel({name: "third element"}) - }, - { - getModel: getModel({name: "THIRD Element 1"}) - } - ]; - - mockScope.filterBy("third element"); - expect(objects.filter(mockScope.searchElements).length).toBe(2); - mockScope.filterBy("element"); - expect(objects.filter(mockScope.searchElements).length).toBe(4); - }); - - it("refreshes composition on selection", function () { - mockOpenMCT.selection.on.calls.mostRecent().args[1](selectable); - - expect(ElementsController.prototype.refreshComposition).toHaveBeenCalledWith(mockDomainObject); - }); - - it("listens on mutation and refreshes composition", function () { - mockOpenMCT.selection.on.calls.mostRecent().args[1](selectable); - - expect(mockDomainObject.getCapability).toHaveBeenCalledWith('mutation'); - expect(mockMutationCapability.listen).toHaveBeenCalled(); - expect(ElementsController.prototype.refreshComposition.calls.count()).toBe(1); - - mockMutationCapability.listen.calls.mostRecent().args[0](mockDomainObject); - - expect(ElementsController.prototype.refreshComposition.calls.count()).toBe(2); - }); - - it("cleans up mutation listener when selection changes", function () { - mockOpenMCT.selection.on.calls.mostRecent().args[1](selectable); - - expect(mockMutationCapability.listen).toHaveBeenCalled(); - - mockOpenMCT.selection.on.calls.mostRecent().args[1](selectable); - - expect(mockUnlisten).toHaveBeenCalled(); - }); - - it("does not listen on mutation for element proxy selectable", function () { - selectable[0] = { - context: { - elementProxy: {} - } - }; - mockOpenMCT.selection.on.calls.mostRecent().args[1](selectable); - - expect(mockDomainObject.getCapability).not.toHaveBeenCalledWith('mutation'); - }); - - it("checks concurrent changes to composition", function () { - var secondMockComposition = ["a", "b", "c"], - secondMockCompositionObjects = secondMockComposition.map(createDomainObject), - firstCompositionCallback, - secondCompositionCallback; - - spyOn(mockCompositionCapability, "then").and.callThrough(); - - controller.refreshComposition(mockDomainObject); - controller.refreshComposition(mockDomainObject); - - firstCompositionCallback = mockCompositionCapability.then.calls.all()[0].args[0]; - secondCompositionCallback = mockCompositionCapability.then.calls.all()[1].args[0]; - secondCompositionCallback(secondMockCompositionObjects); - firstCompositionCallback(mockCompositionObjects); - - expect(mockScope.composition).toBe(secondMockCompositionObjects); - }); - }); - } -); diff --git a/platform/commonUI/edit/test/creation/AddActionProviderSpec.js b/platform/commonUI/edit/test/creation/AddActionProviderSpec.js deleted file mode 100644 index 6d410919d5..0000000000 --- a/platform/commonUI/edit/test/creation/AddActionProviderSpec.js +++ /dev/null @@ -1,105 +0,0 @@ -/***************************************************************************** - * Open MCT, Copyright (c) 2014-2018, United States Government - * as represented by the Administrator of the National Aeronautics and Space - * Administration. All rights reserved. - * - * Open MCT is licensed 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. - * - * Open MCT includes source code licensed under additional open source - * licenses. See the Open Source Licenses file (LICENSES.md) included with - * this source code distribution or the Licensing information page available - * at runtime from the About dialog for additional information. - *****************************************************************************/ - -/** - * MCTRepresentationSpec. Created by ahenry on 01/21/14. - */ -define( - ["../../src/creation/AddActionProvider"], - function (AddActionProvider) { - - describe("The add action provider", function () { - var mockTypeService, - mockDialogService, - mockPolicyService, - mockTypeMap, - mockTypes, - mockDomainObject, - mockQ, - provider; - - function createMockType(name) { - var mockType = jasmine.createSpyObj( - "type" + name, - [ - "getKey", - "getGlyph", - "getCssClass", - "getName", - "getDescription", - "getProperties", - "getInitialModel", - "hasFeature" - ] - ); - mockType.hasFeature.and.returnValue(true); - mockType.getName.and.returnValue(name); - mockType.getKey.and.returnValue(name); - return mockType; - } - - beforeEach(function () { - mockTypeService = jasmine.createSpyObj( - "typeService", - ["getType"] - ); - mockDialogService = {}; - mockPolicyService = {}; - mockDomainObject = {}; - - mockTypes = [ - "timeline", - "activity", - "other" - ].map(createMockType); - mockTypeMap = {}; - - mockTypes.forEach(function (type) { - mockTypeMap[type.getKey()] = type; - }); - - mockTypeService.getType.and.callFake(function (key) { - return mockTypeMap[key]; - }); - - provider = new AddActionProvider( - mockQ, - mockTypeService, - mockDialogService, - mockPolicyService - ); - }); - - it("provides actions for timeline and activity", function () { - var actions = provider.getActions({ - key: "add", - domainObject: mockDomainObject - }); - expect(actions.length).toBe(2); - expect(actions[0].metadata.type).toBe('timeline'); - expect(actions[1].metadata.type).toBe('activity'); - - // Make sure it was creation which was used to check - }); - }); - } -); diff --git a/platform/containment/bundle.js b/platform/containment/bundle.js index c547b3bb17..05585a4268 100644 --- a/platform/containment/bundle.js +++ b/platform/containment/bundle.js @@ -58,7 +58,8 @@ define([ "category": "action", "implementation": ComposeActionPolicy, "depends": [ - "$injector" + "$injector", + "openmct" ], "message": "Objects of this type cannot contain objects of that type." }, diff --git a/platform/containment/src/ComposeActionPolicy.js b/platform/containment/src/ComposeActionPolicy.js index e13d524135..217e05eeec 100644 --- a/platform/containment/src/ComposeActionPolicy.js +++ b/platform/containment/src/ComposeActionPolicy.js @@ -36,10 +36,11 @@ define( * @memberof platform/containment * @implements {Policy.} */ - function ComposeActionPolicy($injector) { + function ComposeActionPolicy($injector, openmct) { this.getPolicyService = function () { return $injector.get('policyService'); }; + this.openmct = openmct; } ComposeActionPolicy.prototype.allowComposition = function (containerObject, selectedObject) { @@ -49,11 +50,8 @@ define( // ...and delegate to the composition policy return containerObject.getId() !== selectedObject.getId() && - this.policyService.allow( - 'composition', - containerObject, - selectedObject - ); + this.openmct.composition.checkPolicy(containerObject.useCapability('adapter'), + selectedObject.useCapability('adapter')); }; /** diff --git a/platform/entanglement/bundle.js b/platform/entanglement/bundle.js index 6233230e3e..3b7b614847 100644 --- a/platform/entanglement/bundle.js +++ b/platform/entanglement/bundle.js @@ -170,7 +170,7 @@ define([ "description": "Provides a service for moving objects", "implementation": MoveService, "depends": [ - "policyService", + "openmct", "linkService", "$q" ] @@ -181,7 +181,7 @@ define([ "description": "Provides a service for linking objects", "implementation": LinkService, "depends": [ - "policyService" + "openmct" ] }, { @@ -192,7 +192,7 @@ define([ "depends": [ "$q", "policyService", - "now" + "openmct" ] }, { diff --git a/platform/entanglement/src/services/CopyService.js b/platform/entanglement/src/services/CopyService.js index 78dc4859de..b08ff696fc 100644 --- a/platform/entanglement/src/services/CopyService.js +++ b/platform/entanglement/src/services/CopyService.js @@ -33,9 +33,10 @@ define( * @memberof platform/entanglement * @implements {platform/entanglement.AbstractComposeService} */ - function CopyService($q, policyService) { + function CopyService($q, policyService, openmct) { this.$q = $q; this.policyService = policyService; + this.openmct = openmct; } CopyService.prototype.validate = function (object, parentCandidate) { @@ -45,11 +46,7 @@ define( if (parentCandidate.getId() === object.getId()) { return false; } - return this.policyService.allow( - "composition", - parentCandidate, - object - ); + return this.openmct.composition.checkPolicy(parentCandidate.useCapability('adapter'), object.useCapability('adapter')); }; /** diff --git a/platform/entanglement/src/services/LinkService.js b/platform/entanglement/src/services/LinkService.js index 9625699837..2234d0b616 100644 --- a/platform/entanglement/src/services/LinkService.js +++ b/platform/entanglement/src/services/LinkService.js @@ -32,8 +32,8 @@ define( * @memberof platform/entanglement * @implements {platform/entanglement.AbstractComposeService} */ - function LinkService(policyService) { - this.policyService = policyService; + function LinkService(openmct) { + this.openmct = openmct; } LinkService.prototype.validate = function (object, parentCandidate) { @@ -49,11 +49,7 @@ define( if (parentCandidate.getModel().composition.indexOf(object.getId()) !== -1) { return false; } - return this.policyService.allow( - "composition", - parentCandidate, - object - ); + return this.openmct.composition.checkPolicy(parentCandidate.useCapability('adapter'), object.useCapability('adapter')); }; LinkService.prototype.perform = function (object, parentObject) { diff --git a/platform/entanglement/src/services/MoveService.js b/platform/entanglement/src/services/MoveService.js index 939f86308b..32c597bebf 100644 --- a/platform/entanglement/src/services/MoveService.js +++ b/platform/entanglement/src/services/MoveService.js @@ -31,8 +31,8 @@ define( * @memberof platform/entanglement * @implements {platform/entanglement.AbstractComposeService} */ - function MoveService(policyService, linkService) { - this.policyService = policyService; + function MoveService(openmct, linkService) { + this.openmct = openmct; this.linkService = linkService; } @@ -53,10 +53,9 @@ define( if (parentCandidate.getModel().composition.indexOf(object.getId()) !== -1) { return false; } - return this.policyService.allow( - "composition", - parentCandidate, - object + return this.openmct.composition.checkPolicy( + parentCandidate.useCapability('adapter'), + object.useCapability('adapter') ); }; diff --git a/platform/features/fixed/src/LayoutCompositionPolicy.js b/platform/features/fixed/src/LayoutCompositionPolicy.js deleted file mode 100644 index 41cfd56713..0000000000 --- a/platform/features/fixed/src/LayoutCompositionPolicy.js +++ /dev/null @@ -1,51 +0,0 @@ -/***************************************************************************** - * Open MCT, Copyright (c) 2014-2018, United States Government - * as represented by the Administrator of the National Aeronautics and Space - * Administration. All rights reserved. - * - * Open MCT is licensed 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. - * - * Open MCT includes source code licensed under additional open source - * licenses. See the Open Source Licenses file (LICENSES.md) included with - * this source code distribution or the Licensing information page available - * at runtime from the About dialog for additional information. - *****************************************************************************/ - -define( - [], - function () { - - /** - * Defines composition policy for Display Layout objects. - * They cannot contain folders. - * @constructor - * @memberof platform/features/layout - * @implements {Policy.} - */ - function LayoutCompositionPolicy() { - } - - LayoutCompositionPolicy.prototype.allow = function (parent, child) { - var parentType = parent.getCapability('type'); - if (parentType.instanceOf('layout') && - child.getCapability('type').instanceOf('folder')) { - - return false; - } - - return true; - }; - - return LayoutCompositionPolicy; - } -); - diff --git a/platform/features/fixed/test/LayoutCompositionPolicySpec.js b/platform/features/fixed/test/LayoutCompositionPolicySpec.js deleted file mode 100644 index 19872ac267..0000000000 --- a/platform/features/fixed/test/LayoutCompositionPolicySpec.js +++ /dev/null @@ -1,82 +0,0 @@ -/***************************************************************************** - * Open MCT, Copyright (c) 2014-2018, United States Government - * as represented by the Administrator of the National Aeronautics and Space - * Administration. All rights reserved. - * - * Open MCT is licensed 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. - * - * Open MCT includes source code licensed under additional open source - * licenses. See the Open Source Licenses file (LICENSES.md) included with - * this source code distribution or the Licensing information page available - * at runtime from the About dialog for additional information. - *****************************************************************************/ - -define( - ["../src/LayoutCompositionPolicy"], - function (LayoutCompositionPolicy) { - describe("Layout's composition policy", function () { - var mockChild, - mockCandidateObj, - mockCandidate, - mockContext, - candidateType, - contextType, - policy; - - beforeEach(function () { - mockChild = jasmine.createSpyObj( - 'childObject', - ['getCapability'] - ); - mockCandidate = - jasmine.createSpyObj('candidateType', ['instanceOf']); - mockContext = - jasmine.createSpyObj('contextType', ['instanceOf']); - - mockCandidateObj = jasmine.createSpyObj('domainObj', [ - 'getCapability' - ]); - mockCandidateObj.getCapability.and.returnValue(mockCandidate); - - mockChild.getCapability.and.returnValue(mockContext); - - mockCandidate.instanceOf.and.callFake(function (t) { - return t === candidateType; - }); - mockContext.instanceOf.and.callFake(function (t) { - return t === contextType; - }); - - policy = new LayoutCompositionPolicy(); - }); - - it("disallows folders in layouts", function () { - candidateType = 'layout'; - contextType = 'folder'; - expect(policy.allow(mockCandidateObj, mockChild)).toBe(false); - }); - - it("does not disallow folders elsewhere", function () { - candidateType = 'nonlayout'; - contextType = 'folder'; - expect(policy.allow(mockCandidateObj, mockChild)).toBe(true); - }); - - it("allows things other than folders in layouts", function () { - candidateType = 'layout'; - contextType = 'nonfolder'; - expect(policy.allow(mockCandidateObj, mockChild)).toBe(true); - }); - - }); - } -); diff --git a/src/adapter/bundle.js b/src/adapter/bundle.js index f32cbb11d8..9e17e268e3 100644 --- a/src/adapter/bundle.js +++ b/src/adapter/bundle.js @@ -28,7 +28,6 @@ define([ './services/Instantiate', './services/MissingModelCompatibilityDecorator', './capabilities/APICapabilityDecorator', - './policies/AdapterCompositionPolicy', './policies/AdaptedViewPolicy', './runs/AlternateCompositionInitializer', './runs/TimeSettingsURLHandler', @@ -36,7 +35,8 @@ define([ './runs/LegacyTelemetryProvider', './runs/RegisterLegacyTypes', './services/LegacyObjectAPIInterceptor', - './views/installLegacyViews' + './views/installLegacyViews', + './policies/legacyCompositionPolicyAdapter' ], function ( legacyRegistry, ActionDialogDecorator, @@ -45,7 +45,6 @@ define([ Instantiate, MissingModelCompatibilityDecorator, APICapabilityDecorator, - AdapterCompositionPolicy, AdaptedViewPolicy, AlternateCompositionInitializer, TimeSettingsURLHandler, @@ -53,7 +52,8 @@ define([ LegacyTelemetryProvider, RegisterLegacyTypes, LegacyObjectAPIInterceptor, - installLegacyViews + installLegacyViews, + legacyCompositionPolicyAdapter ) { legacyRegistry.register('src/adapter', { "extensions": { @@ -117,11 +117,6 @@ define([ } ], policies: [ - { - category: "composition", - implementation: AdapterCompositionPolicy, - depends: ["openmct"] - }, { category: "view", implementation: AdaptedViewPolicy, @@ -168,6 +163,12 @@ define([ "types[]", "openmct" ] + }, + { + implementation: legacyCompositionPolicyAdapter.default, + depends: [ + "openmct" + ] } ], licenses: [ diff --git a/src/adapter/policies/AdapterCompositionPolicy.js b/src/adapter/policies/LegacyCompositionPolicyAdapter.js similarity index 63% rename from src/adapter/policies/AdapterCompositionPolicy.js rename to src/adapter/policies/LegacyCompositionPolicyAdapter.js index 8f639b1811..350eb8a346 100644 --- a/src/adapter/policies/AdapterCompositionPolicy.js +++ b/src/adapter/policies/LegacyCompositionPolicyAdapter.js @@ -20,20 +20,23 @@ * at runtime from the About dialog for additional information. *****************************************************************************/ -define([], function () { - function AdapterCompositionPolicy(openmct) { - this.openmct = openmct; - } +export default function legacyCompositionPolicyAdapter(openmct) { + const instantiate = this.openmct.$injector.get('instantiate'); + const policyService = this.openmct.$injector.get('policyService'); - AdapterCompositionPolicy.prototype.allow = function ( - parent, - child - ) { - return this.openmct.composition.checkPolicy( - parent, - child + openmct.composition.addPolicy((parent, child) => { + + let parentId = this.openmct.objects.makeKeyString(parent.identifier); + let childId = this.openmct.objects.makeKeyString(child.identifier); + + let legacyParent = instantiate(parent, parentId); + let legacyChild = instantiate(child, childId); + let result = policyService.allow( + 'composition', + legacyParent, + legacyChild ); - }; - return AdapterCompositionPolicy; -}); + return result; + }); +} diff --git a/src/api/Editor.js b/src/api/Editor.js index f5590b949f..b0814080a7 100644 --- a/src/api/Editor.js +++ b/src/api/Editor.js @@ -36,6 +36,9 @@ export default class Editor extends EventEmitter { * or finish() are called. */ edit() { + if (this.editing === true) { + throw "Already editing"; + } this.editing = true; this.getTransactionService().startTransaction(); this.emit('isEditing', true); diff --git a/src/api/composition/CompositionAPI.js b/src/api/composition/CompositionAPI.js index a5efe15d43..ea122c290d 100644 --- a/src/api/composition/CompositionAPI.js +++ b/src/api/composition/CompositionAPI.js @@ -44,7 +44,7 @@ define([ function CompositionAPI(publicAPI) { this.registry = []; this.policies = []; - this.addProvider(new DefaultCompositionProvider(publicAPI)); + this.addProvider(new DefaultCompositionProvider(publicAPI, this)); this.publicAPI = publicAPI; } diff --git a/src/api/composition/DefaultCompositionProvider.js b/src/api/composition/DefaultCompositionProvider.js index 8320880cdb..3399a7306d 100644 --- a/src/api/composition/DefaultCompositionProvider.js +++ b/src/api/composition/DefaultCompositionProvider.js @@ -43,9 +43,34 @@ define([ * @memberof module:openmct */ - function DefaultCompositionProvider(publicAPI) { + function DefaultCompositionProvider(publicAPI, compositionAPI) { this.publicAPI = publicAPI; this.listeningTo = {}; + + this.cannotContainDuplicates = this.cannotContainDuplicates.bind(this); + this.cannotContainItself = this.cannotContainItself.bind(this); + + compositionAPI.addPolicy(this.cannotContainDuplicates); + compositionAPI.addPolicy(this.cannotContainItself); + } + + /** + * @private + */ + DefaultCompositionProvider.prototype.cannotContainDuplicates = function (parent, child) { + return this.appliesTo(parent) && + parent.composition.findIndex((composeeId) => { + return composeeId.namespace === child.identifier.namespace && + composeeId.key === child.identifier.key; + }) === -1; + } + + /** + * @private + */ + DefaultCompositionProvider.prototype.cannotContainItself = function (parent, child) { + return !(parent.identifier.namespace === child.identifier.namespace && + parent.identifier.key === child.identifier.key); } /** @@ -203,7 +228,7 @@ define([ } var oldComposition = listeners.composition.map(objectUtils.makeKeyString); - var newComposition = oldDomainObject.getModel().composition; + var newComposition = oldDomainObject.getModel().composition.map(objectUtils.makeKeyString); var added = _.difference(newComposition, oldComposition).map(objectUtils.parseKeyString); var removed = _.difference(oldComposition, newComposition).map(objectUtils.parseKeyString); diff --git a/src/plugins/displayLayout/DisplayLayout.vue b/src/plugins/displayLayout/DisplayLayout.vue index 39bb9d1375..694030205d 100644 --- a/src/plugins/displayLayout/DisplayLayout.vue +++ b/src/plugins/displayLayout/DisplayLayout.vue @@ -276,33 +276,14 @@ }, handleDrop($event) { $event.preventDefault(); - $event.stopPropagation(); let child = JSON.parse($event.dataTransfer.getData('domainObject')); - let duplicates = []; - let composition = this.newDomainObject.composition; - composition.forEach((object) => { - if (this.openmct.objects.makeKeyString(JSON.parse(JSON.stringify(object))) === - this.openmct.objects.makeKeyString(child.identifier)) { - duplicates.push(object); - } - }); - - // Disallow adding a duplicate object to the composition - if (duplicates.length !== 0) { - return; - } let elementRect = this.$el.getBoundingClientRect(); this.droppedObjectPosition = { x: $event.pageX - elementRect.left, y: $event.pageY - elementRect.top } - // TODO: use the composition API to add child once the default composition - // provider supports it instead of mutating the composition directly. - // this.composition.add(child). - composition.push(child.identifier); - this.mutate('composition', composition); }, handleDragOver($event){ $event.preventDefault(); diff --git a/src/plugins/displayLayout/plugin.js b/src/plugins/displayLayout/plugin.js index a9bdbe19de..818d984fd7 100644 --- a/src/plugins/displayLayout/plugin.js +++ b/src/plugins/displayLayout/plugin.js @@ -63,6 +63,13 @@ export default function () { } }); openmct.types.addType('layout', DisplayLayoutType()); + openmct.composition.addPolicy((parent, child) => { + if (parent.type === 'layout' && child.type === 'folder') { + return false; + } else { + return true; + } + }); openmct.toolbars.addProvider({ name: "Display Layout Toolbar", key: "layout", diff --git a/src/plugins/telemetryTable/TelemetryTableType.js b/src/plugins/telemetryTable/TelemetryTableType.js index 395a81fe68..fcb382d0bf 100644 --- a/src/plugins/telemetryTable/TelemetryTableType.js +++ b/src/plugins/telemetryTable/TelemetryTableType.js @@ -21,19 +21,16 @@ *****************************************************************************/ define(function () { - function TelemetryTableType() { - return { - name: 'Telemetry Table', - description: 'Display telemetry values for the current time bounds in tabular form. Supports filtering and sorting.', - creatable: true, - cssClass: 'icon-tabular-realtime', - initialize(domainObject) { - domainObject.composition = []; - domainObject.configuration = { - columns: {} - }; - } + return { + name: 'Telemetry Table', + description: 'Display telemetry values for the current time bounds in tabular form. Supports filtering and sorting.', + creatable: true, + cssClass: 'icon-tabular-realtime', + initialize(domainObject) { + domainObject.composition = []; + domainObject.configuration = { + columns: {} + }; } - } - return TelemetryTableType; -}); \ No newline at end of file + }; +}); diff --git a/src/plugins/telemetryTable/components/table.vue b/src/plugins/telemetryTable/components/table.vue index b22f443a19..8dcdc68361 100644 --- a/src/plugins/telemetryTable/components/table.vue +++ b/src/plugins/telemetryTable/components/table.vue @@ -191,7 +191,6 @@ export default { search }, inject: ['table', 'openmct', 'csvExporter'], - props: ['configuration'], data() { return { headers: {}, diff --git a/src/plugins/telemetryTable/plugin.js b/src/plugins/telemetryTable/plugin.js index 1cc0750ef0..8a56336dc3 100644 --- a/src/plugins/telemetryTable/plugin.js +++ b/src/plugins/telemetryTable/plugin.js @@ -20,20 +20,27 @@ * at runtime from the About dialog for additional information. *****************************************************************************/ - define([ - './TelemetryTableViewProvider', - './TableConfigurationViewProvider', - './TelemetryTableType' - ], function ( - TelemetryTableViewProvider, - TableConfigurationViewProvider, - TelemetryTableType - ) { +define([ + './TelemetryTableViewProvider', + './TableConfigurationViewProvider', + './TelemetryTableType' +], function ( + TelemetryTableViewProvider, + TableConfigurationViewProvider, + TelemetryTableType +) { return function plugin() { return function install(openmct) { openmct.objectViews.addProvider(new TelemetryTableViewProvider(openmct)); openmct.inspectorViews.addProvider(new TableConfigurationViewProvider(openmct)); - openmct.types.addType('table', TelemetryTableType()); + openmct.types.addType('table', TelemetryTableType); + openmct.composition.addPolicy((parent, child) => { + if (parent.type === 'table') { + return child.hasOwnProperty('telemetry'); + } else { + return true; + } + }); }; }; - }); \ No newline at end of file +}); diff --git a/src/ui/components/controls/ObjectLabel.vue b/src/ui/components/controls/ObjectLabel.vue new file mode 100644 index 0000000000..0b63ffdd80 --- /dev/null +++ b/src/ui/components/controls/ObjectLabel.vue @@ -0,0 +1,42 @@ + + + diff --git a/src/ui/components/inspector/Elements.vue b/src/ui/components/inspector/Elements.vue index 4d4f5afd70..951992f74c 100644 --- a/src/ui/components/inspector/Elements.vue +++ b/src/ui/components/inspector/Elements.vue @@ -1,33 +1,136 @@ + diff --git a/src/ui/components/inspector/Inspector.vue b/src/ui/components/inspector/Inspector.vue index a6774f51ed..e1a3b7e272 100644 --- a/src/ui/components/inspector/Inspector.vue +++ b/src/ui/components/inspector/Inspector.vue @@ -8,7 +8,7 @@ + label="Elements" v-if="isEditing"> @@ -188,6 +188,9 @@ export default { inject: ['openmct'], + props: { + 'isEditing': Boolean + }, components: { multipane, pane, diff --git a/src/ui/components/layout/Layout.vue b/src/ui/components/layout/Layout.vue index 4aeed04a4e..d17fe48fcc 100644 --- a/src/ui/components/layout/Layout.vue +++ b/src/ui/components/layout/Layout.vue @@ -43,7 +43,7 @@ handle="before" label="Inspect" collapsable> - +
diff --git a/src/ui/components/layout/ObjectView.vue b/src/ui/components/layout/ObjectView.vue index 2b856272bb..8b903c49af 100644 --- a/src/ui/components/layout/ObjectView.vue +++ b/src/ui/components/layout/ObjectView.vue @@ -35,6 +35,8 @@ export default { mounted() { this.currentObject = this.object; this.updateView(); + this.$el.addEventListener('dragover', this.onDragOver); + this.$el.addEventListener('drop', this.onDrop); }, methods: { clear() { @@ -64,9 +66,34 @@ export default { this.currentView.show(this.viewContainer); }, show(object, viewKey) { + if (this.unlisten) { + this.unlisten(); + } this.currentObject = object; + this.unlisten = this.openmct.objects.observe(this.currentObject, '*', (mutatedObject) => { + this.currentObject = mutatedObject; + }); + this.viewKey = viewKey; this.updateView(); + }, + onDragOver(event) { + event.preventDefault(); + }, + onDrop(event) { + let parentObject = this.currentObject; + let childObject = JSON.parse(event.dataTransfer.getData("domainObject")); + + if (this.openmct.composition.checkPolicy(parentObject, childObject)){ + if (!this.openmct.editor.isEditing() && parentObject.type !== 'folder'){ + this.openmct.editor.edit(); + } + parentObject.composition.push(childObject.identifier); + this.openmct.objects.mutate(parentObject, 'composition', parentObject.composition); + } + + event.preventDefault(); + event.stopPropagation(); } } } diff --git a/src/ui/components/layout/tree-item.vue b/src/ui/components/layout/tree-item.vue index f6feed3910..9892f4f540 100644 --- a/src/ui/components/layout/tree-item.vue +++ b/src/ui/components/layout/tree-item.vue @@ -7,14 +7,7 @@ :expanded="expanded" @click="toggleChildren"> - -
-
{{ node.object.name }}
-
+