mirror of
https://github.com/nasa/openmct.git
synced 2024-12-19 21:27:52 +00:00
[Mobile] Make Time Conductor Usable Again (#7515)
* Initial changes to refactor Time Conductor * Finish refactor using grid-template * Finish total refactor of Time Conductor * Initial mobile changes * Fix TC on mobile by changing grid template * Fix more mobile stuff * Add ellipsize to TC popup options and rearrange popup inputs and labels * Small final changes so TC is adaptive to extreme cases * Add e2e mobile test --------- Co-authored-by: John Hill <john.c.hill@nasa.gov>
This commit is contained in:
parent
ab49f3f3a1
commit
87ba9fcbc0
@ -34,42 +34,62 @@ Make no assumptions about the order that elements appear in the DOM.
|
||||
*/
|
||||
|
||||
import { expect, test } from '../../pluginFixtures.js';
|
||||
test('Verify that My Items Tree appears @mobile', async ({ page, openmctConfig }) => {
|
||||
const { myItemsFolderName } = openmctConfig;
|
||||
//Go to baseURL
|
||||
await page.goto('./');
|
||||
//My Items to be visible
|
||||
await expect(page.getByRole('treeitem', { name: `${myItemsFolderName}` })).toBeVisible();
|
||||
});
|
||||
test('Verify that user can search @mobile', async ({ page }) => {
|
||||
//For now, this test is going to be hardcoded against './test-data/display_layout_with_child_layouts.json'
|
||||
await page.goto('./');
|
||||
await page.getByRole('searchbox', { name: 'Search Input' }).click();
|
||||
await page.getByRole('searchbox', { name: 'Search Input' }).fill('Parent Display Layout');
|
||||
//Search Results appear in search modal
|
||||
await expect(page.getByLabel('Object Results').getByText('Parent Display Layout')).toBeVisible();
|
||||
//Clicking on the search result takes you to the object
|
||||
await page.getByLabel('Object Results').getByText('Parent Display Layout').click();
|
||||
await page.getByTitle('Collapse Browse Pane').click();
|
||||
await expect(page.getByRole('main').getByText('Parent Display Layout')).toBeVisible();
|
||||
});
|
||||
test('Remove Object and confirmation dialog @mobile', async ({ page }) => {
|
||||
await page.goto('./');
|
||||
await page.getByRole('searchbox', { name: 'Search Input' }).click();
|
||||
await page.getByRole('searchbox', { name: 'Search Input' }).fill('Parent Display Layout');
|
||||
//Search Results appear in search modal
|
||||
//Clicking on the search result takes you to the object
|
||||
await page.getByLabel('Object Results').getByText('Parent Display Layout').click();
|
||||
await page.getByTitle('Collapse Browse Pane').click();
|
||||
await expect(page.getByRole('main').getByText('Parent Display Layout')).toBeVisible();
|
||||
//Verify both objects are in view
|
||||
await expect(await page.getByLabel('Child Layout 1 Layout')).toBeVisible();
|
||||
await expect(await page.getByLabel('Child Layout 2 Layout')).toBeVisible();
|
||||
//Remove First Object to bring up confirmation dialog
|
||||
await page.getByLabel('View menu items').nth(1).click();
|
||||
await page.getByLabel('Remove').click();
|
||||
await page.getByRole('button', { name: 'OK' }).click();
|
||||
//Verify that the object is removed
|
||||
await expect(await page.getByLabel('Child Layout 1 Layout')).toBeVisible();
|
||||
expect(await page.getByLabel('Child Layout 2 Layout').count()).toBe(0);
|
||||
|
||||
test.describe('Smoke tests for @mobile', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
//For now, this test is going to be hardcoded against './test-data/display_layout_with_child_layouts.json'
|
||||
await page.goto('./');
|
||||
});
|
||||
|
||||
test('Verify that My Items Tree appears @mobile', async ({ page }) => {
|
||||
//My Items to be visible
|
||||
await expect(page.getByRole('treeitem', { name: 'My Items' })).toBeVisible();
|
||||
});
|
||||
|
||||
test('Verify that user can search @mobile', async ({ page }) => {
|
||||
await page.getByRole('searchbox', { name: 'Search Input' }).click();
|
||||
await page.getByRole('searchbox', { name: 'Search Input' }).fill('Parent Display Layout');
|
||||
//Search Results appear in search modal
|
||||
await expect(
|
||||
page.getByLabel('Object Results').getByText('Parent Display Layout')
|
||||
).toBeVisible();
|
||||
//Clicking on the search result takes you to the object
|
||||
await page.getByLabel('Object Results').getByText('Parent Display Layout').click();
|
||||
await page.getByTitle('Collapse Browse Pane').click();
|
||||
await expect(page.getByRole('main').getByText('Parent Display Layout')).toBeVisible();
|
||||
});
|
||||
|
||||
test('Verify that user can change time conductor @mobile', async ({ page }) => {
|
||||
//Collapse Browse Pane to get more Time Conductor space
|
||||
await page.getByLabel('Collapse Browse Pane').click();
|
||||
//Open Time Conductor and change to Real Time Mode and set offset hour by 1 hour
|
||||
// Disabling line because we're intentionally obscuring the text
|
||||
// eslint-disable-next-line playwright/no-force-option
|
||||
await page.getByLabel('Time Conductor Mode').click({ force: true });
|
||||
await page.getByLabel('Time Conductor Mode Menu').click();
|
||||
await page.getByLabel('Real-Time').click();
|
||||
await page.getByLabel('Start offset hours').fill('01');
|
||||
await page.getByLabel('Submit time offsets').click();
|
||||
await expect(page.getByLabel('Start offset: 01:30:00')).toBeVisible();
|
||||
});
|
||||
|
||||
test('Remove Object and confirmation dialog @mobile', async ({ page }) => {
|
||||
await page.getByRole('searchbox', { name: 'Search Input' }).click();
|
||||
await page.getByRole('searchbox', { name: 'Search Input' }).fill('Parent Display Layout');
|
||||
//Search Results appear in search modal
|
||||
//Clicking on the search result takes you to the object
|
||||
await page.getByLabel('Object Results').getByText('Parent Display Layout').click();
|
||||
await page.getByTitle('Collapse Browse Pane').click();
|
||||
await expect(page.getByRole('main').getByText('Parent Display Layout')).toBeVisible();
|
||||
//Verify both objects are in view
|
||||
await expect(await page.getByLabel('Child Layout 1 Layout')).toBeVisible();
|
||||
await expect(await page.getByLabel('Child Layout 2 Layout')).toBeVisible();
|
||||
//Remove First Object to bring up confirmation dialog
|
||||
await page.getByLabel('View menu items').nth(1).click();
|
||||
await page.getByLabel('Remove').click();
|
||||
await page.getByRole('button', { name: 'OK' }).click();
|
||||
//Verify that the object is removed
|
||||
await expect(await page.getByLabel('Child Layout 1 Layout')).toBeVisible();
|
||||
expect(await page.getByLabel('Child Layout 2 Layout').count()).toBe(0);
|
||||
});
|
||||
});
|
||||
|
@ -1,14 +1,14 @@
|
||||
<template>
|
||||
<form ref="fixedDeltaInput">
|
||||
<div class="c-tc-input-popup__input-grid">
|
||||
<div class="pr-time-label"><em>Start</em> Date</div>
|
||||
<div class="pr-time-label">Time</div>
|
||||
<div class="pr-time-label"></div>
|
||||
<div class="pr-time-label"><em>End</em> Date</div>
|
||||
<div class="pr-time-label">Time</div>
|
||||
<div class="pr-time-label"></div>
|
||||
<div class="pr-time-label pr-time-label-start-date"><em>Start</em> Date</div>
|
||||
<div class="pr-time-label pr-time-label-start-time">Time</div>
|
||||
<div class="pr-time-label pr-time-label-end-date"><em>End</em> Date</div>
|
||||
<div class="pr-time-label pr-time-label-end-time">Time</div>
|
||||
|
||||
<div class="pr-time-input pr-time-input--date pr-time-input--input-and-button">
|
||||
<div
|
||||
class="pr-time-input pr-time-input--date pr-time-input--input-and-button pr-time-input-start-date"
|
||||
>
|
||||
<input
|
||||
ref="startDate"
|
||||
v-model="formattedBounds.start"
|
||||
@ -28,7 +28,7 @@
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="pr-time-input pr-time-input--time">
|
||||
<div class="pr-time-input pr-time-input--time pr-time-input-start-time">
|
||||
<input
|
||||
ref="startTime"
|
||||
v-model="formattedBounds.startTime"
|
||||
@ -43,7 +43,9 @@
|
||||
|
||||
<div class="pr-time-input pr-time-input__start-end-sep icon-arrows-right-left"></div>
|
||||
|
||||
<div class="pr-time-input pr-time-input--date pr-time-input--input-and-button">
|
||||
<div
|
||||
class="pr-time-input pr-time-input--date pr-time-input--input-and-button pr-time-input-end-date"
|
||||
>
|
||||
<input
|
||||
ref="endDate"
|
||||
v-model="formattedBounds.end"
|
||||
@ -63,7 +65,7 @@
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="pr-time-input pr-time-input--time">
|
||||
<div class="pr-time-input pr-time-input--time pr-time-input-end-time">
|
||||
<input
|
||||
ref="endTime"
|
||||
v-model="formattedBounds.endTime"
|
||||
|
@ -1,16 +1,14 @@
|
||||
<template>
|
||||
<form ref="deltaInput">
|
||||
<div class="c-tc-input-popup__input-grid">
|
||||
<div class="pr-time-label icon-minus">Hrs</div>
|
||||
<div class="pr-time-label">Mins</div>
|
||||
<div class="pr-time-label">Secs</div>
|
||||
<div class="pr-time-label"></div>
|
||||
<div class="pr-time-label icon-plus">Hrs</div>
|
||||
<div class="pr-time-label">Mins</div>
|
||||
<div class="pr-time-label">Secs</div>
|
||||
<div class="pr-time-label"></div>
|
||||
<div class="pr-time-label icon-minus pr-time-label-minus-hrs">Hrs</div>
|
||||
<div class="pr-time-label pr-time-label-minus-mins">Mins</div>
|
||||
<div class="pr-time-label pr-time-label-minus-secs">Secs</div>
|
||||
<div class="pr-time-label icon-plus pr-time-label-plus-hrs">Hrs</div>
|
||||
<div class="pr-time-label pr-time-label-plus-mins">Mins</div>
|
||||
<div class="pr-time-label pr-time-label-plus-secs">Secs</div>
|
||||
|
||||
<div class="pr-time-input">
|
||||
<div class="pr-time-input pr-time-input-minus-hrs">
|
||||
<input
|
||||
ref="startInputHrs"
|
||||
v-model="startInputHrs"
|
||||
@ -29,7 +27,7 @@
|
||||
/>
|
||||
<b>:</b>
|
||||
</div>
|
||||
<div class="pr-time-input">
|
||||
<div class="pr-time-input pr-time-input-minus-mins">
|
||||
<input
|
||||
ref="startInputMins"
|
||||
v-model="startInputMins"
|
||||
@ -48,7 +46,7 @@
|
||||
/>
|
||||
<b>:</b>
|
||||
</div>
|
||||
<div class="pr-time-input">
|
||||
<div class="pr-time-input pr-time-input-minus-secs">
|
||||
<input
|
||||
ref="startInputSecs"
|
||||
v-model="startInputSecs"
|
||||
@ -69,7 +67,7 @@
|
||||
|
||||
<div class="pr-time-input pr-time-input__start-end-sep icon-arrows-right-left"></div>
|
||||
|
||||
<div class="pr-time-input">
|
||||
<div class="pr-time-input pr-time-input-plus-hrs">
|
||||
<input
|
||||
ref="endInputHrs"
|
||||
v-model="endInputHrs"
|
||||
@ -88,7 +86,7 @@
|
||||
/>
|
||||
<b>:</b>
|
||||
</div>
|
||||
<div class="pr-time-input">
|
||||
<div class="pr-time-input pr-time-input-plus-mins">
|
||||
<input
|
||||
ref="endInputMins"
|
||||
v-model="endInputMins"
|
||||
@ -106,7 +104,7 @@
|
||||
/>
|
||||
<b>:</b>
|
||||
</div>
|
||||
<div class="pr-time-input">
|
||||
<div class="pr-time-input pr-time-input-plus-secs">
|
||||
<input
|
||||
ref="endInputSecs"
|
||||
v-model="endInputSecs"
|
||||
|
@ -604,23 +604,170 @@
|
||||
padding: cButtonPadding($compact: true);
|
||||
}
|
||||
}
|
||||
.pr-time{
|
||||
// FIXED TIME MODE
|
||||
&-label-start-date{
|
||||
grid-area: sDate;
|
||||
}
|
||||
&-label-start-time{
|
||||
grid-area: sTime;
|
||||
}
|
||||
&-input-start-date{
|
||||
grid-area: sDateInput;
|
||||
}
|
||||
&-input-start-time{
|
||||
grid-area: sTimeInput;
|
||||
}
|
||||
&-label-end-date{
|
||||
grid-area: eDate;
|
||||
}
|
||||
&-label-end-time{
|
||||
grid-area: eTime;
|
||||
|
||||
}
|
||||
&-input-end-date{
|
||||
grid-area: eDateInput;
|
||||
}
|
||||
&-input-end-time{
|
||||
grid-area: eTimeInput;
|
||||
}
|
||||
&-label-blank-grid{
|
||||
grid-area: blank;
|
||||
}
|
||||
|
||||
//REAL TIME MODE
|
||||
&-label-minus-hrs{
|
||||
grid-area: labelMinusHrs;
|
||||
}
|
||||
&-label-minus-mins{
|
||||
grid-area: labelMinusMins;
|
||||
}
|
||||
&-label-minus-secs{
|
||||
grid-area: labelMinusSecs;
|
||||
}
|
||||
&-label-plus-hrs{
|
||||
grid-area: labelPlusHrs;
|
||||
}
|
||||
&-label-plus-mins{
|
||||
grid-area: labelPlusMins;
|
||||
}
|
||||
&-label-plus-secs{
|
||||
grid-area: labelPlusSecs;
|
||||
}
|
||||
&-input-minus-hrs{
|
||||
grid-area: inputMinusHrs;
|
||||
}
|
||||
&-input-minus-mins{
|
||||
grid-area: inputMinusMins;
|
||||
}
|
||||
&-input-minus-secs{
|
||||
grid-area: inputMinusSecs;
|
||||
}
|
||||
&-input-plus-hrs{
|
||||
grid-area: inputPlusHrs;
|
||||
}
|
||||
&-input-plus-mins{
|
||||
grid-area: inputPlusMins;
|
||||
}
|
||||
&-input-plus-secs{
|
||||
grid-area: inputPlusSecs;
|
||||
}
|
||||
// USED FOR BOTH
|
||||
&-label-blank-grid{
|
||||
grid-area: empty;
|
||||
}
|
||||
&-input__start-end-sep{
|
||||
grid-area: arrowIcon;
|
||||
}
|
||||
&-input--buttons{
|
||||
grid-area: buttons;
|
||||
}
|
||||
}
|
||||
|
||||
&--fixed-mode {
|
||||
.c-tc-input-popup__input-grid {
|
||||
grid-template-columns: 1fr 1fr 1fr 1fr 1fr 2fr;
|
||||
grid-template-areas:
|
||||
"sDate sTime . eDate eTime ."
|
||||
"sDateInput sTimeInput arrowIcon eDateInput eTimeInput buttons";
|
||||
}
|
||||
@include phonePortrait(){
|
||||
.c-tc-input-popup__input-grid {
|
||||
grid-template-columns: repeat(2, max-content) 1fr;
|
||||
grid-template-areas:
|
||||
"sDate sTime ."
|
||||
"sDateInput sTimeInput ."
|
||||
"eDate eTime ."
|
||||
"eDateInput eTimeInput buttons";
|
||||
padding: 2px;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
&--realtime-mode {
|
||||
.c-tc-input-popup__input-grid {
|
||||
grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr 2fr;
|
||||
grid-template-areas:
|
||||
"labelMinusHrs labelMinusMins labelMinusSecs . labelPlusHrs labelPlusMins labelPlusSecs ."
|
||||
"inputMinusHrs inputMinusMins inputMinusSecs arrowIcon inputPlusHrs inputPlusMins inputPlusSecs buttons";
|
||||
}
|
||||
@include phonePortrait(){
|
||||
.c-tc-input-popup__input-grid {
|
||||
grid-template-columns: repeat(3, max-content) 1fr;
|
||||
grid-template-areas:
|
||||
"labelMinusHrs labelMinusMins labelMinusSecs ."
|
||||
"inputMinusHrs inputMinusMins inputMinusSecs ."
|
||||
"labelPlusHrs labelPlusMins labelPlusSecs ."
|
||||
"inputPlusHrs inputPlusMins inputPlusSecs buttons";
|
||||
padding: 2px;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__input-grid {
|
||||
display: grid;
|
||||
grid-column-gap: 3px;
|
||||
grid-row-gap: $interiorMargin;
|
||||
grid-column-gap: $interiorMarginSm;
|
||||
align-items: start;
|
||||
}
|
||||
}
|
||||
@include phonePortrait(){ // Additional styling for mobile portrait.
|
||||
.c-tc-input-popup{
|
||||
width: 100%;
|
||||
&__options{
|
||||
> * {
|
||||
overflow: hidden;
|
||||
[class*= 'ctrl-wrapper']{
|
||||
[class*='--menu'] {
|
||||
width: 100%;
|
||||
[class*='__label'] {
|
||||
@include ellipsize();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.pr-time-input-end-time, .pr-time-input-start-time{
|
||||
> * {
|
||||
margin-right: $interiorMargin;
|
||||
}
|
||||
}
|
||||
.pr-time-input--buttons{
|
||||
justify-content: flex-end;
|
||||
}
|
||||
.pr-time-input__start-end-sep{
|
||||
margin: auto;
|
||||
}
|
||||
.pr-time-input__start-end-sep{
|
||||
display: none;
|
||||
}
|
||||
.pr-time-input-start-date, .pr-time-input-end-date{
|
||||
width: max-content;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user