Skip to content

Commit

Permalink
Merge pull request #81 from cmu-delphi/release/v2.1.5
Browse files Browse the repository at this point in the history
Release v2.1.5
  • Loading branch information
melange396 authored Dec 9, 2024
2 parents 78415eb + 730f297 commit 5c8526f
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 34 deletions.
4 changes: 2 additions & 2 deletions 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-epivis",
"version": "2.1.4",
"version": "2.1.5",
"private": true,
"license": "MIT",
"description": "",
Expand Down
40 changes: 29 additions & 11 deletions src/api/EpiData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ export function loadDataSet(
fixedParams: Record<string, unknown>,
userParams: Record<string, unknown>,
columns: string[],
api_key = '',
columnRenamings: Record<string, string> = {},
): Promise<DataGroup | null> {
const duplicates = get(expandedDataGroups).filter((d) => d.title == title);
Expand All @@ -131,7 +132,11 @@ export function loadDataSet(
)
.then(() => null);
}
const url = new URL(ENDPOINT + `/${endpoint}/`);
let url_string = ENDPOINT + `/${endpoint}/`;
if (api_key !== '') {
url_string += `?api_key=${api_key}`;
}
const url = new URL(url_string);
const params = cleanParams(userParams);
Object.entries(fixedParams).forEach(([key, value]) => {
url.searchParams.set(key, String(value));
Expand Down Expand Up @@ -168,10 +173,14 @@ export function loadDataSet(
});
}

export function fetchCOVIDcastMeta(): Promise<
{ geo_type: string; signal: string; data_source: string; time_type?: string }[]
> {
const url = new URL(ENDPOINT + `/covidcast_meta/`);
export function fetchCOVIDcastMeta(
api_key: string,
): Promise<{ geo_type: string; signal: string; data_source: string; time_type?: string }[]> {
let url_string = ENDPOINT + `/covidcast_meta/`;
if (api_key !== '') {
url_string += `?api_key=${api_key}`;
}
const url = new URL(url_string);
url.searchParams.set('format', 'json');
return fetchImpl<{ geo_type: string; signal: string; data_source: string; time_type?: string }[]>(url).catch(
(error) => {
Expand All @@ -190,8 +199,9 @@ export function importCDC({ locations, auth }: { locations: string; auth?: strin
{
epiweeks: epiRange(firstEpiWeek.cdc, currentEpiWeek),
},
{ auth, locations },
{ locations },
['total', 'num1', 'num2', 'num3', 'num4', 'num5', 'num6', 'num7', 'num8'],
auth,
);
}

Expand All @@ -201,12 +211,14 @@ export function importCOVIDcast({
geo_value,
signal,
time_type = 'day',
api_key,
}: {
data_source: string;
signal: string;
time_type?: string;
geo_type: string;
geo_value: string;
api_key: string;
}): Promise<DataGroup | null> {
const title = `[API] COVIDcast: ${data_source}:${signal} (${geo_type}:${geo_value})`;
return loadDataSet(
Expand All @@ -221,6 +233,7 @@ export function importCOVIDcast({
},
{ data_source, signal, time_type, geo_type, geo_value },
['value', 'stderr', 'sample_size'],
api_key,
);
}

Expand Down Expand Up @@ -343,7 +356,7 @@ export function importFluView({
{
epiweeks: epiRange(firstEpiWeek.fluview, currentEpiWeek),
},
{ regions, issues, lag, auth },
{ regions, issues, lag },
[
'wili',
'ili',
Expand All @@ -357,6 +370,7 @@ export function importFluView({
'num_age_4',
'num_age_5',
],
auth,
{
wili: '%wILI',
ili: '%ILI',
Expand Down Expand Up @@ -395,8 +409,9 @@ export function importGHT({
{
epiweeks: epiRange(firstEpiWeek.ght, currentEpiWeek),
},
{ auth, locations, query },
{ locations, query },
['value'],
auth,
);
}

Expand Down Expand Up @@ -456,8 +471,9 @@ export function importQuidel({ auth, locations }: { auth: string; locations: str
{
epiweeks: epiRange(firstEpiWeek.quidel, currentEpiWeek),
},
{ auth, locations },
{ locations },
['value'],
auth,
);
}
export function importSensors({
Expand All @@ -478,8 +494,9 @@ export function importSensors({
{
epiweeks: epiRange(firstEpiWeek.sensors, currentEpiWeek),
},
{ auth, names, locations },
{ names, locations },
['value'],
auth,
);
}
// twtr
Expand All @@ -504,8 +521,9 @@ export function importTwitter({
: {
epiweeks: epiRange(firstEpiWeek.twitter, currentEpiWeek),
},
{ auth, locations, resolution },
{ locations, resolution },
['num', 'total', 'percent'],
auth,
);
}
export function importWiki({
Expand Down
89 changes: 69 additions & 20 deletions src/components/dialogs/dataSources/COVIDcast.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,13 @@
export let id: string;
let api_key = '';
let data_source = '';
let signal = '';
let geo_type = '';
let geo_value = '';
let form_key = '';
let valid_key = true;
let dataSources: (LabelValue & { signals: string[] })[] = [];
let geoTypes: string[] = [];
Expand All @@ -23,38 +26,77 @@
}
}
onMount(() => {
fetchCOVIDcastMeta().then((res) => {
geoTypes = [...new Set(res.map((d) => d.geo_type))];
const byDataSource = new Map<string, LabelValue & { signals: string[] }>();
for (const row of res) {
const ds = byDataSource.get(row.data_source);
if (!ds) {
byDataSource.set(row.data_source, {
label: row.data_source,
value: row.data_source,
signals: [row.signal],
});
} else if (!ds.signals.includes(row.signal)) {
ds.signals.push(row.signal);
// Helper function; delay invoking "fn" until "ms" milliseconds have passed
const debounce = (fn: Function, ms = 500) => {
let timeoutId: ReturnType<typeof setTimeout>;
return function (this: any, ...args: any[]) {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => fn.apply(this, args), ms);
};
};
function fetchMetadata() {
fetchCOVIDcastMeta(form_key).then((res) => {
if (res.length == 0) {
valid_key = false;
} else {
valid_key = true;
api_key = form_key; // API key is valid -> use it to fetch data later on
geoTypes = [...new Set(res.map((d) => d.geo_type))];
const byDataSource = new Map<string, LabelValue & { signals: string[] }>();
for (const row of res) {
const ds = byDataSource.get(row.data_source);
if (!ds) {
byDataSource.set(row.data_source, {
label: row.data_source,
value: row.data_source,
signals: [row.signal],
});
} else if (!ds.signals.includes(row.signal)) {
ds.signals.push(row.signal);
}
}
byDataSource.forEach((entry) => {
entry.signals.sort();
});
dataSources = [...byDataSource.values()].sort((a, b) => a.value.localeCompare(b.value));
}
byDataSource.forEach((entry) => {
entry.signals.sort();
});
dataSources = [...byDataSource.values()].sort((a, b) => a.value.localeCompare(b.value));
});
}
onMount(() => {
fetchMetadata();
});
export function importDataSet() {
return fetchCOVIDcastMeta().then((res) => {
return fetchCOVIDcastMeta(api_key).then((res) => {
const meta = res.filter((row) => row.data_source === data_source && row.signal === signal);
const time_type = meta[0].time_type;
return importCOVIDcast({ data_source, signal, geo_type, geo_value, time_type });
return importCOVIDcast({ data_source, signal, geo_type, geo_value, time_type, api_key });
});
}
</script>

<div>
<label class="uk-form-label" for="{id}-apikey">
<a href="https://cmu-delphi.github.io/delphi-epidata/api/api_keys.html">API Key</a> (optional)
</label>
<div class="uk-form-controls">
<input
id="{id}-apikey"
type="text"
class="uk-input"
class:uk-form-danger={!valid_key}
name="api_key"
required={false}
bind:value={form_key}
on:input={debounce(() => fetchMetadata(), 500)}
/>
{#if !valid_key}
<div class="invalid">API key is invalid - ignoring</div>
{/if}
</div>
</div>
<SelectField id="{id}-r" label="Data Source" name="data_source" bind:value={data_source} options={dataSources} />
<SelectField id="{id}-r" label="Data Signal" name="signal" bind:value={signal} options={dataSignals} />
<SelectField id="{id}-gt" label="Geographic Type" bind:value={geo_type} name="geo_type" options={geoTypes} />
Expand All @@ -65,3 +107,10 @@
name="geo_values"
placeholder="e.g., PA or 42003"
/>

<style>
.invalid {
color: red;
font-size: 0.75rem;
}
</style>

0 comments on commit 5c8526f

Please sign in to comment.