Skip to content

Commit

Permalink
Add wrap break-all to Noteobook CodeBlock output (opensearch-project#974
Browse files Browse the repository at this point in the history
) (opensearch-project#1027)

* Add wrap break-all to Noteobook CodeBlock output

---------


(cherry picked from commit f989783)

Signed-off-by: Peter Fitzgibbons <peter.fitzgibbons@gmail.com>
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
  • Loading branch information
1 parent 7faf731 commit 3684129
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 52 deletions.
59 changes: 51 additions & 8 deletions .cypress/integration/2_notebooks.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import { SAMPLE_PANEL } from '../utils/panel_constants';

import { skipOn } from '@cypress/skip-test';

import { v4 as uuid4 } from 'uuid';

const moveToEventsHome = () => {
cy.visit(`${Cypress.env('opensearchDashboards')}/app/observability-logs#/`);
};
Expand Down Expand Up @@ -157,7 +159,7 @@ describe('Test reporting integration if plugin installed', () => {
beforeEach(() => {
cy.visit(`${Cypress.env('opensearchDashboards')}/app/observability-notebooks#/`);
cy.get('.euiTableCellContent').contains(TEST_NOTEBOOK).click();
cy.wait(delay);//page needs to process before checking
cy.wait(delay); //page needs to process before checking
cy.get('body').then(($body) => {
skipOn($body.find('#reportingActionsButton').length <= 0);
});
Expand Down Expand Up @@ -290,8 +292,9 @@ describe('Testing paragraphs', () => {

it('Adds a SQL query paragraph', () => {
cy.contains('Add paragraph').click();
cy.get('.euiContextMenuItem__text').contains('Code block').click(), { timeout: COMMAND_TIMEOUT_LONG };
cy.wait(delay);//SQL_QUERY_TEXT will sometimes fail to type without this delay
cy.get('.euiContextMenuItem__text').contains('Code block').click(),
{ timeout: COMMAND_TIMEOUT_LONG };
cy.wait(delay); //SQL_QUERY_TEXT will sometimes fail to type without this delay

cy.get('.euiTextArea').type(SQL_QUERY_TEXT);
cy.get('.euiButton__text').contains('Run').click();
Expand All @@ -301,6 +304,45 @@ describe('Testing paragraphs', () => {
cy.get('.euiDataGrid__overflow').should('exist');
});

it('Renders very long markdown as wrapped', () => {
cy.contains('Add paragraph').click();
cy.get('.euiContextMenuItem__text').contains('Code block').click(),
{ timeout: COMMAND_TIMEOUT_LONG };
cy.wait(delay); //SQL_QUERY_TEXT will sometimes fail to type without this delay

const testWord = uuid4().replace(/-/gi, '').repeat(10);
cy.get('.euiTextArea').type(`%md\n${testWord}`);
cy.get('.euiButton__text').contains('Run').click();

cy.get('p')
.contains(testWord)
.then((element) => {
const clientWidth = element[0].clientWidth;
const scrollWidth = element[0].scrollWidth;
console.log('paragraph', { clientWidth, scrollWidth });
expect(scrollWidth, 'Output Text has not been wrapped').to.be.at.most(clientWidth);
});
});

it('Renders very long query as wrapped', () => {
cy.contains('Add paragraph').click();
cy.get('.euiContextMenuItem__text').contains('Code block').click(),
{ timeout: COMMAND_TIMEOUT_LONG };
cy.wait(delay); //SQL_QUERY_TEXT will sometimes fail to type without this delay

const testWord = uuid4().replace(/-/gi, '').repeat(10);
cy.get('.euiTextArea').type(`%sql\nSELECT 1 AS ${testWord}`);
cy.get('.euiButton__text').contains('Run').click();

cy.get('b')
.contains(testWord)
.then((element) => {
const clientWidth = element[0].clientWidth;
const scrollWidth = element[0].scrollWidth;
expect(scrollWidth, 'Output Text has not been wrapped').to.be.at.most(clientWidth);
});
});

it('Adds an observability visualization paragraph', () => {
cy.contains('Add paragraph').click();
cy.get('.euiContextMenuItem__text').contains('Visualization').click();
Expand All @@ -319,8 +361,9 @@ describe('Testing paragraphs', () => {

it('Adds a PPL query paragraph', () => {
cy.contains('Add paragraph').click();
cy.get('.euiContextMenuItem__text').contains('Code block').click(), { timeout: COMMAND_TIMEOUT_LONG };;
cy.wait(delay);//PPL_QUERY_TEXT will sometimes fail to type without this delay
cy.get('.euiContextMenuItem__text').contains('Code block').click(),
{ timeout: COMMAND_TIMEOUT_LONG };
cy.wait(delay); //PPL_QUERY_TEXT will sometimes fail to type without this delay

cy.get('.euiTextArea').type(PPL_QUERY_TEXT);
cy.get('.euiButton__text').contains('Run').click();
Expand Down Expand Up @@ -433,7 +476,7 @@ describe('clean up all test data', () => {
cy.get('.euiButton__text').contains('Actions').trigger('mouseover').click();
cy.get('.euiContextMenuItem__text').contains('Delete').trigger('mouseover').click();
cy.get('button.euiButton--danger').should('be.disabled');
cy.get('input.euiFieldText[placeholder="delete"]').focus().type('delete', {delay: 50, });
cy.get('input.euiFieldText[placeholder="delete"]').focus().type('delete', { delay: 50 });
cy.get('button.euiButton--danger').should('not.be.disabled');
cy.get('.euiButton__text').contains('Delete').trigger('mouseover').click();
cy.get('.euiTextAlign').contains('No Queries or Visualizations').should('exist');
Expand All @@ -445,8 +488,8 @@ describe('clean up all test data', () => {
cy.get('.euiButton__text').contains('Actions').trigger('mouseover').click();
cy.get('.euiContextMenuItem__text').contains('Delete').trigger('mouseover').click();
cy.get('button.euiButton--danger').should('be.disabled');
cy.get('input.euiFieldText[placeholder="delete"]').focus().type('delete', { delay: 50, });
cy.get('input.euiFieldText[placeholder="delete"]').focus().type('delete', { delay: 50 });
cy.get('button.euiButton--danger').should('not.be.disabled');
cy.get('.euiButton__text').contains('Delete').trigger('mouseover').click();
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

exports[`<ParaOutput /> spec renders markdown outputs 1`] = `
<div
class="euiText euiText--medium markdown-output-text"
class="euiText euiText--medium wrapAll markdown-output-text"
>
<div
class="markdown-body "
Expand All @@ -27,7 +27,7 @@ exports[`<ParaOutput /> spec renders other types of outputs 1`] = `
exports[`<ParaOutput /> spec renders query outputs 1`] = `
<div>
<div
class="euiText euiText--medium"
class="euiText euiText--medium wrapAll"
>
<b>
select * from opensearch_dashboards_sample_data_flights limit 2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ exports[`<Paragraphs /> spec renders the component 1`] = `
style="opacity: 1; padding: 15px;"
>
<div
class="euiText euiText--medium markdown-output-text"
class="euiText euiText--medium wrapAll markdown-output-text"
>
<div
class="markdown-body "
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ import { EuiCodeBlock, EuiSpacer, EuiText } from '@elastic/eui';
import MarkdownRender from '@nteract/markdown';
import { Media } from '@nteract/outputs';
import moment from 'moment';
import React, { useState } from 'react';
import { VisualizationContainer } from '../../../../components/custom_panels/panel_modules/visualization_container';
import PPLService from '../../../../services/requests/ppl';
import React, { useState } from 'react';
import { CoreStart } from '../../../../../../../src/core/public';
import {
DashboardContainerInput,
Expand Down Expand Up @@ -38,7 +38,7 @@ export const ParaOutput = (props: {
}) => {
const createQueryColumns = (jsonColumns: any[]) => {
let index = 0;
let datagridColumns = [];
const datagridColumns = [];
for (index = 0; index < jsonColumns.length; ++index) {
const datagridColumnObject = {
id: jsonColumns[index].name,
Expand All @@ -54,7 +54,7 @@ export const ParaOutput = (props: {
let index = 0;
let schemaIndex = 0;
for (index = 0; index < queryObject.datarows.length; ++index) {
let datarowValue = {};
const datarowValue = {};
for (schemaIndex = 0; schemaIndex < queryObject.schema.length; ++schemaIndex) {
const columnName = queryObject.schema[schemaIndex].name;
if (typeof queryObject.datarows[index][schemaIndex] === 'object') {
Expand All @@ -70,7 +70,34 @@ export const ParaOutput = (props: {
return data;
};

const outputBody = (key: string, typeOut: string, val: string) => {
const QueryOutput = ({ typeOut, val }: { typeOut: string; val: string }) => {
const inputQuery = para.inp.substring(4, para.inp.length);
const queryObject = JSON.parse(val);
const columns = createQueryColumns(queryObject.schema);
const data = getQueryOutputData(queryObject);
const [visibleColumns, setVisibleColumns] = useState(() => columns.map(({ id }) => id));
if (queryObject.hasOwnProperty('error')) {
return <EuiCodeBlock>{val}</EuiCodeBlock>;
} else {
return (
<div>
<EuiText className="wrapAll">
<b>{inputQuery}</b>
</EuiText>
<EuiSpacer />
<QueryDataGridMemo
rowCount={queryObject.datarows.length}
queryColumns={columns}
visibleColumns={visibleColumns}
setVisibleColumns={setVisibleColumns}
dataValues={data}
/>
</div>
);
}
};

const OutputBody = ({ typeOut, val }: { typeOut: string; val: string }) => {
/* Returns a component to render paragraph outputs using the para.typeOut property
* Currently supports HTML, TABLE, IMG
* TODO: add table rendering
Expand All @@ -80,34 +107,10 @@ export const ParaOutput = (props: {
if (typeOut !== undefined) {
switch (typeOut) {
case 'QUERY':
const inputQuery = para.inp.substring(4, para.inp.length);
const queryObject = JSON.parse(val);
if (queryObject.hasOwnProperty('error')) {
return <EuiCodeBlock key={key}>{val}</EuiCodeBlock>;
} else {
const columns = createQueryColumns(queryObject.schema);
const data = getQueryOutputData(queryObject);
const [visibleColumns, setVisibleColumns] = useState(() => columns.map(({ id }) => id));
return (
<div>
<EuiText key={'query-input-key'}>
<b>{inputQuery}</b>
</EuiText>
<EuiSpacer />
<QueryDataGridMemo
key={key}
rowCount={queryObject.datarows.length}
queryColumns={columns}
visibleColumns={visibleColumns}
setVisibleColumns={setVisibleColumns}
dataValues={data}
/>
</div>
);
}
return <QueryOutput typeOut={typeOut} val={val} />;
case 'MARKDOWN':
return (
<EuiText key={key} className="markdown-output-text">
<EuiText className="wrapAll markdown-output-text">
<MarkdownRender source={val} />
</EuiText>
);
Expand All @@ -121,11 +124,7 @@ export const ParaOutput = (props: {
<EuiText size="s" style={{ marginLeft: 9 }}>
{`${from} - ${to}`}
</EuiText>
<DashboardContainerByValueRenderer
key={key}
input={visInput}
onInputUpdated={setVisInput}
/>
<DashboardContainerByValueRenderer input={visInput} onInputUpdated={setVisInput} />
</>
);
case 'OBSERVABILITY_VISUALIZATION':
Expand Down Expand Up @@ -160,17 +159,17 @@ export const ParaOutput = (props: {
);
case 'HTML':
return (
<EuiText key={key}>
<EuiText>
{/* eslint-disable-next-line react/jsx-pascal-case */}
<Media.HTML data={val} />
</EuiText>
);
case 'TABLE':
return <pre key={key}>{val}</pre>;
return <pre>{val}</pre>;
case 'IMG':
return <img alt="" src={'data:image/gif;base64,' + val} key={key} />;
return <img alt="" src={'data:image/gif;base64,' + val} />;
default:
return <pre key={key}>{val}</pre>;
return <pre>{val}</pre>;
}
} else {
console.log('output not supported', typeOut);
Expand All @@ -183,7 +182,13 @@ export const ParaOutput = (props: {
return !para.isOutputHidden ? (
<>
{para.typeOut.map((typeOut: string, tIdx: number) => {
return outputBody(para.uniqueId + '_paraOutputBody', typeOut, para.out[tIdx]);
return (
<OutputBody
key={para.uniqueId + '_paraOutputBody_' + tIdx}
typeOut={typeOut}
val={para.out[tIdx]}
/>
);
})}
</>
) : null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,6 @@ export const Paragraphs = forwardRef((props: ParagraphProps, ref) => {
<ParaOutput
http={http}
pplService={pplService}
key={para.uniqueId}
para={para}
visInput={visInput}
setVisInput={setVisInput}
Expand Down
5 changes: 5 additions & 0 deletions public/components/notebooks/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@
font-weight: normal;
}

.wrapAll {
word-break: break-all;
word-wrap: break-word;
}

.markdown-output-text {
font-family: 'Inter UI', -apple-system, system-ui, 'Segoe UI', Helvetica, Arial, sans-serif,
'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol';
Expand Down

0 comments on commit 3684129

Please sign in to comment.