Skip to content

AttributesSelector #226

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

Draft
wants to merge 14 commits into
base: master
Choose a base branch
from
Draft
15 changes: 15 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "pwa-chrome",
"request": "launch",
"name": "Launch Chrome against localhost",
"url": "http://localhost:8080",
"webRoot": "${workspaceFolder}/react/"
}
]
}
34 changes: 33 additions & 1 deletion react/src/demo/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,12 @@
import { Button } from "@material-ui/core";
import React from "react";

import { WebvizPluginPlaceholder, SmartNodeSelector, Dialog } from "../lib";
import {
WebvizPluginPlaceholder,
SmartNodeSelector,
Dialog,
AttributesSelector,
} from "../lib";

const steps = [
{
Expand Down Expand Up @@ -46,6 +51,8 @@ const App: React.FC = () => {

const [dialogOpen, setDialogOpen] = React.useState<boolean>(false);

const [selectedObjects, setSelectedObjects] = React.useState<string[]>([]);

return (
<div>
{currentPage.url.split("#")[1] === "dialog" && (
Expand Down Expand Up @@ -102,6 +109,31 @@ const App: React.FC = () => {
/>
</>
)}

<>
<h1>AttributesSelector</h1>
<AttributesSelector
id={"attributes-selector"}
selectionData={[
{
name: "Well 1",
attributes: {
Zone: ["A", "B", "C"],
},
},
{
name: "Well 2",
attributes: {
Region: ["1", "2", "3"],
Zone: ["A", "B", "C"],
},
},
]}
setProps={(p) => setSelectedObjects(p.selectedObjects)}
/>
<br />
Selected objects: {selectedObjects.join(", ")}
</>
{currentPage.url.split("#")[1] === "smart-node-selector" && (
<>
<h1>SmartNodeSelector</h1>
Expand Down
Empty file.
141 changes: 141 additions & 0 deletions react/src/lib/components/AttributesSelector/attributes-selector.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
import React from "react";

import { AttributeSelector } from "./components";
import { SelectionObjects, Attribute } from "./types";

type ParentProps = {
selectedObjects: string[];
};

export type AttributesSelectorProps = {
id: string;
selectionData: SelectionObjects[];
setProps?: (props: ParentProps) => void;
};

export const AttributesSelector: React.FC<AttributesSelectorProps> = (
props
) => {
const [attributes, setAttributes] = React.useState<Attribute[]>([]);
const [selectedAttributeValues, setSelectedAttributeValues] =
React.useState<{ attributeName: string; values: string[] }[]>([]);

React.useEffect(() => {
const attr: {
name: string;
values: Set<string>;
}[] = [];
props.selectionData.forEach((object) => {
Object.keys(object.attributes).forEach((attributeName) => {
if (!attr.some((el) => el.name === attributeName)) {
attr.push({
name: attributeName,
values: new Set<string>(),
});
}

const attribute = attr.find((el) => el.name === attributeName);
if (!attribute) {
return;
}

if (Array.isArray(object.attributes[attributeName])) {
(object.attributes[attributeName] as string[]).forEach(
(el) => attribute.values.add(el)
);
} else {
attribute.values.add(
object.attributes[attributeName] as string
);
}
});
});

attr.forEach((attrEl) => {
props.selectionData.every((object) => {
if (!Object.keys(object.attributes).includes(attrEl.name)) {
attrEl.values.add("Undefined");
return false;
}
return true;
});
});

setAttributes(
attr.map((el) => ({ name: el.name, values: Array.from(el.values) }))
);
}, [props.selectionData]);

const handleSelectedValuesChanged = (
attributeName: string,
values: string[]
) => {
if (
selectedAttributeValues.some(
(el) => el.attributeName === attributeName
)
) {
setSelectedAttributeValues(
selectedAttributeValues.map((el) =>
el.attributeName === attributeName
? { attributeName: attributeName, values: values }
: el
)
);
} else {
setSelectedAttributeValues([
...selectedAttributeValues,
{ attributeName: attributeName, values: values },
]);
}
};

React.useEffect(() => {
if (!props.setProps) {
return;
}
let selectedObjects: string[] = [];
selectedAttributeValues.forEach((selectedAttribute, index) => {
props.selectionData.forEach((object) => {
const attributeName = Object.keys(object.attributes).find(
(el) => el === selectedAttribute.attributeName
);
let check = false;
if (attributeName) {
if (
selectedAttribute.values.some((el) =>
object.attributes[attributeName].includes(el)
)
) {
check = true;
}
} else if (selectedAttribute.values.includes("Undefined")) {
check = true;
}
if (check && index === 0) {
selectedObjects.push(object.name);
} else if (!check && selectedObjects.includes(object.name)) {
selectedObjects = selectedObjects.filter(
(el) => el !== object.name
);
}
});
});
props.setProps({ selectedObjects: selectedObjects });
}, [selectedAttributeValues]);

return (
<div className="WebvizAttributesSelector">
{attributes.map((attribute, index) => (
<AttributeSelector
id={`${props.id}-${attribute.name}`}
key={`AttributeSelector-${index}`}
attribute={attribute}
onValuesChange={(values: string[]) =>
handleSelectedValuesChanged(attribute.name, values)
}
/>
))}
</div>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
.WebvizAttributeSelector {
position: relative;
}

.WebvizAttributeSelector__Header {
display: flex;
flex-direction: row;
margin-top: 16px;
}

.WebvizAttributeSelector__Header > label {
flex-grow: 4;
margin-bottom: 8px;
font-weight: bold;
}

.WebvizAttributeSelector__Content {
background-color: #f9f9f9;
min-height: 40px;
border: 1px #ccc solid;
border-radius: 4px;
display: flex;
cursor: text;
margin: 0;
padding: 0;
list-style: none;
}

.WebvizAttributeSelector__Content--expanded {
border-bottom-left-radius: 0px;
border-bottom-right-radius: 0px;
}

.WebvizAttributeSelector__Content input {
background: transparent;
border: none;
outline: none;
padding: 8px;
position: relative;
z-index: 11;
display: block;
}

.WebvizAttributeSelector__Dialog__Highlight {
border: 1px rgb(157, 0, 0) solid;
display: inline-block;
flex-wrap: wrap;
border-radius: 4px;
justify-content: left;
align-items: center;
color: #565656;
border-radius: 4px;
white-space: nowrap;
padding: 4px;
padding-left: 8px;
padding-right: 8px;
margin: 4px;
background-color: #fefefe;
}
Loading