Skip to content

Commit

Permalink
Update indicators timeline start years & select components (#841)
Browse files Browse the repository at this point in the history
* Add url params for timeline indicators (#830)

* add indicator param to timeline route, and update history shallow on selection

* fix optional route definition

* replace url rather than adding to history

* swap summary for timeline in route tests

* fix links to timeline, reorg helper funs

* reset url to default indicator if param is invalid or missing

* remove console.log

---------

Co-authored-by: kiwan <kiwan.sim@gmail.com>

* Add Rent Stabilized Units indicator to Timeline (#837)

* change rent stab latest year to 2022

* add 2022 as rsunitslatestyear, update yml dependenc, add csv for tests

* update nycdb src branc

* add nycdb test data for rentstab and hpd_complaints

* add rentstab indicator to timeline

* update MonthlyTimelineData type to match SQL

* remove stacked bar denoting market rate units, add horizontal line for latest total unit count

* add link to THE CITY's map visualization

* run prettier

* fussing around with viz UI

* change minor variable to trigger deploy

* yaxis max handled in switch statement

* run lingui extract

---------

Co-authored-by: Maxwell Austensen <m.austensen@gmail.com>

* replace Dropdown with Select react component, refactor timespan and indicator selectors

* apply JF style to react select

* prettier

* update startYear for different indicators

* run prettier

* lingui

* remove commented out code

---------

Co-authored-by: Maxwell Austensen <maxwell@justfix.org>
Co-authored-by: Maxwell Austensen <m.austensen@gmail.com>
  • Loading branch information
3 people authored Jan 2, 2024
1 parent f50ff8a commit dc26f7d
Show file tree
Hide file tree
Showing 7 changed files with 243 additions and 223 deletions.
181 changes: 97 additions & 84 deletions client/src/components/Indicators.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { Component } from "react";

import Select from "react-select";
import Helpers from "../util/helpers";

import IndicatorsViz from "../components/IndicatorsViz";
Expand All @@ -11,7 +11,7 @@ import { I18n } from "@lingui/core";
import { t, Trans } from "@lingui/macro";

import "styles/Indicators.css";
import { IndicatorsDatasetRadio, INDICATORS_DATASETS } from "./IndicatorsDatasets";
import { INDICATORS_DATASETS } from "./IndicatorsDatasets";
import {
indicatorsInitialState,
IndicatorsProps,
Expand All @@ -23,7 +23,6 @@ import {
indicatorsDatasetIds,
} from "./IndicatorsTypes";
import { NetworkErrorMessage } from "./NetworkErrorMessage";
import { Dropdown } from "./Dropdown";
import { AmplitudeEvent, logAmplitudeEvent } from "./Amplitude";
import { withRouter } from "react-router-dom";
import { RouteComponentProps } from "react-router";
Expand All @@ -33,7 +32,7 @@ type TimeSpanTranslationsMap = {
[K in IndicatorsTimeSpan]: (i18n: I18n) => string;
};

const timeSpanTranslations: TimeSpanTranslationsMap = {
const TIMESPAN_TRANSLATIONS: TimeSpanTranslationsMap = {
month: (i18n) => i18n._(t`month`),
quarter: (i18n) => i18n._(t`quarter`),
year: (i18n) => i18n._(t`year`),
Expand Down Expand Up @@ -73,6 +72,7 @@ class IndicatorsWithoutI18n extends Component<IndicatorsWithRouterProps, Indicat
activeTimeSpan: indicator === "rentstabilizedunits" ? "year" : "quarter",
};
this.handleVisChange = this.handleVisChange.bind(this);
this.handleTimeSpanChange = this.handleTimeSpanChange.bind(this);
}

/** Shifts the X-axis 'left' or 'right', or 'reset' the X-axis to default */
Expand Down Expand Up @@ -119,28 +119,31 @@ class IndicatorsWithoutI18n extends Component<IndicatorsWithRouterProps, Indicat
this.props.history.replace(`${timelinePath}/${indicator}`);
}

handleVisChange(selectedVis: IndicatorsDatasetId) {
if (selectedVis === "rentstabilizedunits") {
this.handleTimeSpanChange("year");
handleVisChange(selectedOption: any) {
const activeVis = selectedOption.value;

logAmplitudeEvent(`${activeVis.analyticsName}TimelineTab` as AmplitudeEvent);
window.gtag("event", `${activeVis.analyticsName}-timeline-tab`);

if (activeVis === "rentstabilizedunits") {
this.setState({
activeTimeSpan: "year",
monthsInGroup: 12,
});
}

this.setState({
activeVis: selectedVis,
});
this.setUrlIndicator(selectedVis);
this.setState({ activeVis });
this.setUrlIndicator(activeVis);
}

/** Changes viewing timespan to be by 'year', 'quarter', or 'month' */
handleTimeSpanChange(selectedTimeSpan: IndicatorsTimeSpan) {
var monthsInGroup = selectedTimeSpan === "quarter" ? 3 : selectedTimeSpan === "year" ? 12 : 1;
handleTimeSpanChange(selectedOption: any) {
const activeTimeSpan = selectedOption.value;
var monthsInGroup = activeTimeSpan === "quarter" ? 3 : activeTimeSpan === "year" ? 12 : 1;

logAmplitudeEvent(`${selectedTimeSpan}TimelineTab` as AmplitudeEvent);
window.gtag("event", `${selectedTimeSpan}-timeline-tab`);
logAmplitudeEvent(`${activeTimeSpan}TimelineTab` as AmplitudeEvent);
window.gtag("event", `${activeTimeSpan}-timeline-tab`);

this.setState({
activeTimeSpan: selectedTimeSpan,
monthsInGroup: monthsInGroup,
});
this.setState({ activeTimeSpan, monthsInGroup });
}

updateData() {
Expand Down Expand Up @@ -225,14 +228,19 @@ class IndicatorsWithoutI18n extends Component<IndicatorsWithRouterProps, Indicat
);
} else {
const { state, send } = this.props;

const { detailAddr } = state.context.portfolioData;

const { activeVis } = this.state;
const {
defaultVis,
activeVis,
activeTimeSpan,
monthsInGroup,
xAxisStart,
xAxisViewableColumns,
} = this.state;
const activeData = state.context.timelineData[activeVis];

const xAxisLength = activeData.labels
? Math.floor(activeData.labels.length / this.state.monthsInGroup)
? Math.floor(activeData.labels.length / monthsInGroup)
: 0;
const indicatorDataTotal = activeData.values.total
? activeData.values.total.reduce((total: number, sum: number) => total + sum)
Expand All @@ -244,14 +252,29 @@ class IndicatorsWithoutI18n extends Component<IndicatorsWithRouterProps, Indicat
INDICATORS_DATASETS[datasetId].name(i18n)
);
const timeSpanSelectionNames = indicatorsTimeSpans.map((timeSpan) =>
timeSpanTranslations[timeSpan](i18n)
TIMESPAN_TRANSLATIONS[timeSpan](i18n)
);

const detailAddrStr = `${detailAddr.housenumber} ${Helpers.titleCase(
detailAddr.streetname
)}, ${Helpers.titleCase(detailAddr.boro)}`;

const datasetDescription = INDICATORS_DATASETS[this.state.activeVis];
const datasetDescription = INDICATORS_DATASETS[activeVis];

const indicatorOptions = indicatorsDatasetIds.map((id) => {
return {
label: INDICATORS_DATASETS[id].name(i18n),
value: id,
};
});

const timeSpanOptions = indicatorsTimeSpans.map((id) => {
return {
label: TIMESPAN_TRANSLATIONS[id](i18n),
value: id,
isDisabled: activeVis === "rentstabilizedunits" && id !== "year",
};
});

return (
<div className="Page Indicators">
Expand All @@ -272,62 +295,59 @@ class IndicatorsWithoutI18n extends Component<IndicatorsWithRouterProps, Indicat
width: `${getDropdownWidthFromLongestSelection(datasetSelectionNames)}px`,
}}
>
<span className="Indicators__linksTitle text-uppercase">
<label
id="indicator-dropdown-title"
className="Indicators__linksTitle text-uppercase"
htmlFor="indicator-dropdown"
aria-label={`${i18n._(t`Display:`)} ${INDICATORS_DATASETS[activeVis].name(
i18n
)}`}
>
<Trans>Display:</Trans>
</span>{" "}
</label>
<br />
<Dropdown
buttonLabel={INDICATORS_DATASETS[activeVis].name(i18n)}
buttonAriaLabel={`${i18n._(t`Display:`)} ${INDICATORS_DATASETS[
activeVis
].name(i18n)}`}
>
{indicatorsDatasetIds.map((datasetKey, i) => (
<IndicatorsDatasetRadio
key={i}
id={datasetKey}
activeId={activeVis}
onChange={this.handleVisChange}
/>
))}
</Dropdown>
<Select
id="indicator-dropdown"
className="basic-single"
classNamePrefix="select"
aria-labelledby="indicator-dropdown-title"
name="indicator-type"
defaultValue={indicatorOptions.find((i) => i.value === defaultVis)}
options={indicatorOptions}
onChange={this.handleVisChange}
/>
</div>
<div
className="Indicators__linksContainer"
style={{
width: `${getDropdownWidthFromLongestSelection(timeSpanSelectionNames)}px`,
}}
>
<span className="Indicators__linksTitle text-uppercase">
<label
id="timespan-dropdown-title"
className="Indicators__linksTitle text-uppercase"
htmlFor="timespan-dropdown"
aria-label={`${i18n._(t`View by:`)} ${TIMESPAN_TRANSLATIONS[activeTimeSpan](
i18n
)}`}
>
<Trans>View by:</Trans>
</span>
</label>
<br />
<Dropdown
buttonLabel={timeSpanTranslations[this.state.activeTimeSpan](i18n)}
buttonAriaLabel={`${i18n._(t`View by:`)} ${timeSpanTranslations[
this.state.activeTimeSpan
](i18n)}`}
>
{indicatorsTimeSpans.map((timespan, i) => (
<li className="menu-item" key={i}>
<label
className={
"form-radio" +
(this.state.activeTimeSpan === timespan ? " active" : "")
}
>
<input
type="radio"
name={timespan}
checked={this.state.activeTimeSpan === timespan ? true : false}
onChange={() => this.handleTimeSpanChange(timespan)}
disabled={activeVis === "rentstabilizedunits" && timespan !== "year"}
/>
<i className="form-icon" /> {timeSpanTranslations[timespan](i18n)}
</label>
</li>
))}
</Dropdown>
<Select
id="timespan-dropdown"
className="basic-single"
classNamePrefix="select"
aria-labelledby="timespan-dropdown-title"
name="timespan"
defaultValue={
activeVis === "rentstabilizedunits"
? timeSpanOptions.find((i) => i.value === "year")
: timeSpanOptions.find((i) => i.value === "quarter")
}
options={timeSpanOptions}
onChange={this.handleTimeSpanChange}
/>
</div>
</div>
<span className="title viz-title">
Expand All @@ -338,14 +358,10 @@ class IndicatorsWithoutI18n extends Component<IndicatorsWithRouterProps, Indicat
<div className="Indicators__viz">
<button
aria-label={i18n._(t`Move chart data left.`)}
aria-hidden={
this.state.xAxisStart === 0 || this.state.activeTimeSpan === "year"
}
aria-disabled={
this.state.xAxisStart === 0 || this.state.activeTimeSpan === "year"
}
aria-hidden={xAxisStart === 0 || activeTimeSpan === "year"}
aria-disabled={xAxisStart === 0 || activeTimeSpan === "year"}
className={
this.state.xAxisStart === 0 || this.state.activeTimeSpan === "year"
xAxisStart === 0 || activeTimeSpan === "year"
? "btn btn-off btn-axis-shift"
: "btn btn-axis-shift"
}
Expand All @@ -360,16 +376,13 @@ class IndicatorsWithoutI18n extends Component<IndicatorsWithRouterProps, Indicat
<button
aria-label={i18n._(t`Move chart data right.`)}
aria-hidden={
this.state.xAxisStart + this.state.xAxisViewableColumns >= xAxisLength ||
this.state.activeTimeSpan === "year"
xAxisStart + xAxisViewableColumns >= xAxisLength || activeTimeSpan === "year"
}
aria-disabled={
this.state.xAxisStart + this.state.xAxisViewableColumns >= xAxisLength ||
this.state.activeTimeSpan === "year"
xAxisStart + xAxisViewableColumns >= xAxisLength || activeTimeSpan === "year"
}
className={
this.state.xAxisStart + this.state.xAxisViewableColumns >= xAxisLength ||
this.state.activeTimeSpan === "year"
xAxisStart + xAxisViewableColumns >= xAxisLength || activeTimeSpan === "year"
? "btn btn-off btn-axis-shift"
: "btn btn-axis-shift"
}
Expand Down
Loading

0 comments on commit dc26f7d

Please sign in to comment.