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

GUI updates and styles #76

Merged
merged 83 commits into from
May 26, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
83 commits
Select commit Hold shift + click to select a range
72fb417
Merge branch 'detections' of github.com:voxel51/fiftyone into detections
benjaminpkane May 13, 2020
85dd6ea
Merge branch 'remote-sessions' into detections
benjaminpkane May 13, 2020
3d06180
getting rid of react gallery
benjaminpkane May 14, 2020
fdf80af
adding back in selection
benjaminpkane May 14, 2020
65aa846
click -> selected, double click -> expand image detail
benjaminpkane May 14, 2020
87943df
hacking player51, trying to make it responsive
benjaminpkane May 14, 2020
65ec6b7
working p51, needs cleanup
benjaminpkane May 15, 2020
c2910f0
refactor Samples
benjaminpkane May 15, 2020
9908e03
more refactoring
benjaminpkane May 15, 2020
f51035f
p51 in sample detail
benjaminpkane May 15, 2020
22a1690
debugging
benjaminpkane May 15, 2020
f88213c
adding player51 as a submodule
benjaminpkane May 15, 2020
69851d6
update player51
benjaminpkane May 15, 2020
3415e3f
Merge branch 'develop' into detections
benjaminpkane May 15, 2020
1200fb5
setting up parsers for p51
benjaminpkane May 15, 2020
567315e
image attribute and bbox support
benjaminpkane May 15, 2020
f3e77fe
include group in bbox label
benjaminpkane May 15, 2020
ec5ba99
making sidebar visibile when not connected
benjaminpkane May 18, 2020
dae9b31
working themes!
benjaminpkane May 18, 2020
96d064e
Palanquin
benjaminpkane May 18, 2020
c01c5ba
figuring out definitions
benjaminpkane May 18, 2020
ae4c4d1
defining variables, overriding where necessary
benjaminpkane May 18, 2020
ddf585e
chasing down style variables
benjaminpkane May 18, 2020
18f6710
getting there
benjaminpkane May 18, 2020
49754f0
fixing sidebar colors:
benjaminpkane May 18, 2020
2a3bef3
adding basic logo
benjaminpkane May 18, 2020
5ac9252
improve selected borders
benjaminpkane May 18, 2020
c205589
maintain selection state from server
benjaminpkane May 18, 2020
fef1569
smaller single click delay
benjaminpkane May 18, 2020
5404ab7
fix key warnings, labels -> fields
benjaminpkane May 18, 2020
e7dce17
styling modal
benjaminpkane May 18, 2020
5d66455
merge
benjaminpkane May 19, 2020
b537dc8
more styling
benjaminpkane May 19, 2020
a0669c4
more styles
benjaminpkane May 19, 2020
971d24f
Merge branch 'views-and-labels-and-insights-oh-my' into instructions
benjaminpkane May 19, 2020
efc3ffa
cleaning
benjaminpkane May 19, 2020
a113446
ensure active tab is set
benjaminpkane May 19, 2020
b1a6844
loader styles
benjaminpkane May 19, 2020
895da01
Merge branch 'packaging' into instructions
benjaminpkane May 19, 2020
b20d3e0
updating instructions
benjaminpkane May 19, 2020
89b9149
actually update instructions
benjaminpkane May 19, 2020
99045ca
fixing spacing
benjaminpkane May 19, 2020
42af910
match headers
benjaminpkane May 19, 2020
1d8b63e
fluid container
benjaminpkane May 19, 2020
c0dfec6
debugging/cleaning up routing
benjaminpkane May 19, 2020
833c80b
merge
benjaminpkane May 19, 2020
0c9c60f
merge
benjaminpkane May 19, 2020
faa7c6c
remove hasDataset check
benjaminpkane May 19, 2020
3980e2c
working through the new data model
benjaminpkane May 20, 2020
72513f8
remove logging
benjaminpkane May 20, 2020
fdd0db8
sticky nav padding
benjaminpkane May 20, 2020
6b653ce
Merge branch 'views-and-labels-and-insights-oh-my' into instructions
benjaminpkane May 20, 2020
372a95a
update parsing
benjaminpkane May 20, 2020
1c7575c
update field charts
benjaminpkane May 20, 2020
1dca7a1
rm loggin
benjaminpkane May 20, 2020
f0a4fe2
making thumbnails cards
benjaminpkane May 20, 2020
a1fb31a
sizing cleanup
benjaminpkane May 20, 2020
f10c90c
quick and dirty thumbnail styles
benjaminpkane May 20, 2020
a3bb2e0
removing search bar for now
benjaminpkane May 20, 2020
df94731
adding responsive behavior
benjaminpkane May 20, 2020
f9e191a
removing stage
benjaminpkane May 20, 2020
fbbb6df
Merge branch 'views-and-labels-and-insights-oh-my' into instructions
benjaminpkane May 20, 2020
7e302bd
neat hover styles
benjaminpkane May 20, 2020
71d70b1
tweak
benjaminpkane May 20, 2020
1a48ef7
Merge branch 'views-and-labels-and-insights-oh-my' into instructions
tylerganter May 20, 2020
62df0d4
init player51 in install script
benjaminpkane May 20, 2020
2a04553
add player51 install steps
benjaminpkane May 20, 2020
5acef0b
Merge branch 'instructions' of github.com:voxel51/fiftyone into instr…
benjaminpkane May 20, 2020
8e1bf84
Merge branch 'develop' into instructions
benjaminpkane May 20, 2020
6e81dd6
Merge branch 'sample-singletons' into instructions
benjaminpkane May 20, 2020
e1a6b23
cleaning up listing
benjaminpkane May 21, 2020
e35c78b
show more info
benjaminpkane May 21, 2020
1370438
style tweak
benjaminpkane May 21, 2020
9961f70
move setting to sidaebar
benjaminpkane May 21, 2020
9b63761
simplify player51 install
benjaminpkane May 21, 2020
4e10224
Merge branch 'sample-copy-bugfix' into instructions
benjaminpkane May 21, 2020
70afb22
Merge branch 'develop' into instructions
benjaminpkane May 21, 2020
0386ddb
use atexit for server service
benjaminpkane May 21, 2020
5623999
fix handler
benjaminpkane May 21, 2020
94c9906
update player15
benjaminpkane May 21, 2020
1466229
Merge branch 'packaging' into instructions
May 22, 2020
2e9e927
Merge branch 'develop' into instructions
May 24, 2020
9128e6b
Adjust BrowserWindow preferences to fix prod build
May 26, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "electron/app/player51"]
path = electron/app/player51
url = git@github.com:voxel51/player51.git
6 changes: 3 additions & 3 deletions electron/app/Routes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ export default function Routes() {
<Switch>
<Route path={routes.LOADING} exact component={Loading} />
<Route path={routes.SETUP} exact component={Setup} />
<Route path={routes.DATASET} exact component={Dataset} />
<Route path={routes.LIST} exact component={Dataset} />
<Route path={routes.CHARTS} exact component={Dataset} />
<Route path={routes.SAMPLES} exact component={Dataset} />
<Route path={routes.FIELDS} exact component={Dataset} />
<Route path={routes.DATASET} component={Dataset} />
</Switch>
</App>
);
Expand Down
49 changes: 46 additions & 3 deletions electron/app/app.global.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,11 @@
* @NOTE: Prepend a `~` to css file paths that are in your node_modules
* See https://github.com/webpack-contrib/sass-loader#imports
*/
@import "~semantic-ui-css/semantic.min.css";
@import "./player51/src/css/player51.css";

body {
position: relative;
color: black;
height: 100vh;
background-color: white;
}

#root {
Expand All @@ -22,3 +20,48 @@ body {
.search > .ui.input {
width: 100%;
}

.sample {
position: relative;
}

.sample-info {
position: absolute;
width: 100%;
top: 0;
height: 100%;
display: block;
z-index: 100;
overflow-y: hidden;
}

.sample:hover > .sample-info {
top: 100%;
height: auto;
}

.sample-info > .menu {
background: hsla(210, 20%, 23%, 0.6) !important;
}

.sample-info > .menu > .item {
white-space: nowrap;
overflow-x: hidden;
}

.sample:not(:hover) .sample-info > .menu > .item:before {
background: none !important;
}

.sample:hover > .sample-info > .menu > .item {
overflow-x: auto;
}

.sample:hover > .sample-info {
background: hsla(210, 20%, 23%, 1);
z-index: 101;
}

.hide-info .sample:not(:hover) .sample-info {
display: none !important;
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import connect from "../utils/connect";

class CustomizedAxisTick extends PureComponent {
render() {
const { x, y, stroke, payload } = this.props;
const { x, y, stroke, payload, fill } = this.props;

return (
<g transform={`translate(${x},${y})`}>
Expand All @@ -17,7 +17,7 @@ class CustomizedAxisTick extends PureComponent {
y={0}
dy={16}
textAnchor="end"
fill="#666"
fill={fill}
transform="rotate(-80)"
>
{payload.value}
Expand All @@ -31,14 +31,16 @@ const Histogram = connect(({ data, name }) => {
const barWidth = 30;
const [rightMargin, setRightMargin] = useState(0);
const container = useRef(null);
const stroke = "hsl(210, 20%, 90%)";
const fill = stroke;

return (
<Segment style={{ overflowY: "auto" }}>
<Header as="h3">{name}</Header>
<BarChart
ref={container}
height={500}
width={data.length * (barWidth + 20)}
width={data.length * (barWidth + 20 + 36.5)}
barCategoryGap={"20px"}
data={data}
margin={{ top: 0, left: 0, bottom: 0, right: rightMargin + 5 }}
Expand All @@ -47,11 +49,17 @@ const Histogram = connect(({ data, name }) => {
dataKey="label"
type="category"
interval={0}
height={150}
height={100}
axisLine={false}
tick={<CustomizedAxisTick />}
tick={<CustomizedAxisTick {...{ fill }} />}
tickLine={{ stroke }}
/>
<YAxis
dataKey="count"
axisLine={false}
tick={{ fill }}
tickLine={{ stroke }}
/>
<YAxis dataKey="count" axisLine={false} />
<Bar dataKey="count" fill="rgb(255, 109, 4)" barSize={barWidth} />
</BarChart>
</Segment>
Expand All @@ -60,14 +68,13 @@ const Histogram = connect(({ data, name }) => {

const Charts = (props) => {
const { state, port } = props;
const hasDataset = Boolean(state && state.dataset);
const socket = getSocket(port, "state");
const [initialLoad, setInitialLoad] = useState(true);
const [loading, setLoading] = useState(true);
const [data, setData] = useState([]);

const getData = () => {
socket.emit("get_label_distributions", "", (data) => {
socket.emit("get_field_distributions", "", (data) => {
setInitialLoad(false);
setLoading(false);
setData(data);
Expand All @@ -86,10 +93,11 @@ const Charts = (props) => {
if (loading) {
return <Loader />;
}

return (
<>
{data.map((chart) => {
return <Histogram data={chart.labels} name={chart._id} />;
{data.map((chart, i) => {
return <Histogram key={i} data={chart.labels} name={chart._id} />;
})}
</>
);
Expand Down
8 changes: 8 additions & 0 deletions electron/app/components/InfoItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import React from "react";
import { Menu } from "semantic-ui-react";

export default ({ k, v }) => (
<Menu.Item as="span">
{k} &middot; <code>{v}</code>
</Menu.Item>
);
17 changes: 17 additions & 0 deletions electron/app/components/LocalInstructions.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import React from "react";
import { Header, Divider } from "semantic-ui-react";

import CodeBlock from "./CodeBlock";
import pySnippet from "../snippets/local.py";

export default () => (
<>
<Header as="h3">Local sessions</Header>
<Divider />
<p>
The following demonstrates how to connect to a local session from a python
shell.
</p>
<CodeBlock language="python">{pySnippet}</CodeBlock>
</>
);
81 changes: 81 additions & 0 deletions electron/app/components/Player51.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import _ from "lodash";
import React, { useState, useEffect } from "react";
import Player51 from "../player51/build/cjs/player51.min.js";

import clickHandler from "../utils/click.ts";

const PARSERS = {
Classification: [
"attrs",
(name, obj) => {
return {
type: "eta.core.data.CategoricalAttribute",
name: name,
confidence: obj.confidence,
value: obj.label,
};
},
],
Detection: [
"objects",
(g, obj) => {
const bb = obj.bounding_box;
return {
type: "eta.core.objects.DetectedObject",
label: `${g}:${obj.label}`,
confidence: obj.confidence,
bounding_box: {
top_left: { x: bb[0], y: bb[1] },
bottom_right: { x: bb[0] + bb[2], y: bb[1] + bb[3] },
},
};
},
],
};

const loadOverlay = (sample) => {
const imgLabels = { attrs: { attrs: [] }, objects: { objects: [] } };
for (const i in sample) {
if (_.indexOf(["metadata", "_id", "tags", "filepath"], i) >= 0) {
continue;
}
const field = sample[i];
if (field._cls === "Detections") {
for (const j in field.detections) {
const detection = field.detections[j];
const [key, fn] = PARSERS[detection._cls];
imgLabels[key][key].push(fn(i, detection));
}
continue;
}
const [key, fn] = PARSERS[field._cls];
imgLabels[key][key].push(fn(i, field));
}
return imgLabels;
};

export default ({ thumbnail, sample, src, style, onClick, onDoubleClick }) => {
const overlay = loadOverlay(sample);
const id = sample._id.$oid;

const [handleClick, handleDoubleClick] = clickHandler(onClick, onDoubleClick);
const [player, setPlayer] = useState(
new Player51({
media: {
src: src,
type: "image/jpg",
},
overlay: overlay,
})
);
const props = thumbnail
? { onClick: handleClick, onDoubleClick: handleDoubleClick }
: {};
useEffect(() => {
if (thumbnail) {
player.thumbnailMode();
}
player.render(id);
}, []);
return <div id={id} style={style} {...props} />;
};
1 change: 0 additions & 1 deletion electron/app/components/PortForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { Input, Label } from "semantic-ui-react";

import connect from "../utils/connect";
import { getSocket, useSubscribe } from "../utils/socket";
import CodeBlock from "./CodeBlock";

export default connect(({ connected, port, setResult }) => {
const [initialState, setInitialState] = useState({ port, connected });
Expand Down
30 changes: 30 additions & 0 deletions electron/app/components/RemoteInstructions.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import React from "react";
import { Header, Divider } from "semantic-ui-react";

import CodeBlock from "./CodeBlock";
import bashSnippet from "../snippets/remote.bash";
import pySnippet from "../snippets/remote.py";

export default () => (
<>
<Header as="h3">Remote sessions</Header>
<Divider />
<p>
If you would like to connect to a remote session, you'll have to configure
port forwarding on your local machine.
</p>
<Header as="h4">On your remote machine</Header>
<Divider />
<CodeBlock language="python">{pySnippet}</CodeBlock>
<Header as="h4">On your local machine</Header>
<Divider />
<CodeBlock language="bash">{bashSnippet}</CodeBlock>

<Header as="h4">Port configuration</Header>
<Divider />
<p>
The default FiftyOne port is <code>5151</code>. You can configure at
anytime using the settings tab.
</p>
</>
);
72 changes: 72 additions & 0 deletions electron/app/components/Sample.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import React, { useState, useEffect } from "react";
import { Menu } from "semantic-ui-react";

import { updateState } from "../actions/update";
import InfoItem from "./InfoItem";
import Player51 from "./Player51";
import { getSocket } from "../utils/socket";
import connect from "../utils/connect";

const Sample = ({ dispatch, sample, port, setSelected, selected, setView }) => {
const host = `http://127.0.0.1:${port}`;
const src = `${host}?path=${sample.filepath}`;
const socket = getSocket(port, "state");
const id = sample._id.$oid;
const s = sample;

const handleClick = () => {
const newSelected = { ...selected };
const event = newSelected[id] ? "remove_selection" : "add_selection";
newSelected[id] = newSelected[id] ? false : true;
setSelected(newSelected);
socket.emit(event, id, (data) => {
dispatch(updateState(data));
});
};

return (
<div
className="sample"
style={{
marginTop: selected[id] ? 0 : "2px",
border: selected[id] ? "2px solid rgb(255, 109, 4)" : "none",
}}
>
<Player51
src={src}
style={{
width: "100%",
position: "relative",
}}
sample={sample}
onClick={() => handleClick()}
onDoubleClick={() => setView({ visible: true, sample })}
thumbnail={true}
/>
<div className="sample-info">
<Menu vertical style={{ width: "100%", height: "100%" }}>
<InfoItem k="id" v={s._id.$oid} />
<InfoItem k="filepath" v={s.filepath} />
<InfoItem k="tags" v={JSON.stringify(s.tags, 2)} />
<InfoItem k="metadata" v={JSON.stringify(s.metadata, 2)} />
{Object.keys(s).map((k, i) => {
if (s[k] && s[k]._cls === "Classification") {
return <InfoItem key={i} k={k} v={s[k].label} />;
} else if (s[k] && s[k]._cls === "Detections") {
const l = s[k].detections.length;
return (
<InfoItem
key={i}
k={k}
v={`${l} detection${l === 1 ? "" : "s"}`}
/>
);
}
})}
</Menu>
</div>
</div>
);
};

export default connect(Sample);