Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add markdown to notebook entries #7084

Merged
merged 36 commits into from
Oct 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
6b36534
try marked out
scottbell Sep 25, 2023
dbade4c
fix url validation
scottbell Sep 25, 2023
d2060a9
Merge remote-tracking branch 'origin/master' into 6060-notebooks-form…
scottbell Sep 26, 2023
6e2c1ed
now rendering blockquotes properly
scottbell Sep 26, 2023
0f29c52
add abbrv, link titles, and strikethrough
scottbell Sep 26, 2023
3802a80
fix tests and lint
scottbell Sep 26, 2023
1116915
Closes #6060
charlesh88 Sep 27, 2023
476dcdf
Merge branch 'master' into 6060-notebooks-formatted-entries-v2
scottbell Sep 27, 2023
811b1eb
add line breaks option
scottbell Sep 27, 2023
90bea00
Closes #6060
charlesh88 Sep 27, 2023
f3d79cb
Merge branch '6060-notebooks-formatted-entries-v2' of github.com:nasa…
charlesh88 Sep 27, 2023
654e6ce
Merge branch 'master' into 6060-notebooks-formatted-entries-v2
scottbell Sep 28, 2023
a069efb
Closes #6060
charlesh88 Sep 28, 2023
f596cab
have it markdown with a textarea and adjust size automatically
scottbell Sep 29, 2023
e091781
Closes #6060
charlesh88 Sep 29, 2023
dbab7c8
Closes #6060
charlesh88 Sep 29, 2023
086cf24
Merge remote-tracking branch 'origin/master' into 6060-notebooks-form…
scottbell Oct 2, 2023
c0c18ae
two step focus/edit. also scroll into view for editing
scottbell Oct 2, 2023
24f816a
add markdown, strip all tags, and truncate
scottbell Oct 2, 2023
063bcca
lint
scottbell Oct 2, 2023
281f4f0
remove unneeded code
scottbell Oct 2, 2023
989a52d
fix notebook entry, selected page may also be null
scottbell Oct 2, 2023
b624616
fix existing notebook tests
scottbell Oct 2, 2023
1cfde0d
lint
scottbell Oct 2, 2023
b05f472
fix whitelist
scottbell Oct 2, 2023
506036a
readd whitelist
scottbell Oct 2, 2023
1e94d10
lint
scottbell Oct 2, 2023
2c841cf
fix link tests
scottbell Oct 2, 2023
7738b58
fix tests
scottbell Oct 2, 2023
05dee07
fix tagging test
scottbell Oct 2, 2023
ab79515
add some markdown test
scottbell Oct 2, 2023
86c2427
Merge branch 'master' into 6060-notebooks-formatted-entries-v2
scottbell Oct 2, 2023
194fede
get rid of pause
scottbell Oct 2, 2023
2c0010a
Merge branch '6060-notebooks-formatted-entries-v2' of github.com:nasa…
scottbell Oct 2, 2023
de287c3
add another sanitization step
scottbell Oct 2, 2023
9ed1ce9
Merge branch 'master' into 6060-notebooks-formatted-entries-v2
ozyx Oct 2, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions e2e/helper/notebookUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ async function enterTextEntry(page, text) {
await page.locator(NOTEBOOK_DROP_AREA).click();

// enter text
await page.locator('[aria-label="Notebook Entry"].is-selected div.c-ne__text').fill(text);
await page.getByLabel('Notebook Entry Display').last().click();
await page.getByLabel('Notebook Entry Input').last().fill(text);
await commitEntry(page);
}

Expand All @@ -52,7 +53,6 @@ async function dragAndDropEmbed(page, notebookObject) {
await page.click('button[title="Show selected item in tree"]');
// Drag and drop the SWG into the notebook
await page.dragAndDrop(`text=${swg.name}`, NOTEBOOK_DROP_AREA);
await commitEntry(page);
}

/**
Expand Down
50 changes: 44 additions & 6 deletions e2e/tests/functional/plugins/notebook/notebook.e2e.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -279,8 +279,8 @@ test.describe('Notebook entry tests', () => {

// Click .c-notebook__drag-area
await page.locator('.c-notebook__drag-area').click();
await expect(page.locator('[aria-label="Notebook Entry Input"]')).toBeVisible();
await expect(page.locator('[aria-label="Notebook Entry"]')).toHaveClass(/is-selected/);
await expect(page.getByLabel('Notebook Entry Display')).toBeVisible();
await expect(page.getByLabel('Notebook Entry', { exact: true })).toHaveClass(/is-selected/);
});
test('When an object is dropped into a notebook, a new entry is created and it should be focused @unstable', async ({
page
Expand Down Expand Up @@ -369,6 +369,8 @@ test.describe('Notebook entry tests', () => {

const validLink = page.locator(`a[href="${TEST_LINK}"]`);

expect(await validLink.count()).toBe(1);

// Start waiting for popup before clicking. Note no await.
const popupPromise = page.waitForEvent('popup');

Expand All @@ -378,8 +380,6 @@ test.describe('Notebook entry tests', () => {
// Wait for the popup to load.
await popup.waitForLoadState();
expect.soft(popup.url()).toContain('www.google.com');

expect(await validLink.count()).toBe(1);
});
test('when an invalid link is entered into a notebook entry, it does not become clickable when viewing', async ({
page
Expand Down Expand Up @@ -447,6 +447,8 @@ test.describe('Notebook entry tests', () => {

const validLink = page.locator(`a[href="${TEST_LINK}"]`);

expect(await validLink.count()).toBe(1);

// Start waiting for popup before clicking. Note no await.
const popupPromise = page.waitForEvent('popup');

Expand All @@ -456,8 +458,6 @@ test.describe('Notebook entry tests', () => {
// Wait for the popup to load.
await popup.waitForLoadState();
expect.soft(popup.url()).toContain('www.google.com');

expect(await validLink.count()).toBe(1);
});
test('when a nefarious link is entered into a notebook entry, it is sanitized when viewing', async ({
page
Expand All @@ -482,4 +482,42 @@ test.describe('Notebook entry tests', () => {
expect.soft(await sanitizedLink.count()).toBe(1);
expect(await unsanitizedLink.count()).toBe(0);
});
test('Can add markdown to a notebook entry', async ({ page }) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't need to block this PR, but we should remember to add a visual test for this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll put in a ticket for that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

await page.goto(notebookObject.url);

// Headers
const headerMarkdown = `# Big Header\n## Large Header\n### Medium Header\n#### Small Header`;
await nbUtils.enterTextEntry(page, headerMarkdown);
await expect(page.getByRole('heading', { name: 'Big Header' })).toBeVisible();

// Text markup
const markupText =
'**This is bold.** _This is italic_. `This is code`. ~This is strikethrough~';
await nbUtils.enterTextEntry(page, markupText);
await expect(page.locator('strong:has-text("This is bold.")')).toBeVisible();

// Tables
const tablesText = '|Col 1|Col 2|Col3|\n|-|-|-|\n |Value 1|Value 2|Value 3|\n';
await nbUtils.enterTextEntry(page, tablesText);
await expect(page.getByRole('cell', { name: 'Value 2' })).toBeVisible();

// Links
const linksText =
'Raw links https://www.google.com and Markdown links like [Google](https://www.google.com) work';
await nbUtils.enterTextEntry(page, linksText);
await expect(page.getByRole('link', { name: 'https://www.google.com' })).toBeVisible();
await expect(page.getByRole('link', { name: 'Google', exact: true })).toBeVisible();

// Lists
const listsText = '- List item 1\n - Item 1A \n- List Item 2\n 1. Order 1\n 1. Order 2\n';
await nbUtils.enterTextEntry(page, listsText);
const childItem = page.locator('li:has-text("List Item 2") ol li:has-text("Order 2")');
await expect(childItem).toBeVisible();

// Blocks
const blockTest = '```javascript\nconst foo = "bar";\nconst bar = "foo";\n```';
await nbUtils.enterTextEntry(page, blockTest);
const codeBlock = page.locator('code.language-javascript:has-text("const foo = \\"bar\\";")');
await expect(codeBlock).toBeVisible();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -192,8 +192,6 @@ test.describe('Snapshot image tests', () => {
// be sure that entry was created
await expect(page.getByText('favicon-96x96.png')).toBeVisible();

// click on image (need to click twice to focus)
await page.getByRole('img', { name: 'favicon-96x96.png thumbnail' }).click();
await page.getByRole('img', { name: 'favicon-96x96.png thumbnail' }).click();

// expect large image to be displayed
Expand Down
10 changes: 4 additions & 6 deletions e2e/tests/functional/plugins/notebook/tags.e2e.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -147,16 +147,14 @@ test.describe('Tagging in Notebooks @addInit', () => {
type: 'issue',
description: 'https://github.com/nasa/openmct/issues/5823'
});

await createNotebookEntryAndTags(page);

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 = 1`;
await page.locator(entryLocator).click();
await page.locator(entryLocator).fill(`An entry without tags`);
await page.locator('[aria-label="Notebook Entry Input"] >> nth=1').press('Enter');
await page.getByLabel('Notebook Entry Display').last().click();
await page.getByLabel('Notebook Entry Input').fill(`An entry without tags`);
await page.locator('.c-ne__save-button > button').click();

await page.hover('[aria-label="Notebook Entry Input"] >> nth=1');
await page.hover('[aria-label="Notebook Entry Display"] >> nth=1');
await page.locator('button[title="Delete this entry"]').last().click();
await expect(
page.locator('text=This action will permanently delete this entry. Do you wish to continue?')
Expand Down
5 changes: 3 additions & 2 deletions e2e/tests/performance/contract/notebook.contract.perf.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,9 @@ test.describe('Performance tests', () => {
await page.evaluate(() => window.performance.mark('new-notebook-entry-created'));

// Enter Notebook Entry text
await page.locator('div.c-ne__text').last().fill('New Entry');
await page.keyboard.press('Enter');
await page.getByLabel('Notebook Entry').last().click();
await page.getByLabel('Notebook Entry Input').last().fill('New Entry');
await page.locator('.c-ne__save-button').click();
await page.evaluate(() => window.performance.mark('new-notebook-entry-filled'));

//Individual Notebook Entry Search
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
"karma-webpack": "5.0.0",
"location-bar": "3.0.1",
"lodash": "4.17.21",
"marked": "9.0.3",
"mini-css-extract-plugin": "2.7.6",
"moment": "2.29.4",
"moment-duration-format": "2.3.2",
Expand Down
16 changes: 11 additions & 5 deletions src/plugins/notebook/components/Notebook.vue
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
this source code distribution or the Licensing information page available
at runtime from the About dialog for additional information.
-->

<template>
<div class="c-notebook" :class="[{ 'c-notebook--restricted': isRestricted }]">
<div class="c-notebook__head">
Expand Down Expand Up @@ -62,7 +61,13 @@
@selectSection="selectSection"
@toggleNav="toggleNav"
/>
<div class="c-notebook__page-view">
<div
class="c-notebook__page-view"
:class="{
'c-notebook--page-locked': selectedPage?.isLocked,
'c-notebook--page-unlocked': !selectedPage?.isLocked
}"
>
<div class="c-notebook__page-view__header">
<button
class="c-notebook__toggle-nav-button c-icon-button c-icon-button--major icon-menu-hamburger"
Expand Down Expand Up @@ -107,9 +112,9 @@
class="c-telemetry-table__progress-bar"
:model="{ progressPerc: null }"
/>
<div v-if="selectedPage && selectedPage.isLocked" class="c-notebook__page-locked">
<div v-if="selectedPage && selectedPage.isLocked" class="c-notebook__page-locked-message">
<div class="icon-lock"></div>
<div class="c-notebook__page-locked__message">
<div class="c-notebook__page-locked-message-text">
This page has been committed and cannot be modified or removed
</div>
</div>
Expand Down Expand Up @@ -142,7 +147,7 @@
class="c-notebook__commit-entries-control"
>
<button
class="c-button c-button--major commit-button icon-lock"
class="c-button commit-button icon-lock"
title="Commit entries and lock this page from further changes"
@click="lockPage()"
>
Expand Down Expand Up @@ -185,6 +190,7 @@ import {
import NotebookEntry from './NotebookEntry.vue';
import SearchResults from './SearchResults.vue';
import Sidebar from './Sidebar.vue';

function objectCopy(obj) {
return JSON.parse(JSON.stringify(obj));
}
Expand Down
Loading