Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sep 2024 Fixes #1181

Merged
merged 6 commits into from
Sep 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions package.cordovabuild.json
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,7 @@
},
"cordova-plugin-bluetooth-classic-serial-port": {},
"cordova-custom-config": {},
"com.unarin.cordova.beacon": {},
"cordova-plugin-statusbar": {}
"com.unarin.cordova.beacon": {}
}
},
"dependencies": {
Expand Down Expand Up @@ -137,7 +136,6 @@
"cordova-plugin-bluetooth-classic-serial-port": "git+https://github.com/e-mission/cordova-plugin-bluetooth-classic-serial-port.git",
"cordova-custom-config": "^5.1.1",
"com.unarin.cordova.beacon": "github:e-mission/cordova-plugin-ibeacon",
"cordova-plugin-statusbar": "^4.0.0",
"core-js": "^2.5.7",
"e-mission-common": "github:JGreenlee/e-mission-common#semver:0.6.1",
"enketo-core": "^6.1.7",
Expand Down
2 changes: 1 addition & 1 deletion setup/setup_native.sh
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ sed -i -e "s|/usr/bin/env node|/usr/bin/env node --unhandled-rejections=strict|"

npx cordova prepare$PLATFORMS

EXPECTED_COUNT=26
EXPECTED_COUNT=25
INSTALLED_COUNT=`npx cordova plugin list | wc -l`
echo "Found $INSTALLED_COUNT plugins, expected $EXPECTED_COUNT"
if [ $INSTALLED_COUNT -lt $EXPECTED_COUNT ];
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { formatForDisplay } from '../js/util';
import { formatForDisplay } from '../js/datetimeUtil';

describe('util.ts', () => {
describe('formatForDisplay', () => {
Expand Down
2 changes: 1 addition & 1 deletion www/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ window.skipLocalNotificationReady = true;
deviceReady.then(() => {
logDebug('deviceReady');
// On init, use 'default' status bar (black text)
window['StatusBar']?.styleDefault();
// window['StatusBar']?.styleDefault();
cordova.plugin.http.setDataSerializer('json');
const rootEl = document.getElementById('appRoot');
const reactRoot = createRoot(rootEl);
Expand Down
2 changes: 1 addition & 1 deletion www/js/TimelineContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import { getNotDeletedCandidates, mapInputsToTimelineEntries } from './survey/in
import { EnketoUserInputEntry } from './survey/enketo/enketoHelper';
import { primarySectionForTrip } from './diary/diaryHelper';
import useAppStateChange from './useAppStateChange';
import { isoDateRangeToTsRange, isoDateWithOffset } from './util';
import { isoDateRangeToTsRange, isoDateWithOffset } from './datetimeUtil';
import { base_modes } from 'e-mission-common';

const TODAY_DATE = DateTime.now().toISODate();
Expand Down
7 changes: 4 additions & 3 deletions www/js/components/Chart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
import { ChartData, Chart as ChartJS, ScriptableContext, registerables } from 'chart.js';
import { Chart as ChartJSChart } from 'react-chartjs-2';
import Annotation, { AnnotationOptions, LabelPosition } from 'chartjs-plugin-annotation';
import { dedupColors, getChartHeight, darkenOrLighten } from './charting';
import { getChartHeight } from './charting';
import { base_modes } from 'e-mission-common';
import { logDebug } from '../plugin/logger';

ChartJS.register(...registerables, Annotation);
Expand Down Expand Up @@ -64,7 +65,7 @@
let labelColorMap; // object mapping labels to colors
if (getColorForLabel) {
const colorEntries = chartDatasets.map((d) => [d.label, getColorForLabel(d.label)]);
labelColorMap = dedupColors(colorEntries);
labelColorMap = base_modes.dedupe_colors(colorEntries, [0.4, 1.6]);

Check warning on line 68 in www/js/components/Chart.tsx

View check run for this annotation

Codecov / codecov/patch

www/js/components/Chart.tsx#L68

Added line #L68 was not covered by tests
}
return {
datasets: chartDatasets.map((e, i) => ({
Expand All @@ -73,7 +74,7 @@
labelColorMap?.[e.label] ||
getColorForChartEl?.(chartRef.current, e, barCtx, 'background'),
borderColor: (barCtx) =>
darkenOrLighten(labelColorMap?.[e.label], -0.5) ||
base_modes.scale_lightness(labelColorMap?.[e.label], 0.5) ||
getColorForChartEl?.(chartRef.current, e, barCtx, 'border'),
borderWidth: borderWidth || 2,
borderRadius: 3,
Expand Down
113 changes: 37 additions & 76 deletions www/js/components/charting.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,44 +59,44 @@ function getBarHeight(stacks) {
return totalHeight;
}

//fill pattern creation
//https://stackoverflow.com/questions/28569667/fill-chart-js-bar-chart-with-diagonal-stripes-or-other-patterns
function createDiagonalPattern(color = 'black') {
let shape = document.createElement('canvas');
shape.width = 10;
shape.height = 10;
let c = shape.getContext('2d') as CanvasRenderingContext2D;
c.strokeStyle = color;
c.lineWidth = 2;
c.beginPath();
c.moveTo(2, 0);
c.lineTo(10, 8);
c.stroke();
c.beginPath();
c.moveTo(0, 8);
c.lineTo(2, 10);
c.stroke();
return c.createPattern(shape, 'repeat');
}
// //fill pattern creation
// //https://stackoverflow.com/questions/28569667/fill-chart-js-bar-chart-with-diagonal-stripes-or-other-patterns
// function createDiagonalPattern(color = 'black') {
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: why is this commented out? will it be restored or removed in the future?

// let shape = document.createElement('canvas');
// shape.width = 10;
// shape.height = 10;
// let c = shape.getContext('2d') as CanvasRenderingContext2D;
// c.strokeStyle = color;
// c.lineWidth = 2;
// c.beginPath();
// c.moveTo(2, 0);
// c.lineTo(10, 8);
// c.stroke();
// c.beginPath();
// c.moveTo(0, 8);
// c.lineTo(2, 10);
// c.stroke();
// return c.createPattern(shape, 'repeat');
// }

export function getMeteredBackgroundColor(meter, currDataset, barCtx, colors, darken = 0) {
if (!barCtx || !currDataset) return;
let bar_height = getBarHeight(barCtx.parsed._stacks);
logDebug(`bar height for ${barCtx.raw.y} is ${bar_height} which in chart is ${currDataset}`);
let meteredColor;
if (bar_height > meter.high) meteredColor = colors.danger;
else if (bar_height > meter.middle) meteredColor = colors.warn;
else meteredColor = colors.success;
if (darken) {
return color(meteredColor).darken(darken).hex();
}
//if "unlabeled", etc -> stripes
if (currDataset.label == meter.uncertainty_prefix) {
return createDiagonalPattern(meteredColor);
}
//if :labeled", etc -> solid
return meteredColor;
}
// export function getMeteredBackgroundColor(meter, currDataset, barCtx, colors, darken = 0) {
// if (!barCtx || !currDataset) return;
// let bar_height = getBarHeight(barCtx.parsed._stacks);
// logDebug(`bar height for ${barCtx.raw.y} is ${bar_height} which in chart is ${currDataset}`);
// let meteredColor;
// if (bar_height > meter.high) meteredColor = colors.danger;
// else if (bar_height > meter.middle) meteredColor = colors.warn;
// else meteredColor = colors.success;
// if (darken) {
// return color(meteredColor).darken(darken).hex();
// }
// //if "unlabeled", etc -> stripes
// if (currDataset.label == meter.uncertainty_prefix) {
// return createDiagonalPattern(meteredColor);
// }
// //if :labeled", etc -> solid
// return meteredColor;
// }

const meterColors = {
below: '#00cc95', // green oklch(75% 0.3 165)
Expand Down Expand Up @@ -142,42 +142,3 @@ export function getGradient(
}
return gradient;
}

/**
* @param baseColor a color string
* @param change a number between -1 and 1, indicating the amount to darken or lighten the color
* @returns an adjusted color, either darkened or lightened, depending on the sign of change
*/
export function darkenOrLighten(baseColor: string, change: number) {
if (!baseColor) return baseColor;
let colorObj = color(baseColor);
if (change < 0) {
// darkening appears more drastic than lightening, so we will be less aggressive (scale change by .5)
return colorObj.darken(Math.abs(change * 0.5)).hex();
} else {
return colorObj.lighten(Math.abs(change)).hex();
}
}

/**
* @param colors an array of colors, each of which is an array of [key, color string]
* @returns an object mapping keys to colors, with duplicates darkened/lightened to be distinguishable
*/
export function dedupColors(colors: string[][]) {
const dedupedColors = {};
const maxAdjustment = 0.7; // more than this is too drastic and the colors approach black/white
for (const [key, clr] of colors) {
if (!clr) continue; // skip empty colors
const duplicates = colors.filter(([k, c]) => c == clr);
if (duplicates.length > 1) {
// there are duplicates; calculate an evenly-spaced adjustment for each one
duplicates.forEach(([k, c], i) => {
const change = -maxAdjustment + ((maxAdjustment * 2) / (duplicates.length - 1)) * i;
dedupedColors[k] = darkenOrLighten(clr, change);
});
} else if (!dedupedColors[key]) {
dedupedColors[key] = clr; // not a dupe, & not already deduped, so use the color as-is
}
}
return dedupedColors;
}
2 changes: 1 addition & 1 deletion www/js/config/useImperialConfig.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { useMemo } from 'react';
import useAppConfig from '../useAppConfig';
import { formatForDisplay } from '../util';
import { formatForDisplay } from '../datetimeUtil';

export type ImperialConfig = {
distanceSuffix: string;
Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion www/js/diary/diaryHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { LabelOptions } from '../types/labelTypes';
import { LocalDt } from '../types/serverData';
import { ImperialConfig } from '../config/useImperialConfig';
import { base_modes } from 'e-mission-common';
import { humanizeIsoRange } from '../util';
import { humanizeIsoRange } from '../datetimeUtil';

export type BaseModeKey = string; // TODO figure out how to get keyof typeof base_modes.BASE_MODES

Expand Down
2 changes: 1 addition & 1 deletion www/js/diary/list/DateSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { Text, useTheme } from 'react-native-paper';
import i18next from 'i18next';
import { useTranslation } from 'react-i18next';
import { NavBarButton } from '../../components/NavBar';
import { formatIsoNoYear, isoDateRangeToTsRange } from '../../util';
import { formatIsoNoYear, isoDateRangeToTsRange } from '../../datetimeUtil';

// formats as e.g. 'Aug 1'
const MONTH_DAY_SHORT: Intl.DateTimeFormatOptions = {
Expand Down
2 changes: 1 addition & 1 deletion www/js/diary/list/TimelineScrollList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { ActivityIndicator, Banner, Button, Icon, Text } from 'react-native-pape
import LoadMoreButton from './LoadMoreButton';
import { useTranslation } from 'react-i18next';
import TimelineContext from '../../TimelineContext';
import { isoDateRangeToTsRange, isoDateWithOffset } from '../../util';
import { isoDateRangeToTsRange, isoDateWithOffset } from '../../datetimeUtil';
import { DateTime } from 'luxon';

function renderCard({ item: listEntry, index }) {
Expand Down
5 changes: 3 additions & 2 deletions www/js/diary/useDerivedProperties.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
primarySectionForTrip,
} from './diaryHelper';
import TimelineContext from '../TimelineContext';
import { formatIsoNoYear, formatIsoWeekday, humanizeIsoRange, isoDatesDifference } from '../util';
import { formatIsoNoYear, formatIsoWeekday, humanizeIsoRange } from '../datetimeUtil';

const useDerivedProperties = (tlEntry) => {
const imperialConfig = useImperialConfig();
Expand All @@ -18,7 +18,8 @@
const endFmt = tlEntry.end_fmt_time || tlEntry.exit_fmt_time;
const beginDt = tlEntry.start_local_dt || tlEntry.enter_local_dt;
const endDt = tlEntry.end_local_dt || tlEntry.exit_local_dt;
const tlEntryIsMultiDay = isoDatesDifference(beginFmt, endFmt);
// given YYYY-MM-DDTHH:MM:SSZ strings: if YYYY-MM-DD differs, is multi-day
const tlEntryIsMultiDay = beginFmt.substring(0, 10) != endFmt.substring(0, 10);

Check warning on line 22 in www/js/diary/useDerivedProperties.tsx

View check run for this annotation

Codecov / codecov/patch

www/js/diary/useDerivedProperties.tsx#L22

Added line #L22 was not covered by tests

return {
confirmedMode: confirmedModeFor(tlEntry),
Expand Down
2 changes: 1 addition & 1 deletion www/js/metrics/MetricsTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { metrics_summaries } from 'e-mission-common';
import MetricsScreen from './MetricsScreen';
import { LabelOptions } from '../types/labelTypes';
import { useAppTheme } from '../appTheme';
import { isoDatesDifference } from '../util';
import { isoDatesDifference } from '../datetimeUtil';

const N_DAYS_TO_LOAD = 14; // 2 weeks
export const DEFAULT_METRIC_LIST: MetricList = {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react';
import { View, StyleSheet } from 'react-native';
import { Card, Text } from 'react-native-paper';
import { formatForDisplay } from '../util';
import { formatForDisplay } from '../datetimeUtil';
import { colors } from '../appTheme';
import { t } from 'i18next';
import { FootprintGoal } from '../types/appConfigTypes';
Expand All @@ -20,9 +20,8 @@
const perDayValue = value.map((v) => v / nDays) as Value;

const formatVal = (v: Value) => {
const opts = { maximumFractionDigits: 1 };
if (valueIsRange) return `${formatForDisplay(v[0], opts)} - ${formatForDisplay(v[1], opts)}`;
return `${formatForDisplay(v[0], opts)}`;
if (valueIsRange) return `${formatForDisplay(v[0])} - ${formatForDisplay(v[1])}`;
return `${formatForDisplay(v[0])}`;

Check warning on line 24 in www/js/metrics/SummaryCard.tsx

View check run for this annotation

Codecov / codecov/patch

www/js/metrics/SummaryCard.tsx#L24

Added line #L24 was not covered by tests
};

const colorFn = (v: Value) => {
Expand Down
2 changes: 1 addition & 1 deletion www/js/metrics/footprint/FootprintComparisonCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import BarChart from '../../components/BarChart';
import { useTranslation } from 'react-i18next';
import { ChartRecord } from '../../components/Chart';
import TimelineContext from '../../TimelineContext';
import { formatIsoNoYear } from '../../util';
import { formatIsoNoYear } from '../../datetimeUtil';

const FootprintComparisonCard = ({
type,
Expand Down
4 changes: 2 additions & 2 deletions www/js/metrics/footprint/FootprintSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ import React, { useContext, useMemo, useState } from 'react';
import { View } from 'react-native';
import { Text } from 'react-native-paper';
import color from 'color';
import SummaryCard from '../SumaryCard';
import SummaryCard from '../SummaryCard';
import { useTranslation } from 'react-i18next';
import { sumMetricEntries } from '../metricsHelper';
import TimelineContext from '../../TimelineContext';
import { formatIso, isoDatesDifference } from '../../util';
import { formatIso, isoDatesDifference } from '../../datetimeUtil';
import WeeklyFootprintCard from './WeeklyFootprintCard';
import useAppConfig from '../../useAppConfig';
import { getFootprintGoals } from './footprintHelper';
Expand Down
2 changes: 1 addition & 1 deletion www/js/metrics/footprint/WeeklyFootprintCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
sumMetricEntries,
trimGroupingPrefix,
} from '../metricsHelper';
import { formatIsoNoYear, isoDateWithOffset } from '../../util';
import { formatIsoNoYear, isoDateWithOffset } from '../../datetimeUtil';
import { useTranslation } from 'react-i18next';
import BarChart from '../../components/BarChart';
import { ChartRecord } from '../../components/Chart';
Expand Down
7 changes: 6 additions & 1 deletion www/js/metrics/metricsHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,12 @@ import { MetricName, groupingFields } from '../types/appConfigTypes';
import { ImperialConfig } from '../config/useImperialConfig';
import i18next from 'i18next';
import { base_modes, metrics_summaries } from 'e-mission-common';
import { formatForDisplay, formatIsoNoYear, isoDatesDifference, isoDateWithOffset } from '../util';
import {
formatForDisplay,
formatIsoNoYear,
isoDatesDifference,
isoDateWithOffset,
} from '../datetimeUtil';
import { LabelOptions, RichMode } from '../types/labelTypes';
import { labelOptions, textToLabelKey } from '../survey/multilabel/confirmHelper';
import { UNCERTAIN_OPACITY } from '../components/charting';
Expand Down
2 changes: 1 addition & 1 deletion www/js/metrics/movement/WeeklyActiveMinutesCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { useTranslation } from 'react-i18next';
import BarChart from '../../components/BarChart';
import { labelKeyToText } from '../../survey/multilabel/confirmHelper';
import TimelineContext from '../../TimelineContext';
import { formatIsoNoYear, isoDateWithOffset } from '../../util';
import { formatIsoNoYear, isoDateWithOffset } from '../../datetimeUtil';

type Props = { userMetrics?: MetricsData; activeModes: string[] };
const WeeklyActiveMinutesCard = ({ userMetrics, activeModes }: Props) => {
Expand Down
4 changes: 2 additions & 2 deletions www/js/onboarding/OnboardingStack.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ const OnboardingStack = () => {

if (onboardingState.route == OnboardingRoute.WELCOME) {
// This page needs 'light content' status bar (white text) due to blue header at the top
window['StatusBar']?.styleLightContent();
// window['StatusBar']?.styleLightContent();
return <WelcomePage />;
}
// All other pages go back to 'default' (black text)
window['StatusBar']?.styleDefault();
// window['StatusBar']?.styleDefault();
if (onboardingState.route == OnboardingRoute.SUMMARY) {
return <SummaryPage />;
} else if (onboardingState.route == OnboardingRoute.PROTOCOL) {
Expand Down
2 changes: 1 addition & 1 deletion www/js/survey/enketo/AddedNotesList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import EnketoModal from './EnketoModal';
import { useTranslation } from 'react-i18next';
import { EnketoUserInputEntry } from './enketoHelper';
import { displayErrorMsg, logDebug } from '../../plugin/logger';
import { formatIsoNoYear, isoDatesDifference } from '../../util';
import { formatIsoNoYear, isoDatesDifference } from '../../datetimeUtil';

type Props = {
timelineEntry: any;
Expand Down
Loading