Skip to content

Commit be54fed

Browse files
charlesh88akhenry
andauthored
Store and retrieve the view type, per object type (#8068)
* Allow user to set machine-based preferences for main object views. - WIP - BrowseBar.vue now stores view selection when viewSwitcher component is invoked as localstorage object 'openmct-stored-view-prefs'. - Browse.js in `#viewObject` looks for an existing value in 'openmct-stored-view-prefs' and uses it. - TODO: stored pref currently overrides `view` querystring parameters, but shouldn't. * Allow user to set machine-based preferences for main object views. - Browse.js now sets currentViewKey in the right spot. - Changes in #viewObject reset. * Allow user to set machine-based preferences for main object views. - Style tweaks to `c-list-view` when used in object-type folder. - Added missing copyright header to list-view.scss. * Fixed linting errors * Add test for Folder 'List View' persistence - Closes #1395. - Update .gitignore to not check in Webstorm test config file. --------- Co-authored-by: Andrew Henry <[email protected]>
1 parent 569c7ff commit be54fed

File tree

9 files changed

+147
-9
lines changed

9 files changed

+147
-9
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,4 @@ codecov
5050

5151
# Don't commit MacOS screenshots
5252
*-darwin.png
53+
/.run/All Tests.run.xml
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*****************************************************************************
2+
* Open MCT, Copyright (c) 2014-2024, United States Government
3+
* as represented by the Administrator of the National Aeronautics and Space
4+
* Administration. All rights reserved.
5+
*
6+
* Open MCT is licensed under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
* http://www.apache.org/licenses/LICENSE-2.0.
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14+
* License for the specific language governing permissions and limitations
15+
* under the License.
16+
*
17+
* Open MCT includes source code licensed under additional open source
18+
* licenses. See the Open Source Licenses file (LICENSES.md) included with
19+
* this source code distribution or the Licensing information page available
20+
* at runtime from the About dialog for additional information.
21+
*****************************************************************************/
22+
23+
import { createDomainObjectWithDefaults } from '../../../../appActions.js';
24+
import { expect, test } from '../../../../pluginFixtures.js';
25+
26+
test.describe('Folder View Persistence', () => {
27+
let folder;
28+
let sineWaveGenerator;
29+
30+
test.beforeEach(async ({ page }) => {
31+
await page.goto('./', { waitUntil: 'domcontentloaded' });
32+
33+
// Create a folder
34+
folder = await createDomainObjectWithDefaults(page, {
35+
type: 'Folder'
36+
});
37+
38+
// Create a sine wave generator inside the folder
39+
sineWaveGenerator = await createDomainObjectWithDefaults(page, {
40+
type: 'Sine Wave Generator',
41+
parent: folder.uuid
42+
});
43+
44+
// Navigate to the folder
45+
await page.goto(folder.url);
46+
});
47+
48+
test('Folder view persists when navigating away and back', async ({ page }) => {
49+
// Click the view switcher button to open the menu
50+
await page.getByLabel('Open the View Switcher Menu').click();
51+
52+
// Click the List View option from the dropdown menu
53+
await page.getByRole('menuitem', { name: /List View/ }).click();
54+
55+
// Verify that we're now in List view by checking for the c-list-view class
56+
await expect(page.locator('.c-list-view')).toBeVisible();
57+
58+
// Navigate to the sine wave generator
59+
await page.goto(sineWaveGenerator.url);
60+
61+
// Verify we're on the sine wave generator page by checking for the object view container
62+
await expect(page.locator('.c-object-view.is-object-type-generator')).toBeVisible();
63+
64+
// Navigate back to the folder
65+
await page.goto(folder.url);
66+
67+
// Verify that the folder is still in List view
68+
await expect(page.locator('.c-list-view')).toBeVisible();
69+
});
70+
});

src/styles/_constants-darkmatter.scss

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -453,8 +453,10 @@ $colorThumbsBubbleFg: pullForward($colorBodyFg, 10%);
453453
$colorThumbsBubbleBg: pullForward($colorBodyBg, 10%);
454454

455455
// Items
456+
$colorSelectableItemBg: transparent;
457+
$colorSelectableItemBgHov: rgba(#fff, 0.1);
456458
$colorItemBg: buttonBg($colorBtnBg);
457-
$colorItemBgHov: buttonBg(pullForward($colorBtnBg, 5%));
459+
$colorItemBgHov: $colorSelectableItemBgHov;
458460
$colorListItemBg: transparent;
459461
$colorListItemBgHov: rgba($colorKey, 0.1);
460462
$colorItemFg: $colorBtnFg;
@@ -527,7 +529,7 @@ $eventLineW: 1px;
527529

528530
// Tree
529531
$colorTreeBg: transparent;
530-
$colorItemTreeHoverBg: rgba(#fff, 0.1);
532+
$colorItemTreeHoverBg: $colorSelectableItemBgHov;
531533
$colorItemTreeHoverFg: #fff;
532534
$colorItemTreeIcon: $colorKey;
533535
$colorItemTreeIconHover: $colorItemTreeIcon;

src/styles/_constants-espresso.scss

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -419,10 +419,12 @@ $colorThumbsBubbleFg: pullForward($colorBodyFg, 10%);
419419
$colorThumbsBubbleBg: pullForward($colorBodyBg, 10%);
420420

421421
// Items
422+
$colorSelectableItemBg: transparent;
423+
$colorSelectableItemBgHov: rgba(#fff, 0.1);
422424
$colorItemBg: buttonBg($colorBtnBg);
423425
$colorItemBgHov: buttonBg(pullForward($colorBtnBg, 5%));
424426
$colorListItemBg: transparent;
425-
$colorListItemBgHov: rgba($colorKey, 0.1);
427+
$colorListItemBgHov: $colorSelectableItemBgHov; //$colorItemTreeHoverBg;
426428
$colorItemFg: $colorBtnFg;
427429
$colorItemFgDetails: $colorBodyFgSubtle;
428430
$shdwItemText: none;
@@ -492,7 +494,7 @@ $opacitySubtle: 0.4;
492494

493495
// Tree
494496
$colorTreeBg: transparent;
495-
$colorItemTreeHoverBg: rgba(#fff, 0.1);
497+
$colorItemTreeHoverBg: $colorSelectableItemBgHov;
496498
$colorItemTreeHoverFg: #fff;
497499
$colorItemTreeIcon: $colorKey;
498500
$colorItemTreeIconHover: $colorItemTreeIcon;

src/styles/_constants-maelstrom.scss

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -438,10 +438,12 @@ $colorThumbsBubbleFg: pullForward($colorBodyFg, 10%);
438438
$colorThumbsBubbleBg: pullForward($colorBodyBg, 10%);
439439

440440
// Items
441+
$colorSelectableItemBg: transparent;
442+
$colorSelectableItemBgHov: rgba(#fff, 0.1);
441443
$colorItemBg: buttonBg($colorBtnBg);
442444
$colorItemBgHov: buttonBg(pullForward($colorBtnBg, 5%));
443445
$colorListItemBg: transparent;
444-
$colorListItemBgHov: rgba($colorKey, 0.1);
446+
$colorListItemBgHov: $colorSelectableItemBgHov;
445447
$colorItemFg: $colorBtnFg;
446448
$colorItemFgDetails: pushBack($colorItemFg, 20%);
447449
$shdwItemText: none;
@@ -511,7 +513,7 @@ $eventLineW: 1px;
511513

512514
// Tree
513515
$colorTreeBg: transparent;
514-
$colorItemTreeHoverBg: rgba(#fff, 0.03);
516+
$colorItemTreeHoverBg: $colorSelectableItemBgHov;
515517
$colorItemTreeHoverFg: #fff;
516518
$colorItemTreeIcon: $colorKey;
517519
$colorItemTreeIconHover: $colorItemTreeIcon;

src/styles/_constants-snow.scss

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -421,10 +421,12 @@ $colorThumbsBubbleFg: pullForward($colorBodyFg, 10%);
421421
$colorThumbsBubbleBg: pullForward($colorBodyBg, 10%);
422422

423423
// Items
424+
$colorSelectableItemBg: transparent;
425+
$colorSelectableItemBgHov: rgba(#000, 0.07);
424426
$colorItemBg: pushBack($colorBtnBg, 20%);
425427
$colorItemBgHov: pushBack($colorItemBg, 5%);
426428
$colorListItemBg: transparent;
427-
$colorListItemBgHov: rgba($colorKey, 0.1);
429+
$colorListItemBgHov: $colorSelectableItemBgHov;
428430
$colorItemFg: $colorBodyFg;
429431
$colorItemFgDetails: pushBack($colorItemFg, 15%);
430432
$shdwItemText: none;
@@ -494,7 +496,7 @@ $eventLineW: 1px;
494496

495497
// Tree
496498
$colorTreeBg: transparent;
497-
$colorItemTreeHoverBg: rgba(black, 0.07);
499+
$colorItemTreeHoverBg: $colorSelectableItemBgHov;
498500
$colorItemTreeHoverFg: pullForward($colorBodyFg, 10%);
499501
$colorItemTreeIcon: $colorKey;
500502
$colorItemTreeIconHover: $colorItemTreeIcon;

src/ui/components/List/list-view.scss

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,32 @@
1+
/*****************************************************************************
2+
* Open MCT, Copyright (c) 2014-2025, United States Government
3+
* as represented by the Administrator of the National Aeronautics and Space
4+
* Administration. All rights reserved.
5+
*
6+
* Open MCT is licensed under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
* http://www.apache.org/licenses/LICENSE-2.0.
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14+
* License for the specific language governing permissions and limitations
15+
* under the License.
16+
*
17+
* Open MCT includes source code licensed under additional open source
18+
* licenses. See the Open Source Licenses file (LICENSES.md) included with
19+
* this source code distribution or the Licensing information page available
20+
* at runtime from the About dialog for additional information.
21+
*****************************************************************************/
122
/******************************* LIST VIEW */
223
.c-list-view {
324
tbody tr {
425
background: $colorListItemBg;
526
}
627

728
td {
8-
$p: floor($interiorMargin * 1.5);
29+
$p: $interiorMargin;
930
@include ellipsize();
1031
line-height: 120%; // Needed for icon alignment
1132
max-width: 0;
@@ -34,4 +55,8 @@
3455
z-index: 2;
3556
}
3657
}
58+
59+
.is-object-type-folder & {
60+
tbody { font-size: 1.1em; }
61+
}
3762
}

src/ui/layout/BrowseBar.vue

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,8 @@ import tooltipHelpers from '../../api/tooltips/tooltipMixins.js';
159159
import { SupportedViewTypes } from '../../utils/constants.js';
160160
import ViewSwitcher from './ViewSwitcher.vue';
161161
162+
const LOCALSTORAGE_VIEW_PREFS = 'openmct-stored-view-prefs';
163+
162164
export default {
163165
components: {
164166
IndependentTimeConductor,
@@ -253,6 +255,18 @@ export default {
253255
254256
return objectType?.definition?.cssClass ?? '';
255257
},
258+
objectTypeKey() {
259+
if (!this.domainObject) {
260+
return '';
261+
}
262+
263+
const objectType = this.openmct.types.get(this.domainObject.type);
264+
if (!objectType) {
265+
return '';
266+
}
267+
268+
return objectType.definition?.key ?? '';
269+
},
256270
isPersistable() {
257271
const persistable =
258272
this.domainObject?.identifier &&
@@ -355,10 +369,19 @@ export default {
355369
},
356370
setView(view) {
357371
this.viewKey = view.key;
372+
this.storeViewPrefs(view.key);
358373
this.openmct.router.updateParams({
359374
view: this.viewKey
360375
});
361376
},
377+
retrieveViewPrefs() {
378+
return JSON.parse(window.localStorage.getItem(LOCALSTORAGE_VIEW_PREFS)) || {};
379+
},
380+
storeViewPrefs(view) {
381+
let storedViews = this.retrieveViewPrefs();
382+
storedViews[this.domainObject.type] = view;
383+
window.localStorage.setItem(LOCALSTORAGE_VIEW_PREFS, JSON.stringify(storedViews));
384+
},
362385
edit() {
363386
this.openmct.editor.edit();
364387
},

src/ui/router/Browse.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,11 @@ class Browse {
121121
'*',
122122
this.#handleBrowseObjectUpdate.bind(this)
123123
);
124+
125+
if (!currentViewKey) {
126+
currentViewKey = this.#getPreferredViewForObjectType(this.#browseObject);
127+
}
128+
124129
const currentProvider = this.#openmct.objectViews.getByProviderKey(currentViewKey);
125130
if (currentProvider && currentProvider.canView(this.#browseObject, this.#openmct.router.path)) {
126131
this.#viewObject(this.#browseObject, currentProvider);
@@ -148,6 +153,12 @@ class Browse {
148153
);
149154
}
150155

156+
#getPreferredViewForObjectType(obj) {
157+
const storedViewPrefs =
158+
JSON.parse(window.localStorage.getItem('openmct-stored-view-prefs')) || {};
159+
return storedViewPrefs[obj.type] ? storedViewPrefs[obj.type] : undefined;
160+
}
161+
151162
async #navigateToFirstChildOfRoot() {
152163
try {
153164
const rootObject = await this.#openmct.objects.get('ROOT');

0 commit comments

Comments
 (0)