CasesControls
Этот коммит содержится в:
		
							родитель
							
								
									467e9de806
								
							
						
					
					
						Коммит
						2ea981c562
					
				| @ -77,7 +77,7 @@ | |||||||
| 	<div class="card-content"> | 	<div class="card-content"> | ||||||
| 		<div class="content"> | 		<div class="content"> | ||||||
| 			{#if expanded} | 			{#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_x} target="_blank">{cardData.source}</a></p> | 				<p><a href={cardData.attribution_url_x} target="_blank">{cardData.source}</a></p> | ||||||
| 			{/if} | 			{/if} | ||||||
| 			<p>{cardData.short_description}</p> | 			<p>{cardData.short_description}</p> | ||||||
| @ -163,4 +163,7 @@ | |||||||
| 	.score-bar-wrapper p { | 	.score-bar-wrapper p { | ||||||
| 		font-size: 0.7rem; | 		font-size: 0.7rem; | ||||||
| 	} | 	} | ||||||
|  | 	button { | ||||||
|  | 		margin: 0.2rem; | ||||||
|  | 	} | ||||||
| </style> | </style> | ||||||
|  | |||||||
							
								
								
									
										68
									
								
								src/lib/components/CasesControls.svelte
									
									
									
									
									
										Обычный файл
									
								
							
							
						
						
									
										68
									
								
								src/lib/components/CasesControls.svelte
									
									
									
									
									
										Обычный файл
									
								
							| @ -0,0 +1,68 @@ | |||||||
|  | <script> | ||||||
|  |     export let displayDataAs | ||||||
|  |     export let selectedSorting | ||||||
|  | 
 | ||||||
|  |     const sortOptions = [ | ||||||
|  | 		{ id: 'attribution_date', label: 'Attribution Date', type: 'date' }, | ||||||
|  | 		{ id: 'attribution_score', label: 'Attribution Score', type: 'number' }, | ||||||
|  | 		{ id: 'actor_nation', label: 'Actor Nation', type: 'array' }, | ||||||
|  | 		{ id: 'platform', label: 'Platform', type: 'array' }, | ||||||
|  | 		{ id: 'source', label: 'Source', type: 'array' }, | ||||||
|  | 		{ id: 'source_category', label: 'Source Category', type: 'string' } | ||||||
|  | 	]; | ||||||
|  | 
 | ||||||
|  | </script> | ||||||
|  | 
 | ||||||
|  | <div class="container cases-controls"> | ||||||
|  |     <div class="cases-control"> | ||||||
|  |         <div class="buttons has-addons"> | ||||||
|  |             <button | ||||||
|  |                 class={displayDataAs == 'Table' | ||||||
|  |                     ? 'button is-dark is-selected is-small' | ||||||
|  |                     : 'button is-small'} | ||||||
|  |                 on:click={() => { | ||||||
|  |                     displayDataAs = 'Table'; | ||||||
|  |                 }}>Table</button | ||||||
|  |             > | ||||||
|  |             <button | ||||||
|  |                 class={displayDataAs == 'Cards' | ||||||
|  |                     ? 'button is-dark is-selected is-small' | ||||||
|  |                     : 'button is-small'} | ||||||
|  |                 on:click={() => { | ||||||
|  |                     displayDataAs = 'Cards'; | ||||||
|  |                 }}>Cards</button | ||||||
|  |             > | ||||||
|  |         </div> | ||||||
|  |     </div> | ||||||
|  |     <div class="cases-control"> | ||||||
|  |         <label for="sort-select" class="sort-label">Sort cases by </label> | ||||||
|  |         <div class="select is-small"> | ||||||
|  |             <select bind:value={selectedSorting} id="sort-select"> | ||||||
|  |                 {#each sortOptions as sortOpt} | ||||||
|  |                     <option value={sortOpt}> | ||||||
|  |                         {sortOpt.label} | ||||||
|  |                     </option> | ||||||
|  |                 {/each} | ||||||
|  |             </select> | ||||||
|  |         </div> | ||||||
|  |     </div> | ||||||
|  |     <div class="cases-control"> | ||||||
|  |         <a | ||||||
|  |             href="https://fiat-2024-processed-data.s3.us-west-2.amazonaws.com/fiat_2024_attribution_data.csv" | ||||||
|  |             class="button is-small">Download the data</a | ||||||
|  |         > | ||||||
|  |     </div> | ||||||
|  | </div> | ||||||
|  | 
 | ||||||
|  | <style> | ||||||
|  |     .cases-controls { | ||||||
|  |         margin-bottom: 1rem; | ||||||
|  |     } | ||||||
|  | 	.cases-control { | ||||||
|  | 		display: inline-block; | ||||||
|  | 		margin-right: 3rem; | ||||||
|  | 	} | ||||||
|  | 	.sort-label { | ||||||
|  | 		font-size: 0.9rem; | ||||||
|  | 	} | ||||||
|  | </style> | ||||||
| @ -9,9 +9,10 @@ | |||||||
| 	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 CardModal from '$lib/components/CardModal.svelte'; | ||||||
| 	import AnimatedFilterIcon from '$lib/components/AnimatedFilterIcon.svelte'; | 	import AnimatedFilterIcon from '$lib/components/AnimatedFilterIcon.svelte'; | ||||||
|     import Collapsible from '$lib/components/Collapsible.svelte'; | 	import Collapsible from '$lib/components/Collapsible.svelte'; | ||||||
|  | 	import CasesControls from '$lib/components/CasesControls.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'; | ||||||
| 	import { page } from '$app/stores'; | 	import { page } from '$app/stores'; | ||||||
| @ -29,7 +30,7 @@ | |||||||
| 		textSearchFilter, | 		textSearchFilter, | ||||||
| 		timeRangeFilter, | 		timeRangeFilter, | ||||||
| 		fullTimeRange, | 		fullTimeRange, | ||||||
|         defaultTimeRange | 		defaultTimeRange | ||||||
| 	} from '../stores/filters'; | 	} from '../stores/filters'; | ||||||
| 
 | 
 | ||||||
| 	//$: console.log($timeRangeFilter) | 	//$: console.log($timeRangeFilter) | ||||||
| @ -85,7 +86,10 @@ | |||||||
| 		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))); | ||||||
|         $defaultTimeRange = [new Date('2024-01-01'), max(cases.map((d) => new Date(d.attribution_date)))]; | 		$defaultTimeRange = [ | ||||||
|  | 			new Date('2024-01-01'), | ||||||
|  | 			max(cases.map((d) => new Date(d.attribution_date))) | ||||||
|  | 		]; | ||||||
| 		$timeRangeFilter = $defaultTimeRange; | 		$timeRangeFilter = $defaultTimeRange; | ||||||
| 		$fullTimeRange = extent(cases.map((d) => new Date(d.attribution_date))); | 		$fullTimeRange = extent(cases.map((d) => new Date(d.attribution_date))); | ||||||
| 		//$fullTimeRange = [new Date('2022-01-01'), max(cases.map((d) => new Date(d.attribution_date)))]; | 		//$fullTimeRange = [new Date('2022-01-01'), max(cases.map((d) => new Date(d.attribution_date)))]; | ||||||
| @ -119,7 +123,7 @@ | |||||||
| 			methodFilter.applyBoolArray(urlFilters.methods); | 			methodFilter.applyBoolArray(urlFilters.methods); | ||||||
| 			sourceFilter.applyBoolArray(urlFilters.sources); | 			sourceFilter.applyBoolArray(urlFilters.sources); | ||||||
| 			sourceCategoryFilter.applyBoolArray(urlFilters.sourceCategories); | 			sourceCategoryFilter.applyBoolArray(urlFilters.sourceCategories); | ||||||
|             campaignFilter.applyBoolArray(urlFilters.campaigns); | 			campaignFilter.applyBoolArray(urlFilters.campaigns); | ||||||
| 			$attributionScoreFilter = urlFilters.attributionScores; | 			$attributionScoreFilter = urlFilters.attributionScores; | ||||||
| 			$textSearchFilter = urlFilters.textSearch; | 			$textSearchFilter = urlFilters.textSearch; | ||||||
| 		} | 		} | ||||||
| @ -235,23 +239,22 @@ | |||||||
| 	<div class="container"> | 	<div class="container"> | ||||||
| 		{#each copy.intro as block} | 		{#each copy.intro as block} | ||||||
| 			{#if block.type == 'concealed-text'} | 			{#if block.type == 'concealed-text'} | ||||||
|                 <Collapsible title={block.title} text={block.text} id={block.id}/> | 				<Collapsible title={block.title} text={block.text} id={block.id} /> | ||||||
| 			{/if} | 			{/if} | ||||||
| 		{/each} | 		{/each} | ||||||
| 	</div> | 	</div> | ||||||
| </section> | </section> | ||||||
| 
 | 
 | ||||||
| {#if !modalOpen} | {#if !modalOpen} | ||||||
| <section | 	<section | ||||||
| 	class={isMobile && sidebarOpen | 		class={isMobile && sidebarOpen | ||||||
| 		? 'section sidebar open controls' | 			? 'section sidebar open controls' | ||||||
| 		: isMobile && !sidebarOpen | 			: isMobile && !sidebarOpen | ||||||
| 			? 'section sidebar closed controls' | 				? 'section sidebar closed controls' | ||||||
| 			: 'section sticky controls'} | 				: 'section sticky controls'} | ||||||
| > | 	> | ||||||
|      | 		<Controls {cases}></Controls> | ||||||
| 	<Controls {cases}></Controls> | 	</section> | ||||||
| </section> |  | ||||||
| {/if} | {/if} | ||||||
| 
 | 
 | ||||||
| <section class="section"> | <section class="section"> | ||||||
| @ -264,55 +267,16 @@ | |||||||
| 	</div> | 	</div> | ||||||
| </section> | </section> | ||||||
| 
 | 
 | ||||||
| <section class="section"> |  | ||||||
| 	<div class="container cases-controls"> |  | ||||||
| 		<div class="field has-addons cases-control"> |  | ||||||
| 			<div class="buttons has-addons"> |  | ||||||
| 				<button |  | ||||||
| 					class={displayDataAs == 'Table' |  | ||||||
| 						? 'button is-dark is-selected is-small' |  | ||||||
| 						: 'button is-small'} |  | ||||||
| 					on:click={() => { |  | ||||||
| 						displayDataAs = 'Table'; |  | ||||||
| 					}}>Table</button |  | ||||||
| 				> |  | ||||||
| 				<button |  | ||||||
| 					class={displayDataAs == 'Cards' |  | ||||||
| 						? 'button is-dark is-selected is-small' |  | ||||||
| 						: 'button is-small'} |  | ||||||
| 					on:click={() => { |  | ||||||
| 						displayDataAs = 'Cards'; |  | ||||||
| 					}}>Cards</button |  | ||||||
| 				> |  | ||||||
| 			</div> |  | ||||||
| 		</div> |  | ||||||
| 		<div class="cases-control"> |  | ||||||
| 			<label for="sort-select">Sort cases by </label> |  | ||||||
| 			<div class="select is-small"> |  | ||||||
| 				<select bind:value={selectedSorting} id="sort-select"> |  | ||||||
| 					{#each sortOptions as sortOpt} |  | ||||||
| 						<option value={sortOpt}> |  | ||||||
| 							{sortOpt.label} |  | ||||||
| 						</option> |  | ||||||
| 					{/each} |  | ||||||
| 				</select> |  | ||||||
| 			</div> |  | ||||||
| 		</div> |  | ||||||
| 	</div> |  | ||||||
| </section> |  | ||||||
| 
 |  | ||||||
| {#if displayDataAs == 'Cards'} | {#if displayDataAs == 'Cards'} | ||||||
| 	<section class="section"> | 	<section class="section"> | ||||||
| 		<div class="container"> | 		<div class="container"> | ||||||
| 			<a | 			<CasesControls bind:displayDataAs bind:selectedSorting></CasesControls> | ||||||
| 				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} expanded={false} bind:modalOpen bind:activeCaseData></CaseCard> | 							<CaseCard cardData={attrCase} expanded={false} bind:modalOpen bind:activeCaseData | ||||||
|  | 							></CaseCard> | ||||||
| 						</div> | 						</div> | ||||||
| 					{/if} | 					{/if} | ||||||
| 				{/each} | 				{/each} | ||||||
| @ -324,10 +288,7 @@ | |||||||
| {#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 | 			<CasesControls bind:displayDataAs bind:selectedSorting></CasesControls> | ||||||
| 				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> | ||||||
| @ -340,7 +301,7 @@ | |||||||
| 				<p>{block.text}</p> | 				<p>{block.text}</p> | ||||||
| 			{/if} | 			{/if} | ||||||
| 			{#if block.type == 'concealed-text'} | 			{#if block.type == 'concealed-text'} | ||||||
|                 <Collapsible title={block.title} text={block.text} id={block.id}/> | 				<Collapsible title={block.title} text={block.text} id={block.id} /> | ||||||
| 			{/if} | 			{/if} | ||||||
| 		{/each} | 		{/each} | ||||||
| 	</div> | 	</div> | ||||||
| @ -384,11 +345,11 @@ | |||||||
| 		padding: 1rem; | 		padding: 1rem; | ||||||
| 		z-index: 750; | 		z-index: 750; | ||||||
| 	} | 	} | ||||||
| 	.cases-controls { |  | ||||||
| 		text-align: center; |  | ||||||
| 	} |  | ||||||
| 	.cases-control { | 	.cases-control { | ||||||
| 		display: inline-block; | 		display: inline-block; | ||||||
| 		margin-left: 3rem; | 		margin-right: 3rem; | ||||||
|  | 	} | ||||||
|  | 	.sort-label { | ||||||
|  | 		font-size: 0.9rem; | ||||||
| 	} | 	} | ||||||
| </style> | </style> | ||||||
|  | |||||||
		Загрузка…
	
	
			
			x
			
			
		
	
		Ссылка в новой задаче
	
	Block a user
	 Maarten
						Maarten