Basic filter, timeline links
Этот коммит содержится в:
родитель
b77aa33417
Коммит
dac693845f
45
package-lock.json
сгенерированный
45
package-lock.json
сгенерированный
@ -25,6 +25,7 @@
|
||||
"prettier": "^3.1.1",
|
||||
"prettier-plugin-svelte": "^3.1.2",
|
||||
"svelte": "^4.2.7",
|
||||
"svelte-select": "^5.8.3",
|
||||
"vite": "^5.0.3"
|
||||
}
|
||||
},
|
||||
@ -524,6 +525,31 @@
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@floating-ui/core": {
|
||||
"version": "1.6.8",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.8.tgz",
|
||||
"integrity": "sha512-7XJ9cPU+yI2QeLS+FCSlqNFZJq8arvswefkZrYI1yQBbftw6FyrZOxYSh+9S7z7TpeWlRt9zJ5IhM1WIL334jA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@floating-ui/utils": "^0.2.8"
|
||||
}
|
||||
},
|
||||
"node_modules/@floating-ui/dom": {
|
||||
"version": "1.6.11",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.11.tgz",
|
||||
"integrity": "sha512-qkMCxSR24v2vGkhYDo/UzxfJN3D4syqSjyuTFz6C7XcpU1pASPRieNI0Kj5VP3/503mOfYiGY891ugBX1GlABQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@floating-ui/core": "^1.6.0",
|
||||
"@floating-ui/utils": "^0.2.8"
|
||||
}
|
||||
},
|
||||
"node_modules/@floating-ui/utils": {
|
||||
"version": "0.2.8",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.8.tgz",
|
||||
"integrity": "sha512-kym7SodPp8/wloecOpcmSnWJsK7M0E5Wg8UcFA+uO4B9s5d0ywXOEro/8HM9x0rW+TljRzul/14UYz3TleT3ig==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@humanwhocodes/module-importer": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
|
||||
@ -2673,6 +2699,16 @@
|
||||
"url": "https://opencollective.com/eslint"
|
||||
}
|
||||
},
|
||||
"node_modules/svelte-floating-ui": {
|
||||
"version": "1.5.8",
|
||||
"resolved": "https://registry.npmjs.org/svelte-floating-ui/-/svelte-floating-ui-1.5.8.tgz",
|
||||
"integrity": "sha512-dVvJhZ2bT+kQDHlE4Lep8t+sgEc0XD96fXLzAi2DDI2bsaegBbClxXVNMma0C2WsG+n9GJSYx292dTvA8CYRtw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@floating-ui/core": "^1.5.0",
|
||||
"@floating-ui/dom": "^1.5.3"
|
||||
}
|
||||
},
|
||||
"node_modules/svelte-hmr": {
|
||||
"version": "0.16.0",
|
||||
"resolved": "https://registry.npmjs.org/svelte-hmr/-/svelte-hmr-0.16.0.tgz",
|
||||
@ -2685,6 +2721,15 @@
|
||||
"svelte": "^3.19.0 || ^4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/svelte-select": {
|
||||
"version": "5.8.3",
|
||||
"resolved": "https://registry.npmjs.org/svelte-select/-/svelte-select-5.8.3.tgz",
|
||||
"integrity": "sha512-nQsvflWmTCOZjssdrNptzfD1Ok45hHVMTL5IHay5DINk7dfu5Er+8KsVJnZMJdSircqtR0YlT4YkCFlxOUhVPA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"svelte-floating-ui": "1.5.8"
|
||||
}
|
||||
},
|
||||
"node_modules/text-table": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
|
||||
|
||||
@ -28,6 +28,7 @@
|
||||
"prettier": "^3.1.1",
|
||||
"prettier-plugin-svelte": "^3.1.2",
|
||||
"svelte": "^4.2.7",
|
||||
"svelte-select": "^5.8.3",
|
||||
"vite": "^5.0.3"
|
||||
},
|
||||
"type": "module"
|
||||
|
||||
@ -1,13 +1,14 @@
|
||||
<script>
|
||||
import { fade } from 'svelte/transition'
|
||||
export let cardData;
|
||||
</script>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<div class="card" transition:fade id={"case-" + cardData.attribution_id}>
|
||||
<!--div class="card-header">
|
||||
<div class="card-header-title">
|
||||
<h2 class="is-size-3">Don't cases have titles?</h2>
|
||||
</div>
|
||||
</div>
|
||||
</div-->
|
||||
<div class="card-image">
|
||||
<figure class="image">
|
||||
<img src={cardData.image_url} alt={cardData.image_credit} />
|
||||
@ -25,3 +26,9 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
div.card {
|
||||
max-width: 780px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,40 +1,31 @@
|
||||
<script>
|
||||
import { scaleUtc } from "d3-scale"
|
||||
import { extent } from "d3-array"
|
||||
import { utcFormat } from "d3-time-format"
|
||||
import { scaleUtc } from 'd3-scale';
|
||||
import { extent } from 'd3-array';
|
||||
import { utcFormat } from 'd3-time-format';
|
||||
|
||||
export let cases
|
||||
export let cases;
|
||||
|
||||
const margins = {
|
||||
top: 24,
|
||||
right: 24,
|
||||
bottom: 24,
|
||||
left: 24
|
||||
}
|
||||
};
|
||||
|
||||
let width
|
||||
let height = 120
|
||||
|
||||
$: dateExtent = extent(cases.map(d => new Date(d.attribution_date)))
|
||||
|
||||
$: xScale = scaleUtc(dateExtent, [0, width - margins.right - margins.left])
|
||||
$: ticks = xScale.ticks(5)
|
||||
let width;
|
||||
let height = 120;
|
||||
|
||||
$: dateExtent = extent(cases.map((d) => new Date(d.attribution_date)));
|
||||
|
||||
$: xScale = scaleUtc(dateExtent, [0, width - margins.right - margins.left]);
|
||||
$: ticks = xScale.ticks(5);
|
||||
</script>
|
||||
|
||||
<div class="timeline-container" bind:clientWidth={width}>
|
||||
<svg {width} {height}>
|
||||
{#if xScale}
|
||||
<g transform={`translate(${margins.left},${margins.top})`}>
|
||||
<line
|
||||
x1={0}
|
||||
x2={width}
|
||||
y1={0}
|
||||
y2={0}
|
||||
stroke={'#000000'}
|
||||
stroke-width={2}
|
||||
></line>
|
||||
<line x1={0} x2={width} y1={0} y2={0} stroke={'#000000'} stroke-width={2}></line>
|
||||
{#each ticks as tick}
|
||||
<line
|
||||
x1={xScale(tick)}
|
||||
@ -44,13 +35,10 @@
|
||||
stroke={'#000000'}
|
||||
stroke-width={2}
|
||||
></line>
|
||||
<text
|
||||
x={xScale(tick)}
|
||||
y={32}
|
||||
text-anchor={'middle'}
|
||||
>{utcFormat("%b")(tick)}</text>
|
||||
<text x={xScale(tick)} y={32} text-anchor={'middle'}>{utcFormat('%b %d')(tick)}</text>
|
||||
{/each}
|
||||
{#each cases as attrCase}
|
||||
<a href={'#case-' + attrCase.attribution_id}>
|
||||
<circle
|
||||
cx={xScale(new Date(attrCase.attribution_date))}
|
||||
cy={0}
|
||||
@ -59,8 +47,8 @@
|
||||
stroke={'#ffffff'}
|
||||
stroke-width={2}
|
||||
></circle>
|
||||
</a>
|
||||
{/each}
|
||||
|
||||
</g>
|
||||
{/if}
|
||||
</svg>
|
||||
|
||||
@ -1,26 +1,36 @@
|
||||
<script>
|
||||
import copy from "../data/copy.json"
|
||||
import { onMount } from "svelte";
|
||||
import { csv } from "d3-fetch"
|
||||
import copy from '../data/copy.json';
|
||||
import { onMount } from 'svelte';
|
||||
import { csv } from 'd3-fetch';
|
||||
import { base } from '$app/paths';
|
||||
import CaseCard from "$lib/components/CaseCard.svelte";
|
||||
import CaseTable from "$lib/components/CaseTable.svelte";
|
||||
import Timeline from "$lib/components/Timeline.svelte";
|
||||
import CaseCard from '$lib/components/CaseCard.svelte';
|
||||
import CaseTable from '$lib/components/CaseTable.svelte';
|
||||
import Timeline from '$lib/components/Timeline.svelte';
|
||||
import Select from 'svelte-select';
|
||||
|
||||
let cases = []
|
||||
let cases = [];
|
||||
|
||||
onMount(async function () {
|
||||
//const response = await csv(`https://fiat-2024-processed-data.s3.us-west-2.amazonaws.com/Demo_Attribution_Data.csv`);
|
||||
const response = await csv(`${base}/Demo_Attribution_Data.csv`);
|
||||
cases = response
|
||||
})
|
||||
cases = response;
|
||||
});
|
||||
|
||||
$: actorNations =
|
||||
cases.length > 0 ? [...new Set(cases.map((d) => d.actor_nation.split(', ')).flat())] : [];
|
||||
$: actorNationsUnique = [...new Set(actorNations)];
|
||||
let selectedActorNations = null;
|
||||
|
||||
$: filteredCases = selectedActorNations
|
||||
? cases.filter((d) => d.actor_nation.includes(selectedActorNations[0].value))
|
||||
: cases;
|
||||
</script>
|
||||
|
||||
<section class="section">
|
||||
<div class="container has-text-centered">
|
||||
<h1 class="is-size-1">{copy.meta.title}</h1>
|
||||
{#each copy.content as block}
|
||||
{#if block.type == "text"}
|
||||
{#if block.type == 'text'}
|
||||
<p>{block.text}</p>
|
||||
{/if}
|
||||
{/each}
|
||||
@ -28,26 +38,42 @@
|
||||
</section>
|
||||
|
||||
<section class="section">
|
||||
<div>
|
||||
<Timeline {cases}></Timeline>
|
||||
<div class="select-container">
|
||||
<Select
|
||||
items={actorNationsUnique}
|
||||
multiple={true}
|
||||
bind:value={selectedActorNations}
|
||||
placeholder={'Select 1 or more actor countries'}
|
||||
></Select>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<div class="container">
|
||||
<div class="grid is-col-min-16">
|
||||
{#each cases as attrCase}
|
||||
<div class="cell">
|
||||
<CaseCard cardData={attrCase}>
|
||||
<section class="section">
|
||||
<div>
|
||||
<Timeline cases={filteredCases}></Timeline>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</CaseCard>
|
||||
<section class="section">
|
||||
<div class="container">
|
||||
<div class="grid is-col-min-12">
|
||||
{#each filteredCases as attrCase}
|
||||
<div class="cell">
|
||||
<CaseCard cardData={attrCase}></CaseCard>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section>
|
||||
|
||||
<section class="section">
|
||||
<div class="container">
|
||||
<CaseTable {cases}></CaseTable>
|
||||
<CaseTable cases={filteredCases}></CaseTable>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<style>
|
||||
.select-container {
|
||||
width: 360px;
|
||||
}
|
||||
</style>
|
||||
|
||||
Загрузка…
x
Ссылка в новой задаче
Block a user