Skip to content

Commit

Permalink
Merge pull request #1023 from JGreenlee/label-ux-and-cleanup
Browse files Browse the repository at this point in the history
🏷️ Label UX: show labeled modes on map, update LabelOptions
  • Loading branch information
shankari authored Sep 5, 2023
2 parents 3f039a9 + eadc652 commit d6637a6
Show file tree
Hide file tree
Showing 45 changed files with 586 additions and 424 deletions.
1 change: 1 addition & 0 deletions package.cordovabuild.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"@babel/preset-typescript": "^7.21.4",
"@ionic/cli": "6.20.8",
"@types/luxon": "^3.3.0",
"@types/react": "^18.2.20",
"babel-loader": "^9.1.2",
"babel-plugin-angularjs-annotate": "^0.10.0",
"babel-plugin-optional-require": "^0.3.1",
Expand Down
1 change: 1 addition & 0 deletions package.serve.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"@babel/preset-typescript": "^7.21.4",
"@ionic/cli": "6.20.8",
"@types/luxon": "^3.3.0",
"@types/react": "^18.2.20",
"babel-loader": "^9.1.2",
"babel-plugin-angularjs-annotate": "^0.10.0",
"babel-plugin-optional-require": "^0.3.1",
Expand Down
7 changes: 6 additions & 1 deletion www/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,10 @@
"select-mode-scroll": "Mode (👇 for more)",
"select-replaced-mode-scroll": "Replaces (👇 for more)",
"select-purpose-scroll": "Purpose (👇 for more)",
"delete-entry-confirm": "Are you sure you wish to delete this entry?",
"detected": "Detected:",
"labeled-mode": "Labeled Mode",
"detected-modes": "Detected Modes",
"today": "Today",
"no-more-travel": "No more travel to show",
"show-more-travel": "Show More Travel",
Expand Down Expand Up @@ -350,6 +354,7 @@
"invalid-subgroup-no-default": "Invalid OPcode {{token}}, no subgroups, expected 'default' subgroup",
"unable-download-config": "Unable to download study config",
"invalid-opcode-format": "Invalid OPcode format",
"error-loading-config-app-start": "Error loading config on app start"
"error-loading-config-app-start": "Error loading config on app start",
"survey-missing-formpath": "Error while fetching resources in config: survey_info.surveys has a survey without a formPath"
}
}
7 changes: 5 additions & 2 deletions www/js/appTheme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,14 @@ const AppTheme = {
primary: '#0080b9', // lch(50% 50 250)
primaryContainer: '#90ceff', // lch(80% 40 250)
onPrimaryContainer: '#001e30', // lch(10% 50 250)
secondary: '#f2795c', // lch(65% 60 40)
secondaryContainer: '#ffb39e', // lch(80% 45 40)
secondary: '#c08331', // lch(60% 55 70)
secondaryContainer: '#fcefda', // lch(95% 12 80)
onSecondaryContainer: '#45392e', // lch(25% 10 65)
background: '#edf1f6', // lch(95% 3 250) - background of label screen, other screens still have this as CSS .pane
surface: '#fafdff', // lch(99% 30 250)
surfaceVariant: '#e0f0ff', // lch(94% 50 250) - background of DataTable
surfaceDisabled: '#c7e0f7', // lch(88% 15 250)
onSurfaceDisabled: '#3a4955', // lch(30% 10 250)
elevation: {
level0: 'transparent',
level1: '#fafdff', // lch(99% 30 250)
Expand Down
23 changes: 15 additions & 8 deletions www/js/diary/DiaryButton.tsx → www/js/components/DiaryButton.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,31 @@
import React from "react";
import { StyleSheet } from 'react-native';
import { Button, ButtonProps, useTheme } from 'react-native-paper';
import { Icon } from "../components/Icon";
import color from 'color';
import { Icon } from "./Icon";

type Props = ButtonProps & { fillColor?: string };
const DiaryButton = ({ children, fillColor, icon, ...rest } : Props) => {
type Props = ButtonProps & { fillColor?: string, borderColor?: string };
const DiaryButton = ({ children, fillColor, borderColor, icon, ...rest } : Props) => {

const { colors } = useTheme();
const style = fillColor ? { color: colors.onPrimary }
: { borderColor: colors.primary, borderWidth: 1.5 };

const blackAlpha15 = color('black').alpha(0.15).rgb().string();
const style = {
borderColor: borderColor || (fillColor ? blackAlpha15 : colors.primary),
borderWidth: 1.5,
};
const textColor = rest.textColor || (fillColor ? colors.onPrimary : colors.primary);

return (
<Button mode="elevated"
buttonColor={fillColor || "white"} style={style}
labelStyle={fillColor ? {color: 'white', ...s.label} : s.label}
textColor={textColor}
buttonColor={fillColor || colors.onPrimary} style={style}
labelStyle={[s.label, {color: textColor}]}
contentStyle={s.buttonContent}
{...rest}>
<>
{icon &&
<Icon icon={icon} iconColor={fillColor ? 'white' : colors.primary}
<Icon icon={icon} iconColor={textColor}
size={18} style={s.icon} />
}
{children}
Expand Down
7 changes: 6 additions & 1 deletion www/js/components/LeafletView.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,14 @@ const LeafletView = ({ geojson, opts, ...otherProps }) => {
}

useEffect(() => {
// if a Leaflet map already exists (because we are re-rendering), remove it before creating a new one
if (leafletMapRef.current) {
leafletMapRef.current.remove();
mapSet.delete(leafletMapRef.current);
}
const map = L.map(mapElRef.current, opts || {});
initMap(map);
}, []);
}, [geojson]);

/* If the geojson is different between renders, we need to recreate the map
(happens because of FlashList's view recycling on the trip cards:
Expand Down
26 changes: 26 additions & 0 deletions www/js/components/ToggleSwitch.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import React from 'react';
import { SegmentedButtons, SegmentedButtonsProps, useTheme } from "react-native-paper";

const ToggleSwitch = ({ value, buttons, ...rest}: SegmentedButtonsProps) => {

const { colors } = useTheme();

return (
<SegmentedButtons value={value as any} onValueChange={v => rest.onValueChange(v as any)}
buttons={buttons.map(o => ({
value: o.value,
icon: o.icon,
uncheckedColor: colors.onSurfaceDisabled,
showSelectedCheck: true,
style: {
minWidth: 0,
borderTopWidth: rest.density == 'high' ? 0 : 1,
borderBottomWidth: rest.density == 'high' ? 0 : 1,
backgroundColor: value == o.value ? colors.elevation.level2 : colors.surfaceDisabled,
},
...o
}))} {...rest} />
)
}

export default ToggleSwitch;
2 changes: 1 addition & 1 deletion www/js/config/dynamic_config.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ angular.module('emission.config.dynamic', ['emission.plugin.logger',
if (config.survey_info?.surveys) {
Object.values(config.survey_info.surveys).forEach((survey) => {
if (!survey?.formPath)
throw new Error('while fetching resources in config, survey_info.surveys has a survey without a formPath');
throw new Error(i18next.t('config.survey-missing-formpath'));
fetchUrlCached(survey.formPath);
});
}
Expand Down
115 changes: 0 additions & 115 deletions www/js/diary/LabelDetailsScreen.tsx

This file was deleted.

12 changes: 7 additions & 5 deletions www/js/diary/LabelTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ import { angularize, getAngularService } from "../angular-react-helper";
import useAppConfig from "../useAppConfig";
import { useTranslation } from "react-i18next";
import { invalidateMaps } from "../components/LeafletView";
import Bottleneck from "bottleneck";
import moment from "moment";
import LabelListScreen from "./LabelListScreen";
import LabelListScreen from "./list/LabelListScreen";
import { createStackNavigator } from "@react-navigation/stack";
import LabelScreenDetails from "./LabelDetailsScreen";
import LabelScreenDetails from "./details/LabelDetailsScreen";
import { NavigationContainer } from "@react-navigation/native";
import { compositeTrips2TimelineMap, getAllUnprocessedInputs, getLocalUnprocessedInputs, populateCompositeTrips } from "./timelineHelper";
import { fillLocationNamesOfTrip, resetNominatimLimiter } from "./addressNamesHelper";
import { SurveyOptions } from "../survey/survey";
import { getLabelOptions } from "../survey/multilabel/confirmHelper";

let labelPopulateFactory, labelsResultMap, notesResultMap, showPlaces;
const ONE_DAY = 24 * 60 * 60; // seconds
Expand All @@ -31,6 +31,7 @@ const LabelTab = () => {
const { t } = useTranslation();

const [surveyOpt, setSurveyOpt] = useState(null);
const [labelOptions, setLabelOptions] = useState(null);
const [filterInputs, setFilterInputs] = useState([]);
const [pipelineRange, setPipelineRange] = useState(null);
const [queriedRange, setQueriedRange] = useState(null);
Expand All @@ -54,6 +55,7 @@ const LabelTab = () => {
const surveyOpt = SurveyOptions[surveyOptKey];
setSurveyOpt(surveyOpt);
showPlaces = appConfig.survey_info?.buttons?.['place-notes'];
getLabelOptions().then((labelOptions) => setLabelOptions(labelOptions));
labelPopulateFactory = getAngularService(surveyOpt.service);
const tripSurveyName = appConfig.survey_info?.buttons?.['trip-notes']?.surveyName;
const placeSurveyName = appConfig.survey_info?.buttons?.['place-notes']?.surveyName;
Expand Down Expand Up @@ -167,9 +169,8 @@ const LabelTab = () => {
function handleFetchedTrips(ctList, utList, mode: 'prepend' | 'append' | 'replace') {
const tripsRead = ctList.concat(utList);
populateCompositeTrips(tripsRead, showPlaces, labelPopulateFactory, labelsResultMap, enbs, notesResultMap);
// Fill place names and trajectories on a reversed copy of the list so we fill from the bottom up
// Fill place names on a reversed copy of the list so we fill from the bottom up
tripsRead.slice().reverse().forEach(function (trip, index) {
trip.geojson = Timeline.compositeTrip2Geojson(trip);
fillLocationNamesOfTrip(trip);
});
const readTimelineMap = compositeTrips2TimelineMap(tripsRead, showPlaces);
Expand Down Expand Up @@ -258,6 +259,7 @@ const LabelTab = () => {

const contextVals = {
surveyOpt,
labelOptions,
timelineMap,
displayedEntries,
filterInputs,
Expand Down
2 changes: 1 addition & 1 deletion www/js/diary/addressNamesHelper.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* This is a temporary solution; localstorage is not a good long-term option and we should
be looking to other key-value storage options in the React Native ecosystem. */

import { useEffect, useState, useRef, useContext } from 'react';
import { useEffect, useState, useRef } from 'react';

export type Listener<EventType> = (event: EventType) => void;

Expand Down
4 changes: 2 additions & 2 deletions www/js/diary/cards/DiaryCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,12 @@ export const DiaryCard = ({ timelineEntry, children, flavoredTheme, ...otherProp
<PaperProvider theme={theme}>
<Card style={[cardStyles.card, { width: windowWidth * .9 }]}
contentStyle={{ alignItems: 'center' }} {...otherProps}>
<View accessibilityHidden={true} style={{ position: 'absolute', left: 0, right: 0, top: -10, justifyContent: 'center', zIndex: 999 }}>
<View aria-hidden={true} style={{ position: 'absolute', left: 0, right: 0, top: -10, justifyContent: 'center', zIndex: 999 }}>
<TimestampBadge time={displayStartTime} date={displayStartDateAbbr}
lightBg={true} />
</View>
{children}
<View accessibilityHidden={true} style={{ position: 'absolute', left: 0, right: 0, bottom: -10, justifyContent: 'center', zIndex: 999 }}>
<View aria-hidden={true} style={{ position: 'absolute', left: 0, right: 0, bottom: -10, justifyContent: 'center', zIndex: 999 }}>
<TimestampBadge time={displayEndTime} date={displayEndDateAbbr}
lightBg={false} />
</View>
Expand Down
Loading

0 comments on commit d6637a6

Please sign in to comment.