Fix Notebook enter key 6354 (#6365)

* Closes #6354 Notebook Enter key adds new lines
- Removed enter key handlers from Vue component.
- Added "Save" button.
* entry must be selected before editing
* focus on newly created entry
* Closes #6354 Notebook Enter key adds new lines
- Removed enter key handlers from Vue component.
- Added "Save" button.
* do not allow edit unless entry is selected
* remove css for disabled cass

---------

Co-authored-by: David Tsay <david.e.tsay@nasa.gov>
This commit is contained in:
Charles Hacskaylo 2023-03-10 11:00:01 -08:00 committed by GitHub
parent 73734d99ea
commit 39cff51db0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 57 additions and 21 deletions

View File

@ -32,9 +32,8 @@ async function enterTextEntry(page, text) {
await page.locator(NOTEBOOK_DROP_AREA).click(); await page.locator(NOTEBOOK_DROP_AREA).click();
// enter text // enter text
await page.locator('div.c-ne__text').click(); await page.locator('[aria-label="Notebook Entry"].is-selected div.c-ne__text').fill(text);
await page.locator('div.c-ne__text').fill(text); await commitEntry(page);
await page.locator('div.c-ne__text').press('Enter');
} }
/** /**
@ -51,6 +50,15 @@ async function dragAndDropEmbed(page, notebookObject) {
await page.click('button[title="Show selected item in tree"]'); await page.click('button[title="Show selected item in tree"]');
// Drag and drop the SWG into the notebook // Drag and drop the SWG into the notebook
await page.dragAndDrop(`text=${swg.name}`, NOTEBOOK_DROP_AREA); await page.dragAndDrop(`text=${swg.name}`, NOTEBOOK_DROP_AREA);
await commitEntry(page);
}
/**
* @private
* @param {import('@playwright/test').Page} page
*/
async function commitEntry(page) {
await page.locator('.c-ne__save-button > button').click();
} }
// eslint-disable-next-line no-undef // eslint-disable-next-line no-undef

View File

@ -25,7 +25,8 @@ This test suite is dedicated to tests which verify form functionality.
*/ */
const { test, expect } = require('../../../../pluginFixtures'); const { test, expect } = require('../../../../pluginFixtures');
const { createDomainObjectWithDefaults } = require('../../../../appActions'); const { createDomainObjectWithDefaults, selectInspectorTab } = require('../../../../appActions');
const nbUtils = require('../../../../helper/notebookUtils');
/** /**
* Creates a notebook object and adds an entry. * Creates a notebook object and adds an entry.
@ -39,12 +40,7 @@ async function createNotebookAndEntry(page, iterations = 1) {
const notebook = createDomainObjectWithDefaults(page, { type: 'Notebook' }); const notebook = createDomainObjectWithDefaults(page, { type: 'Notebook' });
for (let iteration = 0; iteration < iterations; iteration++) { for (let iteration = 0; iteration < iterations; iteration++) {
// Create an entry await nbUtils.enterTextEntry(page, `Entry ${iteration}`);
await page.locator('text=To start a new entry, click here or drag and drop any object').click();
const entryLocator = `[aria-label="Notebook Entry Input"] >> nth = ${iteration}`;
await page.locator(entryLocator).click();
await page.locator(entryLocator).fill(`Entry ${iteration}`);
await page.locator(entryLocator).press('Enter');
} }
return notebook; return notebook;
@ -57,7 +53,7 @@ async function createNotebookAndEntry(page, iterations = 1) {
*/ */
async function createNotebookEntryAndTags(page, iterations = 1) { async function createNotebookEntryAndTags(page, iterations = 1) {
const notebook = await createNotebookAndEntry(page, iterations); const notebook = await createNotebookAndEntry(page, iterations);
await page.locator('text=Annotations').click(); await selectInspectorTab(page, 'Annotations');
for (let iteration = 0; iteration < iterations; iteration++) { for (let iteration = 0; iteration < iterations; iteration++) {
// Hover and click "Add Tag" button // Hover and click "Add Tag" button
@ -88,7 +84,10 @@ test.describe('Tagging in Notebooks @addInit', () => {
test('Can load tags', async ({ page }) => { test('Can load tags', async ({ page }) => {
await createNotebookAndEntry(page); await createNotebookAndEntry(page);
await page.locator('text=Annotations').click(); // TODO can be removed with fix for https://github.com/nasa/openmct/issues/6411
await page.locator('[aria-label="Notebook Entry"].is-selected div.c-ne__text').click();
await selectInspectorTab(page, 'Annotations');
await page.locator('button:has-text("Add Tag")').click(); await page.locator('button:has-text("Add Tag")').click();
@ -247,8 +246,10 @@ test.describe('Tagging in Notebooks @addInit', () => {
test('Can cancel adding a tag', async ({ page }) => { test('Can cancel adding a tag', async ({ page }) => {
await createNotebookAndEntry(page); await createNotebookAndEntry(page);
// Click on Annotations tab // TODO can be removed with fix for https://github.com/nasa/openmct/issues/6411
await page.locator('.c-inspector__tab', { hasText: "Annotations" }).click(); await page.locator('[aria-label="Notebook Entry"].is-selected div.c-ne__text').click();
await selectInspectorTab(page, 'Annotations');
// Click on the "Add Tag" button // Click on the "Add Tag" button
await page.locator('button:has-text("Add Tag")').click(); await page.locator('button:has-text("Add Tag")').click();

View File

@ -791,6 +791,7 @@ export default {
this.updateDefaultNotebook(notebookStorage); this.updateDefaultNotebook(notebookStorage);
const id = await addNotebookEntry(this.openmct, this.domainObject, notebookStorage, embed); const id = await addNotebookEntry(this.openmct, this.domainObject, notebookStorage, embed);
this.focusEntryId = id; this.focusEntryId = id;
this.selectedEntryId = id;
this.filterAndSortEntries(); this.filterAndSortEntries();
}, },
orientationChange() { orientationChange() {

View File

@ -25,7 +25,10 @@
<div <div
class="c-notebook__entry c-ne has-local-controls" class="c-notebook__entry c-ne has-local-controls"
aria-label="Notebook Entry" aria-label="Notebook Entry"
:class="{ 'locked': isLocked, 'is-selected': isSelectedEntry }" :class="{ 'locked': isLocked,
'is-selected': isSelectedEntry,
'is-editing' : editMode
}"
@dragover="changeCursor" @dragover="changeCursor"
@drop.capture="cancelEditMode" @drop.capture="cancelEditMode"
@drop.prevent="dropOnEntry" @drop.prevent="dropOnEntry"
@ -80,12 +83,17 @@
v-bind.prop="formattedText" v-bind.prop="formattedText"
@mouseover="checkEditability($event)" @mouseover="checkEditability($event)"
@mouseleave="canEdit = true" @mouseleave="canEdit = true"
@mousedown="preventFocusIfNotSelected($event)"
@focus="editingEntry()" @focus="editingEntry()"
@blur="updateEntryValue($event)" @blur="updateEntryValue($event)"
@keydown.enter.exact.prevent
@keyup.enter.exact.prevent="forceBlur($event)"
> >
</div> </div>
<div
v-if="editMode"
class="c-ne__save-button"
>
<button class="c-button c-button--major icon-check"></button>
</div>
</template> </template>
<template v-else> <template v-else>
@ -454,6 +462,13 @@ export default {
this.$emit('updateEntry', this.entry); this.$emit('updateEntry', this.entry);
}, },
preventFocusIfNotSelected($event) {
if (!this.isSelectedEntry) {
$event.preventDefault();
// blur the previous focused entry if clicking on non selected entry input
document.activeElement.blur();
}
},
editingEntry() { editingEntry() {
this.editMode = true; this.editMode = true;
this.$emit('editingEntry'); this.$emit('editingEntry');

View File

@ -283,11 +283,11 @@
@include discreteItem(); @include discreteItem();
display: flex; display: flex;
padding: $interiorMarginSm $interiorMarginSm $interiorMarginSm $interiorMargin; padding: $interiorMarginSm $interiorMarginSm $interiorMarginSm $interiorMargin;
&:hover { &:hover {
background: rgba($colorBodyFg, 0.2); background: rgba($colorBodyFg, 0.2);
} }
&.is-selected { &.is-selected {
background: rgba($colorKey, 0.3); background: rgba($colorKey, 0.3);
} }
@ -389,6 +389,17 @@
white-space: pre-wrap; white-space: pre-wrap;
} }
&__save-button {
display: flex;
justify-content: flex-end;
.c-button {
$lrP: 15px;
padding-left: $lrP;
padding-right: $lrP;
}
}
&__section-and-page { &__section-and-page {
// Shown when c-ne within search results // Shown when c-ne within search results
background: rgba($colorBodyFg, 0.1); //$colorInteriorBorder; background: rgba($colorBodyFg, 0.1); //$colorInteriorBorder;
@ -491,7 +502,7 @@
} }
&__actions-menu { &__actions-menu {
width: 55vh; width: 55vh;
max-width: 500px; max-width: 500px;
height: 130px; height: 130px;
z-index: 70; z-index: 70;
[class*="__icon"] { [class*="__icon"] {
@ -500,7 +511,7 @@
height: 4vh; height: 4vh;
} }
[class*="__item-description"] { [class*="__item-description"] {
min-width: 200px; min-width: 200px;
} }
} }