mirror of
https://github.com/nasa/openmct.git
synced 2025-06-25 10:44:21 +00:00
Compare commits
24 Commits
plot-perfo
...
tree-refac
Author | SHA1 | Date | |
---|---|---|---|
dbb5544c09 | |||
91b58d1d34 | |||
d217d83e93 | |||
c644e5266a | |||
5b6e61d95a | |||
474b1ed2bf | |||
125702865e | |||
0d0de1ed64 | |||
85ab5cb319 | |||
3801f5eb21 | |||
fd663392b8 | |||
299005982f | |||
8d3b277ef4 | |||
8eae707833 | |||
f62b39054a | |||
7515ce504e | |||
0b5ca621ec | |||
0e0644cd1f | |||
6089ae3531 | |||
876eb59787 | |||
17be0d7132 | |||
ace880dd41 | |||
dc3781c8e5 | |||
b76b4e4098 |
@ -3,8 +3,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@keyframes rotation-centered {
|
@keyframes rotation-centered {
|
||||||
0% { transform: translate(-50%, -50%) rotate(0deg); }
|
0% { transform: rotate(0deg); }
|
||||||
100% { transform: translate(-50%, -50%) rotate(360deg); }
|
100% { transform: rotate(360deg); }
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes clock-hands {
|
@keyframes clock-hands {
|
||||||
|
@ -391,7 +391,7 @@ $splitterBtnColorBg: $colorBtnBg;
|
|||||||
$splitterBtnColorFg: #999;
|
$splitterBtnColorFg: #999;
|
||||||
$splitterBtnLabelColorFg: #666;
|
$splitterBtnLabelColorFg: #666;
|
||||||
$splitterCollapsedBtnColorBg: #222;
|
$splitterCollapsedBtnColorBg: #222;
|
||||||
$splitterCollapsedBtnColorFg: #666;
|
$splitterCollapsedBtnColorFg: #555;
|
||||||
$splitterCollapsedBtnColorBgHov: $colorKey;
|
$splitterCollapsedBtnColorBgHov: $colorKey;
|
||||||
$splitterCollapsedBtnColorFgHov: $colorKeyFg;
|
$splitterCollapsedBtnColorFgHov: $colorKeyFg;
|
||||||
|
|
||||||
|
@ -45,6 +45,7 @@ $overlayOuterMarginFullscreen: 0%;
|
|||||||
$overlayOuterMarginDialog: 20%;
|
$overlayOuterMarginDialog: 20%;
|
||||||
$overlayInnerMargin: 25px;
|
$overlayInnerMargin: 25px;
|
||||||
$mainViewPad: 2px;
|
$mainViewPad: 2px;
|
||||||
|
$treeNavArrowD: 20px;
|
||||||
/*************** Items */
|
/*************** Items */
|
||||||
$itemPadLR: 5px;
|
$itemPadLR: 5px;
|
||||||
$gridItemDesk: 175px;
|
$gridItemDesk: 175px;
|
||||||
@ -82,8 +83,8 @@ $formLabelMinW: 120px;
|
|||||||
$formLabelW: 30%;
|
$formLabelW: 30%;
|
||||||
/*************** Wait Spinner */
|
/*************** Wait Spinner */
|
||||||
$waitSpinnerD: 32px;
|
$waitSpinnerD: 32px;
|
||||||
$waitSpinnerTreeD: 20px;
|
|
||||||
$waitSpinnerBorderW: 5px;
|
$waitSpinnerBorderW: 5px;
|
||||||
|
$waitSpinnerTreeD: 20px;
|
||||||
$waitSpinnerTreeBorderW: 3px;
|
$waitSpinnerTreeBorderW: 3px;
|
||||||
/*************** Messages */
|
/*************** Messages */
|
||||||
$messageIconD: 80px;
|
$messageIconD: 80px;
|
||||||
@ -198,6 +199,8 @@ $glyph-icon-export: '\ea2e';
|
|||||||
$glyph-icon-font-size: '\ea2f';
|
$glyph-icon-font-size: '\ea2f';
|
||||||
$glyph-icon-clear-data: '\ea30';
|
$glyph-icon-clear-data: '\ea30';
|
||||||
$glyph-icon-history: '\ea31';
|
$glyph-icon-history: '\ea31';
|
||||||
|
$glyph-icon-arrow-nav-to-parent: '\ea32';
|
||||||
|
$glyph-icon-crosshair-in-circle: '\ea33';
|
||||||
$glyph-icon-activity: '\eb00';
|
$glyph-icon-activity: '\eb00';
|
||||||
$glyph-icon-activity-mode: '\eb01';
|
$glyph-icon-activity-mode: '\eb01';
|
||||||
$glyph-icon-autoflow-tabular: '\eb02';
|
$glyph-icon-autoflow-tabular: '\eb02';
|
||||||
@ -240,6 +243,7 @@ $glyph-icon-command: '\eb26';
|
|||||||
$glyph-icon-conditional: '\eb27';
|
$glyph-icon-conditional: '\eb27';
|
||||||
$glyph-icon-condition-widget: '\eb28';
|
$glyph-icon-condition-widget: '\eb28';
|
||||||
$glyph-icon-alphanumeric: '\eb29';
|
$glyph-icon-alphanumeric: '\eb29';
|
||||||
|
$glyph-icon-image-telemetry: '\eb2a';
|
||||||
|
|
||||||
/************************** GLYPHS AS DATA URI */
|
/************************** GLYPHS AS DATA URI */
|
||||||
// Only objects have been converted, for use in Create menu and folder views
|
// Only objects have been converted, for use in Create menu and folder views
|
||||||
|
@ -102,7 +102,8 @@ button {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.c-click-link {
|
.c-click-link,
|
||||||
|
.c-icon-link {
|
||||||
// A clickable element, typically inline, with an icon and label
|
// A clickable element, typically inline, with an icon and label
|
||||||
@include cControl();
|
@include cControl();
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@ -117,8 +118,15 @@ button {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.c-icon-link {
|
||||||
|
&:before {
|
||||||
|
// Icon
|
||||||
|
//color: $colorBtnMajorBg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.c-icon-button {
|
.c-icon-button {
|
||||||
.c-icon-button__label {
|
&__label {
|
||||||
margin-left: $interiorMargin;
|
margin-left: $interiorMargin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -284,19 +284,23 @@ body.desktop .has-local-controls {
|
|||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding-left: $spinnerL + $d/2 + $interiorMargin;
|
margin-left: $treeNavArrowD + $interiorMargin;
|
||||||
background: $colorLoadingBg;
|
|
||||||
min-height: 5px + $d;
|
min-height: 5px + $d;
|
||||||
|
|
||||||
.c-tree__item__label {
|
.c-tree__item__label {
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
|
margin-left: $interiorMargin;
|
||||||
opacity: 0.6;
|
opacity: 0.6;
|
||||||
}
|
}
|
||||||
&:before {
|
&:before {
|
||||||
|
left: auto;
|
||||||
|
top: auto;
|
||||||
|
transform: translate(0);
|
||||||
height: $d;
|
height: $d;
|
||||||
width: $d;
|
width: $d;
|
||||||
border-width: 4px;
|
border-width: 3px;
|
||||||
left: $spinnerL;
|
//left: $spinnerL;
|
||||||
|
position: relative;
|
||||||
}
|
}
|
||||||
&:after {
|
&:after {
|
||||||
display: none;
|
display: none;
|
||||||
|
@ -134,6 +134,8 @@
|
|||||||
.icon-font-size { @include glyphBefore($glyph-icon-font-size); }
|
.icon-font-size { @include glyphBefore($glyph-icon-font-size); }
|
||||||
.icon-clear-data { @include glyphBefore($glyph-icon-clear-data); }
|
.icon-clear-data { @include glyphBefore($glyph-icon-clear-data); }
|
||||||
.icon-history { @include glyphBefore($glyph-icon-history); }
|
.icon-history { @include glyphBefore($glyph-icon-history); }
|
||||||
|
.icon-arrow-nav-to-parent { @include glyphBefore($glyph-icon-arrow-nav-to-parent); }
|
||||||
|
.icon-crosshair-in-circle { @include glyphBefore($glyph-icon-crosshair-in-circle); }
|
||||||
.icon-activity { @include glyphBefore($glyph-icon-activity); }
|
.icon-activity { @include glyphBefore($glyph-icon-activity); }
|
||||||
.icon-activity-mode { @include glyphBefore($glyph-icon-activity-mode); }
|
.icon-activity-mode { @include glyphBefore($glyph-icon-activity-mode); }
|
||||||
.icon-autoflow-tabular { @include glyphBefore($glyph-icon-autoflow-tabular); }
|
.icon-autoflow-tabular { @include glyphBefore($glyph-icon-autoflow-tabular); }
|
||||||
@ -176,6 +178,7 @@
|
|||||||
.icon-conditional { @include glyphBefore($glyph-icon-conditional); }
|
.icon-conditional { @include glyphBefore($glyph-icon-conditional); }
|
||||||
.icon-condition-widget { @include glyphBefore($glyph-icon-condition-widget); }
|
.icon-condition-widget { @include glyphBefore($glyph-icon-condition-widget); }
|
||||||
.icon-alphanumeric { @include glyphBefore($glyph-icon-alphanumeric); }
|
.icon-alphanumeric { @include glyphBefore($glyph-icon-alphanumeric); }
|
||||||
|
.icon-image-telemetry { @include glyphBefore($glyph-icon-image-telemetry); }
|
||||||
|
|
||||||
/************************** 12 PX CLASSES */
|
/************************** 12 PX CLASSES */
|
||||||
// TODO: sync with 16px redo as of 10/25/18
|
// TODO: sync with 16px redo as of 10/25/18
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -102,6 +102,8 @@
|
|||||||
<glyph unicode="" glyph-name="icon-font-size" d="M842.841 451.952h-120.956l-52.382-139.676 52.918-141.12 59.942 159.84 62.361-166.314h-119.884l34.019-90.717h119.884l39.695-105.836h105.836l-181.434 483.823zM263.903 671.871l-263.903-703.742h153.944l57.729 153.944h280.397l57.729-153.944h153.944l-263.903 703.742zM261.154 254.024l90.717 241.911 90.717-241.911z" />
|
<glyph unicode="" glyph-name="icon-font-size" d="M842.841 451.952h-120.956l-52.382-139.676 52.918-141.12 59.942 159.84 62.361-166.314h-119.884l34.019-90.717h119.884l39.695-105.836h105.836l-181.434 483.823zM263.903 671.871l-263.903-703.742h153.944l57.729 153.944h280.397l57.729-153.944h153.944l-263.903 703.742zM261.154 254.024l90.717 241.911 90.717-241.911z" />
|
||||||
<glyph unicode="" glyph-name="icon-clear-data" d="M632 520l-120-120-120 120-80-80 120-120-120-120 80-80 120 120 120-120 80 80-120 120 120 120-80 80zM512 832c-282.76 0-512-86-512-192v-640c0-106 229.24-192 512-192s512 86 512 192v640c0 106-229.24 192-512 192zM512 0c-176.731 0-320 143.269-320 320s143.269 320 320 320c176.731 0 320-143.269 320-320v0c0-176.731-143.269-320-320-320v0z" />
|
<glyph unicode="" glyph-name="icon-clear-data" d="M632 520l-120-120-120 120-80-80 120-120-120-120 80-80 120 120 120-120 80 80-120 120 120 120-80 80zM512 832c-282.76 0-512-86-512-192v-640c0-106 229.24-192 512-192s512 86 512 192v640c0 106-229.24 192-512 192zM512 0c-176.731 0-320 143.269-320 320s143.269 320 320 320c176.731 0 320-143.269 320-320v0c0-176.731-143.269-320-320-320v0z" />
|
||||||
<glyph unicode="" glyph-name="icon-history" d="M576 768c-247.4 0-448-200.6-448-448h-128l192-192 192 192h-128c0 85.4 33.2 165.8 93.8 226.2 60.4 60.6 140.8 93.8 226.2 93.8s165.8-33.2 226.2-93.8c60.6-60.4 93.8-140.8 93.8-226.2s-33.2-165.8-93.8-226.2c-60.4-60.6-140.8-93.8-226.2-93.8s-165.8 33.2-226.2 93.8l-90.6-90.6c81-81 193-131.2 316.8-131.2 247.4 0 448 200.6 448 448s-200.6 448-448 448zM576 560c-26.6 0-48-21.4-48-48v-211.8l142-142c9.4-9.4 21.6-14 34-14s24.6 4.6 34 14c18.8 18.8 18.8 49.2 0 67.8l-114 114v172c0 26.6-21.4 48-48 48z" />
|
<glyph unicode="" glyph-name="icon-history" d="M576 768c-247.4 0-448-200.6-448-448h-128l192-192 192 192h-128c0 85.4 33.2 165.8 93.8 226.2 60.4 60.6 140.8 93.8 226.2 93.8s165.8-33.2 226.2-93.8c60.6-60.4 93.8-140.8 93.8-226.2s-33.2-165.8-93.8-226.2c-60.4-60.6-140.8-93.8-226.2-93.8s-165.8 33.2-226.2 93.8l-90.6-90.6c81-81 193-131.2 316.8-131.2 247.4 0 448 200.6 448 448s-200.6 448-448 448zM576 560c-26.6 0-48-21.4-48-48v-211.8l142-142c9.4-9.4 21.6-14 34-14s24.6 4.6 34 14c18.8 18.8 18.8 49.2 0 67.8l-114 114v172c0 26.6-21.4 48-48 48z" />
|
||||||
|
<glyph unicode="" glyph-name="icon-arrow-up-to-parent" horiz-adv-x="1056" d="M643.427 6.739c-81.955 0.697-148.179 67.065-148.642 149.010v395.872l296.871-247.393v197.914l-395.828 329.857-395.828-328.62v-197.502l296.871 246.156v-396.241c0-190.905 155.239-346.556 346.144-346.968l412.321-0.825 0.412 197.914z" />
|
||||||
|
<glyph unicode="" glyph-name="icon-crosshair-in-circle" d="M512 832c-282.8 0-512-229.2-512-512s229.2-512 512-512 512 229.2 512 512-229.2 512-512 512zM783.6 48.4c-54.634-54.8-125.77-93.12-205.322-106.874l-2.278-0.326v250.8h-128v-250.8c-161.302 28.062-286.738 153.497-314.468 312.5l-0.332 2.3h250.8v128h-250.8c28.062 161.302 153.497 286.738 312.5 314.468l2.3 0.332v-250.8h128v250.8c161.302-28.062 286.738-153.497 314.468-312.5l0.332-2.3h-250.8v-128h250.8c-14.080-81.83-52.4-152.966-107.191-207.591l-0.009-0.009z" />
|
||||||
<glyph unicode="" glyph-name="icon-activity" d="M576 768h-256l320-320h-290.256c-44.264 76.516-126.99 128-221.744 128h-128v-512h128c94.754 0 177.48 51.484 221.744 128h290.256l-320-320h256l448 448-448 448z" />
|
<glyph unicode="" glyph-name="icon-activity" d="M576 768h-256l320-320h-290.256c-44.264 76.516-126.99 128-221.744 128h-128v-512h128c94.754 0 177.48 51.484 221.744 128h290.256l-320-320h256l448 448-448 448z" />
|
||||||
<glyph unicode="" glyph-name="icon-activity-mode" d="M512 832c-214.8 0-398.8-132.4-474.8-320h90.8c56.8 0 108-24.8 143-64h241l-192 192h256l320-320-320-320h-256l192 192h-241c-35-39.2-86.2-64-143-64h-90.8c76-187.6 259.8-320 474.8-320 282.8 0 512 229.2 512 512s-229.2 512-512 512z" />
|
<glyph unicode="" glyph-name="icon-activity-mode" d="M512 832c-214.8 0-398.8-132.4-474.8-320h90.8c56.8 0 108-24.8 143-64h241l-192 192h256l320-320-320-320h-256l192 192h-241c-35-39.2-86.2-64-143-64h-90.8c76-187.6 259.8-320 474.8-320 282.8 0 512 229.2 512 512s-229.2 512-512 512z" />
|
||||||
<glyph unicode="" glyph-name="icon-autoflow-tabular" d="M192 832c-105.6 0-192-86.4-192-192v-640c0-105.6 86.4-192 192-192h64v1024h-64zM384 832h256v-1024h-256v1024zM832 832h-64v-704h256v512c0 105.6-86.4 192-192 192z" />
|
<glyph unicode="" glyph-name="icon-autoflow-tabular" d="M192 832c-105.6 0-192-86.4-192-192v-640c0-105.6 86.4-192 192-192h64v1024h-64zM384 832h256v-1024h-256v1024zM832 832h-64v-704h256v512c0 105.6-86.4 192-192 192z" />
|
||||||
@ -144,4 +146,5 @@
|
|||||||
<glyph unicode="" glyph-name="icon-conditional" d="M512 832c-282.76 0-512-229.24-512-512s229.24-512 512-512 512 229.24 512 512-229.24 512-512 512zM512 64l-384 256 384 256 384-256z" />
|
<glyph unicode="" glyph-name="icon-conditional" d="M512 832c-282.76 0-512-229.24-512-512s229.24-512 512-512 512 229.24 512 512-229.24 512-512 512zM512 64l-384 256 384 256 384-256z" />
|
||||||
<glyph unicode="" glyph-name="icon-condition-widget" d="M832 832h-640c-105.6 0-192-86.4-192-192v-640c0-105.6 86.4-192 192-192h640c105.6 0 192 86.4 192 192v640c0 105.6-86.4 192-192 192zM512 64l-384 256 384 256 384-256z" />
|
<glyph unicode="" glyph-name="icon-condition-widget" d="M832 832h-640c-105.6 0-192-86.4-192-192v-640c0-105.6 86.4-192 192-192h640c105.6 0 192 86.4 192 192v640c0 105.6-86.4 192-192 192zM512 64l-384 256 384 256 384-256z" />
|
||||||
<glyph unicode="" glyph-name="icon-alphanumeric" d="M535.6 301.4c-8.4-1.6-17.2-3-26.2-4s-18.2-2.4-27.2-4c-10.196-1.861-18.808-4.010-27.21-6.633l1.61 0.433c-8.609-2.674-16.105-6.348-22.89-10.987l0.29 0.187c-6.693-4.517-12.283-10.107-16.663-16.585l-0.137-0.215c-4.6-6.8-7.4-15.6-8.8-26s-0.4-18.4 2.4-25.2c2.746-6.688 7.224-12.195 12.881-16.122l0.119-0.078c5.967-4.053 13.057-6.94 20.704-8.161l0.296-0.039c7.592-1.527 16.319-2.4 25.25-2.4 0.123 0 0.246 0 0.369 0h-0.019c22.2 0 39.6 3.6 52.6 11s23.2 16.2 30.2 26.4c6.273 8.873 11.271 19.191 14.426 30.285l0.174 0.715c1.853 6.809 3.601 15.41 4.855 24.169l0.145 1.231 5.2 41.6c-5.4-4.217-11.723-7.564-18.583-9.689l-0.417-0.111c-6.489-2.241-14.362-4.255-22.444-5.662l-0.956-0.138zM1024 448v192h-152l24 192h-192l-24-192h-256l24 192h-192l-24-192h-232v-192h208l-32-256h-176v-192h152l-24-192h192l24 192h256l-24-192h192l24 192h232v192h-208l32 256zM702.8 420.2l-26.4-211.8c-2.231-15.809-3.537-34.122-3.6-52.727v-0.073c0-16.8 2.2-29.4 6.4-37.8h-113.4c-1.342 5.556-2.338 12.122-2.781 18.84l-0.019 0.36c-0.261 3.524-0.409 7.634-0.409 11.778 0 2.962 0.076 5.907 0.226 8.832l-0.017-0.41c-18.663-17.401-41.395-30.694-66.597-38.289l-1.203-0.311c-22.627-6.956-48.639-10.974-75.586-11h-0.014c-0.764-0.011-1.666-0.018-2.569-0.018-18.098 0-35.598 2.563-52.156 7.345l1.325-0.328c-15.991 4.512-29.851 12.090-41.545 22.122l0.145-0.122c-11.233 9.982-19.792 22.733-24.624 37.192l-0.176 0.608c-5.2 15.2-6.4 33.4-3.8 54.4s9.4 42.2 19.4 57.2c9.524 14.399 21.535 26.346 35.532 35.512l0.468 0.288c13.387 8.662 28.922 15.533 45.512 19.765l1.088 0.235c13.436 3.792 30.801 7.554 48.47 10.41l2.93 0.39c17 2.6 33.8 4.6 50.4 6.2 16.628 1.527 31.69 4.070 46.349 7.643l-2.149-0.443c13 3 23.6 7.6 31.6 13.6s12.6 15 13.6 26.4 0.8 21.8-2.4 28.8c-2.849 6.902-7.542 12.56-13.468 16.517l-0.132 0.083c-6.217 4.011-13.604 6.78-21.543 7.774l-0.257 0.026c-7.897 1.277-17 2.007-26.274 2.007-0.537 0-1.073-0.002-1.609-0.007l0.082 0.001c-22 0-40-4.6-53.8-14.2s-23-25.2-28-47.2h-111.8c4.8 26.2 14.2 48 27.8 65.4 13.475 16.978 29.89 30.968 48.574 41.377l0.826 0.423c18.192 10.038 39.297 17.806 61.619 22.175l1.381 0.225c20.488 4.162 44.053 6.563 68.171 6.6h0.029c21.8-0.005 43.239-1.532 64.222-4.479l-2.422 0.279c20.641-2.809 39.324-8.783 56.401-17.461l-1.001 0.461c15.909-8.108 28.858-20.031 37.967-34.601l0.233-0.399c9-15 12.2-34.8 9-59.6z" />
|
<glyph unicode="" glyph-name="icon-alphanumeric" d="M535.6 301.4c-8.4-1.6-17.2-3-26.2-4s-18.2-2.4-27.2-4c-10.196-1.861-18.808-4.010-27.21-6.633l1.61 0.433c-8.609-2.674-16.105-6.348-22.89-10.987l0.29 0.187c-6.693-4.517-12.283-10.107-16.663-16.585l-0.137-0.215c-4.6-6.8-7.4-15.6-8.8-26s-0.4-18.4 2.4-25.2c2.746-6.688 7.224-12.195 12.881-16.122l0.119-0.078c5.967-4.053 13.057-6.94 20.704-8.161l0.296-0.039c7.592-1.527 16.319-2.4 25.25-2.4 0.123 0 0.246 0 0.369 0h-0.019c22.2 0 39.6 3.6 52.6 11s23.2 16.2 30.2 26.4c6.273 8.873 11.271 19.191 14.426 30.285l0.174 0.715c1.853 6.809 3.601 15.41 4.855 24.169l0.145 1.231 5.2 41.6c-5.4-4.217-11.723-7.564-18.583-9.689l-0.417-0.111c-6.489-2.241-14.362-4.255-22.444-5.662l-0.956-0.138zM1024 448v192h-152l24 192h-192l-24-192h-256l24 192h-192l-24-192h-232v-192h208l-32-256h-176v-192h152l-24-192h192l24 192h256l-24-192h192l24 192h232v192h-208l32 256zM702.8 420.2l-26.4-211.8c-2.231-15.809-3.537-34.122-3.6-52.727v-0.073c0-16.8 2.2-29.4 6.4-37.8h-113.4c-1.342 5.556-2.338 12.122-2.781 18.84l-0.019 0.36c-0.261 3.524-0.409 7.634-0.409 11.778 0 2.962 0.076 5.907 0.226 8.832l-0.017-0.41c-18.663-17.401-41.395-30.694-66.597-38.289l-1.203-0.311c-22.627-6.956-48.639-10.974-75.586-11h-0.014c-0.764-0.011-1.666-0.018-2.569-0.018-18.098 0-35.598 2.563-52.156 7.345l1.325-0.328c-15.991 4.512-29.851 12.090-41.545 22.122l0.145-0.122c-11.233 9.982-19.792 22.733-24.624 37.192l-0.176 0.608c-5.2 15.2-6.4 33.4-3.8 54.4s9.4 42.2 19.4 57.2c9.524 14.399 21.535 26.346 35.532 35.512l0.468 0.288c13.387 8.662 28.922 15.533 45.512 19.765l1.088 0.235c13.436 3.792 30.801 7.554 48.47 10.41l2.93 0.39c17 2.6 33.8 4.6 50.4 6.2 16.628 1.527 31.69 4.070 46.349 7.643l-2.149-0.443c13 3 23.6 7.6 31.6 13.6s12.6 15 13.6 26.4 0.8 21.8-2.4 28.8c-2.849 6.902-7.542 12.56-13.468 16.517l-0.132 0.083c-6.217 4.011-13.604 6.78-21.543 7.774l-0.257 0.026c-7.897 1.277-17 2.007-26.274 2.007-0.537 0-1.073-0.002-1.609-0.007l0.082 0.001c-22 0-40-4.6-53.8-14.2s-23-25.2-28-47.2h-111.8c4.8 26.2 14.2 48 27.8 65.4 13.475 16.978 29.89 30.968 48.574 41.377l0.826 0.423c18.192 10.038 39.297 17.806 61.619 22.175l1.381 0.225c20.488 4.162 44.053 6.563 68.171 6.6h0.029c21.8-0.005 43.239-1.532 64.222-4.479l-2.422 0.279c20.641-2.809 39.324-8.783 56.401-17.461l-1.001 0.461c15.909-8.108 28.858-20.031 37.967-34.601l0.233-0.399c9-15 12.2-34.8 9-59.6z" />
|
||||||
|
<glyph unicode="" glyph-name="icon-image-telemetry" d="M512 832c-282.8 0-512-229.2-512-512s229.2-512 512-512 512 229.2 512 512-229.2 512-512 512zM783.6 48.4c-69.581-69.675-165.757-112.776-272-112.776-212.298 0-384.4 172.102-384.4 384.4s172.102 384.4 384.4 384.4c212.298 0 384.4-172.102 384.4-384.4 0-0.008 0-0.017 0-0.025v0.001c0.001-0.264 0.001-0.575 0.001-0.887 0-105.769-42.964-201.503-112.391-270.703l-0.010-0.010zM704 448l-128-128-192 192-192-192c0-176.731 143.269-320 320-320s320 143.269 320 320v0z" />
|
||||||
</font></defs></svg>
|
</font></defs></svg>
|
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 56 KiB |
@ -1,10 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<span
|
<span
|
||||||
class="c-disclosure-triangle"
|
:class="[
|
||||||
:class="{
|
controlClass,
|
||||||
'c-disclosure-triangle--expanded' : value,
|
{ 'c-disclosure-triangle--expanded' : value },
|
||||||
'is-enabled' : enabled
|
{'is-enabled' : enabled }
|
||||||
}"
|
]"
|
||||||
@click="handleClick"
|
@click="handleClick"
|
||||||
></span>
|
></span>
|
||||||
</template>
|
</template>
|
||||||
@ -25,6 +25,10 @@ export default {
|
|||||||
propagate: {
|
propagate: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true
|
default: true
|
||||||
|
},
|
||||||
|
controlClass: {
|
||||||
|
type: String,
|
||||||
|
default: 'c-disclosure-triangle'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
@ -3,7 +3,8 @@
|
|||||||
<div class="l-browse-bar__start">
|
<div class="l-browse-bar__start">
|
||||||
<button
|
<button
|
||||||
v-if="hasParent"
|
v-if="hasParent"
|
||||||
class="l-browse-bar__nav-to-parent-button c-icon-button c-icon-button--major icon-pointer-left"
|
class="l-browse-bar__nav-to-parent-button c-icon-button c-icon-button--major icon-arrow-nav-to-parent"
|
||||||
|
title="Navigate up to parent"
|
||||||
@click="goToParent"
|
@click="goToParent"
|
||||||
></button>
|
></button>
|
||||||
<div
|
<div
|
||||||
|
@ -47,12 +47,23 @@
|
|||||||
label="Browse"
|
label="Browse"
|
||||||
collapsable
|
collapsable
|
||||||
>
|
>
|
||||||
<mct-tree class="l-shell__tree" />
|
<button
|
||||||
|
slot="controls"
|
||||||
|
class="c-icon-button icon-crosshair-in-circle"
|
||||||
|
title="Show selected item in tree"
|
||||||
|
@click="handleSyncTreeNavigation"
|
||||||
|
>
|
||||||
|
</button>
|
||||||
|
<mct-tree
|
||||||
|
:sync-tree-navigation="triggerSync"
|
||||||
|
class="l-shell__tree"
|
||||||
|
/>
|
||||||
</pane>
|
</pane>
|
||||||
<pane class="l-shell__pane-main">
|
<pane class="l-shell__pane-main">
|
||||||
<browse-bar
|
<browse-bar
|
||||||
ref="browseBar"
|
ref="browseBar"
|
||||||
class="l-shell__main-view-browse-bar"
|
class="l-shell__main-view-browse-bar"
|
||||||
|
@sync-tree-navigation="handleSyncTreeNavigation"
|
||||||
/>
|
/>
|
||||||
<toolbar
|
<toolbar
|
||||||
v-if="toolbar"
|
v-if="toolbar"
|
||||||
@ -154,7 +165,8 @@ export default {
|
|||||||
conductorComponent: undefined,
|
conductorComponent: undefined,
|
||||||
isEditing: false,
|
isEditing: false,
|
||||||
hasToolbar: false,
|
hasToolbar: false,
|
||||||
headExpanded
|
headExpanded,
|
||||||
|
triggerSync: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@ -204,6 +216,9 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.hasToolbar = structure.length > 0;
|
this.hasToolbar = structure.length > 0;
|
||||||
|
},
|
||||||
|
handleSyncTreeNavigation() {
|
||||||
|
this.triggerSync = !this.triggerSync;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -304,6 +304,10 @@
|
|||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
> * + * {
|
||||||
|
margin-left: $interiorMarginSm;
|
||||||
|
}
|
||||||
|
|
||||||
&__start,
|
&__start,
|
||||||
&__end,
|
&__end,
|
||||||
&__actions {
|
&__actions {
|
||||||
@ -320,8 +324,12 @@
|
|||||||
|
|
||||||
&__start {
|
&__start {
|
||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
margin-right: $interiorMargin;
|
//margin-right: $interiorMargin;
|
||||||
min-width: 0; // Forces interior to compress when pushed on
|
min-width: 0; // Forces interior to compress when pushed on
|
||||||
|
|
||||||
|
[class*='button'] {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&__end {
|
&__end {
|
||||||
@ -330,15 +338,15 @@
|
|||||||
|
|
||||||
&__nav-to-parent-button,
|
&__nav-to-parent-button,
|
||||||
&__disclosure-button {
|
&__disclosure-button {
|
||||||
flex: 0 0 auto;
|
//flex: 0 0 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__nav-to-parent-button {
|
&__nav-to-parent-button {
|
||||||
// This is an icon-button
|
// This is an icon-button
|
||||||
$p: $interiorMargin;
|
//$p: $interiorMargin;
|
||||||
margin-right: $interiorMargin;
|
//margin-right: $interiorMargin;
|
||||||
padding-left: $p;
|
//padding-left: $p;
|
||||||
padding-right: $p;
|
//padding-right: $p;
|
||||||
|
|
||||||
.is-editing & {
|
.is-editing & {
|
||||||
display: none;
|
display: none;
|
||||||
@ -351,7 +359,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&__object-name--w {
|
&__object-name--w {
|
||||||
@include headerFont(1.4em);
|
@include headerFont(1.5em);
|
||||||
|
margin-left: $interiorMarginLg;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
|
|
||||||
&:before {
|
&:before {
|
||||||
|
69
src/ui/layout/layoutSpec.js
Normal file
69
src/ui/layout/layoutSpec.js
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
import {
|
||||||
|
createOpenMct,
|
||||||
|
spyOnBuiltins,
|
||||||
|
resetApplicationState,
|
||||||
|
generatePromises,
|
||||||
|
getMockObjects
|
||||||
|
} from 'utils/testing';
|
||||||
|
|
||||||
|
fdescribe("the tree navigation", () => {
|
||||||
|
let openmct,
|
||||||
|
element,
|
||||||
|
child;
|
||||||
|
|
||||||
|
beforeAll(() => {
|
||||||
|
this.removeAllSpies();
|
||||||
|
resetApplicationState(openmct);
|
||||||
|
})
|
||||||
|
|
||||||
|
beforeEach((done) => {
|
||||||
|
openmct = createOpenMct();
|
||||||
|
|
||||||
|
element = document.createElement('div');
|
||||||
|
child = document.createElement('div');
|
||||||
|
element.appendChild(child);
|
||||||
|
|
||||||
|
spyOnBuiltins(['requestAnimationFrame']);
|
||||||
|
window.requestAnimationFrame.and.callFake((callBack) => {
|
||||||
|
callBack();
|
||||||
|
});
|
||||||
|
|
||||||
|
let promises = generatePromises(['root']),
|
||||||
|
root = getMockObjects({
|
||||||
|
objectKeyStrings: ['root'],
|
||||||
|
overwrite: {
|
||||||
|
root: {
|
||||||
|
composition: [{ namespace: '', key: 'mine' }]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).root;
|
||||||
|
|
||||||
|
spyOn(openmct.objects, 'get').and.callFake((id) => {
|
||||||
|
console.log('object get', id);
|
||||||
|
if (id === 'ROOT' || id.key === 'ROOT') {
|
||||||
|
promises.rootPromiseResolve(root);
|
||||||
|
return promises.rootPromise;
|
||||||
|
} else {
|
||||||
|
console.log('get other');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
spyOn(openmct.composition, 'get').and.callFake((domainObject) => {
|
||||||
|
console.log('comp get', domainObject);
|
||||||
|
});
|
||||||
|
|
||||||
|
openmct.on('start', done);
|
||||||
|
openmct.start();
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
this.removeAllSpies();
|
||||||
|
resetApplicationState(openmct);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should be true", () => {
|
||||||
|
let tree = document.querySelector('.c-tree-and-search');
|
||||||
|
console.log('tree', tree);
|
||||||
|
expect(true).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
@ -1,9 +1,13 @@
|
|||||||
.c-tree-and-search {
|
.c-tree-and-search {
|
||||||
|
$hoverBg: rgba(#000, 0.1);
|
||||||
|
$hoverFg: #ccc;
|
||||||
|
$selected: #fff;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
//TODO: Do we need this???
|
//TODO: Do we need this???
|
||||||
//padding-right: $interiorMarginSm;
|
//padding-right: $interiorMarginSm;
|
||||||
|
width: 100%;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
|
|
||||||
> * + * { margin-top: $interiorMargin; }
|
> * + * { margin-top: $interiorMargin; }
|
||||||
@ -12,10 +16,6 @@
|
|||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__loading {
|
|
||||||
flex: 1 1 auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__no-results {
|
&__no-results {
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
opacity: 0.6;
|
opacity: 0.6;
|
||||||
@ -26,6 +26,115 @@
|
|||||||
height: 0; // Chrome 73 overflow bug fix
|
height: 0; // Chrome 73 overflow bug fix
|
||||||
padding-right: $interiorMarginSm;
|
padding-right: $interiorMarginSm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// new tree refactor
|
||||||
|
.c-tree,
|
||||||
|
.c-list {
|
||||||
|
&__item {
|
||||||
|
border-radius: 0;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: $hoverBg;
|
||||||
|
|
||||||
|
[class*="__name"] {
|
||||||
|
color: darken($colorKeyFg, 10%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.is-navigated-object,
|
||||||
|
&.is-selected {
|
||||||
|
background: none;
|
||||||
|
|
||||||
|
[class*="__name"] {
|
||||||
|
color: $selected;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// new tree refactor
|
||||||
|
.c-tree {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
overflow-x: hidden;
|
||||||
|
overflow-y: auto;
|
||||||
|
transition: all;
|
||||||
|
|
||||||
|
.scrollable-children {
|
||||||
|
.c-tree__item-h {
|
||||||
|
width: 100%;
|
||||||
|
&.empty {
|
||||||
|
font-style: italic;
|
||||||
|
color: #666;
|
||||||
|
display: inline;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.c-tree {
|
||||||
|
padding-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__item {
|
||||||
|
//border-bottom: 1px solid $colorInteriorBorder;
|
||||||
|
|
||||||
|
&.is-navigated-object,
|
||||||
|
&.is-selected {
|
||||||
|
.c-tree__item__type-icon:before {
|
||||||
|
color: $selected;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.c-nav {
|
||||||
|
$dimension: 20px;
|
||||||
|
|
||||||
|
&__up, &__down {
|
||||||
|
color: #fff;
|
||||||
|
flex: 0 0 auto;
|
||||||
|
height: $dimension;
|
||||||
|
width: $dimension;
|
||||||
|
visibility: hidden;
|
||||||
|
position: relative;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
&.is-enabled {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: darken($colorKeyFg, 10%);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
// Nav arrow
|
||||||
|
$color: rgba(#999, 0.5); // TODO: must make this theme-compliant
|
||||||
|
$dimension: 9px;
|
||||||
|
$width: 3px;
|
||||||
|
border: solid $color;
|
||||||
|
//border-width: $width;
|
||||||
|
border-width: 0 $width $width 0;
|
||||||
|
content: '';
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
left: 50%; top: 50%;
|
||||||
|
height: $dimension;
|
||||||
|
width: $dimension;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover:before {
|
||||||
|
border-color: $colorItemTreeHoverFg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__up:before {
|
||||||
|
transform: translate(-30%, -50%) rotate(135deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
&__down:before {
|
||||||
|
transform: translate(-70%, -50%) rotate(-45deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.c-tree,
|
.c-tree,
|
||||||
@ -157,3 +266,32 @@
|
|||||||
padding: $interiorMargin;
|
padding: $interiorMargin;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TRANSITIONS
|
||||||
|
.slide-left,
|
||||||
|
.slide-right {
|
||||||
|
animation-duration: 500ms;
|
||||||
|
animation-iteration-count: 1;
|
||||||
|
transition: all;
|
||||||
|
transition-timing-function: ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slide-left {
|
||||||
|
animation-name: animSlideLeft;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slide-right {
|
||||||
|
animation-name: animSlideRight;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes animSlideLeft {
|
||||||
|
0% {opactiy: 0; transform: translateX(100%);}
|
||||||
|
10% {opacity: 1;}
|
||||||
|
100% {transform: translateX(0);}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes animSlideRight {
|
||||||
|
0% {opactiy: 0; transform: translateX(-100%);}
|
||||||
|
10% {opacity: 1;}
|
||||||
|
100% {transform: translateX(0);}
|
||||||
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="c-tree-and-search">
|
<div
|
||||||
|
class="c-tree-and-search"
|
||||||
|
>
|
||||||
<div class="c-tree-and-search__search">
|
<div class="c-tree-and-search__search">
|
||||||
<search
|
<search
|
||||||
ref="shell-search"
|
ref="shell-search"
|
||||||
@ -10,15 +12,8 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- loading -->
|
|
||||||
<div
|
<div
|
||||||
v-if="isLoading"
|
v-if="(searchValue && allTreeItems.length === 0 && !isLoading) || (searchValue && searchResultItems.length === 0)"
|
||||||
class="c-tree-and-search__loading loading"
|
|
||||||
></div>
|
|
||||||
<!-- end loading -->
|
|
||||||
|
|
||||||
<div
|
|
||||||
v-if="(allTreeItems.length === 0) || (searchValue && filteredTreeItems.length === 0)"
|
|
||||||
class="c-tree-and-search__no-results"
|
class="c-tree-and-search__no-results"
|
||||||
>
|
>
|
||||||
No results found
|
No results found
|
||||||
@ -26,30 +21,70 @@
|
|||||||
|
|
||||||
<!-- main tree -->
|
<!-- main tree -->
|
||||||
<ul
|
<ul
|
||||||
v-if="!isLoading"
|
ref="mainTree"
|
||||||
v-show="!searchValue"
|
|
||||||
class="c-tree-and-search__tree c-tree"
|
class="c-tree-and-search__tree c-tree"
|
||||||
>
|
>
|
||||||
<tree-item
|
<!-- ancestors -->
|
||||||
v-for="treeItem in allTreeItems"
|
<div v-if="!activeSearch">
|
||||||
:key="treeItem.id"
|
<tree-item
|
||||||
:node="treeItem"
|
v-for="(ancestor, index) in ancestors"
|
||||||
/>
|
:key="ancestor.id"
|
||||||
|
:node="ancestor"
|
||||||
|
:show-up="index < ancestors.length - 1"
|
||||||
|
:show-down="false"
|
||||||
|
:left-offset="index * 10 + 'px'"
|
||||||
|
@resetTree="handleReset"
|
||||||
|
/>
|
||||||
|
<!-- loading -->
|
||||||
|
<li
|
||||||
|
v-if="isLoading"
|
||||||
|
class="c-tree__item c-tree-and-search__loading loading"
|
||||||
|
>
|
||||||
|
<span class="c-tree__item__label">Loading...</span>
|
||||||
|
</li>
|
||||||
|
<!-- end loading -->
|
||||||
|
</div>
|
||||||
|
<!-- currently viewed children -->
|
||||||
|
<transition
|
||||||
|
@enter="childrenIn"
|
||||||
|
>
|
||||||
|
<li
|
||||||
|
v-if="!isLoading"
|
||||||
|
:class="childrenSlideClass"
|
||||||
|
style="{ position: relative }"
|
||||||
|
>
|
||||||
|
<ul
|
||||||
|
ref="scrollable"
|
||||||
|
class="scrollable-children"
|
||||||
|
:style="scrollableStyles()"
|
||||||
|
@scroll="scrollItems"
|
||||||
|
>
|
||||||
|
<div :style="{ height: childrenHeight + 'px'}">
|
||||||
|
<tree-item
|
||||||
|
v-for="(treeItem, index) in visibleItems"
|
||||||
|
:key="treeItem.id"
|
||||||
|
:node="treeItem"
|
||||||
|
:left-offset="itemLeftOffset"
|
||||||
|
:item-offset="itemOffset"
|
||||||
|
:item-index="index"
|
||||||
|
:item-height="itemHeight"
|
||||||
|
:virtual-scroll="!noScroll"
|
||||||
|
:show-down="activeSearch ? false : true"
|
||||||
|
@expanded="handleExpanded"
|
||||||
|
/>
|
||||||
|
<li
|
||||||
|
v-if="visibleItems.length === 0"
|
||||||
|
:style="emptyStyles()"
|
||||||
|
class="c-tree__item-h empty"
|
||||||
|
>
|
||||||
|
Empty
|
||||||
|
</li>
|
||||||
|
</div>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</transition>
|
||||||
</ul>
|
</ul>
|
||||||
<!-- end main tree -->
|
<!-- end main tree -->
|
||||||
|
|
||||||
<!-- search tree -->
|
|
||||||
<ul
|
|
||||||
v-if="searchValue"
|
|
||||||
class="c-tree-and-search__tree c-tree"
|
|
||||||
>
|
|
||||||
<tree-item
|
|
||||||
v-for="treeItem in filteredTreeItems"
|
|
||||||
:key="treeItem.id"
|
|
||||||
:node="treeItem"
|
|
||||||
/>
|
|
||||||
</ul>
|
|
||||||
<!-- end search tree -->
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -57,6 +92,14 @@
|
|||||||
import treeItem from './tree-item.vue'
|
import treeItem from './tree-item.vue'
|
||||||
import search from '../components/search.vue';
|
import search from '../components/search.vue';
|
||||||
|
|
||||||
|
const LOCAL_STORAGE_KEY__TREE_EXPANDED = 'mct-tree-expanded';
|
||||||
|
const ROOT_PATH = '/browse/';
|
||||||
|
const ITEM_BUFFER = 5;
|
||||||
|
const MAIN_TREE_RECHECK_DELAY = 100;
|
||||||
|
const RESIZE_FIRE_DELAY_MS = 500;
|
||||||
|
let windowResizeId = undefined,
|
||||||
|
windowResizing = false;
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
inject: ['openmct'],
|
inject: ['openmct'],
|
||||||
name: 'MctTree',
|
name: 'MctTree',
|
||||||
@ -64,40 +107,290 @@ export default {
|
|||||||
search,
|
search,
|
||||||
treeItem
|
treeItem
|
||||||
},
|
},
|
||||||
|
props: {
|
||||||
|
syncTreeNavigation: {
|
||||||
|
type: Boolean,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
isLoading: false,
|
||||||
searchValue: '',
|
searchValue: '',
|
||||||
allTreeItems: [],
|
allTreeItems: [],
|
||||||
filteredTreeItems: [],
|
searchResultItems: [],
|
||||||
isLoading: false
|
visibleItems: [],
|
||||||
|
ancestors: [],
|
||||||
|
childrenSlideClass: 'slide-left',
|
||||||
|
availableContainerHeight: 0,
|
||||||
|
noScroll: true,
|
||||||
|
updatingView: false,
|
||||||
|
itemHeight: 28,
|
||||||
|
itemOffset: 0,
|
||||||
|
childrenHeight: 0,
|
||||||
|
scrollable: undefined,
|
||||||
|
pageThreshold: 50,
|
||||||
|
activeSearch: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
currentNavigatedPath() {
|
||||||
|
return this.ancestors
|
||||||
|
.map((ancestor) => ancestor.id)
|
||||||
|
.join('/');
|
||||||
|
},
|
||||||
|
currentObjectPath() {
|
||||||
|
let ancestorsCopy = [...this.ancestors];
|
||||||
|
return ancestorsCopy
|
||||||
|
.reverse()
|
||||||
|
.map((ancestor) => ancestor.object);
|
||||||
|
},
|
||||||
|
focusedItems() {
|
||||||
|
return this.activeSearch ? this.searchResultItems : this.allTreeItems;
|
||||||
|
},
|
||||||
|
itemLeftOffset() {
|
||||||
|
return this.activeSearch ? '0px' : this.ancestors.length * 10 + 'px';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
syncTreeNavigation() {
|
||||||
|
const AND_SAVE_PATH = true;
|
||||||
|
let currentLocationPath = this.openmct.router.currentLocation.path,
|
||||||
|
jumpAndScroll = currentLocationPath &&
|
||||||
|
this.currentlyViewedObjectParentPath() &&
|
||||||
|
!this.currentPathIsActivePath(),
|
||||||
|
justScroll = this.currentPathIsActivePath() && !this.noScroll;
|
||||||
|
|
||||||
|
if(this.searchValue) {
|
||||||
|
this.searchValue = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
if(jumpAndScroll) {
|
||||||
|
this.scrollTo = this.currentlyViewedObjectId();
|
||||||
|
this.allChildren = [];
|
||||||
|
this.ancestors = [];
|
||||||
|
this.jumpPath = this.currentlyViewedObjectParentPath();
|
||||||
|
this.jumpToPath(AND_SAVE_PATH);
|
||||||
|
} else if(justScroll) {
|
||||||
|
this.scrollTo = this.currentlyViewedObjectId();
|
||||||
|
this.autoScroll();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
searchValue() {
|
||||||
|
if(this.searchValue !== '' && !this.activeSearch) {
|
||||||
|
this.searchActivated();
|
||||||
|
} else if(this.searchValue === '') {
|
||||||
|
this.searchDeactivated();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
searchResultItems() {
|
||||||
|
this.setContainerHeight();
|
||||||
|
this.setChildrenHeight();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
|
let savedPath = this.getSavedNavigatedPath();
|
||||||
|
if(savedPath) {
|
||||||
|
let scrollIfApplicable = () => {
|
||||||
|
if(this.currentPathIsActivePath()) {
|
||||||
|
this.scrollTo = this.currentlyViewedObjectId();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
this.jumpPath = savedPath;
|
||||||
|
this.afterJump = scrollIfApplicable;
|
||||||
|
}
|
||||||
this.searchService = this.openmct.$injector.get('searchService');
|
this.searchService = this.openmct.$injector.get('searchService');
|
||||||
this.getAllChildren();
|
window.addEventListener('resize', this.handleWindowResize);
|
||||||
|
this.openmct.objects.get('ROOT').then(root => {
|
||||||
|
let rootNode = this.buildTreeItem(root);
|
||||||
|
this.getAllChildren(rootNode);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
destroyed() {
|
||||||
|
window.removeEventListener('resize', this.handleWindowResize);
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
getAllChildren() {
|
updatevisibleItems() {
|
||||||
this.isLoading = true;
|
if (!this.updatingView) {
|
||||||
this.openmct.objects.get('ROOT')
|
this.updatingView = true;
|
||||||
.then(root => {
|
requestAnimationFrame(()=> {
|
||||||
return this.openmct.composition.get(root).load()
|
let start = 0,
|
||||||
})
|
end = this.pageThreshold,
|
||||||
.then(children => {
|
allItemsCount = this.focusedItems.length;
|
||||||
this.isLoading = false;
|
|
||||||
this.allTreeItems = children.map(c => {
|
if (allItemsCount < this.pageThreshold) {
|
||||||
return {
|
end = allItemsCount;
|
||||||
id: this.openmct.objects.makeKeyString(c.identifier),
|
} else {
|
||||||
object: c,
|
let firstVisible = this.calculateFirstVisibleItem(),
|
||||||
objectPath: [c],
|
lastVisible = this.calculateLastVisibleItem(),
|
||||||
navigateToParent: '/browse'
|
totalVisible = lastVisible - firstVisible,
|
||||||
};
|
numberOffscreen = this.pageThreshold - totalVisible;
|
||||||
});
|
|
||||||
|
start = firstVisible - Math.floor(numberOffscreen / 2);
|
||||||
|
end = lastVisible + Math.ceil(numberOffscreen / 2);
|
||||||
|
|
||||||
|
if (start < 0) {
|
||||||
|
start = 0;
|
||||||
|
end = Math.min(this.pageThreshold, allItemsCount);
|
||||||
|
} else if (end >= allItemsCount) {
|
||||||
|
end = allItemsCount;
|
||||||
|
start = end - this.pageThreshold + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.itemOffset = start;
|
||||||
|
this.visibleItems = this.focusedItems.slice(start, end);
|
||||||
|
|
||||||
|
this.updatingView = false;
|
||||||
});
|
});
|
||||||
|
}
|
||||||
},
|
},
|
||||||
getFilteredChildren() {
|
setContainerHeight() {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
let mainTree = this.$refs.mainTree,
|
||||||
|
mainTreeHeight = mainTree.clientHeight;
|
||||||
|
|
||||||
|
if(mainTreeHeight !== 0) {
|
||||||
|
let ancestorsHeight = this.calculateAncestorHeight(),
|
||||||
|
allChildrenHeight = this.calculateChildrenHeight();
|
||||||
|
|
||||||
|
if(this.activeSearch) {
|
||||||
|
ancestorsHeight = 0;
|
||||||
|
}
|
||||||
|
this.availableContainerHeight = mainTreeHeight - ancestorsHeight;
|
||||||
|
|
||||||
|
if(allChildrenHeight > this.availableContainerHeight) {
|
||||||
|
this.setPageThreshold();
|
||||||
|
this.noScroll = false;
|
||||||
|
} else {
|
||||||
|
this.noScroll = true;
|
||||||
|
}
|
||||||
|
this.updatevisibleItems();
|
||||||
|
} else {
|
||||||
|
setTimeout(this.setContainerHeight, MAIN_TREE_RECHECK_DELAY);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
calculateFirstVisibleItem() {
|
||||||
|
let scrollTop = this.$refs.scrollable.scrollTop;
|
||||||
|
return Math.floor(scrollTop / this.itemHeight);
|
||||||
|
},
|
||||||
|
calculateLastVisibleItem() {
|
||||||
|
let scrollBottom = this.$refs.scrollable.scrollTop + this.$refs.scrollable.offsetHeight;
|
||||||
|
return Math.ceil(scrollBottom / this.itemHeight);
|
||||||
|
},
|
||||||
|
calculateChildrenHeight() {
|
||||||
|
let childrenCount = this.focusedItems.length;
|
||||||
|
return this.itemHeight * childrenCount;
|
||||||
|
},
|
||||||
|
setChildrenHeight() {
|
||||||
|
this.childrenHeight = this.calculateChildrenHeight();
|
||||||
|
},
|
||||||
|
calculateAncestorHeight() {
|
||||||
|
let ancestorCount = this.ancestors.length;
|
||||||
|
return this.itemHeight * ancestorCount;
|
||||||
|
},
|
||||||
|
setPageThreshold() {
|
||||||
|
let threshold = Math.ceil(this.availableContainerHeight / this.itemHeight) + ITEM_BUFFER;
|
||||||
|
// all items haven't loaded yet (nextTick not working for this)
|
||||||
|
if(threshold === ITEM_BUFFER) {
|
||||||
|
setTimeout(this.setPageThreshold, 100);
|
||||||
|
} else {
|
||||||
|
this.pageThreshold = threshold;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleWindowResize() {
|
||||||
|
if(!windowResizing) {
|
||||||
|
windowResizing = true;
|
||||||
|
window.clearTimeout(windowResizeId);
|
||||||
|
windowResizeId = window.setTimeout(() => {
|
||||||
|
this.setContainerHeight();
|
||||||
|
windowResizing = false;
|
||||||
|
}, RESIZE_FIRE_DELAY_MS);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getAllChildren(node) {
|
||||||
|
this.isLoading = true;
|
||||||
|
if (this.composition) {
|
||||||
|
this.composition.off('add', this.addChild);
|
||||||
|
this.composition.off('remove', this.removeChild);
|
||||||
|
delete this.composition;
|
||||||
|
}
|
||||||
|
this.allTreeItems = [];
|
||||||
|
this.composition = this.openmct.composition.get(node.object);
|
||||||
|
this.composition.on('add', this.addChild);
|
||||||
|
this.composition.on('remove', this.removeChild);
|
||||||
|
this.composition.load().then(this.finishLoading);
|
||||||
|
},
|
||||||
|
buildTreeItem(domainObject) {
|
||||||
|
let navToParent = ROOT_PATH + this.currentNavigatedPath;
|
||||||
|
if(navToParent === ROOT_PATH) {
|
||||||
|
navToParent = navToParent.slice(0, -1);
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
id: this.openmct.objects.makeKeyString(domainObject.identifier),
|
||||||
|
object: domainObject,
|
||||||
|
objectPath: [domainObject].concat(this.currentObjectPath),
|
||||||
|
navigateToParent: navToParent
|
||||||
|
};
|
||||||
|
},
|
||||||
|
addChild(child) {
|
||||||
|
this.allTreeItems.push(this.buildTreeItem(child));
|
||||||
|
},
|
||||||
|
removeChild(identifier) {
|
||||||
|
let removeId = this.openmct.objects.makeKeyString(identifier);
|
||||||
|
this.allChildren = this.children
|
||||||
|
.filter(c => c.id !== removeId);
|
||||||
|
},
|
||||||
|
finishLoading() {
|
||||||
|
this.isLoading = false;
|
||||||
|
if(this.jumpPath) {
|
||||||
|
this.jumpToPath();
|
||||||
|
}
|
||||||
|
this.autoScroll();
|
||||||
|
},
|
||||||
|
async jumpToPath(saveExpandedPath = false) {
|
||||||
|
let nodes = this.jumpPath.split('/'),
|
||||||
|
currentNode,
|
||||||
|
newParent;
|
||||||
|
|
||||||
|
for(let i = 0; i < nodes.length; i++) {
|
||||||
|
currentNode = await this.openmct.objects.get(nodes[i]);
|
||||||
|
newParent = this.buildTreeItem(currentNode);
|
||||||
|
this.ancestors.push(newParent);
|
||||||
|
if(i === nodes.length - 1) {
|
||||||
|
this.jumpPath = '';
|
||||||
|
this.getAllChildren(newParent);
|
||||||
|
if(this.afterJump) {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.afterJump();
|
||||||
|
delete this.afterJump;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if(saveExpandedPath) {
|
||||||
|
this.setCurrentNavigatedPath();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
autoScroll() {
|
||||||
|
if(this.scrollTo) {
|
||||||
|
let indexOfScroll = this.indexOfItemById(this.scrollTo);
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.$refs.scrollable.scrollTop = indexOfScroll * this.itemHeight;
|
||||||
|
});
|
||||||
|
this.scrollTo = undefined;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
indexOfItemById(id) {
|
||||||
|
for(let i = 0; i < this.allTreeItems.length; i++) {
|
||||||
|
if(this.allTreeItems[i].id === id) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getSearchResults() {
|
||||||
this.searchService.query(this.searchValue).then(children => {
|
this.searchService.query(this.searchValue).then(children => {
|
||||||
this.filteredTreeItems = children.hits.map(child => {
|
this.searchResultItems = children.hits.map(child => {
|
||||||
|
|
||||||
let context = child.object.getCapability('context'),
|
let context = child.object.getCapability('context'),
|
||||||
object = child.object.useCapability('adapter'),
|
object = child.object.useCapability('adapter'),
|
||||||
@ -108,9 +401,9 @@ export default {
|
|||||||
objectPath = context.getPath().slice(1)
|
objectPath = context.getPath().slice(1)
|
||||||
.map(oldObject => oldObject.useCapability('adapter'))
|
.map(oldObject => oldObject.useCapability('adapter'))
|
||||||
.reverse();
|
.reverse();
|
||||||
navigateToParent = '/browse/' + objectPath.slice(1)
|
navigateToParent = objectPath.slice(1)
|
||||||
.map((parent) => this.openmct.objects.makeKeyString(parent.identifier))
|
.map((parent) => this.openmct.objects.makeKeyString(parent.identifier));
|
||||||
.join('/');
|
navigateToParent = ROOT_PATH + navigateToParent.reverse().join('/');
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -126,8 +419,88 @@ export default {
|
|||||||
this.searchValue = value;
|
this.searchValue = value;
|
||||||
|
|
||||||
if (this.searchValue !== '') {
|
if (this.searchValue !== '') {
|
||||||
this.getFilteredChildren();
|
this.getSearchResults();
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
searchActivated() {
|
||||||
|
this.activeSearch = true;
|
||||||
|
this.$refs.scrollable.scrollTop = 0;
|
||||||
|
},
|
||||||
|
searchDeactivated() {
|
||||||
|
this.activeSearch = false;
|
||||||
|
this.$refs.scrollable.scrollTop = 0;
|
||||||
|
this.setContainerHeight();
|
||||||
|
this.setChildrenHeight();
|
||||||
|
},
|
||||||
|
handleReset(node) {
|
||||||
|
this.childrenSlideClass = 'slide-right';
|
||||||
|
this.ancestors.splice(this.ancestors.indexOf(node) + 1);
|
||||||
|
this.getAllChildren(node);
|
||||||
|
this.setCurrentNavigatedPath();
|
||||||
|
},
|
||||||
|
handleExpanded(node) {
|
||||||
|
if(!this.activeSearch) {
|
||||||
|
this.childrenSlideClass = 'slide-left';
|
||||||
|
let newParent = this.buildTreeItem(node);
|
||||||
|
this.ancestors.push(newParent);
|
||||||
|
this.getAllChildren(newParent);
|
||||||
|
this.setCurrentNavigatedPath();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getSavedNavigatedPath() {
|
||||||
|
return JSON.parse(localStorage.getItem(LOCAL_STORAGE_KEY__TREE_EXPANDED));
|
||||||
|
},
|
||||||
|
setCurrentNavigatedPath() {
|
||||||
|
if(!this.searchValue) {
|
||||||
|
localStorage.setItem(LOCAL_STORAGE_KEY__TREE_EXPANDED, JSON.stringify(this.currentNavigatedPath));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
currentPathIsActivePath() {
|
||||||
|
return this.getSavedNavigatedPath() === this.currentlyViewedObjectParentPath();
|
||||||
|
},
|
||||||
|
currentlyViewedObjectId() {
|
||||||
|
let currentPath = this.openmct.router.currentLocation.path,
|
||||||
|
id;
|
||||||
|
if(currentPath) {
|
||||||
|
currentPath = currentPath.split(ROOT_PATH)[1];
|
||||||
|
id = currentPath.split('/').pop();
|
||||||
|
}
|
||||||
|
return id;
|
||||||
|
},
|
||||||
|
currentlyViewedObjectParentPath() {
|
||||||
|
let currentPath = this.openmct.router.currentLocation.path,
|
||||||
|
path;
|
||||||
|
if(currentPath) {
|
||||||
|
currentPath = currentPath.split(ROOT_PATH)[1];
|
||||||
|
currentPath = currentPath.split('/');
|
||||||
|
currentPath.pop();
|
||||||
|
path = currentPath.join('/');
|
||||||
|
}
|
||||||
|
return path;
|
||||||
|
},
|
||||||
|
scrollItems(event) {
|
||||||
|
if(!windowResizing) {
|
||||||
|
this.updatevisibleItems();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
scrollableStyles() {
|
||||||
|
return {
|
||||||
|
height: this.availableContainerHeight + 'px',
|
||||||
|
overflow: this.noScroll ? 'hidden' : 'scroll'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
emptyStyles() {
|
||||||
|
let offset = ((this.ancestors.length + 1) * 10) + 20; // extra 20 accounts for up arrow nav space
|
||||||
|
return {
|
||||||
|
paddingLeft: offset + 'px',
|
||||||
|
height: this.itemHeight + 'px'
|
||||||
|
};
|
||||||
|
},
|
||||||
|
childrenIn(el, done) {
|
||||||
|
// more reliable way then nextTick
|
||||||
|
this.setContainerHeight();
|
||||||
|
this.setChildrenHeight();
|
||||||
|
done();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,6 +40,10 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@include desktop() { margin-bottom: $interiorMargin; }
|
@include desktop() { margin-bottom: $interiorMargin; }
|
||||||
|
|
||||||
|
[class*="button"] {
|
||||||
|
color: $colorBtnMajorBg;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&--reacts {
|
&--reacts {
|
||||||
@ -128,12 +132,23 @@
|
|||||||
@include userSelectNone();
|
@include userSelectNone();
|
||||||
color: $splitterBtnLabelColorFg;
|
color: $splitterBtnLabelColorFg;
|
||||||
display: block;
|
display: block;
|
||||||
pointer-events: none;
|
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
transform-origin: top left;
|
|
||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[class*="expand-button"] {
|
||||||
|
display: none; // Hidden by default
|
||||||
|
background: $splitterCollapsedBtnColorBg;
|
||||||
|
color: $splitterCollapsedBtnColorFg;
|
||||||
|
font-size: 0.9em;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: $splitterCollapsedBtnColorBgHov;
|
||||||
|
color: inherit;
|
||||||
|
transition: $transIn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&--resizing {
|
&--resizing {
|
||||||
// User is dragging the handle and resizing a pane
|
// User is dragging the handle and resizing a pane
|
||||||
@include userSelectNone();
|
@include userSelectNone();
|
||||||
@ -160,23 +175,12 @@
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.l-pane__header {
|
[class*="collapse-button"] {
|
||||||
&:hover {
|
display: none;
|
||||||
color: $splitterCollapsedBtnColorFgHov;
|
|
||||||
.l-pane__label {
|
|
||||||
color: inherit;
|
|
||||||
}
|
|
||||||
.l-pane__collapse-button {
|
|
||||||
background: $splitterCollapsedBtnColorBgHov;
|
|
||||||
color: inherit;
|
|
||||||
transition: $transIn;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.l-pane__collapse-button {
|
[class*="expand-button"] {
|
||||||
background: $splitterCollapsedBtnColorBg;
|
display: block;
|
||||||
color: $splitterCollapsedBtnColorFg;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -198,36 +202,26 @@
|
|||||||
|
|
||||||
.l-pane__collapse-button {
|
.l-pane__collapse-button {
|
||||||
&:before {
|
&:before {
|
||||||
content: $glyph-icon-arrow-right-equilateral;
|
content: $glyph-icon-line-horz;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&[class*="--collapsed"] {
|
&[class*="--collapsed"] {
|
||||||
/************************ COLLAPSED HORIZONTAL SPLITTER, EITHER DIRECTION */
|
/************************ COLLAPSED HORIZONTAL SPLITTER, EITHER DIRECTION */
|
||||||
[class*="__header"] {
|
[class*="__header"] {
|
||||||
@include abs();
|
display: none;
|
||||||
margin: 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[class*="label"] {
|
[class*="expand-button"] {
|
||||||
position: absolute;
|
|
||||||
transform: translate($interiorMarginLg + 1, 18px) rotate(90deg);
|
|
||||||
left: 3px;
|
|
||||||
top: 0;
|
|
||||||
z-index: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.l-pane__collapse-button {
|
|
||||||
border-top-left-radius: 0;
|
|
||||||
border-bottom-left-radius: 0; // Only have to do this once, because of scaleX(-1) below.
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0; right: 0; bottom: 0; left: 0;
|
top: 0; right: 0; bottom: 0; left: 0;
|
||||||
height: auto; width: 100%;
|
height: auto; width: 100%;
|
||||||
padding: 0;
|
padding: $interiorMargin 2px;
|
||||||
|
|
||||||
&:before {
|
[class*="label"] {
|
||||||
position: absolute;
|
text-orientation: mixed;
|
||||||
top: 5px;
|
text-transform: uppercase;
|
||||||
|
writing-mode: vertical-lr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -243,10 +237,9 @@
|
|||||||
transform: translateX(floor($splitterHandleD / -2)); // Center over the pane edge
|
transform: translateX(floor($splitterHandleD / -2)); // Center over the pane edge
|
||||||
}
|
}
|
||||||
|
|
||||||
&[class*="--collapsed"] {
|
[class*="expand-button"] {
|
||||||
.l-pane__collapse-button {
|
border-top-left-radius: $controlCr;
|
||||||
transform: scaleX(-1);
|
border-bottom-left-radius: $controlCr;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -261,10 +254,9 @@
|
|||||||
transform: translateX(floor($splitterHandleD / 2));
|
transform: translateX(floor($splitterHandleD / 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
&:not([class*="--collapsed"]) {
|
[class*="expand-button"] {
|
||||||
.l-pane__collapse-button {
|
border-top-right-radius: $controlCr;
|
||||||
transform: scaleX(-1);
|
border-bottom-right-radius: $controlCr;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,12 +20,19 @@
|
|||||||
<span v-if="label"
|
<span v-if="label"
|
||||||
class="l-pane__label"
|
class="l-pane__label"
|
||||||
>{{ label }}</span>
|
>{{ label }}</span>
|
||||||
|
<slot name="controls"></slot>
|
||||||
<button
|
<button
|
||||||
v-if="collapsable"
|
v-if="collapsable"
|
||||||
class="l-pane__collapse-button c-button"
|
class="l-pane__collapse-button c-icon-button"
|
||||||
@click="toggleCollapse"
|
@click="toggleCollapse"
|
||||||
></button>
|
></button>
|
||||||
</div>
|
</div>
|
||||||
|
<button
|
||||||
|
class="l-pane__expand-button"
|
||||||
|
@click="toggleCollapse"
|
||||||
|
>
|
||||||
|
<span class="l-pane__expand-button__label">{{ label }}</span>
|
||||||
|
</button>
|
||||||
<div class="l-pane__contents">
|
<div class="l-pane__contents">
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,38 +1,38 @@
|
|||||||
<template>
|
<template>
|
||||||
<li class="c-tree__item-h">
|
<li
|
||||||
|
:style="{
|
||||||
|
'top': virtualScroll ? itemTop : 'auto',
|
||||||
|
'position': virtualScroll ? 'absolute' : 'relative'
|
||||||
|
}"
|
||||||
|
class="c-tree__item-h"
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
class="c-tree__item"
|
class="c-tree__item"
|
||||||
:class="{ 'is-alias': isAlias, 'is-navigated-object': navigated }"
|
:class="{
|
||||||
|
'is-alias': isAlias,
|
||||||
|
'is-navigated-object': navigated
|
||||||
|
}"
|
||||||
|
:style="{ paddingLeft: leftOffset }"
|
||||||
>
|
>
|
||||||
<view-control
|
<view-control
|
||||||
v-model="expanded"
|
v-model="expanded"
|
||||||
class="c-tree__item__view-control"
|
class="c-tree__item__view-control"
|
||||||
:enabled="hasChildren"
|
:control-class="'c-nav__up'"
|
||||||
|
:enabled="showUp"
|
||||||
|
@input="resetTreeHere"
|
||||||
/>
|
/>
|
||||||
<object-label
|
<object-label
|
||||||
:domain-object="node.object"
|
:domain-object="node.object"
|
||||||
:object-path="node.objectPath"
|
:object-path="node.objectPath"
|
||||||
:navigate-to-path="navigateToPath"
|
:navigate-to-path="navigateToPath"
|
||||||
/>
|
/>
|
||||||
</div>
|
<view-control
|
||||||
<ul
|
v-model="expanded"
|
||||||
v-if="expanded"
|
class="c-tree__item__view-control"
|
||||||
class="c-tree"
|
:control-class="'c-nav__down'"
|
||||||
>
|
:enabled="hasComposition && showDown"
|
||||||
<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>
|
|
||||||
<tree-item
|
|
||||||
v-for="child in children"
|
|
||||||
:key="child.id"
|
|
||||||
:node="child"
|
|
||||||
/>
|
/>
|
||||||
</ul>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -40,8 +40,6 @@
|
|||||||
import viewControl from '../components/viewControl.vue';
|
import viewControl from '../components/viewControl.vue';
|
||||||
import ObjectLabel from '../components/ObjectLabel.vue';
|
import ObjectLabel from '../components/ObjectLabel.vue';
|
||||||
|
|
||||||
const LOCAL_STORAGE_KEY__TREE_EXPANDED = 'mct-tree-expanded';
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'TreeItem',
|
name: 'TreeItem',
|
||||||
inject: ['openmct'],
|
inject: ['openmct'],
|
||||||
@ -53,16 +51,44 @@ export default {
|
|||||||
node: {
|
node: {
|
||||||
type: Object,
|
type: Object,
|
||||||
required: true
|
required: true
|
||||||
|
},
|
||||||
|
leftOffset: {
|
||||||
|
type: String,
|
||||||
|
default: '0px'
|
||||||
|
},
|
||||||
|
showUp: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
showDown: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
itemIndex: {
|
||||||
|
type: Number,
|
||||||
|
required: false,
|
||||||
|
default: undefined
|
||||||
|
},
|
||||||
|
itemOffset: {
|
||||||
|
type: Number,
|
||||||
|
required: false,
|
||||||
|
default: undefined
|
||||||
|
},
|
||||||
|
itemHeight: {
|
||||||
|
type: Number,
|
||||||
|
required: false,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
virtualScroll: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
this.navigateToPath = this.buildPathString(this.node.navigateToParent);
|
this.navigateToPath = this.buildPathString(this.node.navigateToParent);
|
||||||
return {
|
return {
|
||||||
hasChildren: false,
|
hasComposition: false,
|
||||||
isLoading: false,
|
|
||||||
loaded: false,
|
|
||||||
navigated: this.navigateToPath === this.openmct.router.currentLocation.path,
|
navigated: this.navigateToPath === this.openmct.router.currentLocation.path,
|
||||||
children: [],
|
|
||||||
expanded: false
|
expanded: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -74,30 +100,18 @@ export default {
|
|||||||
}
|
}
|
||||||
let parentKeyString = this.openmct.objects.makeKeyString(parent.identifier);
|
let parentKeyString = this.openmct.objects.makeKeyString(parent.identifier);
|
||||||
return parentKeyString !== this.node.object.location;
|
return parentKeyString !== this.node.object.location;
|
||||||
|
},
|
||||||
|
itemTop() {
|
||||||
|
return (this.itemOffset + this.itemIndex) * this.itemHeight + 'px';
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
expanded() {
|
expanded() {
|
||||||
if (!this.hasChildren) {
|
this.$emit('expanded', this.domainObject);
|
||||||
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;
|
|
||||||
}
|
|
||||||
this.setLocalStorageExpanded(this.navigateToPath);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
// TODO: should update on mutation.
|
let objectComposition = this.openmct.composition.get(this.node.object);
|
||||||
// TODO: click navigation should not fubar hash quite so much.
|
|
||||||
// TODO: should highlight if navigated to.
|
|
||||||
// TODO: should have context menu.
|
|
||||||
// TODO: should support drag/drop composition
|
|
||||||
// TODO: set isAlias per tree-item
|
|
||||||
|
|
||||||
this.domainObject = this.node.object;
|
this.domainObject = this.node.object;
|
||||||
let removeListener = this.openmct.objects.observe(this.domainObject, '*', (newObject) => {
|
let removeListener = this.openmct.objects.observe(this.domainObject, '*', (newObject) => {
|
||||||
@ -105,49 +119,17 @@ export default {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.$once('hook:destroyed', removeListener);
|
this.$once('hook:destroyed', removeListener);
|
||||||
if (this.openmct.composition.get(this.node.object)) {
|
if (objectComposition) {
|
||||||
this.hasChildren = true;
|
this.hasComposition = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.openmct.router.on('change:path', this.highlightIfNavigated);
|
this.openmct.router.on('change:path', this.highlightIfNavigated);
|
||||||
|
console.log(this.navigateToPath, this.openmct.router.currentLocation.path);
|
||||||
this.getLocalStorageExpanded();
|
|
||||||
},
|
|
||||||
beforeDestroy() {
|
|
||||||
/****
|
|
||||||
* calling this.setLocalStorageExpanded explicitly here because for whatever reason,
|
|
||||||
* the watcher on this.expanded is not triggering this.setLocalStorageExpanded(),
|
|
||||||
* even though Vue documentation states, "At this stage the instance is still fully functional."
|
|
||||||
*****/
|
|
||||||
this.expanded = false;
|
|
||||||
this.setLocalStorageExpanded();
|
|
||||||
},
|
},
|
||||||
destroyed() {
|
destroyed() {
|
||||||
this.openmct.router.off('change:path', this.highlightIfNavigated);
|
this.openmct.router.off('change:path', this.highlightIfNavigated);
|
||||||
if (this.composition) {
|
|
||||||
this.composition.off('add', this.addChild);
|
|
||||||
this.composition.off('remove', this.removeChild);
|
|
||||||
delete this.composition;
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
methods: {
|
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;
|
|
||||||
},
|
|
||||||
buildPathString(parentPath) {
|
buildPathString(parentPath) {
|
||||||
return [parentPath, this.openmct.objects.makeKeyString(this.node.object.identifier)].join('/');
|
return [parentPath, this.openmct.objects.makeKeyString(this.node.object.identifier)].join('/');
|
||||||
},
|
},
|
||||||
@ -158,35 +140,8 @@ export default {
|
|||||||
this.navigated = false;
|
this.navigated = false;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
getLocalStorageExpanded() {
|
resetTreeHere() {
|
||||||
let expandedPaths = localStorage.getItem(LOCAL_STORAGE_KEY__TREE_EXPANDED);
|
this.$emit('resetTree', this.node);
|
||||||
|
|
||||||
if (expandedPaths) {
|
|
||||||
expandedPaths = JSON.parse(expandedPaths);
|
|
||||||
this.expanded = expandedPaths.includes(this.navigateToPath);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// expanded nodes/paths are stored in local storage as an array
|
|
||||||
setLocalStorageExpanded() {
|
|
||||||
let expandedPaths = localStorage.getItem(LOCAL_STORAGE_KEY__TREE_EXPANDED);
|
|
||||||
expandedPaths = expandedPaths ? JSON.parse(expandedPaths) : [];
|
|
||||||
|
|
||||||
if (this.expanded) {
|
|
||||||
if (!expandedPaths.includes(this.navigateToPath)) {
|
|
||||||
expandedPaths.push(this.navigateToPath);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// remove this node path and all children paths from stored expanded paths
|
|
||||||
expandedPaths = expandedPaths.filter(path => !path.startsWith(this.navigateToPath));
|
|
||||||
}
|
|
||||||
|
|
||||||
localStorage.setItem(LOCAL_STORAGE_KEY__TREE_EXPANDED, JSON.stringify(expandedPaths));
|
|
||||||
},
|
|
||||||
removeLocalStorageExpanded() {
|
|
||||||
let expandedPaths = localStorage.getItem(LOCAL_STORAGE_KEY__TREE_EXPANDED);
|
|
||||||
expandedPaths = expandedPaths ? JSON.parse(expandedPaths) : [];
|
|
||||||
expandedPaths = expandedPaths.filter(path => !path.startsWith(this.navigateToPath));
|
|
||||||
localStorage.setItem(LOCAL_STORAGE_KEY__TREE_EXPANDED, JSON.stringify(expandedPaths));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -70,6 +70,24 @@ function clearBuiltinSpy(funcDefinition) {
|
|||||||
funcDefinition.object[funcDefinition.functionName] = funcDefinition.nativeFunction;
|
funcDefinition.object[funcDefinition.functionName] = funcDefinition.nativeFunction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// for each name in the array passed in a promise and promiseResolve will be created
|
||||||
|
// ex. names = ['test']
|
||||||
|
// return {
|
||||||
|
// testPromise: ...,
|
||||||
|
// testPromiseResolve: ...
|
||||||
|
// }
|
||||||
|
export function generatePromises(names = []) {
|
||||||
|
let promises = {};
|
||||||
|
|
||||||
|
names.forEach((name) => {
|
||||||
|
promises[name + 'Promise'] = new Promise((resolve) => {
|
||||||
|
promises[name + 'PromiseResolve'] = resolve;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return promises;
|
||||||
|
}
|
||||||
|
|
||||||
export function getLatestTelemetry(telemetry = [], opts = {}) {
|
export function getLatestTelemetry(telemetry = [], opts = {}) {
|
||||||
let latest = [],
|
let latest = [],
|
||||||
timeFormat = opts.timeFormat || 'utc';
|
timeFormat = opts.timeFormat || 'utc';
|
||||||
@ -83,22 +101,6 @@ export function getLatestTelemetry(telemetry = [], opts = {}) {
|
|||||||
return latest;
|
return latest;
|
||||||
}
|
}
|
||||||
|
|
||||||
// EXAMPLE:
|
|
||||||
// getMockObjects({
|
|
||||||
// name: 'Jamie Telemetry',
|
|
||||||
// keys: ['test','other','yeah','sup'],
|
|
||||||
// format: 'local',
|
|
||||||
// telemetryConfig: {
|
|
||||||
// hints: {
|
|
||||||
// test: {
|
|
||||||
// domain: 1
|
|
||||||
// },
|
|
||||||
// other: {
|
|
||||||
// range: 2
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// })
|
|
||||||
export function getMockObjects(opts = {}) {
|
export function getMockObjects(opts = {}) {
|
||||||
opts.type = opts.type || 'default';
|
opts.type = opts.type || 'default';
|
||||||
if(opts.objectKeyStrings && !Array.isArray(opts.objectKeyStrings)) {
|
if(opts.objectKeyStrings && !Array.isArray(opts.objectKeyStrings)) {
|
||||||
@ -227,6 +229,12 @@ function copyObj(obj) {
|
|||||||
function setMockObjects() {
|
function setMockObjects() {
|
||||||
return {
|
return {
|
||||||
default: {
|
default: {
|
||||||
|
root: {
|
||||||
|
identifier: { key: "ROOT", namespace: "" },
|
||||||
|
name: "The root object",
|
||||||
|
type: "root",
|
||||||
|
composition: [{ namespace: "", key: "mine"}]
|
||||||
|
},
|
||||||
ladTable: {
|
ladTable: {
|
||||||
identifier: { namespace: "", key: "lad-object"},
|
identifier: { namespace: "", key: "lad-object"},
|
||||||
type: 'LadTable',
|
type: 'LadTable',
|
||||||
|
Reference in New Issue
Block a user