npm run lint:fix

This commit is contained in:
wattroll
2022-04-06 21:40:40 +03:00
parent 24d50fd773
commit b4eb4edcae
10 changed files with 437 additions and 427 deletions

View File

@@ -11,7 +11,7 @@ export const DEFAULT_TAB_ICONS = {
NARRATIVE: "timeline",
FILTER: "filter_list",
SHAPE: "change_history",
DOWNLOAD: "download"
DOWNLOAD: "download",
};
export const AVAILABLE_SHAPES = {
@@ -25,8 +25,7 @@ export const AVAILABLE_SHAPES = {
};
export const POLYGON_CLIP_PATH = {
STAR:
"polygon(50% 0%, 61% 35%, 98% 35%, 68% 57%, 79% 91%, 50% 70%, 21% 91%, 32% 57%, 2% 35%, 39% 35%)",
STAR: "polygon(50% 0%, 61% 35%, 98% 35%, 68% 57%, 79% 91%, 50% 70%, 21% 91%, 32% 57%, 2% 35%, 39% 35%)",
DIAMOND: "polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%)",
PENTAGON: "polygon(50% 0%, 100% 38%, 82% 100%, 18% 100%, 0% 38%)",
TRIANGLE: "polygon(50% 0%, 0% 100%, 100% 100%)",

View File

@@ -161,8 +161,8 @@
"fullscreen_enter": "Fullscreen",
"fullscreen_exit": "Exit Fullscreen",
"download": {
"button": "Download",
"panel":{
"button": "Download",
"panel": {
"title": "Download events",
"description": "Export the most recent available events in different formats.",
"formats": {
@@ -175,7 +175,7 @@
"description": "JSON file where each event is a structured object containing nested arrays of sources and filters."
}
}
}
}
}
},
"timeline": {

View File

@@ -577,11 +577,14 @@ export function getFilterIdx(
}
export function downloadAsFile(filename, content) {
let element = document.createElement('a');
element.setAttribute('href', `data:application/octet-stream;charset=utf-8,${encodeURIComponent(content)}`);
element.setAttribute('download', filename);
let element = document.createElement("a");
element.setAttribute(
"href",
`data:application/octet-stream;charset=utf-8,${encodeURIComponent(content)}`
);
element.setAttribute("download", filename);
element.style.display = 'none';
element.style.display = "none";
document.body.appendChild(element);
element.click();

View File

@@ -296,34 +296,34 @@ class Toolbar extends React.Component {
<TabList>
{narrativesExist
? this.renderToolbarTab(
narrativesIdx,
panels.narratives.label,
panels.narratives.icon
)
narrativesIdx,
panels.narratives.label,
panels.narratives.icon
)
: null}
{features.USE_CATEGORIES
? this.renderToolbarCategoryTabs(categoryIdxs)
: null}
{features.USE_ASSOCIATIONS
? this.renderToolbarTab(
filtersIdx,
panels.filters.label,
panels.filters.icon
)
filtersIdx,
panels.filters.label,
panels.filters.icon
)
: null}
{features.USE_SHAPES
? this.renderToolbarTab(
shapesIdx,
panels.shapes.label,
panels.shapes.icon
)
shapesIdx,
panels.shapes.label,
panels.shapes.icon
)
: null}
{features.USE_DOWNLOAD
? this.renderToolbarTab(
downloadIdx,
panels.download.label,
panels.download.icon
)
downloadIdx,
panels.download.label,
panels.download.icon
)
: null}
{features.USE_FULLSCREEN && (
<FullscreenToggle language={this.props.language} />

View File

@@ -29,7 +29,13 @@ function BottomActions(props) {
<CoverIcon onClickHandler={props.cover.toggle} />
) : null}
</div>
<div style={{ fontSize: 9, paddingTop: 10 }}>Made with <a href="https://github.com/forensic-architecture/timemap">TimeMap</a><br />Free software from <br /> <a href="https://forensic-architecture.org">Forensic Architecture</a></div>
<div style={{ fontSize: 9, paddingTop: 10 }}>
Made with{" "}
<a href="https://github.com/forensic-architecture/timemap">TimeMap</a>
<br />
Free software from <br />{" "}
<a href="https://forensic-architecture.org">Forensic Architecture</a>
</div>
</>
);
}

View File

@@ -1,84 +1,86 @@
import React from "react";
import copy from "../../common/data/copy.json";
import { parse } from 'json2csv'
import { downloadAsFile } from "../../common/utilities"
import { parse } from "json2csv";
import { downloadAsFile } from "../../common/utilities";
export class DownloadButton extends React.Component {
onDownload(format, domain) {
let filename = `ukr-civharm-${this.datetimeToDateString(new Date())}`;
if (format === "csv") {
let outputData = this.getCsvData(domain)
downloadAsFile(`${filename}.csv`, outputData);
} else if (format === "json") {
let outputData = this.getJsonData(domain)
downloadAsFile(`${filename}.json`, outputData);
}
}
getCsvData(domain) {
const { events, sources } = domain;
const exportEvents = events.map(e => {
return {
id: e.civId,
date: this.datetimeToDateString(e.datetime),
latitude: e.latitude,
longitude: e.longitude,
location: e.location,
description: e.description,
sources: e.sources.map(s => sources[s].paths[0]).join(","),
associations: e.associations.map(a => a.filter_paths.join("=")).join(",")
}
})
return parse(exportEvents, { flatten: true })
}
getJsonData(domain) {
const { events, sources } = domain;
const exportEvents = events.map(e => {
return {
id: e.civId,
date: this.datetimeToDateString(e.datetime),
latitude: e.latitude,
longitude: e.longitude,
location: e.location,
description: e.description,
sources: e.sources.map(id => {
const s = sources[id]
return {
id,
path: s.paths[0],
description: s.description
}
}),
filters: e.associations.map(a => {
return {
key: a.filter_paths[0],
value: a.filter_paths[1]
}
})
}
});
return JSON.stringify(exportEvents);
}
datetimeToDateString(datetime) {
try {
return datetime.toISOString().split("T")[0]
} catch (_) { }
return "";
}
render() {
const { language, domain, format } = this.props;
const textByFormat = copy[language].toolbar.download.panel.formats[format]
return (
<div className="download-row">
<span
className="download-button"
key={`download-${format}`}
onClick={() => this.onDownload(format, domain)}
>
<i className="material-icons">{"download"}</i>
<span className="tab-caption">{textByFormat.label}</span>
</span>
<span className="download-description">{textByFormat.description}</span>
</div>
);
}
onDownload(format, domain) {
let filename = `ukr-civharm-${this.datetimeToDateString(new Date())}`;
if (format === "csv") {
let outputData = this.getCsvData(domain);
downloadAsFile(`${filename}.csv`, outputData);
} else if (format === "json") {
let outputData = this.getJsonData(domain);
downloadAsFile(`${filename}.json`, outputData);
}
}
getCsvData(domain) {
const { events, sources } = domain;
const exportEvents = events.map((e) => {
return {
id: e.civId,
date: this.datetimeToDateString(e.datetime),
latitude: e.latitude,
longitude: e.longitude,
location: e.location,
description: e.description,
sources: e.sources.map((s) => sources[s].paths[0]).join(","),
associations: e.associations
.map((a) => a.filter_paths.join("="))
.join(","),
};
});
return parse(exportEvents, { flatten: true });
}
getJsonData(domain) {
const { events, sources } = domain;
const exportEvents = events.map((e) => {
return {
id: e.civId,
date: this.datetimeToDateString(e.datetime),
latitude: e.latitude,
longitude: e.longitude,
location: e.location,
description: e.description,
sources: e.sources.map((id) => {
const s = sources[id];
return {
id,
path: s.paths[0],
description: s.description,
};
}),
filters: e.associations.map((a) => {
return {
key: a.filter_paths[0],
value: a.filter_paths[1],
};
}),
};
});
return JSON.stringify(exportEvents);
}
datetimeToDateString(datetime) {
try {
return datetime.toISOString().split("T")[0];
} catch (_) {}
return "";
}
render() {
const { language, domain, format } = this.props;
const textByFormat = copy[language].toolbar.download.panel.formats[format];
return (
<div className="download-row">
<span
className="download-button"
key={`download-${format}`}
onClick={() => this.onDownload(format, domain)}
>
<i className="material-icons">{"download"}</i>
<span className="tab-caption">{textByFormat.label}</span>
</span>
<span className="download-description">{textByFormat.description}</span>
</div>
);
}
}

View File

@@ -1,17 +1,12 @@
import React from "react";
import { DownloadButton } from "./DownloadButton";
const DownloadPanel = ({
language,
title,
description,
domain
}) => {
const DownloadPanel = ({ language, title, description, domain }) => {
return (
<div className="react-innertabpanel">
<h2>{title}</h2>
<p>{description}</p>
<hr/>
<hr />
<DownloadButton language={language} domain={domain} format="csv" />
<DownloadButton language={language} domain={domain} format="json" />
</div>

View File

@@ -74,7 +74,10 @@ const Media = ({ src, title }) => {
return (
<div className="card-cell media embedded">
<TwitterTweetEmbed tweetId={tweetId} options={{ conversation: "none" }} />
<TwitterTweetEmbed
tweetId={tweetId}
options={{ conversation: "none" }}
/>
</div>
);
default:

View File

@@ -1,343 +1,344 @@
.cover-container {
position: absolute;
top: -100%;
left: 0;
height: 100vh;
background-color: black;
width: 100%;
opacity: 1;
transition: top 0.4s ease;
z-index: $loading-overlay + 1;
overflow-y: auto;
overflow-x: hidden;
color: $offwhite;
position: absolute;
top: -100%;
left: 0;
height: 100vh;
background-color: black;
width: 100%;
opacity: 1;
transition: top 0.4s ease;
z-index: $loading-overlay + 1;
overflow-y: auto;
overflow-x: hidden;
color: $offwhite;
&.showing {
top: 0;
left: 0;
}
&.showing {
top: 0;
left: 0;
}
}
.cover-header {
position: fixed;
bottom: 20px;
left: 0;
position: fixed;
bottom: 20px;
left: 0;
display: flex;
width: 100vw;
@media only screen and (max-width: 1200px) {
position: inherit;
}
.cover-logo-container {
padding: 20px 0 0 20px;
display: flex;
width: 100vw;
@media only screen and (max-width: 1200px) {
position: inherit;
}
.cover-logo-container {
padding: 20px 0 0 20px;
display: flex;
&.minimized {}
.cover-logo {
transition: all 1s;
width: 60px;
height: 60px;
}
}
&.minimized {
bottom: 150px;
max-width: $toolbar-width;
max-height: 30px;
justify-content: center;
align-items: center;
flex-direction: column;
.cover-logo-container {
padding: 5px;
}
.cover-logo {
width: 60px;
height: 60px;
}
}
.cover-logo {
transition: all 1s;
width: 60px;
height: 60px;
}
}
&.minimized {
bottom: 150px;
max-width: $toolbar-width;
max-height: 30px;
justify-content: center;
align-items: center;
flex-direction: column;
.cover-logo-container {
padding: 5px;
}
.cover-logo {
width: 60px;
height: 60px;
}
}
}
.fullscreen-bg {
&.hidden {
top: -100%;
}
&.hidden {
top: -100%;
}
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
// overflow: hidden;
z-index: -100;
background: #000000;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
// overflow: hidden;
z-index: -100;
background: #000000;
}
.fullscreen-bg__video {
position: relative;
top: 0;
left: -25vw;
width: 150vw;
height: 100vh;
-webkit-filter: contrast(70%) brightness(70%) grayscale(100%);
filter: contrast(70%) brightness(70%) grayscale(100%);
position: relative;
top: 0;
left: -25vw;
width: 150vw;
height: 100vh;
-webkit-filter: contrast(70%) brightness(70%) grayscale(100%);
filter: contrast(70%) brightness(70%) grayscale(100%);
@media only screen and (max-width: 992px) {
display: none;
}
@media only screen and (max-width: 992px) {
display: none;
}
}
.default-cover-container {
display: flex;
justify-content: center;
flex-direction: column;
align-items: center;
display: flex;
justify-content: center;
flex-direction: column;
align-items: center;
}
.cover-container {
font-size: 12pt;
font-size: 12pt;
display: flex;
flex-direction: column;
max-height: 100%;
hr,
br {
width: 100%;
}
.sidebar {
display: flex;
flex-direction: column;
max-height: 100%;
hr,
br {
width: 100%;
}
.sidebar {
display: flex;
flex-direction: column;
justify-content: space-around;
align-items: space-around;
position: fixed;
left: 0;
background-color: $offwhite;
margin-top: 60px;
min-height: calc(100% - 280px);
max-height: calc(100% - 280px);
min-width: 19%;
max-width: 19%;
color: black;
.il-video-pill {
display: flex;
justify-content: center;
align-items: center;
text-align: center;
flex: 1;
background-color: transparent;
border-bottom: 5px solid black;
transition: all 0.4s ease;
&.explore {
background-color: $yellow;
}
&.videos {
background-color: blue;
}
&:hover {
cursor: pointer;
background-color: $darkwhite;
color: white;
}
}
}
.hero {
min-width: 100%;
min-height: 80px;
margin: auto;
display: flex;
flex-direction: column;
margin-bottom: 20px;
margin-top: 60px;
@media only screen and (max-width: 1200px) {
min-height: 250px;
}
.row {
display: flex;
flex: 1;
flex-direction: row;
@media only screen and (max-width: 1200px) {
flex-direction: column;
}
justify-content: space-around;
&.vertical {
flex-direction: column;
}
.cell {
border: 1px solid white;
display: flex;
justify-content: center;
align-items: center;
text-align: center;
flex: 1;
background-color: $darkgrey;
padding: 10px 0;
transition: all 0.4s ease;
letter-spacing: 2px;
min-height: 40px;
&.small {
letter-spacing: inherit;
font-size: 10pt;
}
&.plain {
min-height: 10px;
background-color: black;
letter-spacing: 1px;
@media only screen and (max-width: 1200px) {
min-height: 100px;
}
}
&.yellow {
color: black !important;
background-color: $yellow;
}
&:hover {
cursor: pointer;
background-color: $darkwhite;
color: white;
}
@media only screen and (max-width: 1200px) {
min-height: 100px;
}
}
}
}
.cover-content {
display: flex;
flex-direction: column;
max-width: 600px;
overflow-y: auto;
overflow-x: hidden;
padding-bottom: 10em;
h1,
h2,
h3,
h4,
h5 {
text-align: center;
}
h1 {
margin-bottom: -15px;
margin-top: 30px;
}
h5 {
margin-top: -15px;
}
.md-container {
width: 100%;
overflow-wrap: break-word;
// white-space: pre-line;
ul {
list-style: none;
}
li::before {
content: "* ";
}
p {
text-align: justify;
}
}
// mobile styles, remove overlay buttons
@media only screen and (max-width: 1200px) {
font-size: 22pt !important;
max-width: 100vw;
padding: 0 40px 80px 40px;
margin-bottom: 0;
}
.verify-tabs {
background-color: $yellow;
color: black;
display: flex;
flex-direction: column;
.v-tab {
display: flex;
margin: auto;
justify-content: center;
align-content: center;
flex: 1;
}
}
.il-cover-verification-container {
display: flex;
flex-direction: column;
.il-cover-verification {
.il-video {
border-radius: 1em;
background-color: rgba(240, 240, 240, 0.5);
}
}
}
}
_::-webkit-full-page-media,
_:future,
:root .cover-content {
max-width: auto;
}
}
.cover-footer {
&.disabled {
display: none;
}
justify-content: space-around;
align-items: space-around;
position: fixed;
bottom: 0;
min-height: 150px;
min-width: 100%;
padding: 10px;
background-color: black;
display: flex;
justify-content: center;
left: 0;
background-color: $offwhite;
margin-top: 60px;
min-height: calc(100% - 280px);
max-height: calc(100% - 280px);
min-width: 19%;
max-width: 19%;
color: black;
.il-cover-button {
.il-video-pill {
display: flex;
justify-content: center;
align-items: center;
text-align: center;
flex: 1;
background-color: transparent;
border-bottom: 5px solid black;
transition: all 0.4s ease;
&.explore {
background-color: $yellow;
}
&.videos {
background-color: blue;
}
&:hover {
cursor: pointer;
background-color: $darkwhite;
color: white;
}
}
}
.hero {
min-width: 100%;
min-height: 80px;
margin: auto;
display: flex;
flex-direction: column;
margin-bottom: 20px;
margin-top: 60px;
@media only screen and (max-width: 1200px) {
min-height: 250px;
}
.row {
display: flex;
flex: 1;
flex-direction: row;
@media only screen and (max-width: 1200px) {
flex-direction: column;
}
justify-content: space-around;
&.vertical {
flex-direction: column;
}
.cell {
border: 1px solid white;
display: flex;
justify-content: center;
align-items: center;
min-width: 300px;
max-height: 80px;
margin-top: 30px;
background-color: $offwhite;
color: black;
transition: all 0.3s ease;
text-align: center;
flex: 1;
background-color: $darkgrey;
padding: 10px 0;
transition: all 0.4s ease;
letter-spacing: 2px;
min-height: 40px;
&.small {
letter-spacing: inherit;
font-size: 10pt;
}
&.plain {
min-height: 10px;
background-color: black;
letter-spacing: 1px;
@media only screen and (max-width: 1200px) {
min-height: 100px;
}
}
&.yellow {
color: black !important;
background-color: $yellow;
}
&:hover {
cursor: pointer;
background-color: darken($offwhite, 30%);
color: black;
cursor: pointer;
background-color: $darkwhite;
color: white;
}
@media only screen and (max-width: 1200px) {
min-height: 100px;
}
}
}
}
}
.cover-content {
display: flex;
flex-direction: column;
max-width: 600px;
overflow-y: auto;
overflow-x: hidden;
padding-bottom: 10em;
h1,
h2,
h3,
h4,
h5 {
text-align: center;
}
h1 {
margin-bottom: -15px;
margin-top: 30px;
}
h5 {
margin-top: -15px;
}
.md-container {
width: 100%;
overflow-wrap: break-word;
// white-space: pre-line;
ul {
list-style: none;
}
li::before {
content: "* ";
}
p {
text-align: justify;
}
}
// mobile styles, remove overlay buttons
@media only screen and (max-width: 1200px) {
font-size: 22pt !important;
max-width: 100vw;
padding: 0 40px 80px 40px;
margin-bottom: 0;
}
.verify-tabs {
background-color: $yellow;
color: black;
display: flex;
flex-direction: column;
.v-tab {
display: flex;
margin: auto;
justify-content: center;
align-content: center;
flex: 1;
}
}
.il-cover-verification-container {
display: flex;
flex-direction: column;
.il-cover-verification {
.il-video {
border-radius: 1em;
background-color: rgba(240, 240, 240, 0.5);
}
}
}
}
_::-webkit-full-page-media,
_:future,
:root .cover-content {
max-width: auto;
}
}
.cover-footer {
&.disabled {
display: none;
}
position: fixed;
bottom: 0;
min-height: 150px;
min-width: 100%;
padding: 10px;
background-color: black;
display: flex;
justify-content: center;
.il-cover-button {
display: flex;
justify-content: center;
align-items: center;
min-width: 300px;
max-height: 80px;
margin-top: 30px;
background-color: $offwhite;
color: black;
transition: all 0.3s ease;
&:hover {
cursor: pointer;
background-color: darken($offwhite, 30%);
color: black;
}
}
}

View File

@@ -186,20 +186,21 @@
}
}
.download-row{
.download-row {
display: flex;
flex-direction: row;
}
.download-button{
.download-button {
flex: 1 1 auto;
}
.download-description{
.download-description {
flex: 1 5 auto;
text-align: justify;
margin: auto;
}
.toolbar-tab, .download-button {
.toolbar-tab,
.download-button {
display: flex;
align-items: center;
justify-content: center;