Show which slide show hours is fetched
This commit is contained in:
@@ -27,12 +27,14 @@ object DataService {
|
||||
class DataService(log: Logger[IO]) {
|
||||
val BASE_FOLDER = "data"
|
||||
val GRIB_FOLDER = s"$BASE_FOLDER/grib"
|
||||
val TMP_FOLDER = s"$BASE_FOLDER/tmp"
|
||||
|
||||
def init: IO[Unit] = {
|
||||
for {
|
||||
_ <- fs2.io.file.Files[IO].createDirectories(fs2.io.file.Path(BASE_FOLDER))
|
||||
_ <- fs2.io.file.Files[IO].createDirectories(fs2.io.file.Path(GRIB_FOLDER))
|
||||
_ <- log.info(s"Created directories: $BASE_FOLDER and $GRIB_FOLDER")
|
||||
_ <- fs2.io.file.Files[IO].createDirectories(fs2.io.file.Path(TMP_FOLDER))
|
||||
_ <- log.info(s"Created directories: $BASE_FOLDER, $GRIB_FOLDER, ${TMP_FOLDER}")
|
||||
} yield ()
|
||||
}
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ class FetchService(dataService: DataService, log: Logger[IO]) {
|
||||
request = Request[IO](Method.GET, urlWithParams)
|
||||
|
||||
// TODO proly better to call dataService method than property
|
||||
tmpPath = Path(s"${dataService.GRIB_FOLDER}/tmp.grib")
|
||||
tmpPath = Path(s"${dataService.TMP_FOLDER}/tmp.grib")
|
||||
_ <- client.stream(request)
|
||||
.flatMap(_.body)
|
||||
.through(Files[IO].writeAll(tmpPath))
|
||||
|
||||
@@ -17,7 +17,7 @@ export const Harmonie: Component<{}> = () => {
|
||||
const [getIsInterpolated, setIsInterpolated] = createSignal(true)
|
||||
const [getGribList, setGribList] = createSignal<GribMessage[]>([])
|
||||
const [getCanvas, setCanvas] = createSignal<HTMLCanvasElement>()
|
||||
const [getImgList, setImgList] = createSignal<[string, ImageBitmap][]>([])
|
||||
const [getImgList, setImgList] = createSignal<[string, ImageBitmap | undefined][]>([])
|
||||
|
||||
const cachedMessagesSignal = createSignal<GribMessage[]>([])
|
||||
const cachedBuffersSignal = createSignal<Uint8Array[]>([])
|
||||
@@ -70,7 +70,7 @@ export const Harmonie: Component<{}> = () => {
|
||||
getGribList={getGribList}
|
||||
getCanvas={getCanvas}
|
||||
options={{ getIsCrop: getIsCrop, getIsContour: getIsContour, getIsInterpolated: getIsInterpolated }}
|
||||
setImgList={setImgList}
|
||||
imgListSignal={[getImgList, setImgList]}
|
||||
onClick={getAllGribStructure}
|
||||
/>
|
||||
<ul class={styles.fileList}>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Accessor, Component, createSignal, resetErrorBoundaries, Setter } from 'solid-js'
|
||||
import { Accessor, Component, createSignal, resetErrorBoundaries, Setter, Signal } from 'solid-js'
|
||||
|
||||
import { DrawOptions, GribMessage } from './interfaces'
|
||||
import { fetchGribBinaries } from './fetchGrib'
|
||||
@@ -6,6 +6,7 @@ import { drawGrib } from './draw/drawGrib'
|
||||
import { CROP_BOUNDS } from './DrawView'
|
||||
|
||||
import styles from './harmonie.module.css'
|
||||
import { handleProgressivePromises } from '../helpers/progressivePromises'
|
||||
|
||||
export const ReferenceTimes: Component<{
|
||||
setIsLoading: Setter<boolean>,
|
||||
@@ -13,7 +14,7 @@ export const ReferenceTimes: Component<{
|
||||
getGribList: Accessor<GribMessage[]>,
|
||||
getCanvas: Accessor<HTMLCanvasElement | undefined>,
|
||||
options: DrawOptions,
|
||||
setImgList: Setter<[string, ImageBitmap][]>,
|
||||
imgListSignal: Signal<[string, ImageBitmap | undefined][]>,
|
||||
onClick: () => void,
|
||||
}> = ({
|
||||
setIsLoading,
|
||||
@@ -21,7 +22,7 @@ export const ReferenceTimes: Component<{
|
||||
getGribList,
|
||||
getCanvas,
|
||||
options,
|
||||
setImgList,
|
||||
imgListSignal: [getImgList, setImgList],
|
||||
onClick,
|
||||
}) => {
|
||||
const [getActiveDate, setActiveDate] = createSignal('')
|
||||
@@ -40,16 +41,19 @@ export const ReferenceTimes: Component<{
|
||||
setActiveDate(newValue)
|
||||
}
|
||||
|
||||
async function getImgList(dateStr: string) {
|
||||
async function fetchDrawImgList(refDateStr: string) {
|
||||
setIsLoading(true)
|
||||
const canvas = getCanvas()!
|
||||
const cropBounds = options.getIsCrop() ? CROP_BOUNDS : undefined
|
||||
const contour = options.getIsContour()
|
||||
const isInterpolated = options.getIsInterpolated()
|
||||
const forecastList = getGribList()
|
||||
.filter(g => g.time.referenceTime === dateStr)
|
||||
.filter(g => g.time.referenceTime === refDateStr)
|
||||
.filter(g => g.meteo.discipline === 0 && g.meteo.category === 1 && g.meteo.product === 192)
|
||||
// .slice(0, 5) // TODO remove this
|
||||
const emptyImgList: [string, undefined][] = forecastList
|
||||
.map((grib): [string, undefined] => [grib.time.forecastTime, undefined])
|
||||
.sort((a, b) => a[0] > b[0] ? 1 : -1)
|
||||
setImgList(emptyImgList)
|
||||
const promiseList = forecastList.map(async (grib): Promise<[string, ImageBitmap]> => {
|
||||
const [messages, buffers, bitmasks] = await fetchGribBinaries(grib, getGribList())
|
||||
drawGrib(canvas, messages, buffers, bitmasks, cropBounds, contour, isInterpolated)
|
||||
@@ -59,17 +63,20 @@ export const ReferenceTimes: Component<{
|
||||
return [grib.time.forecastTime, img]
|
||||
})
|
||||
|
||||
Promise.all(promiseList)
|
||||
.then(imgList => {
|
||||
imgList.sort((a, b) => a[0] > b[0] ? 1 : -1)
|
||||
setImgList(imgList)
|
||||
})
|
||||
.finally(() => {
|
||||
handleProgressivePromises(
|
||||
promiseList,
|
||||
([forecastDate, img]) => {
|
||||
const udpdatedImgList = [...getImgList()]
|
||||
const idx = udpdatedImgList.findIndex(([d]) => forecastDate === d)
|
||||
if (idx >= 0) udpdatedImgList[idx][1] = img
|
||||
setImgList(udpdatedImgList)
|
||||
},
|
||||
).finally(() => {
|
||||
console.log("FINALLLY")
|
||||
const ctx = canvas.getContext('2d')!
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height)
|
||||
setIsLoading(false)
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
return <ul class={styles.dateList}>
|
||||
@@ -81,7 +88,7 @@ export const ReferenceTimes: Component<{
|
||||
<div
|
||||
class={styles.controls}
|
||||
style={{ display: getActiveDate() === dateStr ? 'block' : 'none'}}
|
||||
onClick={() => getImgList(dateStr)}
|
||||
onClick={() => fetchDrawImgList(dateStr)}
|
||||
>
|
||||
{
|
||||
getGribList().some(g => g.time.referenceTime === dateStr)
|
||||
|
||||
@@ -4,21 +4,23 @@ import styles from './harmonie.module.css'
|
||||
|
||||
export const SlideShow: Component<{
|
||||
getCanvas: Accessor<HTMLCanvasElement | undefined>,
|
||||
getImgList: Accessor<[string, ImageBitmap][]>,
|
||||
getImgList: Accessor<[string, ImageBitmap | undefined][]>,
|
||||
}> = ({
|
||||
getCanvas,
|
||||
getImgList
|
||||
}) => {
|
||||
function draw(img: ImageBitmap) {
|
||||
function draw(img: ImageBitmap | undefined) {
|
||||
const canvas = getCanvas()!
|
||||
const ctx = canvas.getContext('2d')!
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height)
|
||||
if (!img) return;
|
||||
|
||||
ctx.drawImage(img, 0, 0)
|
||||
}
|
||||
|
||||
return <ul class={styles.slideShow}>
|
||||
{ getImgList().map(([forecastDate, img]) =>
|
||||
<li onClick={() => draw(img)}>
|
||||
<li class={img ? styles.withImg : ''} onClick={() => draw(img)}>
|
||||
{ format(forecastDate) }
|
||||
</li>)}
|
||||
</ul>
|
||||
|
||||
@@ -70,7 +70,17 @@
|
||||
padding: 10px 3px;
|
||||
}
|
||||
|
||||
.slideShow {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.slideShow li {
|
||||
display: inline;
|
||||
font-size: 14px;
|
||||
padding: 3px 3px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.withImg {
|
||||
background-color: rgb(187, 247, 187);
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
export async function handleProgressivePromises<T>(
|
||||
promises: Promise<T>[],
|
||||
onProgress: (result: T) => void,
|
||||
): Promise<(T | undefined)[]> {
|
||||
const allPromises = promises.map(async promise => {
|
||||
try {
|
||||
const result = await promise;
|
||||
onProgress(result)
|
||||
return result
|
||||
} catch (error) {
|
||||
return undefined
|
||||
}
|
||||
})
|
||||
|
||||
const results = await Promise.allSettled(allPromises)
|
||||
return results.map(result =>
|
||||
result.status === 'fulfilled' ? result.value : undefined
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user