Compare commits

...

18 Commits

Author SHA1 Message Date
Nikhil Mandlik
388e73157e test 2022-02-02 13:35:07 -08:00
dependabot[bot]
e434b294b9 Bump karma from 6.3.11 to 6.3.13 (#4816)
Bumps [karma](https://github.com/karma-runner/karma) from 6.3.11 to 6.3.13.
- [Release notes](https://github.com/karma-runner/karma/releases)
- [Changelog](https://github.com/karma-runner/karma/blob/master/CHANGELOG.md)
- [Commits](https://github.com/karma-runner/karma/compare/v6.3.11...v6.3.13)

---
updated-dependencies:
- dependency-name: karma
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-02-01 12:15:09 -08:00
John Hill
48b66e0af2 [CI] Update playwright to 1.18.1 (#4805)
* Update package.json
* Update config.yml
2022-01-31 16:19:41 -08:00
Scott Bell
54ef9a830e Show all options when clicking arrow in autocomplete form - Mct4578 (#4708)
Co-authored-by: Andrew Henry <akhenry@gmail.com>
Co-authored-by: Nikhil <nikhil.k.mandlik@nasa.gov>
Co-authored-by: Jamie V <jamie.j.vigliotta@nasa.gov>
2022-01-28 13:24:04 -08:00
John Hill
cd38545267 [Build]npm run clean uses absolute node_modules directory instead of relative (#4801) 2022-01-27 11:00:01 -08:00
John Hill
8aed21d670 [CI] Update github actions automation to work across forks (#4799)
* Update e2e-pr.yml

* Update e2e-pr.yml
2022-01-27 08:41:33 -08:00
Shefali Joshi
b27f24cc30 Merge release 1.8.4 into master (#4797)
* Update version number (#4759)

* update copyright (#4775)

* Observe changes to sub-objects in flexible layouts. (#4780)

* Get child of flex layout as mutable if possible

* Fix bug when no default notebook defined

* Follow domain object changes for Independent time conductor (#4783)

* Track if domain object changes when independent time conductor is in use.

* fix typo when using fallback template (#4784)

Co-authored-by: Scott Bell <scott@traclabs.com>
Co-authored-by: Andrew Henry <akhenry@gmail.com>
2022-01-27 06:32:47 -08:00
dependabot[bot]
a7df8bf168 Bump eslint-plugin-playwright from 0.7.1 to 0.8.0 (#4792)
Bumps [eslint-plugin-playwright](https://github.com/playwright-community/eslint-plugin-playwright) from 0.7.1 to 0.8.0.
- [Release notes](https://github.com/playwright-community/eslint-plugin-playwright/releases)
- [Commits](https://github.com/playwright-community/eslint-plugin-playwright/compare/v0.7.1...v0.8.0)

---
updated-dependencies:
- dependency-name: eslint-plugin-playwright
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-26 12:34:39 -08:00
John Hill
ff269ac390 [Docs] Update PR Template warning (#4791)
* [Docs] Update PR Template warning
2022-01-26 19:55:55 +00:00
John Hill
cdee5e8102 [CI] Update PR Template to remove the colon from Closes (#4785) 2022-01-26 11:34:07 -08:00
John Hill
159457a52d [Build] Update minimum node12 version (#4779) 2022-01-25 14:06:15 -08:00
David 'Epper' Marshall
d637420da1 Mct4467 (#4468)
* dynamic grid display
* add one more guard
2022-01-25 12:56:51 -08:00
John Hill
eb4da293c6 [CI]Update dependabot rules again (#4762)
* Update dependabot rules again

* update safeword

Co-authored-by: Shefali Joshi <simplyrender@gmail.com>
2022-01-25 14:10:00 +00:00
dependabot[bot]
738fac64b8 Bump vue-eslint-parser from 8.1.0 to 8.2.0 (#4770)
Bumps [vue-eslint-parser](https://github.com/vuejs/vue-eslint-parser) from 8.1.0 to 8.2.0.
- [Release notes](https://github.com/vuejs/vue-eslint-parser/releases)
- [Commits](https://github.com/vuejs/vue-eslint-parser/compare/v8.1.0...v8.2.0)

---
updated-dependencies:
- dependency-name: vue-eslint-parser
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-24 15:57:30 -08:00
dependabot[bot]
7703ec0a61 Bump vue-eslint-parser from 8.0.1 to 8.1.0 (#4761)
Bumps [vue-eslint-parser](https://github.com/vuejs/vue-eslint-parser) from 8.0.1 to 8.1.0.
- [Release notes](https://github.com/vuejs/vue-eslint-parser/releases)
- [Commits](https://github.com/vuejs/vue-eslint-parser/compare/v8.0.1...v8.1.0)

---
updated-dependencies:
- dependency-name: vue-eslint-parser
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-21 13:36:26 -08:00
Shefali Joshi
52466999b8 Prepare for sprint 1.8.5 (#4760) 2022-01-20 18:57:29 -08:00
Jamie V
45373c56f7 [MCT Tree] Enhance to be used as selection tree as well (#4734)
* removed selector tree, using mct-tree for selctor now, updated style view to use new forms api, update mct-tree to be a selector if need be

* added some extra calculations for height when the tree is being used as a selector in forms

Co-authored-by: Shefali Joshi <simplyrender@gmail.com>
2022-01-21 02:46:40 +00:00
Andrew Henry
91e909bb4a Fix notebook sync (#4738)
* Do not keep fetching default notebook

* Fixes issue where notebooks would stop listening for remote changes.

* Fix issue with notebook merge conflicts
2022-01-20 18:43:17 -08:00
37 changed files with 319 additions and 690 deletions

View File

@@ -2,7 +2,7 @@ version: 2.1
executors:
pw-focal-development:
docker:
- image: mcr.microsoft.com/playwright:v1.18.0-focal
- image: mcr.microsoft.com/playwright:v1.18.1-focal
environment:
NODE_ENV: development # Needed to ensure 'dist' folder created and devDependencies installed
parameters:

View File

@@ -1,5 +1,5 @@
<!--- Note: Please open the PR in draft form until you are ready for active review. -->
Closes: <!--- Insert Issue Number(s) this PR addresses. Start by typing # will open a dropdown of recent issues. -->
Closes <!--- Insert Issue Number(s) this PR addresses. Start by typing # will open a dropdown of recent issues. Note: this does not work on PRs which target release branches -->
### Describe your changes:
<!--- Describe your changes and add any comments about your approach either here or inline if code comments aren't added -->

View File

@@ -10,6 +10,7 @@ updates:
- "type:maintenance"
- "dependencies"
- "pr:e2e"
- "pr:daveit"
allow:
- dependency-name: "*eslint*"
- dependency-name: "*karma*"
@@ -25,4 +26,4 @@ updates:
labels:
- "type:maintenance"
- "dependencies"
- "prcop:disable"
- "pr:daveit"

View File

@@ -15,8 +15,8 @@ jobs:
script: |
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
owner: "nasa",
repo: "openmct",
body: 'Started e2e Run. Follow along: https://github.com/nasa/openmct/actions/runs/' + context.runId
})
- uses: actions/checkout@v2
@@ -37,8 +37,8 @@ jobs:
script: |
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
owner: "nasa",
repo: "openmct",
body: 'Success ✅ ! Build artifacts are here: https://github.com/nasa/openmct/actions/runs/' + context.runId
})
- name: Test failure
@@ -48,7 +48,7 @@ jobs:
script: |
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
owner: "nasa",
repo: "openmct",
body: 'Failure ❌ ! Build artifacts are here: https://github.com/nasa/openmct/actions/runs/' + context.runId
})

View File

@@ -15,5 +15,5 @@
}
}
],
"disableWord": "prcop:disable"
"disableWord": "pr:daveit"
}

View File

@@ -1,5 +1,5 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2021, United States Government
* Open MCT, Copyright (c) 2014-2022, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*

View File

@@ -1,5 +1,5 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2021, United States Government
* Open MCT, Copyright (c) 2014-2022, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*

View File

@@ -1,5 +1,5 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2021, United States Government
* Open MCT, Copyright (c) 2014-2022, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*

View File

@@ -1,5 +1,5 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2021, United States Government
* Open MCT, Copyright (c) 2014-2022, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*

View File

@@ -1,12 +1,12 @@
{
"name": "openmct",
"version": "1.8.4-SNAPSHOT",
"version": "1.8.5-SNAPSHOT",
"description": "The Open MCT core platform",
"devDependencies": {
"@braintree/sanitize-url": "^5.0.2",
"@percy/cli": "^1.0.0-beta.73",
"@percy/playwright": "^1.0.1",
"@playwright/test": "^1.18.0",
"@playwright/test": "^1.18.1",
"allure-playwright": "^2.0.0-beta.14",
"angular": ">=1.8.0",
"angular-route": "1.4.14",
@@ -20,7 +20,7 @@
"d3-scale": "1.0.x",
"d3-selection": "1.3.x",
"eslint": "7.0.0",
"eslint-plugin-playwright": "0.7.1",
"eslint-plugin-playwright": "0.8.0",
"eslint-plugin-vue": "^7.5.0",
"eslint-plugin-you-dont-need-lodash-underscore": "^6.10.0",
"eventemitter3": "^1.2.0",
@@ -36,7 +36,7 @@
"istanbul-instrumenter-loader": "^3.0.1",
"jasmine-core": "^4.0.0",
"jsdoc": "^3.3.2",
"karma": "6.3.11",
"karma": "6.3.13",
"karma-chrome-launcher": "3.1.0",
"karma-cli": "2.0.0",
"karma-coverage": "2.1.0",
@@ -58,7 +58,7 @@
"moment-timezone": "0.5.28",
"node-bourbon": "^4.2.3",
"painterro": "^1.2.56",
"playwright": "^1.18.0",
"playwright": "^1.18.1",
"plotly.js-basic-dist": "^2.5.0",
"plotly.js-gl2d-dist": "^2.5.0",
"printj": "^1.2.1",
@@ -73,7 +73,7 @@
"uuid": "^3.3.3",
"v8-compile-cache": "^1.1.0",
"vue": "2.5.6",
"vue-eslint-parser": "8.0.1",
"vue-eslint-parser": "8.2.0",
"vue-loader": "15.9.8",
"vue-template-compiler": "2.5.6",
"webpack": "^5.65.0",
@@ -84,8 +84,8 @@
"zepto": "^1.2.0"
},
"scripts": {
"clean": "rm -rf ./dist /node_modules; rm package-lock.json",
"clean-test-lint": "npm run clean; npm install ; npm run test; npm run lint",
"clean": "rm -rf ./dist ./node_modules; rm package-lock.json",
"clean-test-lint": "npm run clean; npm install; npm run test; npm run lint",
"start": "node app.js",
"lint": "eslint platform example src --ext .js,.vue openmct.js",
"lint:fix": "eslint platform example src --ext .js,.vue openmct.js --fix",
@@ -114,7 +114,7 @@
"url": "https://github.com/nasa/openmct.git"
},
"engines": {
"node": ">=12.0.1 <15.0.0"
"node": ">=12.20.1 <15.0.0"
},
"author": "",
"license": "Apache-2.0",

View File

@@ -65,6 +65,7 @@ export default {
data() {
return {
hideOptions: true,
showFilteredOptions: false,
optionIndex: 0,
field: this.model.value
};
@@ -72,16 +73,24 @@ export default {
computed: {
filteredOptions() {
const options = this.optionNames || [];
if (this.showFilteredOptions) {
return options
.filter(option => {
return option.toLowerCase().indexOf(this.field.toLowerCase()) >= 0;
}).map((option, index) => {
return {
optionId: index,
name: option
};
});
}
return options
.filter(option => {
return option.toLowerCase().indexOf(this.field.toLowerCase()) >= 0;
}).map((option, index) => {
return {
optionId: index,
name: option
};
});
return options.map((option, index) => {
return {
optionId: index,
name: option
};
});
}
},
watch: {
@@ -131,11 +140,12 @@ export default {
this.hideOptions = true;
this.field = string;
},
showOptions(string) {
showOptions() {
this.hideOptions = false;
this.optionIndex = 0;
},
keyDown($event) {
this.showFilteredOptions = true;
if (this.filteredOptions) {
let keyCode = $event.keyCode;
switch (keyCode) {
@@ -155,11 +165,14 @@ export default {
},
inputClicked() {
this.autocompleteInputElement.select();
this.showOptions(this.autocompleteInputElement.value);
this.showOptions();
},
arrowClicked() {
// if the user clicked the arrow, we want
// to show them all the options
this.showFilteredOptions = false;
this.autocompleteInputElement.select();
this.showOptions('');
this.showOptions();
},
optionMouseover(optionId) {
this.optionIndex = optionId;

View File

@@ -21,19 +21,19 @@
*****************************************************************************/
<template>
<SelectorDialogTree :ignore-type-check="true"
:css-class="`form-locator c-form-control--locator`"
:parent="model.parent"
@treeItemSelected="handleItemSelection"
<mct-tree
:is-selector-tree="true"
:initial-selection="model.parent"
@tree-item-selection="handleItemSelection"
/>
</template>
<script>
import SelectorDialogTree from '@/ui/components/SelectorDialogTree.vue';
import MctTree from '@/ui/layout/mct-tree.vue';
export default {
components: {
SelectorDialogTree
MctTree
},
inject: ['openmct'],
props: {
@@ -43,10 +43,10 @@ export default {
}
},
methods: {
handleItemSelection({ parentObjectPath }) {
handleItemSelection(item) {
const data = {
model: this.model,
value: parentObjectPath
value: item.objectPath
};
this.$emit('onChange', data);

View File

@@ -465,23 +465,6 @@ ObjectAPI.prototype.mutate = function (domainObject, path, value) {
}
};
/**
* Updates a domain object based on its latest persisted state. Note that this will mutate the provided object.
* @param {module:openmct.DomainObject} domainObject an object to refresh from its persistence store
* @returns {Promise} the provided object, updated to reflect the latest persisted state of the object.
*/
ObjectAPI.prototype.refresh = async function (domainObject) {
const refreshedObject = await this.get(domainObject.identifier);
if (domainObject.isMutable) {
domainObject.$refresh(refreshedObject);
} else {
utils.refresh(domainObject, refreshedObject);
}
return domainObject;
};
/**
* @private
*/

View File

@@ -1,5 +1,5 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2021, United States Government
* Open MCT, Copyright (c) 2014-2022, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*

View File

@@ -1,5 +1,5 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2021, United States Government
* Open MCT, Copyright (c) 2014-2022, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*

View File

@@ -1,5 +1,5 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2021, United States Government
* Open MCT, Copyright (c) 2014-2022, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*

View File

@@ -1,5 +1,5 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2021, United States Government
* Open MCT, Copyright (c) 2014-2022, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*

View File

@@ -148,10 +148,8 @@ import FontStyleEditor from '@/ui/inspector/styles/FontStyleEditor.vue';
import StyleEditor from "./StyleEditor.vue";
import PreviewAction from "@/ui/preview/PreviewAction.js";
import { getApplicableStylesForItem, getConsolidatedStyleValues, getConditionSetIdentifierForItem } from "@/plugins/condition/utils/styleUtils";
import SelectorDialogTree from '@/ui/components/SelectorDialogTree.vue';
import ConditionError from "@/plugins/condition/components/ConditionError.vue";
import ConditionDescription from "@/plugins/condition/components/ConditionDescription.vue";
import Vue from 'vue';
const NON_SPECIFIC = '??';
const NON_STYLEABLE_CONTAINER_TYPES = [
@@ -551,53 +549,28 @@ export default {
return this.conditions ? this.conditions[id] : {};
},
addConditionSet() {
let conditionSetDomainObject;
let self = this;
function handleItemSelection({ item }) {
if (item) {
conditionSetDomainObject = item;
}
}
const conditionWidgetParent = this.openmct.router.path[1];
const formStructure = {
title: 'Select Condition Set',
sections: [{
name: 'Location',
cssClass: 'grows',
rows: [{
key: 'location',
name: 'Condition Set',
cssClass: 'grows',
control: 'locator',
required: true,
parent: conditionWidgetParent,
validate: data => data.value[0].type === 'conditionSet'
}]
}]
};
function dismissDialog(overlay, initialize) {
overlay.dismiss();
if (initialize && conditionSetDomainObject) {
self.conditionSetDomainObject = conditionSetDomainObject;
self.conditionalStyles = [];
self.initializeConditionalStyles();
}
}
let vm = new Vue({
components: { SelectorDialogTree },
provide: {
openmct: this.openmct
},
data() {
return {
handleItemSelection,
title: 'Select Condition Set'
};
},
template: '<SelectorDialogTree :title="title" @treeItemSelected="handleItemSelection"></SelectorDialogTree>'
}).$mount();
let overlay = this.openmct.overlays.overlay({
element: vm.$el,
size: 'small',
buttons: [
{
label: 'OK',
emphasis: 'true',
callback: () => dismissDialog(overlay, true)
},
{
label: 'Cancel',
callback: () => dismissDialog(overlay, false)
}
],
onDestroy: () => vm.$destroy()
this.openmct.forms.showForm(formStructure).then(data => {
this.conditionSetDomainObject = data.location[0];
this.conditionalStyles = [];
this.initializeConditionalStyles();
});
},
removeConditionSet() {

View File

@@ -209,18 +209,7 @@ export default {
},
layoutItems: {
handler(value) {
let wMax = this.$el.clientWidth / this.gridSize[0];
let hMax = this.$el.clientHeight / this.gridSize[1];
value.forEach(item => {
if (item.x + item.width > wMax) {
wMax = item.x + item.width + 2;
}
if (item.y + item.height > hMax) {
hMax = item.y + item.height + 2;
}
});
this.gridDimensions = [wMax * this.gridSize[0], hMax * this.gridSize[1]];
this.updateGrid();
},
deep: true
}
@@ -233,6 +222,8 @@ export default {
this.composition.on('remove', this.removeChild);
this.composition.load();
this.gridDimensions = [this.$el.offsetWidth, this.$el.scrollHeight];
this.watchDisplayResize();
},
destroyed: function () {
this.openmct.selection.off('change', this.setSelection);
@@ -240,6 +231,25 @@ export default {
this.composition.off('remove', this.removeChild);
},
methods: {
updateGrid() {
let wMax = this.$el.clientWidth / this.gridSize[0];
let hMax = this.$el.clientHeight / this.gridSize[1];
this.layoutItems.forEach(item => {
if (item.x + item.width > wMax) {
wMax = item.x + item.width + 2;
}
if (item.y + item.height > hMax) {
hMax = item.y + item.height + 2;
}
});
this.gridDimensions = [wMax * this.gridSize[0], hMax * this.gridSize[1]];
},
watchDisplayResize() {
const resizeObserver = new ResizeObserver(() => this.updateGrid());
resizeObserver.observe(this.$el);
},
addElement(itemType, element) {
this.addItem(itemType + '-view', element);
},
@@ -404,8 +414,12 @@ export default {
}
},
containsObject(identifier) {
return _.get(this.domainObject, 'composition')
.some(childId => this.openmct.objects.areIdsEqual(childId, identifier));
if ('composition' in this.domainObject) {
return this.domainObject.composition
.some(childId => this.openmct.objects.areIdsEqual(childId, identifier));
}
return false;
},
handleDragOver($event) {
if (this.domainObject.locked) {
@@ -494,7 +508,7 @@ export default {
}
},
removeFromComposition(keyString) {
let composition = _.get(this.domainObject, 'composition');
let composition = this.domainObject.composition ? this.domainObject.composition : [];
composition = composition.filter(identifier => {
return this.openmct.objects.makeKeyString(identifier) !== keyString;
});

View File

@@ -97,7 +97,14 @@ export default {
},
mounted() {
if (this.frame.domainObjectIdentifier) {
this.openmct.objects.get(this.frame.domainObjectIdentifier).then((object) => {
let domainObjectPromise;
if (this.openmct.objects.supportsMutation(this.frame.domainObjectIdentifier)) {
domainObjectPromise = this.openmct.objects.getMutable(this.frame.domainObjectIdentifier);
} else {
domainObjectPromise = this.openmct.objects.get(this.frame.domainObjectIdentifier);
}
domainObjectPromise.then((object) => {
this.setDomainObject(object);
});
}
@@ -105,6 +112,10 @@ export default {
this.dragGhost = document.getElementById('js-fl-drag-ghost');
},
beforeDestroy() {
if (this.domainObject.isMutable) {
this.openmct.objects.destroyMutable(this.domainObject);
}
if (this.unsubscribeSelection) {
this.unsubscribeSelection();
}

View File

@@ -702,12 +702,15 @@ export default {
focusedIndex = matchIndex > -1 ? matchIndex : this.imageHistory.length - 1;
}
if (!(this.isPaused || thumbnailClick)
|| focusedIndex === this.imageHistory.length - 1) {
const isLastImageFocused = focusedIndex === this.imageHistory.length - 1;
if (!(this.isPaused || thumbnailClick) && isLastImageFocused) {
delete this.previousFocusedImage;
}
}
console.log('old index', this.focusedImageIndex);
console.log('new index', focusedIndex);
this.focusedImageIndex = focusedIndex;
//TODO: do we even need this anymore?
@@ -715,6 +718,9 @@ export default {
this.nextImageIndex = focusedIndex;
//this could happen if bounds changes
if (this.focusedImageIndex > this.imageHistory.length - 1) {
console.log('why this?');
console.log('old index', this.focusedImageIndex);
console.log('new index', focusedIndex);
this.focusedImageIndex = focusedIndex;
}

View File

@@ -322,7 +322,7 @@ export default {
cleanupDefaultNotebook() {
this.defaultPageId = undefined;
this.defaultSectionId = undefined;
this.removeDefaultClass(this.domainObject);
this.removeDefaultClass(this.domainObject.identifier);
clearDefaultNotebook();
},
setSectionAndPageFromUrl() {
@@ -619,12 +619,8 @@ export default {
this.sectionsChanged({ sections });
},
removeDefaultClass(defaultNotebookIdentifier) {
if (!defaultNotebookIdentifier) {
return;
}
this.openmct.status.delete(defaultNotebookIdentifier);
removeDefaultClass(identifier) {
this.openmct.status.delete(identifier);
},
resetSearch() {
this.search = '';
@@ -633,27 +629,25 @@ export default {
toggleNav() {
this.showNav = !this.showNav;
},
updateDefaultNotebook(notebookStorage) {
const defaultNotebook = getDefaultNotebook();
const defaultNotebookIdentifier = defaultNotebook && defaultNotebook.identifier;
const isSameNotebook = defaultNotebookIdentifier
&& this.openmct.objects.areIdsEqual(defaultNotebookIdentifier, notebookStorage.identifier);
if (!isSameNotebook) {
this.removeDefaultClass(defaultNotebookIdentifier);
updateDefaultNotebook(updatedNotebookStorageObject) {
if (!this.isDefaultNotebook()) {
const persistedNotebookStorageObject = getDefaultNotebook();
if (persistedNotebookStorageObject
&& persistedNotebookStorageObject.identifier !== undefined) {
this.removeDefaultClass(persistedNotebookStorageObject.identifier);
}
setDefaultNotebook(this.openmct, updatedNotebookStorageObject, this.domainObject);
}
if (!defaultNotebookIdentifier || !isSameNotebook) {
setDefaultNotebook(this.openmct, notebookStorage, this.domainObject);
if (this.defaultSectionId !== updatedNotebookStorageObject.defaultSectionId) {
setDefaultNotebookSectionId(updatedNotebookStorageObject.defaultSectionId);
this.defaultSectionId = updatedNotebookStorageObject.defaultSectionId;
}
if (this.defaultSectionId !== notebookStorage.defaultSectionId) {
setDefaultNotebookSectionId(notebookStorage.defaultSectionId);
this.defaultSectionId = notebookStorage.defaultSectionId;
}
if (this.defaultPageId !== notebookStorage.defaultPageId) {
setDefaultNotebookPageId(notebookStorage.defaultPageId);
this.defaultPageId = notebookStorage.defaultPageId;
if (this.defaultPageId !== updatedNotebookStorageObject.defaultPageId) {
setDefaultNotebookPageId(updatedNotebookStorageObject.defaultPageId);
this.defaultPageId = updatedNotebookStorageObject.defaultPageId;
}
},
updateDefaultNotebookSection(sections, id) {
@@ -671,7 +665,7 @@ export default {
if (defaultNotebookSectionId === id) {
const section = sections.find(s => s.id === id);
if (!section) {
this.removeDefaultClass(this.domainObject);
this.removeDefaultClass(this.domainObject.identifier);
clearDefaultNotebook();
return;

View File

@@ -8,6 +8,7 @@ export default function (openmct) {
return apiSave(domainObject);
}
const isNewMutable = !domainObject.isMutable;
const localMutable = openmct.objects._toMutable(domainObject);
let result;
@@ -20,7 +21,9 @@ export default function (openmct) {
result = Promise.reject(error);
}
} finally {
openmct.objects.destroyMutable(localMutable);
if (isNewMutable) {
openmct.objects.destroyMutable(localMutable);
}
}
return result;
@@ -28,10 +31,10 @@ export default function (openmct) {
}
function resolveConflicts(localMutable, openmct) {
const localEntries = JSON.parse(JSON.stringify(localMutable.configuration.entries));
return openmct.objects.getMutable(localMutable.identifier).then((remoteMutable) => {
const localEntries = localMutable.configuration.entries;
remoteMutable.$refresh(remoteMutable);
applyLocalEntries(remoteMutable, localEntries);
applyLocalEntries(remoteMutable, localEntries, openmct);
openmct.objects.destroyMutable(remoteMutable);
@@ -39,7 +42,7 @@ function resolveConflicts(localMutable, openmct) {
});
}
function applyLocalEntries(mutable, entries) {
function applyLocalEntries(mutable, entries, openmct) {
Object.entries(entries).forEach(([sectionKey, pagesInSection]) => {
Object.entries(pagesInSection).forEach(([pageKey, localEntries]) => {
const remoteEntries = mutable.configuration.entries[sectionKey][pageKey];
@@ -58,14 +61,15 @@ function applyLocalEntries(mutable, entries) {
locallyModifiedEntries.forEach((locallyModifiedEntry) => {
let mergedEntry = mergedEntries.find(entry => entry.id === locallyModifiedEntry.id);
if (mergedEntry !== undefined) {
if (mergedEntry !== undefined
&& locallyModifiedEntry.text.match(/\S/)) {
mergedEntry.text = locallyModifiedEntry.text;
shouldMutate = true;
}
});
if (shouldMutate) {
mutable.$set(`configuration.entries.${sectionKey}.${pageKey}`, mergedEntries);
openmct.objects.mutate(mutable, `configuration.entries.${sectionKey}.${pageKey}`, mergedEntries);
}
});
});

View File

@@ -120,7 +120,6 @@ export function addNotebookEntry(openmct, domainObject, notebookStorage, embed =
const newEntries = addEntryIntoPage(notebookStorage, entries, entry);
addDefaultClass(domainObject, openmct);
mutateObject(openmct, domainObject, 'configuration.entries', newEntries);
return id;

View File

@@ -1,5 +1,5 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2021, United States Government
* Open MCT, Copyright (c) 2014-2022, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*

View File

@@ -278,7 +278,7 @@ export default {
// Have to throw away the old canvas elements and replace with new
// canvas elements in order to get new drawing contexts.
const div = document.createElement('div');
div.innerHTML = this.TEMPLATE;
div.innerHTML = this.canvasTemplate + this.canvasTemplate;
const mainCanvas = div.querySelectorAll("canvas")[1];
const overlayCanvas = div.querySelectorAll("canvas")[0];
this.canvas.parentNode.replaceChild(mainCanvas, this.canvas);

View File

@@ -95,6 +95,11 @@ export default {
isUTCBased: timeSystem.isUTCBased
};
},
watch: {
keyString() {
this.setTimeContext();
}
},
mounted() {
this.handleNewBounds = _.throttle(this.handleNewBounds, 300);
this.setTimeSystem(JSON.parse(JSON.stringify(this.openmct.time.timeSystem())));

View File

@@ -115,6 +115,11 @@ export default {
isUTCBased: timeSystem.isUTCBased
};
},
watch: {
keyString() {
this.setTimeContext();
}
},
mounted() {
this.handleNewBounds = _.throttle(this.handleNewBounds, 300);
this.setTimeSystem(JSON.parse(JSON.stringify(this.openmct.time.timeSystem())));

View File

@@ -105,42 +105,49 @@ export default {
watch: {
domainObject: {
handler(domainObject) {
this.independentTCEnabled = domainObject.configuration.useIndependentTime === true;
if (!domainObject.configuration.timeOptions || !this.independentTCEnabled) {
const key = this.openmct.objects.makeKeyString(domainObject.identifier);
if (key !== this.keyString) {
//domain object has changed
this.destroyIndependentTime();
return;
}
this.independentTCEnabled = domainObject.configuration.useIndependentTime === true;
this.timeOptions = domainObject.configuration.timeOptions || {
clockOffsets: this.openmct.time.clockOffsets(),
fixedOffsets: this.openmct.time.bounds()
};
if (this.timeOptions.start !== domainObject.configuration.timeOptions.start
|| this.timeOptions.end !== domainObject.configuration.timeOptions.end) {
this.timeOptions = domainObject.configuration.timeOptions;
this.destroyIndependentTime();
this.registerIndependentTimeOffsets();
this.initialize();
}
},
deep: true
}
},
mounted() {
this.setTimeContext();
if (this.timeOptions.mode) {
this.mode = this.timeOptions.mode;
} else {
this.timeOptions.mode = this.mode = this.timeContext.clock() === undefined ? { key: 'fixed' } : { key: Object.create(this.timeContext.clock()).key};
}
if (this.independentTCEnabled) {
this.registerIndependentTimeOffsets();
}
this.initialize();
},
beforeDestroy() {
this.stopFollowingTimeContext();
this.destroyIndependentTime();
},
methods: {
initialize() {
this.keyString = this.openmct.objects.makeKeyString(this.domainObject.identifier);
this.setTimeContext();
if (this.timeOptions.mode) {
this.mode = this.timeOptions.mode;
} else {
if (this.timeContext.clock() === undefined) {
this.timeOptions.mode = this.mode = { key: 'fixed' };
} else {
this.timeOptions.mode = this.mode = { key: Object.create(this.timeContext.clock()).key};
}
}
if (this.independentTCEnabled) {
this.registerIndependentTimeOffsets();
}
},
toggleIndependentTC() {
this.independentTCEnabled = !this.independentTCEnabled;
if (this.independentTCEnabled) {
@@ -213,10 +220,9 @@ export default {
offsets = this.timeOptions.clockOffsets;
}
const key = this.openmct.objects.makeKeyString(this.domainObject.identifier);
const timeContext = this.openmct.time.getIndependentContext(key);
const timeContext = this.openmct.time.getIndependentContext(this.keyString);
if (!timeContext.hasOwnContext()) {
this.unregisterIndependentTime = this.openmct.time.addIndependentContext(key, offsets, this.isFixed ? undefined : this.mode.key);
this.unregisterIndependentTime = this.openmct.time.addIndependentContext(this.keyString, offsets, this.isFixed ? undefined : this.mode.key);
} else {
if (this.isFixed) {
timeContext.stopClock();

View File

@@ -1,5 +1,5 @@
<!--
Open MCT, Copyright (c) 2014-2021, United States Government
Open MCT, Copyright (c) 2014-2022, United States Government
as represented by the Administrator of the National Aeronautics and Space
Administration. All rights reserved.

View File

@@ -1,5 +1,5 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2021, United States Government
* Open MCT, Copyright (c) 2014-2022, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*

View File

@@ -1,5 +1,5 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2021, United States Government
* Open MCT, Copyright (c) 2014-2022, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*

View File

@@ -1,240 +0,0 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2022, 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.
*****************************************************************************/
<template>
<div class="u-contents">
<div v-if="title.length"
class="c-overlay__top-bar"
>
<div class="c-overlay__dialog-title">{{ title }}</div>
</div>
<div class="c-selector c-tree-and-search"
:class="cssClass"
>
<div class="c-tree-and-search__search">
<Search ref="shell-search"
class="c-search"
:value="searchValue"
@input="searchTree"
@clear="searchTree"
/>
</div>
<div v-if="isLoading"
class="c-tree-and-search__loading loading"
></div>
<div v-if="shouldDisplayNoResultsText"
class="c-tree-and-search__no-results"
>
No results found
</div>
<ul v-if="!isLoading"
v-show="!searchValue"
class="c-tree-and-search__tree c-tree"
>
<SelectorDialogTreeItem
v-for="treeItem in allTreeItems"
:key="treeItem.id"
:node="treeItem"
:selected-item="selectedItem"
:handle-item-selected="handleItemSelection"
:navigate-to-parent="navigateToParent"
/>
</ul>
<ul v-if="searchValue && !isLoading"
class="c-tree-and-search__tree c-tree"
>
<SelectorDialogTreeItem
v-for="treeItem in filteredTreeItems"
:key="treeItem.id"
:node="treeItem"
:selected-item="selectedItem"
:handle-item-selected="handleItemSelection"
/>
</ul>
</div>
</div>
</template>
<script>
import debounce from 'lodash/debounce';
import Search from '@/ui/components/search.vue';
import SelectorDialogTreeItem from './SelectorDialogTreeItem.vue';
export default {
name: 'SelectorDialogTree',
components: {
Search,
SelectorDialogTreeItem
},
inject: ['openmct'],
props: {
cssClass: {
type: String,
required: false,
default() {
return '';
}
},
title: {
type: String,
required: false,
default() {
return '';
}
},
ignoreTypeCheck: {
type: Boolean,
required: false,
default() {
return false;
}
},
parent: {
type: Object,
required: false,
default() {
return undefined;
}
}
},
data() {
return {
allTreeItems: [],
expanded: false,
filteredTreeItems: [],
isLoading: false,
navigateToParent: undefined,
searchValue: '',
selectedItem: undefined
};
},
computed: {
shouldDisplayNoResultsText() {
if (this.isLoading) {
return false;
}
return this.allTreeItems.length === 0
|| (this.searchValue && this.filteredTreeItems.length === 0);
}
},
created() {
this.getDebouncedFilteredChildren = debounce(this.getFilteredChildren, 400);
},
mounted() {
if (this.parent) {
(async () => {
const objectPath = await this.openmct.objects.getOriginalPath(this.parent.identifier);
this.navigateToParent = '/browse/'
+ objectPath
.map(parent => this.openmct.objects.makeKeyString(parent.identifier))
.reverse()
.join('/');
this.getAllChildren(this.navigateToParent);
})();
} else {
this.getAllChildren();
}
},
methods: {
async aggregateFilteredChildren(results) {
for (const object of results) {
const objectPath = await this.openmct.objects.getOriginalPath(object.identifier);
const navigateToParent = '/browse/'
+ objectPath.slice(1)
.map(parent => this.openmct.objects.makeKeyString(parent.identifier))
.join('/');
const filteredChild = {
id: this.openmct.objects.makeKeyString(object.identifier),
object,
objectPath,
navigateToParent
};
this.filteredTreeItems.push(filteredChild);
}
},
getAllChildren(navigateToParent) {
this.isLoading = true;
this.openmct.objects.get('ROOT')
.then(root => {
return this.openmct.composition.get(root).load();
})
.then(children => {
this.isLoading = false;
this.allTreeItems = children.map(c => {
return {
id: this.openmct.objects.makeKeyString(c.identifier),
object: c,
objectPath: [c],
navigateToParent: navigateToParent || '/browse'
};
});
});
},
getFilteredChildren() {
// clear any previous search results
this.filteredTreeItems = [];
const promises = this.openmct.objects.search(this.searchValue)
.map(promise => promise
.then(results => this.aggregateFilteredChildren(results)));
Promise.all(promises).then(() => {
this.isLoading = false;
});
},
handleItemSelection(item, node) {
if (item && (this.ignoreTypeCheck || item.type === 'conditionSet')) {
const parentId = (node.objectPath && node.objectPath.length > 1) ? node.objectPath[1].identifier : undefined;
this.selectedItem = {
itemId: item.identifier,
parentId
};
this.$emit('treeItemSelected',
{
item,
parentObjectPath: node.objectPath
});
}
},
searchTree(value) {
this.searchValue = value;
this.isLoading = true;
if (this.searchValue !== '') {
this.getDebouncedFilteredChildren();
} else {
this.isLoading = false;
}
}
}
};
</script>

View File

@@ -1,206 +0,0 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2022, 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.
*****************************************************************************/
<template>
<li class="c-tree__item-h">
<div
class="c-tree__item"
:class="{ 'is-alias': isAlias, 'is-navigated-object': navigated }"
@click="handleItemSelected(node.object, node)"
>
<view-control
v-model="expanded"
class="c-tree__item__view-control"
:enabled="hasChildren"
/>
<div class="c-tree__item__label c-object-label">
<div
class="c-tree__item__type-icon c-object-label__type-icon"
:class="typeClass"
></div>
<div class="c-tree__item__name c-object-label__name">{{ node.object.name }}</div>
</div>
</div>
<ul
v-if="expanded && !isLoading"
class="c-tree"
>
<li
v-if="isLoading && !loaded"
class="c-tree__item-h"
>
<div class="c-tree__item loading">
<span class="c-tree__item__label">Loading...</span>
</div>
</li>
<SelectorDialogTreeItem
v-for="child in children"
:key="child.id"
:node="child"
:selected-item="selectedItem"
:handle-item-selected="handleItemSelected"
:navigate-to-parent="navigateToParent"
/>
</ul>
</li>
</template>
<script>
import viewControl from '@/ui/components/viewControl.vue';
export default {
name: 'SelectorDialogTreeItem',
components: {
viewControl
},
inject: ['openmct'],
props: {
node: {
type: Object,
required: true
},
selectedItem: {
type: Object,
default() {
return undefined;
}
},
handleItemSelected: {
type: Function,
default() {
return (item) => {};
}
},
navigateToParent: {
type: String,
default() {
return undefined;
}
}
},
data() {
return {
hasChildren: false,
isLoading: false,
loaded: false,
children: [],
expanded: false
};
},
computed: {
navigated() {
const itemId = this.selectedItem && this.selectedItem.itemId;
const isSelectedObject = itemId && this.openmct.objects.areIdsEqual(this.node.object.identifier, itemId);
if (isSelectedObject && this.node.objectPath && this.node.objectPath.length > 1) {
const isParent = this.openmct.objects.areIdsEqual(this.node.objectPath[1].identifier, this.selectedItem.parentId);
return isSelectedObject && isParent;
}
return isSelectedObject;
},
isAlias() {
let parent = this.node.objectPath[1];
if (!parent) {
return false;
}
let parentKeyString = this.openmct.objects.makeKeyString(parent.identifier);
return parentKeyString !== this.node.object.location;
},
typeClass() {
let type = this.openmct.types.get(this.node.object.type);
if (!type) {
return 'icon-object-unknown';
}
return type.definition.cssClass;
}
},
watch: {
expanded() {
if (!this.hasChildren) {
return;
}
if (!this.loaded && !this.isLoading) {
this.composition = this.openmct.composition.get(this.domainObject);
this.composition.on('add', this.addChild);
this.composition.on('remove', this.removeChild);
this.composition.load().then(this.finishLoading);
this.isLoading = true;
}
}
},
mounted() {
this.domainObject = this.node.object;
if (this.navigateToParent && this.navigateToParent.includes(this.openmct.objects.makeKeyString(this.domainObject.identifier))) {
this.expanded = true;
}
if (this.navigateToParent && this.navigateToParent.endsWith(this.openmct.objects.makeKeyString(this.domainObject.identifier))) {
this.handleItemSelected(this.node.object, this.node);
}
let removeListener = this.openmct.objects.observe(this.domainObject, '*', (newObject) => {
this.domainObject = newObject;
});
this.$once('hook:destroyed', removeListener);
if (this.openmct.composition.get(this.node.object)) {
this.hasChildren = true;
}
},
beforeDestroy() {
this.expanded = false;
},
destroyed() {
if (this.composition) {
this.composition.off('add', this.addChild);
this.composition.off('remove', this.removeChild);
delete this.composition;
}
},
methods: {
addChild(child) {
this.children.push({
id: this.openmct.objects.makeKeyString(child.identifier),
object: child,
objectPath: [child].concat(this.node.objectPath),
navigateToParent: this.navigateToPath
});
},
removeChild(identifier) {
let removeId = this.openmct.objects.makeKeyString(identifier);
this.children = this.children
.filter(c => c.id !== removeId);
},
finishLoading() {
this.isLoading = false;
this.loaded = true;
}
}
};
</script>

View File

@@ -280,38 +280,5 @@
border: 1px solid $colorFormLines;
border-radius: $controlCr;
padding: $interiorMargin;
> .c-tree {
overflow: auto;
}
}
}
// TRANSITIONS
.children-enter-active {
&.down {
animation: animSlideLeft 500ms;
}
&.up {
animation: animSlideRight 500ms;
}
}
@keyframes animSlideLeft {
0% {opacity: 0; transform: translateX(100%);}
10% {opacity: 1;}
100% {transform: translateX(0);}
}
@keyframes animSlideRight {
0% {opacity: 0; transform: translateX(-100%);}
10% {opacity: 1;}
100% {transform: translateX(0);}
}
@keyframes animTemporaryHighlight {
from { background: transparent; }
30% { background: $colorItemTreeNewNode; }
100% { background: transparent; }
}

View File

@@ -1,6 +1,12 @@
<template>
<div class="c-tree-and-search">
<div
ref="treeContainer"
class="c-tree-and-search"
:class="{
'c-selector': isSelectorTree
}"
:style="treeHeight"
>
<div
ref="search"
class="c-tree-and-search__search"
@@ -72,6 +78,8 @@
v-for="(treeItem, index) in visibleItems"
:key="treeItem.navigationPath"
:node="treeItem"
:is-selector-tree="isSelectorTree"
:selected-item="selectedItem"
:active-search="activeSearch"
:left-offset="!activeSearch ? treeItem.leftOffset : '0px'"
:is-new="treeItem.isNew"
@@ -82,7 +90,8 @@
:loading-items="treeItemLoading"
@tree-item-mounted="scrollToCheck($event)"
@tree-item-destroyed="removeCompositionListenerFor($event)"
@navigation-click="treeItemAction(treeItem, $event)"
@tree-item-action="treeItemAction(treeItem, $event)"
@tree-item-selection="treeItemSelection(treeItem)"
/>
<!-- main loading -->
<div
@@ -115,6 +124,7 @@ const ITEM_BUFFER = 25;
const LOCAL_STORAGE_KEY__TREE_EXPANDED = 'mct-tree-expanded';
const SORT_MY_ITEMS_ALPH_ASC = true;
const TREE_ITEM_INDENT_PX = 18;
const LOCATOR_ITEM_COUNT_HEIGHT = 10; // how many tree items to make the locator selection box show
export default {
name: 'MctTree',
@@ -124,13 +134,27 @@ export default {
},
inject: ['openmct'],
props: {
isSelectorTree: {
type: Boolean,
required: false,
default() {
return false;
}
},
initialSelection: {
type: Object,
required: false,
default() {
return {};
}
},
syncTreeNavigation: {
type: Boolean,
required: true
required: false
},
resetTreeNavigation: {
type: Boolean,
required: true
required: false
}
},
data() {
@@ -149,7 +173,8 @@ export default {
itemHeight: 27,
itemOffset: 0,
activeSearch: false,
mainTreeTopMargin: undefined
mainTreeTopMargin: undefined,
selectedItem: {}
};
},
computed: {
@@ -179,6 +204,13 @@ export default {
},
showNoSearchResults() {
return this.searchValue && this.searchResultItems.length === 0 && !this.searchLoading;
},
treeHeight() {
if (!this.isSelectorTree) {
return {};
} else {
return { height: this.itemHeight * LOCATOR_ITEM_COUNT_HEIGHT + 'px' };
}
}
},
watch: {
@@ -223,7 +255,14 @@ export default {
await this.loadRoot();
this.isLoading = false;
await this.syncTreeOpenItems();
if (!this.isSelectorTree) {
await this.syncTreeOpenItems();
} else {
const objectPath = await this.openmct.objects.getOriginalPath(this.initialSelection.identifier);
const navigationPath = this.buildNavigationPath(objectPath);
this.openAndScrollTo(navigationPath);
}
},
created() {
this.getSearchResults = _.debounce(this.getSearchResults, 400);
@@ -265,6 +304,10 @@ export default {
this.openTreeItem(parentItem);
}
},
treeItemSelection(item) {
this.selectedItem = item;
this.$emit('tree-item-selection', item);
},
async openTreeItem(parentItem) {
let parentPath = parentItem.navigationPath;
@@ -358,6 +401,10 @@ export default {
}
},
openAndScrollTo(navigationPath) {
if (navigationPath.includes('/ROOT')) {
navigationPath = navigationPath.split('/ROOT').join('');
}
let idArray = navigationPath.split('/');
let fullPathArray = [];
let pathsToOpen;
@@ -367,7 +414,6 @@ export default {
// skip root
idArray.splice(0, 2);
idArray[0] = 'browse/' + idArray[0];
idArray.reduce((parentPath, childPath) => {
let fullPath = [parentPath, childPath].join('/');
@@ -383,7 +429,11 @@ export default {
return this.openTreeItem(this.getTreeItemByPath(childPath));
}, Promise.resolve());
}, Promise.resolve()).then(() => {
if (this.isSelectorTree) {
this.treeItemSelection(this.getTreeItemByPath(navigationPath));
}
});
},
scrollToCheck(navigationPath) {
if (this.scrollToPath && this.scrollToPath === navigationPath) {
@@ -721,18 +771,26 @@ export default {
let checkHeights = () => {
let treeTopMargin = this.getElementStyleValue(this.$refs.mainTree, 'marginTop');
let paddingOffset = 0;
if (
this.$el
&& this.$refs.search
&& this.$refs.mainTree
&& this.$refs.treeContainer
&& this.$refs.dummyItem
&& this.$el.offsetHeight !== 0
&& treeTopMargin > 0
) {
if (this.isSelectorTree) {
paddingOffset = this.getElementStyleValue(this.$refs.treeContainer, 'padding');
}
this.mainTreeTopMargin = treeTopMargin;
this.mainTreeHeight = this.$el.offsetHeight
- this.$refs.search.offsetHeight
- this.mainTreeTopMargin;
- this.mainTreeTopMargin
- (paddingOffset * 2);
this.itemHeight = this.getElementStyleValue(this.$refs.dummyItem, 'height');
resolve();
@@ -783,10 +841,18 @@ export default {
return Number(styleString.slice(0, index));
},
getSavedOpenItems() {
if (this.isSelectorTree) {
return;
}
let openItems = localStorage.getItem(LOCAL_STORAGE_KEY__TREE_EXPANDED);
this.openTreeItems = openItems ? JSON.parse(openItems) : [];
},
setSavedOpenItems() {
if (this.isSelectorTree) {
return;
}
localStorage.setItem(LOCAL_STORAGE_KEY__TREE_EXPANDED, JSON.stringify(this.openTreeItems));
},
handleTreeResize() {

View File

@@ -7,19 +7,19 @@
class="c-tree__item"
:class="{
'is-alias': isAlias,
'is-navigated-object': navigated,
'is-navigated-object': shouldHightlight,
'is-context-clicked': contextClickActive,
'is-new': isNewItem
}"
@click.capture="handleClick"
@click.capture="itemClick"
@contextmenu.capture="handleContextMenu"
>
<view-control
ref="navigate"
ref="action"
class="c-tree__item__view-control"
:value="isOpen || isLoading"
:enabled="!activeSearch && hasComposition"
@input="navigationClick()"
@input="itemAction()"
/>
<object-label
ref="objectLabel"
@@ -52,6 +52,14 @@ export default {
type: Object,
required: true
},
isSelectorTree: {
type: Boolean,
required: true
},
selectedItem: {
type: Object,
required: true
},
activeSearch: {
type: Boolean,
default: false
@@ -109,6 +117,9 @@ export default {
return parentKeyString !== this.node.object.location;
},
isSelectedItem() {
return this.selectedItem.objectPath === this.node.objectPath;
},
isNewItem() {
return this.isNew;
},
@@ -118,6 +129,13 @@ export default {
isOpen() {
return this.openItems.includes(this.navigationPath);
},
shouldHightlight() {
if (this.isSelectorTree) {
return this.isSelectedItem;
} else {
return this.navigated;
}
},
treeItemStyles() {
let itemTop = (this.itemOffset + this.itemIndex) * this.itemHeight + 'px';
@@ -144,20 +162,30 @@ export default {
this.$emit('tree-item-destoyed', this.navigationPath);
},
methods: {
navigationClick() {
this.$emit('navigation-click', this.isOpen || this.isLoading ? 'close' : 'open');
itemAction() {
this.$emit('tree-item-action', this.isOpen || this.isLoading ? 'close' : 'open');
},
handleClick(event) {
itemClick(event) {
// skip for navigation, let viewControl handle click
if (this.$refs.navigate.$el === event.target) {
if (this.$refs.action.$el === event.target) {
return;
}
event.stopPropagation();
this.$refs.objectLabel.navigateOrPreview(event);
if (!this.isSelectorTree) {
this.$refs.objectLabel.navigateOrPreview(event);
} else {
this.$emit('tree-item-selection', this.node);
}
},
handleContextMenu(event) {
event.stopPropagation();
if (this.isSelectorTree) {
return;
}
this.$refs.objectLabel.showContextMenu(event);
},
isNavigated() {