Sort MyItems alphabetically when building the tree #1717 (#4376)

* 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:
Michael Rogers 2021-11-04 13:35:10 -07:00 committed by GitHub
parent 980777691a
commit 61dd85c704
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 77 additions and 8 deletions

View File

@ -382,6 +382,7 @@ $colorItemTreeEditingFg: $editUIColor;
$colorItemTreeEditingIcon: $editUIColor;
$colorItemTreeVC: $colorDisclosureCtrl;
$colorItemTreeVCHover: $colorDisclosureCtrlHov;
$colorItemTreeNewNode: rgba($colorBodyFg, 0.7);
$shdwItemTreeIcon: none;
// Layout frame controls

View File

@ -386,6 +386,7 @@ $colorItemTreeEditingFg: $editUIColor;
$colorItemTreeEditingIcon: $editUIColor;
$colorItemTreeVC: $colorDisclosureCtrl;
$colorItemTreeVCHover: $colorDisclosureCtrlHov;
$colorItemTreeNewNode: rgba($colorBodyFg, 0.7);
$shdwItemTreeIcon: none;
// Layout frame controls

View File

@ -382,6 +382,7 @@ $colorItemTreeEditingFg: $editUIColor;
$colorItemTreeEditingIcon: $editUIColor;
$colorItemTreeVC: $colorDisclosureCtrl;
$colorItemTreeVCHover: $colorDisclosureCtrlHov;
$colorItemTreeNewNode: rgba($colorBodyFg, 0.5);
$shdwItemTreeIcon: none;
// Layout frame controls

View File

@ -105,7 +105,12 @@
color: $colorItemTreeSelectedFg;
}
}
&.is-new {
animation-name: animTemporaryHighlight;
animation-timing-function: ease-out;
animation-duration: 3s;
animation-iteration-count: 1;
}
&.is-context-clicked {
box-shadow: inset $colorItemTreeSelectedBg 0 0 0 1px;
}
@ -289,13 +294,19 @@
}
@keyframes animSlideLeft {
0% {opactiy: 0; transform: translateX(100%);}
0% {opacity: 0; transform: translateX(100%);}
10% {opacity: 1;}
100% {transform: translateX(0);}
}
@keyframes animSlideRight {
0% {opactiy: 0; transform: translateX(-100%);}
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

@ -74,6 +74,7 @@
:node="treeItem"
:active-search="activeSearch"
:left-offset="!activeSearch ? treeItem.leftOffset : '0px'"
:is-new="treeItem.isNew"
:item-offset="itemOffset"
:item-index="index"
:item-height="itemHeight"
@ -112,7 +113,8 @@ import search from '../components/search.vue';
const ITEM_BUFFER = 25;
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;
export default {
@ -430,9 +432,40 @@ export default {
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) {
let collection = this.openmct.composition.get(domainObject);
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) {
let navigationPath = this.buildNavigationPath(parentObjectPath);
@ -456,7 +489,7 @@ export default {
return this.buildTreeItem(object, parentObjectPath);
});
},
buildTreeItem(domainObject, parentObjectPath) {
buildTreeItem(domainObject, parentObjectPath, isNew = false) {
let objectPath = [domainObject].concat(parentObjectPath);
let navigationPath = this.buildNavigationPath(objectPath);
@ -464,6 +497,7 @@ export default {
id: this.openmct.objects.makeKeyString(domainObject.identifier),
object: domainObject,
leftOffset: ((objectPath.length - 1) * TREE_ITEM_INDENT_PX) + 'px',
isNew,
objectPath,
navigationPath
};
@ -476,11 +510,16 @@ export default {
compositionAddHandler(navigationPath) {
return (domainObject) => {
let parentItem = this.getTreeItemByPath(navigationPath);
let newItem = this.buildTreeItem(domainObject, parentItem.objectPath);
let allDescendants = this.getChildrenInTreeFor(parentItem, RETURN_ALL_DESCDNDANTS);
let newItem = this.buildTreeItem(domainObject, parentItem.objectPath, true);
let allDescendants = this.getChildrenInTreeFor(parentItem, RETURN_ALL_DESCENDANTS);
let afterItem = allDescendants.length ? allDescendants.pop() : parentItem;
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) {
@ -512,6 +551,14 @@ export default {
const removeIndex = this.getTreeItemIndex(item.navigationPath);
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) {
const addIndex = this.getTreeItemIndex(afterItem.navigationPath);
this.treeItems.splice(addIndex + 1, 0, addItem);

View File

@ -8,7 +8,8 @@
:class="{
'is-alias': isAlias,
'is-navigated-object': navigated,
'is-context-clicked': contextClickActive
'is-context-clicked': contextClickActive,
'is-new': isNewItem
}"
@click.capture="handleClick"
@contextmenu.capture="handleContextMenu"
@ -59,6 +60,10 @@ export default {
type: String,
default: '0px'
},
isNew: {
type: Boolean,
default: false
},
itemIndex: {
type: Number,
required: false,
@ -104,6 +109,9 @@ export default {
return parentKeyString !== this.node.object.location;
},
isNewItem() {
return this.isNew;
},
isLoading() {
return Boolean(this.loadingItems[this.navigationPath]);
},