|
53 | 53 | */
|
54 | 54 | export let ends = null;
|
55 | 55 |
|
| 56 | + export let expandableWindow = false; |
| 57 | +
|
| 58 | + let showFull = false; |
| 59 | +
|
56 | 60 | /**
|
57 | 61 | * @type {import("../../stores/params").Region}
|
58 | 62 | */
|
|
66 | 70 | };
|
67 | 71 |
|
68 | 72 | $: highlightDate = date.value;
|
| 73 | + $: timeFrame = showFull && expandableWindow ? date.sensorTimeFrame : date.windowTimeFrame; |
69 | 74 |
|
70 | 75 | /**
|
71 | 76 | * @param {import('../../stores/params').SensorParam} sensor
|
72 | 77 | * @param {import('../../stores/params').RegionParam} region
|
73 | 78 | * @param {import('../../stores/params').DateParam} date
|
74 | 79 | */
|
75 |
| - function genSpec(sensor, region, date, height, zero, singleRaw, isMobile) { |
| 80 | + function genSpec(sensor, region, date, timeFrame, height, zero, singleRaw, isMobile) { |
76 | 81 | const options = {
|
77 | 82 | initialDate: highlightDate || date.value,
|
78 | 83 | height,
|
79 | 84 | color: MULTI_COLORS[0],
|
80 |
| - domain: date.windowTimeFrame.domain, |
| 85 | + domain: timeFrame.domain, |
81 | 86 | zero,
|
82 | 87 | xTitle: sensor.xAxis,
|
83 | 88 | title: [sensor.name, `in ${region.displayName}`],
|
|
111 | 116 | * @param {import("../../stores/params").DateParam} date
|
112 | 117 | * @param {import("../../stores/params").RegionParam} region
|
113 | 118 | */
|
114 |
| - function loadData(sensor, region, date) { |
115 |
| - if (!region.value || !date.value) { |
| 119 | + function loadData(sensor, region, timeFrame) { |
| 120 | + if (!region.value) { |
116 | 121 | return null;
|
117 | 122 | }
|
118 |
| - const selfData = fetcher.fetch1Sensor1RegionNDates(sensor, region, date.windowTimeFrame); |
| 123 | + const selfData = fetcher.fetch1Sensor1RegionNDates(sensor, region, timeFrame); |
119 | 124 |
|
120 | 125 | const data = [selfData];
|
121 | 126 |
|
122 | 127 | if (region.level === 'county') {
|
123 | 128 | const state = getInfoByName(region.state);
|
124 |
| - const stateData = fetcher.fetch1Sensor1RegionNDates(sensor, state, date.windowTimeFrame); |
| 129 | + const stateData = fetcher.fetch1Sensor1RegionNDates(sensor, state, timeFrame); |
125 | 130 | const relatedCounties = getRelatedCounties(region.value);
|
126 | 131 | const relatedData = fetcher
|
127 |
| - .fetch1SensorNRegionsNDates(sensor, relatedCounties, date.windowTimeFrame) |
| 132 | + .fetch1SensorNRegionsNDates(sensor, relatedCounties, timeFrame) |
128 | 133 | .then((r) => averageByDate(r, sensor, neighboringInfo))
|
129 | 134 | .then((r) => addMissing(r, sensor));
|
130 | 135 | data.push(relatedData, stateData);
|
131 | 136 | }
|
132 | 137 | if (region.level !== 'nation') {
|
133 |
| - data.push(fetcher.fetch1Sensor1RegionNDates(sensor, nationInfo, date.windowTimeFrame)); |
| 138 | + data.push(fetcher.fetch1Sensor1RegionNDates(sensor, nationInfo, timeFrame)); |
134 | 139 | }
|
135 | 140 | return Promise.all(data).then((rows) => rows.reverse().flat());
|
136 | 141 | }
|
|
140 | 145 | * @param {import("../../stores/params").DateParam} date
|
141 | 146 | * @param {import("../../stores/params").RegionParam} region
|
142 | 147 | */
|
143 |
| - function loadSingleData(sensor, region, date) { |
144 |
| - if (!region.value || !date.value) { |
| 148 | + function loadSingleData(sensor, region, timeFrame) { |
| 149 | + if (!region.value) { |
145 | 150 | return null;
|
146 | 151 | }
|
147 |
| - const selfData = fetcher.fetch1Sensor1RegionNDates(sensor, region, date.windowTimeFrame); |
148 |
| - const rawData = fetcher.fetch1Sensor1RegionNDates(sensor.rawValue, region, date.windowTimeFrame); |
| 152 | + const selfData = fetcher.fetch1Sensor1RegionNDates(sensor, region, timeFrame); |
| 153 | + const rawData = fetcher.fetch1Sensor1RegionNDates(sensor.rawValue, region, timeFrame); |
149 | 154 |
|
150 | 155 | return Promise.all([selfData, rawData]).then((data) => {
|
151 | 156 | return combineSignals(data, data[0], ['smoothed', 'raw']);
|
|
174 | 179 | /**
|
175 | 180 | * @param {import("../../stores/params").SensorParam} sensor
|
176 | 181 | * @param {import("../../stores/params").Region[]} region
|
177 |
| - * @param {import("../../stores/params").DateParam} date |
178 | 182 | */
|
179 |
| - function generateFileName(sensor, regions, date, raw) { |
| 183 | + function generateFileName(sensor, regions, timeFrame, raw) { |
180 | 184 | const regionName = regions.map((region) => `${region.propertyId}-${region.displayName}`).join(',');
|
181 | 185 | let suffix = '';
|
182 | 186 | if (raw) {
|
183 | 187 | suffix = '_RawVsSmoothed';
|
184 | 188 | }
|
185 |
| - return `${sensor.name}_${regionName}_${formatDateISO(date.windowTimeFrame.min)}-${formatDateISO( |
186 |
| - date.windowTimeFrame.max, |
187 |
| - )}${suffix}`; |
| 189 | + return `${sensor.name}_${regionName}_${formatDateISO(timeFrame.min)}-${formatDateISO(timeFrame.max)}${suffix}`; |
188 | 190 | }
|
189 | 191 |
|
190 |
| - function injectRanges(spec, date, annotations) { |
| 192 | + function injectRanges(spec, timeFrame, annotations) { |
191 | 193 | if (annotations.length > 0) {
|
192 |
| - spec.layer.unshift(genAnnotationLayer(annotations, date.windowTimeFrame)); |
| 194 | + spec.layer.unshift(genAnnotationLayer(annotations, timeFrame)); |
193 | 195 | }
|
194 |
| - if (starts && starts > date.windowTimeFrame.min) { |
195 |
| - spec.layer.unshift(genDateHighlight(starts > date.windowTimeFrame.max ? date.windowTimeFrame.max : starts)); |
| 196 | + if (starts && starts > timeFrame.min) { |
| 197 | + spec.layer.unshift(genDateHighlight(starts > timeFrame.max ? timeFrame.max : starts)); |
196 | 198 | }
|
197 |
| - if (ends && ends < date.windowTimeFrame.max) { |
198 |
| - spec.layer.unshift(genDateHighlight(ends < date.windowTimeFrame.min ? date.windowTimeFrame.min : ends)); |
| 199 | + if (ends && ends < timeFrame.max) { |
| 200 | + spec.layer.unshift(genDateHighlight(ends < timeFrame.min ? timeFrame.min : ends)); |
199 | 201 | }
|
200 | 202 | return spec;
|
201 | 203 | }
|
|
204 | 206 | let singleRaw = false;
|
205 | 207 |
|
206 | 208 | $: regions = raw ? [region.value] : resolveRegions(region.value);
|
207 |
| - $: annotations = $annotationManager.getWindowAnnotations( |
208 |
| - sensor.value, |
209 |
| - regions, |
210 |
| - date.windowTimeFrame.min, |
211 |
| - date.windowTimeFrame.max, |
212 |
| - ); |
| 209 | + $: annotations = $annotationManager.getWindowAnnotations(sensor.value, regions, timeFrame.min, timeFrame.max); |
213 | 210 | $: raw = singleRaw && sensor.rawValue != null;
|
214 |
| - $: spec = injectRanges(genSpec(sensor, region, date, height, !zoom, raw, $isMobileDevice), date, annotations); |
215 |
| - $: data = raw ? loadSingleData(sensor, region, date) : loadData(sensor, region, date); |
216 |
| - $: fileName = generateFileName(sensor, regions, date, raw); |
| 211 | + $: spec = injectRanges( |
| 212 | + genSpec(sensor, region, date, timeFrame, height, !zoom, raw, $isMobileDevice), |
| 213 | + timeFrame, |
| 214 | + annotations, |
| 215 | + ); |
| 216 | + $: data = raw ? loadSingleData(sensor, region, timeFrame) : loadData(sensor, region, timeFrame); |
| 217 | + $: fileName = generateFileName(sensor, regions, timeFrame, raw); |
217 | 218 |
|
218 | 219 | function findValue(region, data, date, prop = 'value') {
|
219 | 220 | if (!date) {
|
|
243 | 244 |
|
244 | 245 | <Vega
|
245 | 246 | bind:this={vegaRef}
|
246 |
| - {className} |
| 247 | + className="{className} {showFull && expandableWindow ? 'chart-breakout' : ''}" |
247 | 248 | {spec}
|
248 | 249 | {data}
|
249 | 250 | tooltip={HistoryLineTooltip}
|
|
258 | 259 | {#if sensor.rawValue != null}
|
259 | 260 | <Toggle bind:checked={singleRaw}>Raw Data</Toggle>
|
260 | 261 | {/if}
|
| 262 | + {#if expandableWindow} |
| 263 | + <Toggle bind:checked={showFull}>Show All Dates</Toggle> |
| 264 | + {/if} |
261 | 265 | <div class="spacer" />
|
262 | 266 | <DownloadMenu {fileName} {vegaRef} {data} {sensor} {raw} />
|
263 | 267 | </div>
|
|
0 commit comments