Skip to content

Commit

Permalink
New default display and related functionality (#478)
Browse files Browse the repository at this point in the history
* adding functionality for initial load example display layout

* readding mistakenly removed line

* New example default display and supporting components.

* New example default display and supporting components.

* Finalized new example default display and supporting components.
- New main flex layout exercises conditionals and most available object views.
- Modded index.js to look for new main layout name.

* Updated README.md to include workaround for issue as noted in #427.

* Enhancements to example Health display.

* fix: add retry / polling limits so browser doesn't hang

* chore: lint:fix

* test: add smoke test for default display

---------

Co-authored-by: Jamie V <[email protected]>
Co-authored-by: Mazzella, Jesse D. (ARC-TI)[KBR Wyle Services, LLC] <[email protected]>
  • Loading branch information
3 people authored Nov 1, 2024
1 parent 1cffd82 commit 433e720
Show file tree
Hide file tree
Showing 4 changed files with 133 additions and 1 deletion.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ npm start
This should build the example, and launch a web browser with Open MCT connected to a locally running YAMCS server. By
default it is configured to connect to the "myproject" instance provided in the [YAMCS QuickStart](https://github.com/yamcs/quickstart) server.

> #### IMPORTANT NOTE
> If Open MCT version issues are encountered with `npm run build:example`, try using `npm run build:example:master` to force usage of the latest version of Open MCT.
### Testing

This project is using the openmct-e2e-as-a-dependency model. For getting started with our tests, please see [our README](./tests/README.md)
Expand Down
1 change: 1 addition & 0 deletions example/example-display.json

Large diffs are not rendered by default.

112 changes: 112 additions & 0 deletions example/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ const STATUS_STYLES = {
const openmct = window.openmct;

(() => {
const POLL_INTERVAL = 100; // ms
const MAX_POLL_TIME = 10000; // 10 seconds
const COMPOSITION_RETRY_DELAY = 250; // ms
const MAX_COMPOSITION_RETRIES = 20; // 5 seconds total with 250ms intervals
const ONE_SECOND = 1000;
const ONE_MINUTE = ONE_SECOND * 60;
const THIRTY_MINUTES = ONE_MINUTE * 30;
Expand Down Expand Up @@ -111,5 +115,113 @@ const openmct = window.openmct;

openmct.install(openmct.plugins.FaultManagement());
openmct.install(openmct.plugins.BarChart());

// setup example display layout
openmct.on('start', async () => {
if (localStorage.getItem('exampleLayout') !== null) {
return;
}

// try to import the example display layout, fail gracefully
try {
// Function to fetch JSON content as text
async function fetchJsonText(url) {
const response = await fetch(url);
const text = await response.text();

return text;
}

async function getExampleLayoutPath() {
const objects = Object.values(JSON.parse(localStorage.getItem('mct')));
const exampleLayout = objects.find(object => object.name === 'Example Flexible Layout');
let path = await openmct.objects.getOriginalPath(exampleLayout.identifier);

path.pop();
path = path.reverse();
path = path.reduce((prev, curr) => {
return prev + '/' + openmct.objects.makeKeyString(curr.identifier);
}, '#/browse');

return path;
}

// poll for the localStorage item
function mctItemExists() {
return new Promise((resolve, reject) => {
const startTime = Date.now();

function checkItem() {
if (localStorage.getItem('mct') !== null) {
resolve(true);

return;
}

if (Date.now() - startTime > MAX_POLL_TIME) {
reject(new Error('Timeout waiting for mct localStorage item'));

return;
}

setTimeout(checkItem, POLL_INTERVAL);
}

checkItem();
});
}

// wait for the 'mct' item to exist
await mctItemExists();

// setup to use import as JSON action
const importAction = openmct.actions.getAction('import.JSON');
const myItems = await openmct.objects.get('mine');
const exampleDisplayText = await fetchJsonText('./example-display.json');
const selectFile = {
body: exampleDisplayText
};

// import the example display layout
importAction.onSave(myItems, { selectFile });

// the importAction has asynchronous code, so we will need to check
// the composition of My Items to confirm the import was successful
const compositionCollection = openmct.composition.get(myItems);
let compositionLength = 0;
let composition;

let retryCount = 0;
while (compositionLength === 0 && retryCount < MAX_COMPOSITION_RETRIES) {
composition = await compositionCollection.load();
compositionLength = composition.length;

if (compositionLength === 0) {
retryCount++;
await new Promise(resolve => setTimeout(resolve, COMPOSITION_RETRY_DELAY));
}
}

if (compositionLength === 0) {
throw new Error('Failed to load composition after maximum retries');
}

const exampleLayoutPath = await getExampleLayoutPath();

// give everything time to initialize
await new Promise(resolve => setTimeout(resolve, 250));

openmct.notifications.info('Navigated to Example Display Layout');

// navigate to the "Example Display Layout"
openmct.router.navigate(exampleLayoutPath);

// set the localStorage item to prevent this from running again
localStorage.setItem('exampleLayout', 'true');
} catch (error) {
console.error('Failed to set up example display layout:', error);
openmct.notifications.error('Failed to load example display layout: ' + error.message);
}
});
}
})();
18 changes: 17 additions & 1 deletion tests/e2e/yamcs/quickstartSmoke.e2e.spec.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,12 @@ import { baseFixtures } from 'openmct-e2e';
const { test, expect } = baseFixtures;

test.describe("Quickstart smoke tests @yamcs", () => {
test('Verify that the create button appears and that the Folder Domain Object is available for selection', async ({ page }) => {
test.beforeEach(async ({ page }) => {
//Go to baseURL
await page.goto('./', { waitUntil: 'networkidle' });
});

test('Verify that the create button appears and that the Folder Domain Object is available for selection', async ({ page }) => {
//Click the Create button
await page.getByRole('button', { name: 'Create' }).click();

Expand All @@ -57,4 +59,18 @@ test.describe("Quickstart smoke tests @yamcs", () => {
await expect(page.locator('.c-tree__item :text-is("myproject")')).toBeEnabled();
await expect(page.locator('.c-tree__item :text-is("My Items")')).toBeEnabled();
});

test('Verify that the default display is generated and navigated to without error', async ({ page }) => {
await expect(page.getByRole('main').getByText('Example Flexible Layout')).toBeVisible();
await expect(page.getByLabel('Health tab')).toBeVisible();
await expect(page.getByLabel('Position tab')).toBeVisible();
await expect(page.getByLabel('Velocity tab')).toBeVisible();
await expect(page.getByLabel('All Current Values tab')).toBeVisible();
await expect(page.getByText('SUBSYS')).toBeVisible();
await expect(page.getByText('ADCS', { exact: true })).toBeVisible();
await expect(page.getByText('CDHS', { exact: true })).toBeVisible();
await expect(page.getByText('COMMS', { exact: true })).toBeVisible();
await expect(page.getByText('EPS', { exact: true })).toBeVisible();
await expect(page.getByLabel('CW PYLD Status Object View').getByText('PAYLOAD')).toBeVisible();
});
});

0 comments on commit 433e720

Please sign in to comment.