Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
24 changes: 24 additions & 0 deletions src/components/BrowserCell/BrowserCell.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,28 @@ export default class BrowserCell extends Component {
menuItems.length && setContextMenu(pageX, pageY, menuItems);
}

onMouseMove(event) {
this.props.setDataForPreview();

const { pageX, pageY } = event;
clearTimeout(this.hoverTimer);

this.hoverTimer = setTimeout(() => {
this.props.setDataForPreview({
value: this.copyableValue,
type: this.props.type,
pageX,
pageY,
});
}, 400);
}

onMouseOut() {
clearTimeout(this.hoverTimer);
delete this.hoverTimer;
this.props.setDataForPreview();
}

getContextMenuOptions(constraints) {
let { onEditSelectedRow, readonly } = this.props;
const contextMenuOptions = [];
Expand Down Expand Up @@ -459,6 +481,8 @@ export default class BrowserCell extends Component {
}
}}}
onContextMenu={this.onContextMenu.bind(this)}
onMouseMove={this.onMouseMove.bind(this)}
onMouseOut={this.onMouseOut.bind(this)}
>
{this.state.content}
</span>
Expand Down
3 changes: 2 additions & 1 deletion src/components/BrowserRow/BrowserRow.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export default class BrowserRow extends Component {
}

render() {
const { className, columns, currentCol, isUnique, obj, onPointerClick, onPointerCmdClick, order, readOnlyFields, row, rowWidth, selection, selectRow, setCopyableValue, setCurrent, setEditing, setRelation, onEditSelectedRow, setContextMenu, onFilterChange, markRequiredFieldRow } = this.props;
const { className, columns, currentCol, isUnique, obj, onPointerClick, onPointerCmdClick, order, readOnlyFields, row, rowWidth, selection, selectRow, setCopyableValue, setCurrent, setEditing, setRelation, onEditSelectedRow, setContextMenu, setDataForPreview, onFilterChange, markRequiredFieldRow } = this.props;
let attributes = obj.attributes;
let requiredCols = [];
Object.entries(columns).reduce((acc, cur) => {
Expand Down Expand Up @@ -100,6 +100,7 @@ export default class BrowserRow extends Component {
markRequiredFieldRow={markRequiredFieldRow}
setCopyableValue={setCopyableValue}
setContextMenu={setContextMenu}
setDataForPreview={setDataForPreview}
onEditSelectedRow={onEditSelectedRow} />
);
})}
Expand Down
64 changes: 64 additions & 0 deletions src/components/DataPreview/DataPreview.react.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import React, { useEffect, useState } from "react";
import PropTypes from "lib/PropTypes";
import Popover from "components/Popover/Popover.react";
import StringDataHandler from "./StringDataHandler";
import PointerDataHandler from "./PointerDataHandler";
import ObjectDataHandler from "./ObjectDataHandler";

const DATA_HANDLERS = {
String: StringDataHandler,
Pointer: PointerDataHandler,
Object: ObjectDataHandler,
};

function DataPreview({ data }) {
const [dataComponent, setDataComponent] = useState();

async function handleData(type, value) {
const dataHandler = DATA_HANDLERS[type];
if (!dataHandler) {
return;
}
const dataComponent = await dataHandler(value);
setDataComponent(dataComponent);
}

useEffect(() => {
dataComponent && setDataComponent();
if (!data) {
return;
}

handleData(data.type, data.value);
}, [JSON.stringify(data)]);

if (!dataComponent) {
return null;
}

return (
<Popover
fadeIn={true}
fixed={true}
position={{
x: data?.pageX,
y: data?.pageY,
}}
color="rgba(17,13,17,0.8)"
style={{ pointerEvents: "none" }}
>
{dataComponent}
</Popover>
);
}

DataPreview.propTypes = {
data: PropTypes.shape({
value: PropTypes.any.isRequired,
type: PropTypes.string.isRequired,
pageX: PropTypes.number,
pageY: PropTypes.number,
}),
};

export default DataPreview;
4 changes: 4 additions & 0 deletions src/components/DataPreview/ObjectDataHandler.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export default async function (value) {
// TODO: show whole object in a readable way
// <CodeSnippet> component might be useful here
}
3 changes: 3 additions & 0 deletions src/components/DataPreview/PointerDataHandler.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default async function (value) {
// TODO: fetch data from Pointer and present it in a nice way
}
40 changes: 40 additions & 0 deletions src/components/DataPreview/StringDataHandler.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import React from "react";

function isValidHttpUrl(string) {
let url;
try {
url = new URL(string);
} catch (_) {
return false;
}

return url.protocol === "http:" || url.protocol === "https:";
}

async function loadImage(url) {
return new Promise((resolve) => {
const testImage = new Image();
testImage.onerror = () => resolve();
testImage.onload = function (event) {
const { width, height } = event?.currentTarget;
const style = {};
if (width >= height) {
style.width = window.innerWidth / 3;
} else {
style.height = window.innerHeight / 3;
}
const imageComponent = <img style={style} src={url} />;
resolve(imageComponent);
};
testImage.src = url;
});
}

export default async function (value) {
if (isValidHttpUrl(value)) {
return loadImage(value);
}

// TODO: return paragraoh with value inside, set styles for element to fit the view
// return <p>{value}</p>
}
16 changes: 14 additions & 2 deletions src/components/Popover/Popover.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ export default class Popover extends React.Component {
this._checkExternalClick = this._checkExternalClick.bind(this);

this._popoverLayer = document.createElement('div');
if (props.style) {
this._popoverLayer.style = props.style;
}
}

componentDidUpdate(prevState) {
Expand All @@ -41,8 +44,17 @@ export default class Popover extends React.Component {
this._popoverWrapper.appendChild(this._popoverLayer);

if (this.props.position) {
this._popoverLayer.style.left = this.props.position.x + 'px';
this._popoverLayer.style.top = this.props.position.y + 'px';
// Fix position if Popover goes off the screen
this._popoverLayer.style.left =
Math.min(
this.props.position.x,
window.innerWidth - this._popoverLayer.clientWidth
) + 'px';
this._popoverLayer.style.top =
Math.min(
this.props.position.y,
window.innerHeight - this._popoverLayer.clientHeight
) + 'px';
}
if (this.props.modal) {
this._popoverLayer.style.right = 0;
Expand Down
3 changes: 3 additions & 0 deletions src/dashboard/Data/Browser/BrowserTable.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ export default class BrowserTable extends React.Component {
setRelation={this.props.setRelation}
setCopyableValue={this.props.setCopyableValue}
setContextMenu={this.props.setContextMenu}
setDataForPreview={this.props.setDataForPreview}
onEditSelectedRow={this.props.onEditSelectedRow}
markRequiredFieldRow={this.props.markRequiredFieldRow}
/>
Expand Down Expand Up @@ -206,6 +207,7 @@ export default class BrowserTable extends React.Component {
setRelation={this.props.setRelation}
setCopyableValue={this.props.setCopyableValue}
setContextMenu={this.props.setContextMenu}
setDataForPreview={this.props.setDataForPreview}
onEditSelectedRow={this.props.onEditSelectedRow}
markRequiredFieldRow={this.props.markRequiredFieldRow}
/>
Expand Down Expand Up @@ -264,6 +266,7 @@ export default class BrowserTable extends React.Component {
setRelation={this.props.setRelation}
setCopyableValue={this.props.setCopyableValue}
setContextMenu={this.props.setContextMenu}
setDataForPreview={this.props.setDataForPreview}
onEditSelectedRow={this.props.onEditSelectedRow} />
}

Expand Down
8 changes: 8 additions & 0 deletions src/dashboard/Data/Browser/DataBrowser.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import copy from 'copy-to-clipboard';
import BrowserTable from 'dashboard/Data/Browser/BrowserTable.react';
import BrowserToolbar from 'dashboard/Data/Browser/BrowserToolbar.react';
import ContextMenu from 'components/ContextMenu/ContextMenu.react';
import DataPreview from 'components/DataPreview/DataPreview.react';
import * as ColumnPreferences from 'lib/ColumnPreferences';
import React from 'react';

Expand Down Expand Up @@ -44,6 +45,7 @@ export default class DataBrowser extends React.Component {
this.handleColumnsOrder = this.handleColumnsOrder.bind(this);
this.setCopyableValue = this.setCopyableValue.bind(this);
this.setContextMenu = this.setContextMenu.bind(this);
this.setDataForPreview = this.setDataForPreview.bind(this);

this.saveOrderTimeout = null;
}
Expand Down Expand Up @@ -290,6 +292,10 @@ export default class DataBrowser extends React.Component {
this.setState({ contextMenuX, contextMenuY, contextMenuItems });
}

setDataForPreview(dataForPreview) {
this.setState({ dataForPreview });
}

handleColumnsOrder(order, shouldReload) {
this.setState({ order: [...order] }, () => {
this.updatePreferences(order, shouldReload);
Expand All @@ -315,6 +321,7 @@ export default class DataBrowser extends React.Component {
setCurrent={this.setCurrent}
setCopyableValue={this.setCopyableValue}
setContextMenu={this.setContextMenu}
setDataForPreview={this.setDataForPreview}
onFilterChange={this.props.onFilterChange}
{...other} />
<BrowserToolbar
Expand All @@ -340,6 +347,7 @@ export default class DataBrowser extends React.Component {
y={this.state.contextMenuY}
items={this.state.contextMenuItems}
/>}
<DataPreview data={this.state.dataForPreview} />
</div>
);
}
Expand Down