mirror of
https://github.com/nasa/openmct.git
synced 2025-05-11 13:03:03 +00:00
* Sort MyItems alphabetically when building the tree * Fixed brace indentation * Modified tree-item to accept is-new prop for initial highlighting * Adjusted sort function and properly sort children before splicing treetItems * Mods for #1717 - Refined color and timing, color is now theme-compliant; - Added new theme color constants; - Smoke tested in Espresso and Snow themes; Co-authored-by: Andrew Henry <akhenry@gmail.com> Co-authored-by: Charles Hacskaylo <charlesh88@gmail.com>
This commit is contained in:
parent
980777691a
commit
61dd85c704
@ -382,6 +382,7 @@ $colorItemTreeEditingFg: $editUIColor;
|
|||||||
$colorItemTreeEditingIcon: $editUIColor;
|
$colorItemTreeEditingIcon: $editUIColor;
|
||||||
$colorItemTreeVC: $colorDisclosureCtrl;
|
$colorItemTreeVC: $colorDisclosureCtrl;
|
||||||
$colorItemTreeVCHover: $colorDisclosureCtrlHov;
|
$colorItemTreeVCHover: $colorDisclosureCtrlHov;
|
||||||
|
$colorItemTreeNewNode: rgba($colorBodyFg, 0.7);
|
||||||
$shdwItemTreeIcon: none;
|
$shdwItemTreeIcon: none;
|
||||||
|
|
||||||
// Layout frame controls
|
// Layout frame controls
|
||||||
|
@ -386,6 +386,7 @@ $colorItemTreeEditingFg: $editUIColor;
|
|||||||
$colorItemTreeEditingIcon: $editUIColor;
|
$colorItemTreeEditingIcon: $editUIColor;
|
||||||
$colorItemTreeVC: $colorDisclosureCtrl;
|
$colorItemTreeVC: $colorDisclosureCtrl;
|
||||||
$colorItemTreeVCHover: $colorDisclosureCtrlHov;
|
$colorItemTreeVCHover: $colorDisclosureCtrlHov;
|
||||||
|
$colorItemTreeNewNode: rgba($colorBodyFg, 0.7);
|
||||||
$shdwItemTreeIcon: none;
|
$shdwItemTreeIcon: none;
|
||||||
|
|
||||||
// Layout frame controls
|
// Layout frame controls
|
||||||
|
@ -382,6 +382,7 @@ $colorItemTreeEditingFg: $editUIColor;
|
|||||||
$colorItemTreeEditingIcon: $editUIColor;
|
$colorItemTreeEditingIcon: $editUIColor;
|
||||||
$colorItemTreeVC: $colorDisclosureCtrl;
|
$colorItemTreeVC: $colorDisclosureCtrl;
|
||||||
$colorItemTreeVCHover: $colorDisclosureCtrlHov;
|
$colorItemTreeVCHover: $colorDisclosureCtrlHov;
|
||||||
|
$colorItemTreeNewNode: rgba($colorBodyFg, 0.5);
|
||||||
$shdwItemTreeIcon: none;
|
$shdwItemTreeIcon: none;
|
||||||
|
|
||||||
// Layout frame controls
|
// Layout frame controls
|
||||||
|
@ -105,7 +105,12 @@
|
|||||||
color: $colorItemTreeSelectedFg;
|
color: $colorItemTreeSelectedFg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
&.is-new {
|
||||||
|
animation-name: animTemporaryHighlight;
|
||||||
|
animation-timing-function: ease-out;
|
||||||
|
animation-duration: 3s;
|
||||||
|
animation-iteration-count: 1;
|
||||||
|
}
|
||||||
&.is-context-clicked {
|
&.is-context-clicked {
|
||||||
box-shadow: inset $colorItemTreeSelectedBg 0 0 0 1px;
|
box-shadow: inset $colorItemTreeSelectedBg 0 0 0 1px;
|
||||||
}
|
}
|
||||||
@ -289,13 +294,19 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@keyframes animSlideLeft {
|
@keyframes animSlideLeft {
|
||||||
0% {opactiy: 0; transform: translateX(100%);}
|
0% {opacity: 0; transform: translateX(100%);}
|
||||||
10% {opacity: 1;}
|
10% {opacity: 1;}
|
||||||
100% {transform: translateX(0);}
|
100% {transform: translateX(0);}
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes animSlideRight {
|
@keyframes animSlideRight {
|
||||||
0% {opactiy: 0; transform: translateX(-100%);}
|
0% {opacity: 0; transform: translateX(-100%);}
|
||||||
10% {opacity: 1;}
|
10% {opacity: 1;}
|
||||||
100% {transform: translateX(0);}
|
100% {transform: translateX(0);}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@keyframes animTemporaryHighlight {
|
||||||
|
from { background: transparent; }
|
||||||
|
30% { background: $colorItemTreeNewNode; }
|
||||||
|
100% { background: transparent; }
|
||||||
|
}
|
||||||
|
@ -74,6 +74,7 @@
|
|||||||
:node="treeItem"
|
:node="treeItem"
|
||||||
:active-search="activeSearch"
|
:active-search="activeSearch"
|
||||||
:left-offset="!activeSearch ? treeItem.leftOffset : '0px'"
|
:left-offset="!activeSearch ? treeItem.leftOffset : '0px'"
|
||||||
|
:is-new="treeItem.isNew"
|
||||||
:item-offset="itemOffset"
|
:item-offset="itemOffset"
|
||||||
:item-index="index"
|
:item-index="index"
|
||||||
:item-height="itemHeight"
|
:item-height="itemHeight"
|
||||||
@ -112,7 +113,8 @@ import search from '../components/search.vue';
|
|||||||
|
|
||||||
const ITEM_BUFFER = 25;
|
const ITEM_BUFFER = 25;
|
||||||
const LOCAL_STORAGE_KEY__TREE_EXPANDED = 'mct-tree-expanded';
|
const LOCAL_STORAGE_KEY__TREE_EXPANDED = 'mct-tree-expanded';
|
||||||
const RETURN_ALL_DESCDNDANTS = true;
|
const RETURN_ALL_DESCENDANTS = true;
|
||||||
|
const SORT_MY_ITEMS_ALPH_ASC = true;
|
||||||
const TREE_ITEM_INDENT_PX = 18;
|
const TREE_ITEM_INDENT_PX = 18;
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@ -430,9 +432,40 @@ export default {
|
|||||||
|
|
||||||
return scrollTopAmount >= treeStart && scrollTopAmount < treeEnd;
|
return scrollTopAmount >= treeStart && scrollTopAmount < treeEnd;
|
||||||
},
|
},
|
||||||
|
sortNameDescending(a, b) {
|
||||||
|
// sorting tree children items
|
||||||
|
if (!(a.name && b.name)) {
|
||||||
|
if (a.object.name > b.object.name) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (b.object.name > a.object.name) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// sorting compositon items
|
||||||
|
if (a.name > b.name) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (b.name > a.name) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
},
|
||||||
|
|
||||||
async loadAndBuildTreeItemsFor(domainObject, parentObjectPath, abortSignal) {
|
async loadAndBuildTreeItemsFor(domainObject, parentObjectPath, abortSignal) {
|
||||||
let collection = this.openmct.composition.get(domainObject);
|
let collection = this.openmct.composition.get(domainObject);
|
||||||
let composition = await collection.load(abortSignal);
|
let composition = await collection.load(abortSignal);
|
||||||
|
// determine if any part of the parent's path includes a key value of mine; aka My Items
|
||||||
|
const isNestedInMyItems = Boolean(parentObjectPath.find(path => path.identifier.key === 'mine'));
|
||||||
|
|
||||||
|
if (SORT_MY_ITEMS_ALPH_ASC && isNestedInMyItems) {
|
||||||
|
const sortedComposition = composition.sort(this.sortNameDescending);
|
||||||
|
composition = sortedComposition;
|
||||||
|
}
|
||||||
|
|
||||||
if (parentObjectPath.length) {
|
if (parentObjectPath.length) {
|
||||||
let navigationPath = this.buildNavigationPath(parentObjectPath);
|
let navigationPath = this.buildNavigationPath(parentObjectPath);
|
||||||
@ -456,7 +489,7 @@ export default {
|
|||||||
return this.buildTreeItem(object, parentObjectPath);
|
return this.buildTreeItem(object, parentObjectPath);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
buildTreeItem(domainObject, parentObjectPath) {
|
buildTreeItem(domainObject, parentObjectPath, isNew = false) {
|
||||||
let objectPath = [domainObject].concat(parentObjectPath);
|
let objectPath = [domainObject].concat(parentObjectPath);
|
||||||
let navigationPath = this.buildNavigationPath(objectPath);
|
let navigationPath = this.buildNavigationPath(objectPath);
|
||||||
|
|
||||||
@ -464,6 +497,7 @@ export default {
|
|||||||
id: this.openmct.objects.makeKeyString(domainObject.identifier),
|
id: this.openmct.objects.makeKeyString(domainObject.identifier),
|
||||||
object: domainObject,
|
object: domainObject,
|
||||||
leftOffset: ((objectPath.length - 1) * TREE_ITEM_INDENT_PX) + 'px',
|
leftOffset: ((objectPath.length - 1) * TREE_ITEM_INDENT_PX) + 'px',
|
||||||
|
isNew,
|
||||||
objectPath,
|
objectPath,
|
||||||
navigationPath
|
navigationPath
|
||||||
};
|
};
|
||||||
@ -476,11 +510,16 @@ export default {
|
|||||||
compositionAddHandler(navigationPath) {
|
compositionAddHandler(navigationPath) {
|
||||||
return (domainObject) => {
|
return (domainObject) => {
|
||||||
let parentItem = this.getTreeItemByPath(navigationPath);
|
let parentItem = this.getTreeItemByPath(navigationPath);
|
||||||
let newItem = this.buildTreeItem(domainObject, parentItem.objectPath);
|
let newItem = this.buildTreeItem(domainObject, parentItem.objectPath, true);
|
||||||
let allDescendants = this.getChildrenInTreeFor(parentItem, RETURN_ALL_DESCDNDANTS);
|
let allDescendants = this.getChildrenInTreeFor(parentItem, RETURN_ALL_DESCENDANTS);
|
||||||
let afterItem = allDescendants.length ? allDescendants.pop() : parentItem;
|
let afterItem = allDescendants.length ? allDescendants.pop() : parentItem;
|
||||||
|
|
||||||
this.addItemToTreeAfter(newItem, afterItem);
|
this.addItemToTreeAfter(newItem, afterItem);
|
||||||
|
const isNestedInMyItems = Boolean(parentItem.objectPath && parentItem.objectPath.find(path => path.identifier.key === 'mine'));
|
||||||
|
|
||||||
|
if (SORT_MY_ITEMS_ALPH_ASC && isNestedInMyItems) {
|
||||||
|
this.sortTreeComposition(this.sortNameDescending, navigationPath);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
compositionRemoveHandler(navigationPath) {
|
compositionRemoveHandler(navigationPath) {
|
||||||
@ -512,6 +551,14 @@ export default {
|
|||||||
const removeIndex = this.getTreeItemIndex(item.navigationPath);
|
const removeIndex = this.getTreeItemIndex(item.navigationPath);
|
||||||
this.treeItems.splice(removeIndex, 1);
|
this.treeItems.splice(removeIndex, 1);
|
||||||
},
|
},
|
||||||
|
sortTreeComposition(algorithem, parentPath) {
|
||||||
|
const parentIndex = this.getTreeItemIndex(parentPath);
|
||||||
|
const parentItem = this.treeItems[parentIndex];
|
||||||
|
|
||||||
|
const allDescendants = this.getChildrenInTreeFor(parentItem);
|
||||||
|
const sortedChildren = allDescendants.sort(algorithem);
|
||||||
|
this.treeItems.splice(parentIndex + 1, allDescendants.length, ...sortedChildren);
|
||||||
|
},
|
||||||
addItemToTreeAfter(addItem, afterItem) {
|
addItemToTreeAfter(addItem, afterItem) {
|
||||||
const addIndex = this.getTreeItemIndex(afterItem.navigationPath);
|
const addIndex = this.getTreeItemIndex(afterItem.navigationPath);
|
||||||
this.treeItems.splice(addIndex + 1, 0, addItem);
|
this.treeItems.splice(addIndex + 1, 0, addItem);
|
||||||
|
@ -8,7 +8,8 @@
|
|||||||
:class="{
|
:class="{
|
||||||
'is-alias': isAlias,
|
'is-alias': isAlias,
|
||||||
'is-navigated-object': navigated,
|
'is-navigated-object': navigated,
|
||||||
'is-context-clicked': contextClickActive
|
'is-context-clicked': contextClickActive,
|
||||||
|
'is-new': isNewItem
|
||||||
}"
|
}"
|
||||||
@click.capture="handleClick"
|
@click.capture="handleClick"
|
||||||
@contextmenu.capture="handleContextMenu"
|
@contextmenu.capture="handleContextMenu"
|
||||||
@ -59,6 +60,10 @@ export default {
|
|||||||
type: String,
|
type: String,
|
||||||
default: '0px'
|
default: '0px'
|
||||||
},
|
},
|
||||||
|
isNew: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
itemIndex: {
|
itemIndex: {
|
||||||
type: Number,
|
type: Number,
|
||||||
required: false,
|
required: false,
|
||||||
@ -104,6 +109,9 @@ export default {
|
|||||||
|
|
||||||
return parentKeyString !== this.node.object.location;
|
return parentKeyString !== this.node.object.location;
|
||||||
},
|
},
|
||||||
|
isNewItem() {
|
||||||
|
return this.isNew;
|
||||||
|
},
|
||||||
isLoading() {
|
isLoading() {
|
||||||
return Boolean(this.loadingItems[this.navigationPath]);
|
return Boolean(this.loadingItems[this.navigationPath]);
|
||||||
},
|
},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user