Skip to content

Commit

Permalink
[migrate] upgrade Map page & components
Browse files Browse the repository at this point in the history
[optimize] simplify Type & Logic of Map page
  • Loading branch information
TechQuery committed Jan 28, 2024
1 parent a55361c commit e66403e
Show file tree
Hide file tree
Showing 16 changed files with 373 additions and 424 deletions.
1 change: 1 addition & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"prefer-const": "warn",
"no-unused-vars": "warn",
"@typescript-eslint/no-unused-vars": "warn",
"@typescript-eslint/no-explicit-any": "warn",
"@typescript-eslint/no-unsafe-declaration-merging": "warn",
"@typescript-eslint/explicit-module-boundary-types": "off",
"@typescript-eslint/ban-ts-comment": "warn"
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "wuhan2020-pwa",
"version": "1.1.0",
"version": "1.2.0",
"license": "AGPL-3.0",
"author": "[email protected]",
"description": "武汉新型冠状病毒防疫信息平台",
Expand Down
4 changes: 1 addition & 3 deletions source/page/Factory/edit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -180,19 +180,17 @@ export class FactoryEdit
label="备注"
defaultValue={remark}
/>
<div className="form-group mt-3">
<div className="form-group mt-3 d-flex flex-column">
<Button
type="submit"
variant="primary"
className="d-block"
disabled={factory.loading}
>
提交
</Button>
<Button
type="reset"
variant="danger"
className="d-block"
onClick={() => (location.hash = RouteRoot.Factory)}
>
取消
Expand Down
4 changes: 1 addition & 3 deletions source/page/Hospital/Edit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -174,19 +174,17 @@ export class HospitalEdit
label="备注"
defaultValue={remark}
/>
<div className="form-group mt-3">
<div className="form-group mt-3 d-flex flex-column">
<Button
type="submit"
variant="primary"
className="d-block"
disabled={suppliesRequirement.loading}
>
提交
</Button>
<Button
type="reset"
variant="danger"
className="d-block"
onClick={() => (location.hash = RouteRoot.Hospital)}
>
取消
Expand Down
4 changes: 1 addition & 3 deletions source/page/Hotel/Edit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -159,19 +159,17 @@ export class HotelEdit extends HTMLElement implements WebCell<HotelEditProps> {
defaultValue={remark}
label="备注"
/>
<div className="form-group mt-3">
<div className="form-group mt-3 d-flex flex-column">
<Button
type="submit"
variant="primary"
className="d-block"
disabled={hotel.loading}
>
提交
</Button>
<Button
type="reset"
variant="danger"
className="d-block"
onClick={() => (location.hash = RouteRoot.Hotel)}
>
取消
Expand Down
90 changes: 47 additions & 43 deletions source/page/Map/adapter/isaaclin.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { Hour } from 'web-utility';
import {
CountryOverviewData,
CountryData,
Expand All @@ -7,30 +8,28 @@ import {
Series
} from './patientStatInterface';
import { long2short } from './long2short'; // some city names are NOT short names so we also convert them here
import { City, Province } from '../../../service/Epidemic';

function convertStat(source): PatientStatData {
return {
confirmed: source.confirmedCount,
suspected: source.suspectedCount,
cured: source.curedCount,
dead: source.deadCount
};
}

export function convertCountry(source: Province[]): CountryData {
// currently we only support china
return {
name: '中国',
confirmed: 0,
suspected: 0,
cured: 0,
dead: 0,
provinces: Object.fromEntries(
source.map(item => [item.provinceShortName, convertProvince(item)])
)
};
}
import { City, Province, StatisticData } from '../../../service/Epidemic';

const convertStat = (source: StatisticData): PatientStatData => ({
confirmed: source.confirmedCount,
suspected: source.suspectedCount,
cured: source.curedCount,
dead: source.deadCount
});

/**
* currently we only support china
*/
export const convertCountry = (source: Province[]): CountryData => ({
name: '中国',
confirmed: 0,
suspected: 0,
cured: 0,
dead: 0,
provinces: Object.fromEntries(
source.map(item => [item.provinceShortName, convertProvince(item)])
)
});

export function convertProvince(province: Province): ProvinceData {
const { provinceShortName: name, updateTime, cities } = province;
Expand All @@ -50,16 +49,17 @@ export function convertProvince(province: Province): ProvinceData {
};
}

export function convertCity(source: City, updateTime: number): CityData {
return {
name: long2short(source.cityName),
timestamp: updateTime, // 使用传入的省级数据更新时间
...convertStat(source)
};
}
/**
* @param timestamp 使用传入的省级数据更新时间
*/
export const convertCity = (source: City, timestamp: number): CityData => ({
name: long2short(source.cityName),
timestamp,
...convertStat(source)
});

function roundTime(t: number, resolution: number) {
const offset = resolution >= 24 * 3600000 ? 8 * 3600000 : 0; // consider locale if resolution > 1 day
const offset = resolution >= 24 * Hour ? 8 * Hour : 0; // consider locale if resolution > 1 day

return Math.floor((t + offset) / resolution) * resolution - offset;
}
Expand All @@ -69,23 +69,25 @@ function fillForward<T extends ProvinceData | CityData | CountryData>(
) {
const all_ts = Object.keys(series).sort();

all_ts.forEach((t, i) => {
for (const [i, t] of all_ts.entries())
if (i < all_ts.length - 1)
for (const name of Object.keys(series[t])) {
const next_t = parseInt(all_ts[i + 1], 10);

if (series[next_t][name] === undefined)
series[next_t][name] = series[t][name];
}
});
}

/**
* @param resolution in ms
*/
export function convertProvincesSeries(
source: Province[],
resolution: number, // in ms
resolution: number,
shouldFillForward = false
): Series<ProvinceData> {
let res: Series<ProvinceData> = {};
) {
const res: Series<ProvinceData> = {};

source.sort(item => item.updateTime);

Expand All @@ -109,7 +111,7 @@ export function extractCitiesSeries(
name: string,
resolution: number,
shouldFillForward = false
): Series<CityData> {
) {
const res: Series<CityData> = Object.fromEntries(
Object.values(series)
.map(provs => {
Expand All @@ -126,11 +128,13 @@ export function extractCitiesSeries(
return res;
}

export function convertCountrySeries(
/**
* @param resolution // in ms
*/
export const convertCountrySeries = (
source: any[],
resolution: number // in ms
): Series<CountryOverviewData> {
return Object.fromEntries(
resolution: number
): Series<CountryOverviewData> =>
Object.fromEntries(
source.map(item => [roundTime(item.updateTime, resolution), item])
);
}
31 changes: 12 additions & 19 deletions source/page/Map/adapter/patientStatInterface.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,27 @@
export interface PatientStatData {
confirmed: number;
suspected: number;
cured: number;
dead: number;
}
import { StatisticType } from '../../../service';

export interface CountryOverviewData extends PatientStatData {
name: string; // '中国'
timestamp?: number; // integer, unit is 'ms', unix epoch time
}
export type PatientStatData = Record<StatisticType, number>;

export interface CountryData extends PatientStatData {
name: string; // '中国'
timestamp?: number; // integer, unit is 'ms', unix epoch time
provinces?: { [name: string]: ProvinceData };
export type CountryOverviewData = CityData;

export interface CountryData extends CityData {
provinces?: Record<string, ProvinceData>;
}

export interface ProvinceData extends PatientStatData {
name: string; // '湖北'
timestamp?: number;
cities: { [name: string]: CityData };
export interface ProvinceData extends CityData {
cities: Record<string, CityData>;
}

export interface CityData extends PatientStatData {
name: string; // '武汉'
/**
* integer, unit is 'ms', unix epoch time
*/
timestamp?: number;
}

export type Series<T extends CountryData | ProvinceData | CityData> = {
[timestamp: number]: { [name: string]: T };
[timestamp: number]: Record<string, T>;
};

export interface OverallCountryData {
Expand Down
35 changes: 19 additions & 16 deletions source/page/Map/component/CellCharts.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,30 +6,33 @@
* 传入props说明:
* chartOptions: ECharts 中的所有 options。
*/
import { WebCellProps, component, mixin, watch } from 'web-cell';
import { observer } from 'mobx-web-cell';
import { init } from 'echarts';
import { WebCell, component, observer } from 'web-cell';
import { observable } from 'mobx';
import { EChartsType, EChartsOption, init } from 'echarts';

interface CellChartsProp extends WebCellProps {
chartOptions?: Record<string, any>;
export interface CellChartsProps {
chartOptions?: EChartsOption;
}

export interface CellCharts extends WebCell<CellChartsProps> {}

@component({ tagName: 'cell-charts' })
@observer
@component({
tagName: 'cell-charts',
renderTarget: 'children'
})
export class CellCharts extends mixin<CellChartsProp>() {
@watch
chartOptions = {};
export class CellCharts
extends HTMLElement
implements WebCell<CellChartsProps>
{
@observable
accessor chartOptions = {};

chart: any;
chart: EChartsType;

connectedCallback() {
this.classList.add('w-100', 'h-100');
// @ts-ignore
this.chart = init(this).setOption(this.chartOptions, false, false);

self.addEventListener('resize', () => this.chart?.resize());
this.chart = init(this);
this.chart.setOption(this.chartOptions, false, false);

self.addEventListener('resize', () => this.chart.resize());
}
}
Loading

1 comment on commit e66403e

@github-actions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deploy preview for wuhan2020 ready!

✅ Preview
https://wuhan2020-quszhvcqc-techquery.vercel.app

Built with commit e66403e.
This pull request is being automatically deployed with vercel-action

Please sign in to comment.