Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions netlify.toml
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
[context.production.environment]
COVIDCAST_ENDPOINT_URL = "https://api.covidcast.cmu.edu/epidata/api.php"
COVIDCAST_ENDPOINT_URL = "https://api.covidcast.cmu.edu/epidata"

[context.branch-deploy.environment]
COVIDCAST_ENDPOINT_URL = "https://api.covidcast.cmu.edu/epidata/api.php"
COVIDCAST_ENDPOINT_URL = "https://api.covidcast.cmu.edu/epidata"
COVIDCAST_ANNOTATION_DRAFTS = "true"

[context.deploy-preview.environment]
COVIDCAST_ENDPOINT_URL = "https://api.covidcast.cmu.edu/epidata/api.php"
COVIDCAST_ENDPOINT_URL = "https://api.covidcast.cmu.edu/epidata"
COVIDCAST_ANNOTATION_DRAFTS = "true"

[context.staging.environment]
COVIDCAST_ENDPOINT_URL = "https://api-staging.delphi.cmu.edu/epidata/api.php"
COVIDCAST_ENDPOINT_URL = "https://api-staging.delphi.cmu.edu/epidata"
COVIDCAST_SIGNAL_DOC = "https://docs.google.com/document/d/1llv6xh8jMlmVv7WpyDSv4VgUpFAZQ6QjFUeRxxOinmk,https://docs.google.com/document/d/17GQFgJDHF_ckkn-BE72QaHtyL2Dh09S8-4xk0r6G47w"
COVIDCAST_ANNOTATION_DRAFTS = "true"
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "www-covidcast",
"version": "2.3.1",
"version": "2.4.0",
"private": true,
"license": "MIT",
"description": "",
Expand Down
2 changes: 1 addition & 1 deletion src/blocks/HistoryLineChart.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
genDateHighlight,
genAnnotationLayer,
} from '../specs/lineSpec';
import { toTimeValue } from '../stores/params';
import { toTimeValue } from '../data/utils';
import Toggle from '../components/Toggle.svelte';
import SensorValue from '../components/SensorValue.svelte';
import { combineSignals } from '../data/utils';
Expand Down
6 changes: 3 additions & 3 deletions src/blocks/IndicatorOverview.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@
*/
export let fetcher;

$: trend = fetcher.fetchWindowTrend(sensor, region, date);
$: sparkline = fetcher.fetchSparkLine(sensor, region, date);
$: trend = fetcher.fetch1Sensor1Region1DateTrend(sensor, region, date);
$: sparkline = fetcher.fetch1Sensor1RegionSparkline(sensor, region, date);
$: spec = generateSparkLine({
domain: date.sparkLineTimeFrame.domain,
highlightDate: 'top',
Expand All @@ -42,7 +42,7 @@
{#await trend}
<KPIValue value={null} loading />
{:then d}
<KPIValue value={d && d.current ? d.current.value : null} digits={sensor.isPercentage ? 2 : 1} />
<KPIValue value={d ? d.value : null} digits={sensor.isPercentage ? 2 : 1} />
{/await}
</div>
<div class="sub">
Expand Down
2 changes: 1 addition & 1 deletion src/blocks/RegionCountyMap.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
domain: sensor.domain($stats, 'county'),
scheme: sensor.value.vegaColorScale,
});
$: data = fetcher.fetch1SensorNRegions1Date(sensor, 'county', '*', date);
$: data = fetcher.fetch1SensorNRegions1Date(sensor, 'county', date);

function onClickHandler(evt) {
const item = evt.detail.item;
Expand Down
8 changes: 3 additions & 5 deletions src/blocks/RegionHexMap.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import { generateSparkLine } from '../specs/lineSpec';
import HexGrid from '../components/HexGrid/HexGrid.svelte';
import HexGridCell from '../components/HexGrid/HexGridCell.svelte';
import { getInfoByName, stateInfo } from '../data/regions';
import { getInfoByName } from '../data/regions';
import { addMissing } from '../data';
import { groupByRegion } from '../stores/params';
import Vega from '../components/vega/Vega.svelte';
Expand Down Expand Up @@ -40,11 +40,9 @@
*/
function loadData(sensor, date, isMobile) {
loading = true;
const dateData = fetcher.fetch1SensorNRegions1Date(sensor, 'state', '*', date).then((rows) => groupByRegion(rows));
const dateData = fetcher.fetch1SensorNRegions1Date(sensor, 'state', date).then((rows) => groupByRegion(rows));
const sparkLines = !isMobile
? fetcher
.fetch1SensorNRegionsNDates(sensor, stateInfo, date.sparkLineTimeFrame, true)
.then((rows) => groupByRegion(rows))
? fetcher.fetch1SensorNRegionsNDates(sensor, 'state', date.sparkLineTimeFrame).then((rows) => groupByRegion(rows))
: null;

Promise.all([dateData, sparkLines]).then(() => {
Expand Down
11 changes: 5 additions & 6 deletions src/blocks/RegionMap.svelte
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<script>
import Vega from '../components/vega/Vega.svelte';
import { formatDateISO } from '../formats';
import { getCountiesOfState } from '../data/regions';
import { getCountiesOfState, getInfoByName } from '../data/regions';
import { generateCountiesOfStateSpec, generateRelatedCountySpec, generateStateSpec } from '../specs/mapSpec';
import { stats, isMobileDevice } from '../stores';
import DownloadMenu from '../components/DownloadMenu.svelte';
Expand Down Expand Up @@ -54,17 +54,16 @@
const counties = getCountiesOfState(region.value);
const countyData = fetcher.fetch1SensorNRegions1Date(
sensor,
'county',
`${region.id}000,${counties.map((d) => d.id).join(',')}`,
[...counties, getInfoByName(`${region.id}000`)],
date,
);
const stateData = fetcher.fetch1SensorNRegions1Date(sensor, 'state', '*', date);
const stateData = fetcher.fetch1SensorNRegions1Date(sensor, 'state', date);
return Promise.all([countyData, stateData]).then((r) => r.flat());
}
if (region.level === 'county') {
return fetcher.fetch1SensorNRegions1Date(sensor, 'county', '*', date);
return fetcher.fetch1SensorNRegions1Date(sensor, 'county', date);
}
return fetcher.fetch1SensorNRegions1Date(sensor, 'state', '*', date);
return fetcher.fetch1SensorNRegions1Date(sensor, 'state', date);
}

function generateFileName(sensor, date, region) {
Expand Down
6 changes: 3 additions & 3 deletions src/components/TrendIndicator.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

export let block = false;
/**
* @type {import("../stores/trend").TrendInfo}
* @type {import("../data/trend").SensorTrend}
*/
export let trend;
export let long = false;
Expand Down Expand Up @@ -42,9 +42,9 @@
{#if long}
<span class="trend-text"> {trend != null ? trend.trend : 'Unknown'} </span>
{#if trend != null && !trend.isUnknown}
<span class="trend-value"> {formatFraction(trend ? trend.fractionChange : null, true)} </span>
<span class="trend-value"> {formatFraction(trend ? trend.change : null, true)} </span>
{/if}
{:else}<span class="trend-value"> {formatFraction(trend ? trend.fractionChange : null, true)} </span>{/if}
{:else}<span class="trend-value"> {formatFraction(trend ? trend.change : null, true)} </span>{/if}
</div>

<style>
Expand Down
8 changes: 4 additions & 4 deletions src/components/TrendText.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@
?
{:else if trend.isBetter}
better by
{formatFraction(trend.fractionChange)}
{formatFraction(trend.change)}
{:else if trend.isWorse}
worse by
{formatFraction(trend.fractionChange)}
{formatFraction(trend.change)}
{:else if trend.isNeutral}
changed by
{formatFraction(trend.fractionChange)}
{:else}around the same with {formatFraction(trend.fractionChange)}{/if}
{formatFraction(trend.change)}
{:else}around the same with {formatFraction(trend.change)}{/if}
24 changes: 12 additions & 12 deletions src/components/TrendTextSummary.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import TrendText from './TrendText.svelte';

/**
* @type {Promise<import("../../stores/params").Trend>}
* @type {Promise<import("../../data/trend").SensorTrend>}
*/
export let trend;
/**
Expand Down Expand Up @@ -45,13 +45,13 @@
<strong>{sensor.value.name}</strong>
has
<strong>
<TrendText trend={d.minTrend} />
<TrendText trend={d.min} />
</strong>
compared to the
<strong
>{WINDOW_SIZE}
month minimum value of
<SensorValue {sensor} value={d.min ? d.min.value : null} medium /></strong
<SensorValue {sensor} value={d.min ? d.min.refValue : null} medium /></strong
>
on
<strong>{formatDateYearWeekdayAbbr(d.minDate, true)}</strong>.
Expand All @@ -61,13 +61,13 @@
<strong>{sensor.value.name}</strong>
has
<strong>
<TrendText trend={d.maxTrend} />
<TrendText trend={d.max} />
</strong>
compared to the
<strong
>{WINDOW_SIZE}
month maximum value of
<SensorValue {sensor} value={d.max ? d.max.value : null} medium /></strong
<SensorValue {sensor} value={d.max ? d.max.refValue : null} medium /></strong
>
on
<strong>{formatDateYearWeekdayAbbr(d.maxDate, true)}</strong>.
Expand All @@ -77,13 +77,13 @@
<strong>{sensor.value.name}</strong>
has
<strong>
<TrendText trend={d.minTrend} />
<TrendText trend={d.min} />
</strong>
compared to the
<strong
>{WINDOW_SIZE}
month minimum value of
<SensorValue {sensor} value={d.min ? d.min.value : null} medium /></strong
<SensorValue {sensor} value={d.min ? d.min.refValue : null} medium /></strong
>
on
<strong>{formatDateYearWeekdayAbbr(d.minDate, true)}</strong>.
Expand All @@ -93,13 +93,13 @@
<strong>{sensor.value.name}</strong>
has
<strong>
<TrendText trend={d.minTrend} />
<TrendText trend={d.min} />
</strong>
compared to the
<strong
>{WINDOW_SIZE}
month minimum value of
<SensorValue {sensor} value={d.min ? d.min.value : null} medium /></strong
<SensorValue {sensor} value={d.min ? d.min.refValue : null} medium /></strong
>
on
<strong>{formatDateYearWeekdayAbbr(d.minDate, true)}</strong>.
Expand All @@ -115,7 +115,7 @@
value compared to
<strong
>best value of
<SensorValue {sensor} value={d.best ? d.best.value : null} medium /></strong
<SensorValue {sensor} value={d.best ? d.best.refValue : null} medium /></strong
>
on
<strong>{formatDateYearWeekdayAbbr(d.bestDate, true)}</strong>.
Expand All @@ -125,13 +125,13 @@
<strong>{sensor.value.name}</strong>
was
<strong>
<TrendText trend={d.worstTrend} />
<TrendText trend={d.worst} />
</strong>
compared to the
<strong
>{WINDOW_SIZE}
month worst value of
<SensorValue {sensor} value={d.worst ? d.worst.value : null} medium /></strong
<SensorValue {sensor} value={d.worst ? d.worst.refValue : null} medium /></strong
>
on
<strong>{formatDateYearWeekdayAbbr(d.worstDate, true)}</strong>.
Expand Down
62 changes: 62 additions & 0 deletions src/data/TimeFrame.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { timeDay } from 'd3-time';
import type { EpiDataRow } from '.';
import { yesterdayDate } from '../stores';
import { formatAPITime } from './utils';

export class TimeFrame {
readonly min: Date;
readonly max: Date;
readonly difference: number;
readonly range: string;
readonly domain: [number, number];
readonly filter: (row: EpiDataRow) => boolean;

constructor(min: Date, max: Date) {
this.min = min;
this.max = max;
this.difference = timeDay.count(min, max);
this.range = `${formatAPITime(min)}-${formatAPITime(max)}`;
this.domain = [min.getTime(), max.getTime()];
/**
* @param {EpiDataRow} row
*/
this.filter = (row) => {
return row.date_value >= this.min && row.date_value <= this.max;
};
}

static compute(
date: Date,
offset: (date: Date, step: number) => Date,
offsetFactor: number,
maxDate = yesterdayDate,
): TimeFrame {
let max = offset(date, offsetFactor / 2);
if (max > maxDate) {
max = maxDate;
}
const min = offset(max, -offsetFactor);
return new TimeFrame(min, max);
}

shift(minShiftInDays = 0, maxShiftInDays = 0): TimeFrame {
return new TimeFrame(timeDay.offset(this.min, minShiftInDays), timeDay.offset(this.max, maxShiftInDays));
}

equals(that: TimeFrame): boolean {
return this.range === that.range;
}

includes(date: Date): boolean {
return date >= this.min && date <= this.max;
}

overlaps(timeFrame: TimeFrame): boolean {
// not outside of the range, so at least a partial overlap
return !(timeFrame.max < this.min || timeFrame.min > this.max);
}

toString(): string {
return this.range;
}
}
Loading