You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@druid.apache.org by fj...@apache.org on 2019/06/28 22:50:29 UTC
[incubator-druid] branch master updated: Web-Console: add clipboard
modal (#7964)
This is an automated email from the ASF dual-hosted git repository.
fjy pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-druid.git
The following commit(s) were added to refs/heads/master by this push:
new f1270c1 Web-Console: add clipboard modal (#7964)
f1270c1 is described below
commit f1270c14f8680fd0f69872acb05b9b97680bd4a3
Author: mcbrewster <37...@users.noreply.github.com>
AuthorDate: Fri Jun 28 15:50:18 2019 -0700
Web-Console: add clipboard modal (#7964)
* add clipboard modal
* rename button
* remove console.log
* fix off by one
* update tests
* update snapshot
* fix casing
* update snapshot
---
.../__snapshots__/table-cell.spec.tsx.snap | 28 +++---
.../src/components/table-cell/table-cell.scss | 1 +
.../src/components/table-cell/table-cell.tsx | 21 ++--
.../__snapshots__/show-value-dialog.spec.tsx.snap | 107 +++++++++++++++++++++
.../show-value-dialog/show-value-dialog.scss} | 35 ++-----
.../show-value-dialog/show-value-dialog.spec.tsx} | 31 ++----
.../show-value-dialog/show-value-dialog.tsx | 61 ++++++++++++
.../src/views/load-data-view/load-data-view.tsx | 16 +++
.../parse-data-table/parse-data-table.spec.tsx | 1 +
.../parse-data-table/parse-data-table.tsx | 3 +-
10 files changed, 227 insertions(+), 77 deletions(-)
diff --git a/web-console/src/components/table-cell/__snapshots__/table-cell.spec.tsx.snap b/web-console/src/components/table-cell/__snapshots__/table-cell.spec.tsx.snap
index d1cf2ff..cfba9f0 100644
--- a/web-console/src/components/table-cell/__snapshots__/table-cell.spec.tsx.snap
+++ b/web-console/src/components/table-cell/__snapshots__/table-cell.spec.tsx.snap
@@ -4,28 +4,28 @@ exports[`table cell matches snapshot array long 1`] = `
<span
class="table-cell truncated"
>
- [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16
+ [0, 1, 2, 3, 4, 5, 6, 7
<span
class="omitted"
>
- ...323 omitted...
+ ...357 omitted...
</span>
7, 98, 99]
<span
- class="bp3-icon bp3-icon-clipboard action-icon"
- icon="clipboard"
+ class="bp3-icon bp3-icon-more action-icon"
+ icon="more"
>
<svg
- data-icon="clipboard"
+ data-icon="more"
height="16"
viewBox="0 0 16 16"
width="16"
>
<desc>
- clipboard
+ more
</desc>
<path
- d="M11 2c0-.55-.45-1-1-1h.22C9.88.4 9.24 0 8.5 0S7.12.4 6.78 1H7c-.55 0-1 .45-1 1v1h5V2zm2 0h-1v2H5V2H4c-.55 0-1 .45-1 1v12c0 .55.45 1 1 1h9c.55 0 1-.45 1-1V3c0-.55-.45-1-1-1z"
+ d="M2 6.03a2 2 0 1 0 0 4 2 2 0 1 0 0-4zM14 6.03a2 2 0 1 0 0 4 2 2 0 1 0 0-4zM8 6.03a2 2 0 1 0 0 4 2 2 0 1 0 0-4z"
fill-rule="evenodd"
/>
</svg>
@@ -57,28 +57,28 @@ exports[`table cell matches snapshot truncate 1`] = `
<span
class="table-cell truncated"
>
- testtesttesttesttesttesttesttesttesttesttesttesttesttestt
+ testtesttesttesttesttes
<span
class="omitted"
>
- ...329 omitted...
+ ...363 omitted...
</span>
sttesttest
<span
- class="bp3-icon bp3-icon-clipboard action-icon"
- icon="clipboard"
+ class="bp3-icon bp3-icon-more action-icon"
+ icon="more"
>
<svg
- data-icon="clipboard"
+ data-icon="more"
height="16"
viewBox="0 0 16 16"
width="16"
>
<desc>
- clipboard
+ more
</desc>
<path
- d="M11 2c0-.55-.45-1-1-1h.22C9.88.4 9.24 0 8.5 0S7.12.4 6.78 1H7c-.55 0-1 .45-1 1v1h5V2zm2 0h-1v2H5V2H4c-.55 0-1 .45-1 1v12c0 .55.45 1 1 1h9c.55 0 1-.45 1-1V3c0-.55-.45-1-1-1z"
+ d="M2 6.03a2 2 0 1 0 0 4 2 2 0 1 0 0-4zM14 6.03a2 2 0 1 0 0 4 2 2 0 1 0 0-4zM8 6.03a2 2 0 1 0 0 4 2 2 0 1 0 0-4z"
fill-rule="evenodd"
/>
</svg>
diff --git a/web-console/src/components/table-cell/table-cell.scss b/web-console/src/components/table-cell/table-cell.scss
index 6be6b71..3671b7d 100644
--- a/web-console/src/components/table-cell/table-cell.scss
+++ b/web-console/src/components/table-cell/table-cell.scss
@@ -47,6 +47,7 @@
position: absolute;
top: 0;
right: 0;
+ color: #f5f8fa;
}
}
}
diff --git a/web-console/src/components/table-cell/table-cell.tsx b/web-console/src/components/table-cell/table-cell.tsx
index 88f6b84..92cfa39 100644
--- a/web-console/src/components/table-cell/table-cell.tsx
+++ b/web-console/src/components/table-cell/table-cell.tsx
@@ -30,6 +30,7 @@ export interface NullTableCellProps extends React.Props<any> {
value?: any;
timestamp?: boolean;
unparseable?: boolean;
+ openModal?: (str: string) => void;
}
interface ShortParts {
@@ -41,8 +42,8 @@ interface ShortParts {
export class TableCell extends React.PureComponent<NullTableCellProps> {
static MAX_CHARS_TO_SHOW = 50;
- static possiblyTruncate(str: string): React.ReactNode {
- if (str.length < TableCell.MAX_CHARS_TO_SHOW) return str;
+ possiblyTruncate(str: string): React.ReactNode {
+ if (str.length <= TableCell.MAX_CHARS_TO_SHOW) return str;
const { prefix, omitted, suffix } = TableCell.shortenString(str);
return (
@@ -51,14 +52,8 @@ export class TableCell extends React.PureComponent<NullTableCellProps> {
<span className="omitted">{omitted}</span>
{suffix}
<ActionIcon
- icon={IconNames.CLIPBOARD}
- onClick={() => {
- copy(str, { format: 'text/plain' });
- AppToaster.show({
- message: 'Value copied to clipboard',
- intent: Intent.SUCCESS,
- });
- }}
+ icon={IconNames.MORE}
+ onClick={() => (this.props.openModal ? this.props.openModal(str) : null)}
/>
</span>
);
@@ -67,7 +62,7 @@ export class TableCell extends React.PureComponent<NullTableCellProps> {
static shortenString(str: string): ShortParts {
// Print something like:
// BAAAArAAEiQKpDAEAACwZCBAGSBgiSEAAAAQpAIDwAg...23 omitted...gwiRoQBJIC
- const omit = str.length - (TableCell.MAX_CHARS_TO_SHOW + 17);
+ const omit = str.length - (TableCell.MAX_CHARS_TO_SHOW - 17);
const prefix = str.substr(0, str.length - (omit + 10));
const suffix = str.substr(str.length - 10);
return {
@@ -89,9 +84,9 @@ export class TableCell extends React.PureComponent<NullTableCellProps> {
</span>
);
} else if (Array.isArray(value)) {
- return TableCell.possiblyTruncate(`[${value.join(', ')}]`);
+ return this.possiblyTruncate(`[${value.join(', ')}]`);
} else {
- return TableCell.possiblyTruncate(String(value));
+ return this.possiblyTruncate(String(value));
}
} else {
if (timestamp) {
diff --git a/web-console/src/dialogs/show-value-dialog/__snapshots__/show-value-dialog.spec.tsx.snap b/web-console/src/dialogs/show-value-dialog/__snapshots__/show-value-dialog.spec.tsx.snap
new file mode 100644
index 0000000..144f880
--- /dev/null
+++ b/web-console/src/dialogs/show-value-dialog/__snapshots__/show-value-dialog.spec.tsx.snap
@@ -0,0 +1,107 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`clipboard dialog matches snapshot 1`] = `
+<div
+ class="bp3-portal"
+>
+ <div
+ class="bp3-overlay bp3-overlay-open bp3-overlay-scroll-container"
+ >
+ <div
+ class="bp3-overlay-backdrop bp3-overlay-appear bp3-overlay-appear-active"
+ tabindex="0"
+ />
+ <div
+ class="bp3-dialog-container bp3-overlay-content bp3-overlay-appear bp3-overlay-appear-active"
+ tabindex="0"
+ >
+ <div
+ class="bp3-dialog show-value-dialog"
+ >
+ <div
+ class="bp3-dialog-header"
+ >
+ <h4
+ class="bp3-heading"
+ >
+ Show value
+ </h4>
+ <button
+ aria-label="Close"
+ class="bp3-button bp3-minimal bp3-dialog-close-button"
+ type="button"
+ >
+ <span
+ class="bp3-icon bp3-icon-small-cross"
+ icon="small-cross"
+ >
+ <svg
+ data-icon="small-cross"
+ height="20"
+ viewBox="0 0 20 20"
+ width="20"
+ >
+ <desc>
+ small-cross
+ </desc>
+ <path
+ d="M11.41 10l3.29-3.29c.19-.18.3-.43.3-.71a1.003 1.003 0 0 0-1.71-.71L10 8.59l-3.29-3.3a1.003 1.003 0 0 0-1.42 1.42L8.59 10 5.3 13.29c-.19.18-.3.43-.3.71a1.003 1.003 0 0 0 1.71.71l3.29-3.3 3.29 3.29c.18.19.43.3.71.3a1.003 1.003 0 0 0 .71-1.71L11.41 10z"
+ fill-rule="evenodd"
+ />
+ </svg>
+ </span>
+ </button>
+ </div>
+ <textarea
+ class="bp3-input"
+ >
+ Bot: Automatska zamjena teksta (-[[Administrativna podjela Meksika|Admin]] +[[Administrativna podjela Meksika|Admi]])
+ </textarea>
+ <div
+ class="bp3-dialog-footer-actions"
+ >
+ <button
+ class="bp3-button"
+ type="button"
+ >
+ <span
+ class="bp3-icon bp3-icon-duplicate"
+ icon="duplicate"
+ >
+ <svg
+ data-icon="duplicate"
+ height="16"
+ viewBox="0 0 16 16"
+ width="16"
+ >
+ <desc>
+ duplicate
+ </desc>
+ <path
+ d="M15 0H5c-.55 0-1 .45-1 1v2h2V2h8v7h-1v2h2c.55 0 1-.45 1-1V1c0-.55-.45-1-1-1zm-4 4H1c-.55 0-1 .45-1 1v10c0 .55.45 1 1 1h10c.55 0 1-.45 1-1V5c0-.55-.45-1-1-1zm-1 10H2V6h8v8z"
+ fill-rule="evenodd"
+ />
+ </svg>
+ </span>
+ <span
+ class="bp3-button-text"
+ >
+ Copy
+ </span>
+ </button>
+ <button
+ class="bp3-button bp3-intent-primary"
+ type="button"
+ >
+ <span
+ class="bp3-button-text"
+ >
+ Close
+ </span>
+ </button>
+ </div>
+ </div>
+ </div>
+ </div>
+</div>
+`;
diff --git a/web-console/src/components/table-cell/table-cell.scss b/web-console/src/dialogs/show-value-dialog/show-value-dialog.scss
similarity index 63%
copy from web-console/src/components/table-cell/table-cell.scss
copy to web-console/src/dialogs/show-value-dialog/show-value-dialog.scss
index 6be6b71..1ef9e94 100644
--- a/web-console/src/components/table-cell/table-cell.scss
+++ b/web-console/src/dialogs/show-value-dialog/show-value-dialog.scss
@@ -16,37 +16,18 @@
* limitations under the License.
*/
-.table-cell {
- &.null {
- font-style: italic;
+.show-value-dialog{
+ &.bp3-dialog{
+ padding-bottom: 10px;
}
- &.unparseable {
- color: #9e2b0e;
+ .bp3-input{
+ margin: 10px;
+ height: 400px;
}
- &.timestamp {
- font-weight: bold;
- }
-
- &.truncated {
- position: relative;
- width: 100%;
- display: inline-block;
- overflow: hidden;
- white-space: nowrap;
- text-overflow: ellipsis;
- padding-right: 16px;
-
- .omitted {
- margin: 0 0.2em;
- font-style: italic;
- }
+ .bp3-dialog-footer-actions{
+ padding-right: 10px;
- .action-icon {
- position: absolute;
- top: 0;
- right: 0;
- }
}
}
diff --git a/web-console/src/views/load-data-view/parse-data-table/parse-data-table.spec.tsx b/web-console/src/dialogs/show-value-dialog/show-value-dialog.spec.tsx
similarity index 64%
copy from web-console/src/views/load-data-view/parse-data-table/parse-data-table.spec.tsx
copy to web-console/src/dialogs/show-value-dialog/show-value-dialog.spec.tsx
index c3267f1..d8dc72d 100644
--- a/web-console/src/views/load-data-view/parse-data-table/parse-data-table.spec.tsx
+++ b/web-console/src/dialogs/show-value-dialog/show-value-dialog.spec.tsx
@@ -19,32 +19,19 @@
import React from 'react';
import { render } from 'react-testing-library';
-import { ParseDataTable } from './parse-data-table';
+import { ShowValueDialog } from './show-value-dialog';
-describe('parse data table', () => {
+describe('clipboard dialog', () => {
it('matches snapshot', () => {
- const sampleData = {
- header: ['c1'],
- rows: [
- {
- raw: `{"c1":"hello"}`,
- parsed: { c1: 'hello' },
- },
- ],
- };
-
- const parseDataTable = (
- <ParseDataTable
- sampleData={sampleData}
- columnFilter=""
- canFlatten={false}
- flattenedColumnsOnly={false}
- flattenFields={[]}
- onFlattenFieldSelect={() => null}
+ const compactionDialog = (
+ <ShowValueDialog
+ onClose={() => null}
+ str={
+ 'Bot: Automatska zamjena teksta (-[[Administrativna podjela Meksika|Admin]] +[[Administrativna podjela Meksika|Admi]])'
+ }
/>
);
-
- const { container } = render(parseDataTable);
+ const { container } = render(compactionDialog, { container: document.body });
expect(container.firstChild).toMatchSnapshot();
});
});
diff --git a/web-console/src/dialogs/show-value-dialog/show-value-dialog.tsx b/web-console/src/dialogs/show-value-dialog/show-value-dialog.tsx
new file mode 100644
index 0000000..4a92aa8
--- /dev/null
+++ b/web-console/src/dialogs/show-value-dialog/show-value-dialog.tsx
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { Button, Classes, Dialog, IconName, Intent, TextArea } from '@blueprintjs/core';
+import { IconNames } from '@blueprintjs/icons';
+import copy = require('copy-to-clipboard');
+import React from 'react';
+
+import { AppToaster } from '../../singletons/toaster';
+
+import './show-value-dialog.scss';
+
+export interface ShowValueDialogProps extends React.Props<any> {
+ onClose: () => void;
+ str: string;
+}
+
+export class ShowValueDialog extends React.PureComponent<ShowValueDialogProps> {
+ constructor(props: ShowValueDialogProps) {
+ super(props);
+ this.state = {};
+ }
+
+ render() {
+ const { onClose, str } = this.props;
+
+ return (
+ <Dialog className="show-value-dialog" isOpen onClose={onClose} title={'Show value'}>
+ <TextArea value={str} />
+ <div className={Classes.DIALOG_FOOTER_ACTIONS}>
+ <Button
+ icon={IconNames.DUPLICATE}
+ text={'Copy'}
+ onClick={() => {
+ copy(str, { format: 'text/plain' });
+ AppToaster.show({
+ message: 'Value copied to clipboard',
+ intent: Intent.SUCCESS,
+ });
+ }}
+ />
+ <Button text={'Close'} intent={'primary'} onClick={onClose} />
+ </div>
+ </Dialog>
+ );
+ }
+}
diff --git a/web-console/src/views/load-data-view/load-data-view.tsx b/web-console/src/views/load-data-view/load-data-view.tsx
index efc853d..38f24e6 100644
--- a/web-console/src/views/load-data-view/load-data-view.tsx
+++ b/web-console/src/views/load-data-view/load-data-view.tsx
@@ -25,6 +25,7 @@ import {
Card,
Classes,
Code,
+ Dialog,
Elevation,
FormGroup,
H5,
@@ -50,6 +51,7 @@ import {
Loader,
} from '../../components';
import { AsyncActionDialog } from '../../dialogs';
+import { ShowValueDialog } from '../../dialogs/show-value-dialog/show-value-dialog';
import { AppToaster } from '../../singletons/toaster';
import { UrlBaser } from '../../singletons/url-baser';
import {
@@ -233,6 +235,8 @@ export interface LoadDataViewState {
showResetConfirm: boolean;
newRollup: boolean | null;
newDimensionMode: DimensionMode | null;
+ showViewValueModal: boolean;
+ str: string;
// welcome
overlordModules: string[] | null;
@@ -296,8 +300,10 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
// dialogs / modals
showResetConfirm: false,
+ showViewValueModal: false,
newRollup: null,
newDimensionMode: null,
+ str: '',
// welcome
overlordModules: null,
@@ -426,6 +432,7 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
{step === 'loading' && this.renderLoading()}
{this.renderResetConfirm()}
+ {this.renderViewValueModal()}
</div>
);
}
@@ -539,6 +546,14 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
);
}
+ renderViewValueModal() {
+ const { showViewValueModal, str } = this.state;
+ if (!showViewValueModal) return null;
+ return (
+ <ShowValueDialog onClose={() => this.setState({ showViewValueModal: false })} str={str} />
+ );
+ }
+
renderWelcomeStepMessage() {
const { selectedComboType } = this.state;
@@ -970,6 +985,7 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
)}
</div>
<ParseDataTable
+ openModal={str => this.setState({ showViewValueModal: true, str: str })}
sampleData={parserQueryState.data}
columnFilter={columnFilter}
canFlatten={canFlatten}
diff --git a/web-console/src/views/load-data-view/parse-data-table/parse-data-table.spec.tsx b/web-console/src/views/load-data-view/parse-data-table/parse-data-table.spec.tsx
index c3267f1..4977955 100644
--- a/web-console/src/views/load-data-view/parse-data-table/parse-data-table.spec.tsx
+++ b/web-console/src/views/load-data-view/parse-data-table/parse-data-table.spec.tsx
@@ -35,6 +35,7 @@ describe('parse data table', () => {
const parseDataTable = (
<ParseDataTable
+ openModal={() => null}
sampleData={sampleData}
columnFilter=""
canFlatten={false}
diff --git a/web-console/src/views/load-data-view/parse-data-table/parse-data-table.tsx b/web-console/src/views/load-data-view/parse-data-table/parse-data-table.tsx
index 0045d29..0cee551 100644
--- a/web-console/src/views/load-data-view/parse-data-table/parse-data-table.tsx
+++ b/web-console/src/views/load-data-view/parse-data-table/parse-data-table.tsx
@@ -34,6 +34,7 @@ export interface ParseDataTableProps extends React.Props<any> {
flattenedColumnsOnly: boolean;
flattenFields: FlattenField[];
onFlattenFieldSelect: (field: FlattenField, index: number) => void;
+ openModal: (str: string) => void;
}
export class ParseDataTable extends React.PureComponent<ParseDataTableProps> {
@@ -77,7 +78,7 @@ export class ParseDataTable extends React.PureComponent<ParseDataTableProps> {
if (row.original.unparseable) {
return <TableCell unparseable />;
}
- return <TableCell value={row.value} />;
+ return <TableCell value={row.value} openModal={str => this.props.openModal(str)} />;
},
headerClassName: classNames({
flattened: flattenField,
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@druid.apache.org
For additional commands, e-mail: commits-help@druid.apache.org