checkbox to highlight cases with polarization data

Этот коммит содержится в:
higsch 2020-12-03 15:41:18 +01:00
родитель d0818395a8
Коммит d983f423a2
9 изменённых файлов: 108 добавлений и 23 удалений

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

@ -22,7 +22,7 @@
} }
input[type="checkbox"] { input[type="checkbox"] {
display:none; display: none;
pointer-events: all; pointer-events: all;
} }
@ -30,6 +30,7 @@
display: block; display: block;
width: 15px; width: 15px;
height: 15px; height: 15px;
margin-top: 3px;
margin-right: 0.4rem; margin-right: 0.4rem;
border: 2px solid var(--usa-blue); border: 2px solid var(--usa-blue);
border-radius: 3px; border-radius: 3px;

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

@ -0,0 +1,47 @@
<script>
import { highlightPolarization } from '../stores/filters';
import Checkbox from './Checkbox.svelte';
function handleClick(type) {
switch (type) {
case 'polarization':
$highlightPolarization = !$highlightPolarization;
break;
}
}
</script>
<ul class="checkboxpanel-wrapper">
<li>
<Checkbox id="checkboxpanel-checkbox-polarization"
checked={$highlightPolarization}
on:click={() => handleClick('polarization')}>
<span>Highlight cases with polarization data</span>
</Checkbox>
</li>
</ul>
<style>
ul {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
margin: 0.5rem 0;
list-style-type: none;
}
li {
padding: 0.4rem 0;
position: relative;
}
span {
display: inline-block;
margin: 0 0 0 0.5rem;
font-family: var(--font-02);
font-size: 0.8rem;
color: var(--usa-blue);
}
</style>

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

@ -11,12 +11,14 @@
textSearchFilter, textSearchFilter,
selectAllFilters, selectAllFilters,
contextData, contextData,
originalTimeDomain } from '../stores/filters'; originalTimeDomain,
highlightPolarization } from '../stores/filters';
import { timeScale, attributionScoreScale } from '../stores/scales'; import { timeScale, attributionScoreScale } from '../stores/scales';
import Dropdown from './Dropdown.svelte'; import Dropdown from './Dropdown.svelte';
import Slider from './Slider.svelte'; import Slider from './Slider.svelte';
import SearchText from './SearchText.svelte'; import SearchText from './SearchText.svelte';
import CheckboxPanel from './CheckboxPanel.svelte';
import Share from './Share.svelte'; import Share from './Share.svelte';
export let timePoints; export let timePoints;
@ -32,6 +34,7 @@
function handleButtonClick() { function handleButtonClick() {
selectAllFilters(); selectAllFilters();
contextData.unselectAll(); contextData.unselectAll();
$highlightPolarization = false;
if ($originalTimeDomain) { if ($originalTimeDomain) {
$timeScale.domain($originalTimeDomain); $timeScale.domain($originalTimeDomain);
$timeScale = $timeScale; $timeScale = $timeScale;
@ -89,6 +92,9 @@
Reset Reset
</button> </button>
</div> </div>
<div class="checkbox-panel">
<CheckboxPanel />
</div>
<Share /> <Share />
</div> </div>
{/if} {/if}

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

@ -56,16 +56,18 @@
<div class="polarization-strip" <div class="polarization-strip"
bind:clientWidth={width}> bind:clientWidth={width}>
<svg class="pol-magnifier" {#if (width > 0)}
width={width} <svg class="pol-magnifier"
height={magnifierHeight}> width={width}
<path d={line(leftPathData)} /> height={magnifierHeight}>
<path d={line(rightPathData)} /> <path d={line(leftPathData)} />
<text x={Math.max(15, valueWidth / 2)} <path d={line(rightPathData)} />
y={yScale(1)}> <text x={Math.max(15, valueWidth / 2)}
{Math.round(engagementExplained * 100)}% y={yScale(1)}>
</text> {Math.round(engagementExplained * 100)}%
</svg> </text>
</svg>
{/if}
<div class="pol-layer-wrapper"> <div class="pol-layer-wrapper">
{#each categories as category (category.id)} {#each categories as category (category.id)}
<div class="pol-layer pol-{category.id}" <div class="pol-layer pol-{category.id}"

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

@ -10,7 +10,8 @@
attributionScoreDef, attributionScoreDef,
textSearchFilter, textSearchFilter,
originalTimeDomain, originalTimeDomain,
contextData } from '../stores/filters'; contextData,
highlightPolarization } from '../stores/filters';
import { urlFromFilters } from '../utils/share'; import { urlFromFilters } from '../utils/share';
import Icon from 'svelte-awesome'; import Icon from 'svelte-awesome';
@ -37,7 +38,8 @@
$attributionScoreFilter, $attributionScoreFilter,
$textSearchFilter, $textSearchFilter,
$contextData, $contextData,
caseId); caseId,
$highlightPolarization);
</script> </script>
<div class="share"> <div class="share">

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

@ -35,8 +35,15 @@
originalTimeDomain, originalTimeDomain,
contextData, contextData,
caseIdFilter, caseIdFilter,
tagFilter } from '../stores/filters'; tagFilter,
import { haveOverlap, withinRange, includesTextSearch, isCaseId, preloadImages } from '../utils/misc'; highlightPolarization } from '../stores/filters';
import {
haveOverlap,
withinRange,
includesTextSearch,
isCaseId,
showPolarization,
preloadImages } from '../utils/misc';
import { selected } from '../stores/eventSelections'; import { selected } from '../stores/eventSelections';
import { drawWrapper } from '../stores/elements'; import { drawWrapper } from '../stores/elements';
@ -134,6 +141,7 @@
$attributionScoreFilter = urlFilters.attributionScores; $attributionScoreFilter = urlFilters.attributionScores;
$textSearchFilter = urlFilters.textSearch; $textSearchFilter = urlFilters.textSearch;
$caseIdFilter = urlFilters.caseId; $caseIdFilter = urlFilters.caseId;
$highlightPolarization = urlFilters.highlightPolarization;
} }
}); });
@ -203,6 +211,7 @@
&& includesTextSearch($textSearchFilter, d.search) && includesTextSearch($textSearchFilter, d.search)
&& withinRange($attributionScoreFilter, d.attributionScore) && withinRange($attributionScoreFilter, d.attributionScore)
&& isCaseId($caseIdFilter, d.id) && isCaseId($caseIdFilter, d.id)
&& showPolarization($highlightPolarization, d.polarization)
})); }));
} }
</script> </script>

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

@ -94,3 +94,5 @@ export const brushed = writable(false);
export const originalTimeDomain = writable(null); export const originalTimeDomain = writable(null);
export const caseIdFilter = writable(); export const caseIdFilter = writable();
export const highlightPolarization = writable(false);

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

@ -53,6 +53,12 @@ export const includesTextSearch = (filter, s) => {
// check if case id filter is set and if id is matching // check if case id filter is set and if id is matching
export const isCaseId = (filter, id) => filter === undefined ? true : (filter === id); export const isCaseId = (filter, id) => filter === undefined ? true : (filter === id);
// check, if polarization data can be shown
export const showPolarization = (filter, polarization) => {
if (!filter) return(true);
return(polarization.fulfills10Articles || polarization.fulfills25Percent);
};
// extract filter items from data // extract filter items from data
export const extractFilterCategories = (data, name) => export const extractFilterCategories = (data, name) =>
uniq(data.map((d) => d[name]).flat()); uniq(data.map((d) => d[name]).flat());

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

@ -1,5 +1,5 @@
export const baseUrl = 'https://interference2020.org'; // export const baseUrl = 'https://interference2020.org';
// export const baseUrl = 'http://localhost:5000'; export const baseUrl = 'http://localhost:5000';
export const urlFromFilters = (disinformantNations, export const urlFromFilters = (disinformantNations,
platforms, platforms,
@ -10,15 +10,17 @@ export const urlFromFilters = (disinformantNations,
attributionScores, attributionScores,
textSearch, textSearch,
contextData, contextData,
caseId = '') => { caseId = '',
highlightPolarization) => {
const params = { const params = {
ts: encodeURIComponent(textSearch), ts: encodeURIComponent(textSearch),
as: [attributionScores[0], attributionScores[1]].join(';'), as: [attributionScores[0], attributionScores[1]].join(';'),
f: filtersToHex([disinformantNations, platforms, methods, sources, sourceCategories, tags, contextData]), f: filtersToHex([disinformantNations, platforms, methods, sources, sourceCategories, tags, contextData]),
id: caseId id: caseId,
bool: filtersToBin([highlightPolarization])
}; };
return `${baseUrl}/#${params.f}-${params.id}-${params.ts}-${params.as}`; return `${baseUrl}/#${params.f}-${params.id}-${params.ts}-${params.as}-${params.bool}`;
}; };
export const filtersToHex = (arr) => { export const filtersToHex = (arr) => {
@ -26,6 +28,11 @@ export const filtersToHex = (arr) => {
return hex; return hex;
}; };
export const filtersToBin = (arr) => {
const bin = arr.map((d) => d ? 1 : 0).join('');
return bin;
};
export const binaryToHex = (binary) => parseInt(binary , 2).toString(16).toLowerCase(); export const binaryToHex = (binary) => parseInt(binary , 2).toString(16).toLowerCase();
export const hexToBinary = (hex) => parseInt(hex, 16).toString(2); export const hexToBinary = (hex) => parseInt(hex, 16).toString(2);
@ -34,7 +41,9 @@ export const binaryToBool = (binary) => binary.split('').map((d) => d === '0' ?
export const parseUrl = (hash) => { export const parseUrl = (hash) => {
const s = hash.substring(1); const s = hash.substring(1);
const [ disinformantNations, platforms, methods, sources, sourceCategories, tags, contextData, caseId, textSearch, attributionScores] = s.split('-'); const [ disinformantNations, platforms, methods, sources, sourceCategories, tags, contextData, caseId, textSearch, attributionScores, bools] = s.split('-');
const boolArray = bools.split('').map((d) => +d === 1 ? true : false);
return { return {
disinformantNations: binaryToBool(hexToBinary(disinformantNations)), disinformantNations: binaryToBool(hexToBinary(disinformantNations)),
@ -46,6 +55,7 @@ export const parseUrl = (hash) => {
contextData: binaryToBool(hexToBinary(contextData)), contextData: binaryToBool(hexToBinary(contextData)),
caseId: caseId === '' ? undefined : +caseId, caseId: caseId === '' ? undefined : +caseId,
textSearch: decodeURIComponent(textSearch), textSearch: decodeURIComponent(textSearch),
attributionScores: attributionScores.split(';').map((d) => +d) attributionScores: attributionScores.split(';').map((d) => +d),
highlightPolarization: boolArray[0]
}; };
}; };