Commit 6b1abd6a authored by alain's avatar alain 🐙
Browse files

fix safari bug / add modal with meta data in vis mode

parent 6a5bc3ac
import React from "react";
class Modal extends React.Component {
constructor(props) {
super()
this.state = {}
this.handleKeydown = this.handleKeydown.bind(this)
}
handleKeydown(event){
if(event.keyCode === 27) {
this.props.closeModal()
}
}
componentDidMount(){
this.mountTime = + new Date()
document.addEventListener("keydown", this.handleKeydown, false)
}
componentWillUnmount(){
document.removeEventListener("keydown", this.handleKeydown, false)
}
render() {
const closeModal = this.props.closeModal
return (
<div className="modal" onClick={event => {
// Prevent closing on double click / touch devices (it's registering a click event for some reason..)
if(+ new Date() - this.mountTime > 300) closeModal(event)
}}>
<div className="content" onClick={event => { event.stopPropagation() }}>
<button className="button-close" onClick={event => closeModal(event)}>×</button>
{this.props.children}
</div>
</div>
)
}
}
export default Modal
\ No newline at end of file
import React, { useRef, useEffect } from 'react' import React, { useRef, useState, useEffect } from 'react'
import * as d3 from 'd3' import * as d3 from 'd3'
import Modal from './Modal'
export default function Vis(props) { export default function Vis(props) {
const width = document.getElementById('databronnen').clientWidth const width = document.getElementById('databronnen').clientWidth
const height = document.getElementById('databronnen').clientHeight const height = document.getElementById('databronnen').clientHeight
...@@ -11,10 +13,11 @@ export default function Vis(props) { ...@@ -11,10 +13,11 @@ export default function Vis(props) {
const focus = useRef(null); const focus = useRef(null);
const root = useRef(null); const root = useRef(null);
const svgRef = useRef(null); const svgRef = useRef(null);
const [modalContent, setModalContent] = useState(null);
useEffect(() => { useEffect(() => {
init() init()
}) }, [])
function init() { function init() {
const pack = d3.pack().size([diameter - margin, diameter - margin]).padding(4); const pack = d3.pack().size([diameter - margin, diameter - margin]).padding(4);
...@@ -38,7 +41,7 @@ export default function Vis(props) { ...@@ -38,7 +41,7 @@ export default function Vis(props) {
if(d.children) { if(d.children) {
if (focus.current !== d) zoom(d); if (focus.current !== d) zoom(d);
} else { } else {
window.open(d.data.url, '_blank'); setModalContent({ ...d.data })
} }
event.stopPropagation(); event.stopPropagation();
}); });
...@@ -49,7 +52,7 @@ export default function Vis(props) { ...@@ -49,7 +52,7 @@ export default function Vis(props) {
.attr("class", function(d) { return d.children ? "theme" : "source"; }) .attr("class", function(d) { return d.children ? "theme" : "source"; })
.attr("width", "110") .attr("width", "110")
.attr("height", "110") .attr("height", "110")
.html(function(d) { return `<div>${d.data.name}</div>`}) .html(function(d) { return `<div>${d.data.titel}</div>`})
.style("display", function(d) { return d.parent === root.current ? "inline" : "none"; }) .style("display", function(d) { return d.parent === root.current ? "inline" : "none"; })
zoomTo([root.current.x, root.current.y, root.current.r * 2 + margin]); zoomTo([root.current.x, root.current.y, root.current.r * 2 + margin]);
...@@ -77,14 +80,30 @@ export default function Vis(props) { ...@@ -77,14 +80,30 @@ export default function Vis(props) {
view = v; view = v;
circle circle
.attr("class", function(d) { return focus.current.children.find(node => node.data.name === d.data.name) ? "clickable" : "" }) .attr("class", function(d) { return focus.current.children.find(node => node.data.titel === d.data.titel) ? "clickable" : "" })
.attr("r", function(d) { return (d.r + 3) * k; }) .attr("r", function(d) { return (d.r + 3) * k; })
.attr("transform", function(d) { return `translate(${(d.x - v[0]) * k},${(d.y - v[1]) * k})`; }); .attr("transform", function(d) { return `translate(${(d.x - v[0]) * k},${(d.y - v[1]) * k})`; });
text.attr("transform", function(d) { return `translate(${(d.x - v[0]) * k - 55}, ${(d.y - v[1]) * k - 55})`; }); const textX = x => (x - v[0]) * k - 55
const textY = y => (y - v[1]) * k - 55
text
.attr("transform", function(d) { return `translate(${textX(d.x)}, ${textY(d.y)})`; });
}
const closeModal = (e) => {
setModalContent(null)
} }
return( return (
<svg ref={svgRef} /> <>
<svg ref={svgRef} />
{ modalContent && <Modal closeModal={closeModal}>
<h2 style={{ margin: "0.5em 0 0.75em 0" }}>{modalContent.titel}</h2>
<table><tbody>
{ Object.keys(modalContent).filter(item => item !== "size").map(key => <tr key={key}><td>{ key }</td><td>{ key === "url" ? <a target="_blank" href={modalContent[key]} rel="noopener noreferrer">{modalContent[key]}</a> : modalContent[key] }</td></tr>) }
</tbody></table>
</Modal> }
</>
) )
} }
...@@ -243,6 +243,10 @@ $color: #00954a; ...@@ -243,6 +243,10 @@ $color: #00954a;
} }
} }
tr:last-child td {
border-bottom: none;
}
input { input {
display: block; display: block;
width: calc(100% - 1rem); width: calc(100% - 1rem);
...@@ -291,10 +295,11 @@ $color: #00954a; ...@@ -291,10 +295,11 @@ $color: #00954a;
overflow: visible; overflow: visible;
div { div {
position: absolute; display: flex;
align-items: center;
justify-content: center;
width: 100%; width: 100%;
top: 50%; height: 100%;
transform: translateY(-50%);
line-height: 1.25; line-height: 1.25;
text-align: center; text-align: center;
user-select: none; user-select: none;
...@@ -310,6 +315,93 @@ $color: #00954a; ...@@ -310,6 +315,93 @@ $color: #00954a;
} }
} }
} .modal {
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
padding: 0.5rem;
background: rgba(0, 0, 0, 0.15);
overflow: auto;
text-align: center;
z-index: 1200;
&:before {
content: "";
display: inline-block;
height: 100%;
vertical-align: middle;
}
.content {
display: inline-block;
vertical-align: middle;
position: relative;
background-color: #FFF;
box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.2);
padding: 20px 20px 0 20px;
width: 100%;
max-width: 950px;
min-height: 1rem;
text-align: left;
}
.button-close {
border: none;
background: none !important;
box-shadow: none;
color: #000;
font-size: 20px;
position: absolute;
top: 10px;
right: 10px;
padding: 0;
width: 30px;
line-height: 30px;
cursor: pointer;
transition: all 0ms ease;
&:hover {
font-size: 24px;
transition: all 100ms ease;
}
&:active {
outline: none;
}
&:after {
content: none;
}
}
h1 {
padding-right: 1rem;
}
.description {
margin-bottom: 32px;
}
table {
width: calc(100% + 40px) !important;
margin: 2rem -20px 0;
td {
vertical-align: top;
background-color: #eee;
padding: 1rem;
h4 {
margin-bottom: 0;
font-size: 0.85rem;
}
p {
font-size: 0.85rem;
}
}
}
}
}
\ No newline at end of file
...@@ -18,39 +18,30 @@ export const prepareTableData = data => { ...@@ -18,39 +18,30 @@ export const prepareTableData = data => {
export const prepareVisData = data => { export const prepareVisData = data => {
const output = { const output = {
"name": "databronnen", "titel": "databronnen",
"children": [] "children": []
} }
data.forEach(element => { data.forEach(element => {
let themeIndex = output["children"].findIndex(child => child["name"] === element["thema"]) let themeIndex = output["children"].findIndex(child => child["titel"] === element["thema"])
if(themeIndex === -1) { if(themeIndex === -1) {
output["children"].push({ "name": element["thema"], "children": [] }) output["children"].push({ "titel": element["thema"], "children": [] })
themeIndex = output["children"].findIndex(child => child["name"] === element["thema"]) themeIndex = output["children"].findIndex(child => child["titel"] === element["thema"])
} }
if(element["subthema"]) { if(element["subthema"]) {
let subthemeIndex = output["children"][themeIndex]["children"].findIndex(child => child["name"] === element["subthema"]) let subthemeIndex = output["children"][themeIndex]["children"].findIndex(child => child["titel"] === element["subthema"])
if(subthemeIndex === -1) { if(subthemeIndex === -1) {
output["children"][themeIndex]["children"].push({ "name": element["subthema"], "children": [] }) output["children"][themeIndex]["children"].push({ "titel": element["subthema"], "children": [] })
subthemeIndex = output["children"][themeIndex]["children"].findIndex(child => child["name"] === element["subthema"]) subthemeIndex = output["children"][themeIndex]["children"].findIndex(child => child["titel"] === element["subthema"])
} }
output["children"][themeIndex]["children"][subthemeIndex]["children"].push({ output["children"][themeIndex]["children"][subthemeIndex]["children"].push({ ...element, "size": 1 })
"name": element["titel"],
"size": 1,
"url": element["url"]
})
} else { } else {
output["children"][themeIndex]["children"].push({ ...element, "size": 1 })
output["children"][themeIndex]["children"].push({
"name": element["titel"],
"size": 1
})
} }
}) })
......
...@@ -2764,14 +2764,14 @@ caniuse-api@^3.0.0: ...@@ -2764,14 +2764,14 @@ caniuse-api@^3.0.0:
lodash.uniq "^4.5.0" lodash.uniq "^4.5.0"
caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30001020, caniuse-lite@^1.0.30001035: caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30001020, caniuse-lite@^1.0.30001035:
version "1.0.30001035" version "1.0.30001131"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001035.tgz#2bb53b8aa4716b2ed08e088d4dc816a5fe089a1e" resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001131.tgz"
integrity sha512-C1ZxgkuA4/bUEdMbU5WrGY4+UhMFFiXrgNAfxiMIqWgFTWfv/xsZCS2xEHT2LMq7xAZfuAnu6mcqyDl0ZR6wLQ== integrity sha512-4QYi6Mal4MMfQMSqGIRPGbKIbZygeN83QsWq1ixpUwvtfgAZot5BrCKzGygvZaV+CnELdTwD0S4cqUNozq7/Cw==
caniuse-lite@^1.0.30000929: caniuse-lite@^1.0.30000929:
version "1.0.30001123" version "1.0.30001131"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001123.tgz#7b981d81382ab2c8fd062f3e6439215e8c503c22" resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001131.tgz"
integrity sha512-03dJDoa4YC4332jq0rqwiM+Hw6tA5RJtrnZKvOQy7ASoIUv8CinkcmGhYpCvCjedvkBQrrKnkcELxrUSW/XwNQ== integrity sha512-4QYi6Mal4MMfQMSqGIRPGbKIbZygeN83QsWq1ixpUwvtfgAZot5BrCKzGygvZaV+CnELdTwD0S4cqUNozq7/Cw==
capture-exit@^2.0.0: capture-exit@^2.0.0:
version "2.0.0" version "2.0.0"
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment