Этот коммит содержится в:
Maarten 2024-10-11 10:00:39 +02:00
родитель 3ddd9c467a
Коммит ad33923c37
3 изменённых файлов: 125 добавлений и 80 удалений

20
src/lib/components/CardModal.svelte Обычный файл
Просмотреть файл

@ -0,0 +1,20 @@
<script>
import CaseCard from "./CaseCard.svelte";
export let modalOpen
export let activeCaseData
function closeModal(){
modalOpen = false
}
</script>
<div id="card-modal" class={modalOpen ? "modal is-active" : "modal"}>
<div class="modal-background" on:click={closeModal}></div>
<div class="modal-content">
{#if activeCaseData}
<CaseCard cardData={activeCaseData} expanded={true} ></CaseCard>
{/if}
</div>
<div class="modal-close" on:click={closeModal}></div>
</div>

Просмотреть файл

@ -3,7 +3,16 @@
import { utcFormat } from 'd3-time-format'; import { utcFormat } from 'd3-time-format';
import { platformFilter, actorNationFilter, sourceFilter } from '../../stores/filters'; import { platformFilter, actorNationFilter, sourceFilter } from '../../stores/filters';
import ScoreBar from '$lib/components/ScoreBar.svelte'; import ScoreBar from '$lib/components/ScoreBar.svelte';
export let cardData; export let cardData;
export let expanded;
export let modalOpen;
export let activeCaseData
let openCase = function(caseID){
modalOpen = true
activeCaseData = cardData
}
</script> </script>
<div class="card" transition:fade id={'case-' + cardData.attribution_id}> <div class="card" transition:fade id={'case-' + cardData.attribution_id}>
@ -12,6 +21,7 @@
<h2 class="is-size-5">{cardData.short_title}</h2> <h2 class="is-size-5">{cardData.short_title}</h2>
</div> </div>
</div> </div>
{#if expanded}
<div class="score-bars"> <div class="score-bars">
<div class="score-bar-wrapper"> <div class="score-bar-wrapper">
<ScoreBar value={cardData.credibility} maxValue={5} /> <ScoreBar value={cardData.credibility} maxValue={5} />
@ -33,6 +43,7 @@
{scoreQuestionsExpanded ? 'X' : '?'} {scoreQuestionsExpanded ? 'X' : '?'}
</span--> </span-->
</div> </div>
{/if}
<div class="card-image"> <div class="card-image">
<figure class="image"> <figure class="image">
<img src={`/images/${cardData.attribution_id}.jpg`} /> <img src={`/images/${cardData.attribution_id}.jpg`} />
@ -40,9 +51,12 @@
</div> </div>
<div class="card-content"> <div class="card-content">
<div class="content"> <div class="content">
{#if expanded}
<p>{utcFormat('%B %d, %Y')(new Date(cardData.attribution_date))}</p> <p>{utcFormat('%B %d, %Y')(new Date(cardData.attribution_date))}</p>
<p><a href={cardData.attribution_url} target="_blank">{cardData.source}</a></p> <p><a href={cardData.attribution_url} target="_blank">{cardData.source}</a></p>
{/if}
<p>{cardData.short_description}</p> <p>{cardData.short_description}</p>
{#if expanded}
<p> <p>
<button class="button is-info is-small" on:click={sourceFilter.selectOne(cardData.source)} <button class="button is-info is-small" on:click={sourceFilter.selectOne(cardData.source)}
>{cardData.source}</button >{cardData.source}</button
@ -58,15 +72,19 @@
> >
{/each} {/each}
</p> </p>
{/if}
</div> </div>
</div> </div>
{#if !expanded}
<footer class="card-footer">
<button on:click={openCase(cardData.attribution_id)} class="card-footer-item">Open case</button>
</footer>
{/if}
</div> </div>
<style> <style>
div.card { div.card {
max-width: 780px; max-width: 780px;
/*max-height: 600px;
overflow-y: scroll;*/
} }
.score-bars { .score-bars {
display: flex; display: flex;

Просмотреть файл

@ -9,6 +9,7 @@
import Timeline from '$lib/components/Timeline.svelte'; import Timeline from '$lib/components/Timeline.svelte';
import TimelineMobile from '$lib/components/TimelineMobile.svelte'; import TimelineMobile from '$lib/components/TimelineMobile.svelte';
import Controls from '$lib/components/Controls.svelte'; import Controls from '$lib/components/Controls.svelte';
import CardModal from '$lib/components/CardModal.svelte';
import AnimatedFilterIcon from '$lib/components/AnimatedFilterIcon.svelte'; import AnimatedFilterIcon from '$lib/components/AnimatedFilterIcon.svelte';
import { splitString, haveOverlap, withinRange, includesTextSearch } from '$lib/utils/misc'; import { splitString, haveOverlap, withinRange, includesTextSearch } from '$lib/utils/misc';
//import { setScales } from '$lib/utils/scales'; //import { setScales } from '$lib/utils/scales';
@ -29,7 +30,7 @@
fullTimeRange fullTimeRange
} from '../stores/filters'; } from '../stores/filters';
$: console.log($timeRangeFilter) //$: console.log($timeRangeFilter)
//$: console.log($fullTimeRange) //$: console.log($fullTimeRange)
$: innerWidth = 0; $: innerWidth = 0;
@ -49,11 +50,11 @@
cases = cases.filter((d) => d.attribution_id != ''); cases = cases.filter((d) => d.attribution_id != '');
cases.forEach((d) => { cases.forEach((d) => {
d.platform = splitString(d.platforms); d.platform = splitString(d.platforms);
d.medium = splitString(d.medium) d.medium = splitString(d.medium);
d.actor_nation = splitString(d.actor_nation); d.actor_nation = splitString(d.actor_nation);
d.source = splitString(d.source); d.source = splitString(d.source);
d.methods = splitString(d.methods); d.methods = splitString(d.methods);
d.campaign = splitString(d.campaign) d.campaign = splitString(d.campaign);
d.attribution_total_score = +d.attribution_score; d.attribution_total_score = +d.attribution_score;
d.attribution_date = new Date(d.attribution_date); d.attribution_date = new Date(d.attribution_date);
d.search = [ d.search = [
@ -79,7 +80,7 @@
sourceFilter.init(cases, 'source'); sourceFilter.init(cases, 'source');
sourceCategoryFilter.init(cases, 'source_category'); sourceCategoryFilter.init(cases, 'source_category');
methodFilter.init(cases, 'methods'); methodFilter.init(cases, 'methods');
campaignFilter.init(cases, 'campaign') campaignFilter.init(cases, 'campaign');
$attributionScoreFilter = attributionScoreDef; $attributionScoreFilter = attributionScoreDef;
$timeRangeFilter = extent(cases.map((d) => new Date(d.attribution_date))); $timeRangeFilter = extent(cases.map((d) => new Date(d.attribution_date)));
//$timeRangeFilter = [new Date('2024-01-01'), max(cases.map((d) => new Date(d.attribution_date)))]; //$timeRangeFilter = [new Date('2024-01-01'), max(cases.map((d) => new Date(d.attribution_date)))];
@ -188,6 +189,9 @@
]; ];
let selectedSorting = { id: 'attribution_date', label: 'Attribution Date', type: 'date' }; let selectedSorting = { id: 'attribution_date', label: 'Attribution Date', type: 'date' };
let modalOpen = false;
let activeCaseData;
</script> </script>
<svelte:window bind:innerWidth /> <svelte:window bind:innerWidth />
@ -198,8 +202,8 @@
<meta property="og:description" content={copy.meta.og_description} /> <meta property="og:description" content={copy.meta.og_description} />
<meta property="og:url" content={copy.meta.og_url} /> <meta property="og:url" content={copy.meta.og_url} />
<meta property="og:image" content={copy.meta.og_image} /> <meta property="og:image" content={copy.meta.og_image} />
<meta property="og:type" content="website"> <meta property="og:type" content="website" />
<meta property="og:locale" content="en_US"> <meta property="og:locale" content="en_US" />
</svelte:head> </svelte:head>
{#if isMobile} {#if isMobile}
@ -233,6 +237,7 @@
</div> </div>
</section> </section>
{#if !modalOpen}
<section <section
class={isMobile && sidebarOpen class={isMobile && sidebarOpen
? 'section sidebar open controls' ? 'section sidebar open controls'
@ -240,8 +245,10 @@
? 'section sidebar closed controls' ? 'section sidebar closed controls'
: 'section sticky controls'} : 'section sticky controls'}
> >
<Controls {cases}></Controls> <Controls {cases}></Controls>
</section> </section>
{/if}
<section class="section"> <section class="section">
<div> <div>
@ -293,12 +300,15 @@
{#if displayDataAs == 'Cards'} {#if displayDataAs == 'Cards'}
<section class="section"> <section class="section">
<div class="container"> <div class="container">
<a href="https://fiat-2024-processed-data.s3.us-west-2.amazonaws.com/fiat_2024_attribution_data.csv">Download the data</a> <a
href="https://fiat-2024-processed-data.s3.us-west-2.amazonaws.com/fiat_2024_attribution_data.csv"
>Download the data</a
>
<div class="grid is-col-min-16"> <div class="grid is-col-min-16">
{#each sortedCases as attrCase} {#each sortedCases as attrCase}
{#if attrCase.show} {#if attrCase.show}
<div class="cell"> <div class="cell">
<CaseCard cardData={attrCase}></CaseCard> <CaseCard cardData={attrCase} expanded={false} bind:modalOpen bind:activeCaseData></CaseCard>
</div> </div>
{/if} {/if}
{/each} {/each}
@ -310,7 +320,10 @@
{#if displayDataAs == 'Table' && sortedCases.length > 0} {#if displayDataAs == 'Table' && sortedCases.length > 0}
<section class="section"> <section class="section">
<div class="container"> <div class="container">
<a href="https://fiat-2024-processed-data.s3.us-west-2.amazonaws.com/fiat_2024_attribution_data.csv">Download the data</a> <a
href="https://fiat-2024-processed-data.s3.us-west-2.amazonaws.com/fiat_2024_attribution_data.csv"
>Download the data</a
>
<CaseTable cases={sortedCases}></CaseTable> <CaseTable cases={sortedCases}></CaseTable>
</div> </div>
</section> </section>
@ -329,17 +342,11 @@
</div> </div>
</section> </section>
<CardModal bind:modalOpen {activeCaseData}></CardModal>
<style> <style>
section { section {
font-family: var(--font-02); font-family: var(--font-02);
}
.title {
font-family: var(--font-01);
color: var(--usa-blue)
}
.subtitle {
font-family: var(--font-02);
color: var(--usa-blue)
} }
.intro { .intro {
max-width: 800px; max-width: 800px;