commit ffb11a11570eded74d17db9f12fe8e062c2e52a1
parent 3a6ab29f053d00197a7aca4f06ca2acbb34c2f08
Author: ashermorgan <59518073+ashermorgan@users.noreply.github.com>
Date: Sat, 17 Feb 2024 12:52:41 -0800
Implement default-unit-system setting
Diffstat:
11 files changed, 161 insertions(+), 80 deletions(-)
diff --git a/src/assets/target-calculator.css b/src/assets/target-calculator.css
@@ -22,26 +22,14 @@ h2 {
margin-left: 5px;
}
-/* target set */
-.target-set {
+/* extra settings */
+.target-set, .default-units {
margin-bottom: 5px;
}
.target-set button {
margin-left: 3px;
}
-/* target set editor dialog */
-.target-set-editor-dialog {
- width: min(100% - 2em, 400px);
- max-height: min(100% - 2em, 815px);
- margin-top: 100px;
-}
-@media only screen and (max-height: 800px) {
- .target-set-editor-dialog {
- margin-top: 1em;
- }
-}
-
/* calculator output */
.output {
min-width: 300px;
diff --git a/src/components/SimpleTargetTable.vue b/src/components/SimpleTargetTable.vue
@@ -24,7 +24,7 @@
<td v-if="showPace">
{{ formatDuration(getPace(item), 3, 0, true) }}
- / {{ distanceUnits[getDefaultDistanceUnit()].symbol }}
+ / {{ distanceUnits[getDefaultDistanceUnit(defaultUnitSystem)].symbol }}
</td>
</tr>
@@ -69,6 +69,14 @@ export default {
type: Boolean,
default: false,
},
+
+ /**
+ * The unit system to use when showing result paces
+ */
+ defaultUnitSystem: {
+ type: String,
+ default: 'metric',
+ },
},
data() {
@@ -122,7 +130,7 @@ export default {
*/
getPace(result) {
return result.time / unitUtils.convertDistance(result.distanceValue, result.distanceUnit,
- unitUtils.getDefaultDistanceUnit());
+ unitUtils.getDefaultDistanceUnit(this.defaultUnitSystem));
},
},
};
diff --git a/src/components/TargetEditor.vue b/src/components/TargetEditor.vue
@@ -109,6 +109,14 @@ export default {
type: Boolean,
default: false,
},
+
+ /**
+ * The unit system to use when creating distance targets
+ */
+ defaultUnitSystem: {
+ type: String,
+ default: 'metric',
+ },
},
data() {
@@ -173,7 +181,7 @@ export default {
this.internalValue.targets.push({
result: 'time',
distanceValue: 1,
- distanceUnit: unitUtils.getDefaultDistanceUnit(),
+ distanceUnit: unitUtils.getDefaultDistanceUnit(this.defaultUnitSystem),
});
},
diff --git a/src/components/TargetSetSelector.vue b/src/components/TargetSetSelector.vue
@@ -13,7 +13,7 @@
<dialog ref="dialog" class="target-set-editor-dialog" aria-label="Edit target set">
<target-editor @close="$refs.dialog.close()" v-model="targetSets[internalValue]"
- @revert="revertTargetSet"
+ @revert="revertTargetSet" :default-unit-system="defaultUnitSystem"
:isCustomSet="!internalValue.startsWith('_')"/>
</dialog>
</span>
@@ -43,6 +43,14 @@ export default {
type: String,
default: '_new',
},
+
+ /**
+ * The unit system to use when creating distance targets
+ */
+ defaultUnitSystem: {
+ type: String,
+ default: 'metric',
+ },
},
data() {
@@ -137,4 +145,15 @@ export default {
.target-set-selector .icon {
margin-left: 0.3em;
}
+
+.target-set-editor-dialog {
+ width: min(100% - 2em, 400px);
+ max-height: min(100% - 2em, 815px);
+ margin-top: 100px;
+}
+@media only screen and (max-height: 800px) {
+ .target-set-editor-dialog {
+ margin-top: 1em;
+ }
+}
</style>
diff --git a/src/utils/units.js b/src/utils/units.js
@@ -160,10 +160,10 @@ function convertSpeedPace(inputValue, inputUnit, outputUnit) {
}
/**
- * Get the default unit system
+ * Detect the user's default unit system
* @returns {String} The default unit system
*/
-function getDefaultUnitSystem() {
+function detectDefaultUnitSystem() {
const language = (navigator.language || navigator.userLanguage).toLowerCase();
if (language.endsWith('-us') || language.endsWith('-mm')) {
return 'imperial';
@@ -172,27 +172,30 @@ function getDefaultUnitSystem() {
}
/**
- * Get the default distance unit
+ * Get the default distance unit in a unit system
+ * @param {String} unitSystem The unit system
* @returns {String} The default distance unit
*/
-function getDefaultDistanceUnit() {
- return getDefaultUnitSystem() === 'metric' ? 'kilometers' : 'miles';
+function getDefaultDistanceUnit(unitSystem) {
+ return unitSystem === 'metric' ? 'kilometers' : 'miles';
}
/**
- * Get the default speed unit
+ * Get the default speed unit in a unit system
+ * @param {String} unitSystem The unit system
* @returns {String} The default speed unit
*/
-function getDefaultSpeedUnit() {
- return getDefaultUnitSystem() === 'metric' ? 'kilometers_per_hour' : 'miles_per_hour';
+function getDefaultSpeedUnit(unitSystem) {
+ return unitSystem === 'metric' ? 'kilometers_per_hour' : 'miles_per_hour';
}
/**
- * Get the default pace unit
+ * Get the default pace unit in a unit system
+ * @param {String} unitSystem The unit system
* @returns {String} The default pace unit
*/
-function getDefaultPaceUnit() {
- return getDefaultUnitSystem() === 'metric' ? 'seconds_per_kilometer' : 'seconds_per_mile';
+function getDefaultPaceUnit(unitSystem) {
+ return unitSystem === 'metric' ? 'seconds_per_kilometer' : 'seconds_per_mile';
}
export default {
@@ -207,7 +210,7 @@ export default {
convertPace,
convertSpeedPace,
- getDefaultUnitSystem,
+ detectDefaultUnitSystem,
getDefaultDistanceUnit,
getDefaultSpeedUnit,
getDefaultPaceUnit,
diff --git a/src/views/PaceCalculator.vue b/src/views/PaceCalculator.vue
@@ -19,9 +19,17 @@
</div>
<h2>Equivalent Paces</h2>
+ <div class="default-units">
+ Default units:
+ <select v-model="defaultUnitSystem" aria-label="Default units">
+ <option value="imperial">Miles</option>
+ <option value="metric">Kilometers</option>
+ </select>
+ </div>
<div class="target-set">
Target Set:
- <target-set-selector v-model="selectedTargetSet" @targets-updated="reloadTargets"/>
+ <target-set-selector v-model="selectedTargetSet" @targets-updated="reloadTargets"
+ :default-unit-system="defaultUnitSystem"/>
</div>
<simple-target-table class="output" :calculate-result="calculatePace"
@@ -68,6 +76,13 @@ export default {
inputTime: storage.get('pace-calculator-input-time', 20 * 60),
/**
+ * The default unit system
+ *
+ * Loaded in activate() method
+ */
+ defaultUnitSystem: null,
+
+ /**
* The names of the distance units
*/
distanceUnits: unitUtils.DISTANCE_UNITS,
@@ -79,13 +94,10 @@ export default {
/**
* The target sets
+ *
+ * Loaded in activate() method
*/
- targetSets: storage.get('target-sets', targetUtils.defaultTargetSets),
-
- /**
- * Whether the target set is being edited
- */
- editingTargetSets: false,
+ targetSets: {},
};
},
@@ -112,6 +124,13 @@ export default {
},
/**
+ * Save default unit system
+ */
+ defaultUnitSystem(newValue) {
+ storage.set('default-unit-system', newValue);
+ },
+
+ /**
* Save the current selected target set
*/
selectedTargetSet(newValue) {
@@ -166,11 +185,12 @@ export default {
let distance = paceUtils.getDistance(this.pace, target.time);
// Convert output distance into default distance unit
- distance = unitUtils.convertDistance(distance, 'meters', unitUtils.getDefaultDistanceUnit());
+ distance = unitUtils.convertDistance(distance, 'meters',
+ unitUtils.getDefaultDistanceUnit(this.defaultUnitSystem));
// Update result
result.distanceValue = distance;
- result.distanceUnit = unitUtils.getDefaultDistanceUnit();
+ result.distanceUnit = unitUtils.getDefaultDistanceUnit(this.defaultUnitSystem);
}
// Return result
@@ -178,8 +198,12 @@ export default {
},
},
+ /**
+ * (Re)load settings used in multiple calculators
+ */
activated() {
this.targetSets = storage.get('target-sets', targetUtils.defaultTargetSets);
+ this.defaultUnitSystem = storage.get('default-unit-system', unitUtils.detectDefaultUnitSystem());
},
};
</script>
diff --git a/src/views/RaceCalculator.vue b/src/views/RaceCalculator.vue
@@ -24,6 +24,13 @@
</button>
</h2>
<div class="advanced-options" v-show="showAdvancedOptions">
+ <div class="default-units">
+ Default units:
+ <select v-model="defaultUnitSystem" aria-label="Default units">
+ <option value="imperial">Miles</option>
+ <option value="metric">Kilometers</option>
+ </select>
+ </div>
<div>
Prediction Model:
<select v-model="model" aria-label="Prediction model">
@@ -55,10 +62,11 @@
<h2>Equivalent Race Results</h2>
<div class="target-set">
Target Set:
- <target-set-selector v-model="selectedTargetSet" @targets-updated="reloadTargets"/>
+ <target-set-selector v-model="selectedTargetSet" @targets-updated="reloadTargets"
+ :default-unit-system="defaultUnitSystem"/>
</div>
- <simple-target-table class="output" :calculate-result="predictResult"
+ <simple-target-table class="output" :calculate-result="predictResult" :default-unit-system="defaultUnitSystem"
:targets="targetSets[selectedTargetSet] ? targetSets[selectedTargetSet].targets : []" show-pace/>
</div>
</template>
@@ -103,6 +111,13 @@ export default {
inputTime: storage.get('race-calculator-input-time', 20 * 60),
/**
+ * The default unit system
+ *
+ * Loaded in activate() method
+ */
+ defaultUnitSystem: null,
+
+ /**
* The race prediction model
*/
model: storage.get('race-calculator-model', 'AverageModel'),
@@ -134,13 +149,10 @@ export default {
/**
* The target sets
+ *
+ * Loaded in activate() method
*/
- targetSets: storage.get('target-sets', targetUtils.defaultTargetSets),
-
- /**
- * Whether the target set is being edited
- */
- editingTargetSets: false,
+ targetSets: {},
};
},
@@ -222,11 +234,12 @@ export default {
}
// Convert output distance into default distance unit
- distance = unitUtils.convertDistance(distance, 'meters', unitUtils.getDefaultDistanceUnit());
+ distance = unitUtils.convertDistance(distance, 'meters',
+ unitUtils.getDefaultDistanceUnit(this.defaultUnitSystem));
// Update result
result.distanceValue = distance;
- result.distanceUnit = unitUtils.getDefaultDistanceUnit();
+ result.distanceUnit = unitUtils.getDefaultDistanceUnit(this.defaultUnitSystem);
}
// Return result
@@ -298,6 +311,13 @@ export default {
},
/**
+ * Save default unit system
+ */
+ defaultUnitSystem(newValue) {
+ storage.set('default-unit-system', newValue);
+ },
+
+ /**
* Save prediction model
*/
model(newValue) {
@@ -324,19 +344,14 @@ export default {
selectedTargetSet(newValue) {
storage.set('pace-calculator-target-set', newValue);
},
-
- /**
- * Refresh the target sets
- */
- editingTargetSets(newValue) {
- if (!newValue) {
- this.targetSets = storage.get('target-sets', targetUtils.defaultTargetSets);
- }
- }
},
+ /**
+ * (Re)load settings used in multiple calculators
+ */
activated() {
this.targetSets = storage.get('target-sets', targetUtils.defaultTargetSets);
+ this.defaultUnitSystem = storage.get('default-unit-system', unitUtils.detectDefaultUnitSystem());
},
};
</script>
diff --git a/src/views/SplitCalculator.vue b/src/views/SplitCalculator.vue
@@ -1,8 +1,17 @@
<template>
<div class="calculator">
+ <div class="default-units">
+ Default units:
+ <select v-model="defaultUnitSystem" aria-label="Default units">
+ <option value="imperial">Miles</option>
+ <option value="metric">Kilometers</option>
+ </select>
+ </div>
+
<div class="target-set">
Target Set:
- <target-set-selector v-model="selectedTargetSet" @targets-updated="reloadTargets"/>
+ <target-set-selector v-model="selectedTargetSet" @targets-updated="reloadTargets"
+ :default-unit-system="defaultUnitSystem"/>
</div>
<div class="output">
@@ -40,7 +49,7 @@
<td>
{{ formatDuration(item.pace, 3, 0, true) }}
- / {{ distanceUnits[getDefaultDistanceUnit()].symbol }}
+ / {{ distanceUnits[getDefaultDistanceUnit(defaultUnitSystem)].symbol }}
</td>
</tr>
@@ -75,6 +84,13 @@ export default {
data() {
return {
/**
+ * The default unit system
+ *
+ * Loaded in activate() method
+ */
+ defaultUnitSystem: null,
+
+ /**
* The distance units
*/
distanceUnits: unitUtils.DISTANCE_UNITS,
@@ -101,32 +117,27 @@ export default {
/**
* The default output targets
+ *
+ * Loaded in activate() method
*/
- targetSets: storage.get('target-sets', targetUtils.defaultTargetSets),
-
- /**
- * Whether the target set is being edited
- */
- editingTargetSets: false,
+ targetSets: {},
};
},
watch: {
/**
- * Save the current selected target set
+ * Save default unit system
*/
- selectedTargetSet(newValue) {
- storage.set('split-calculator-target-set', newValue);
+ defaultUnitSystem(newValue) {
+ storage.set('default-unit-system', newValue);
},
/**
- * Refresh the target sets
+ * Save the current selected target set
*/
- editingTargetSets(newValue) {
- if (!newValue) {
- this.targetSets = storage.get('target-sets', targetUtils.defaultTargetSets);
- }
- }
+ selectedTargetSet(newValue) {
+ storage.set('split-calculator-target-set', newValue);
+ },
},
computed: {
@@ -157,7 +168,7 @@ export default {
// Calculate pace
const pace = splitTime / unitUtils.convertDistance(splitDistance, 'meters',
- unitUtils.getDefaultDistanceUnit());
+ unitUtils.getDefaultDistanceUnit(this.defaultUnitSystem));
// Add row to results array
results.push({
@@ -184,8 +195,12 @@ export default {
},
},
+ /**
+ * (Re)load settings used in multiple calculators
+ */
activated() {
this.targetSets = storage.get('target-sets', targetUtils.defaultTargetSets);
+ this.defaultUnitSystem = storage.get('default-unit-system', unitUtils.detectDefaultUnitSystem());
},
};
</script>
diff --git a/tests/unit/components/TargetEditor.spec.js b/tests/unit/components/TargetEditor.spec.js
@@ -15,6 +15,7 @@ test('addDistanceTarget method should correctly add distance target', async () =
{ time: 0, result: 'distance' },
],
},
+ defaultUnitSystem: 'imperial'
},
});
diff --git a/tests/unit/views/PaceCalculator.spec.js b/tests/unit/views/PaceCalculator.spec.js
@@ -51,8 +51,8 @@ test('should correctly calculate distances', async () => {
// Assert result is correct
expect(result).to.deep.equal({
- distanceValue: unitUtils.convertDistance(2, 'miles', unitUtils.getDefaultDistanceUnit()),
- distanceUnit: unitUtils.getDefaultDistanceUnit(),
+ distanceValue: unitUtils.convertDistance(2, 'miles', unitUtils.getDefaultDistanceUnit(unitUtils.detectDefaultUnitSystem())),
+ distanceUnit: unitUtils.getDefaultDistanceUnit(unitUtils.detectDefaultUnitSystem()),
time: 200,
result: 'distance',
});
diff --git a/tests/unit/views/RaceCalculator.spec.js b/tests/unit/views/RaceCalculator.spec.js
@@ -55,8 +55,8 @@ test('should correctly predict race distances', async () => {
const prediction = raceUtils.AverageModel.predictDistance(1200, 5000, 2460);
expect(result).to.deep.equal({
distanceValue: unitUtils.convertDistance(prediction, 'meters',
- unitUtils.getDefaultDistanceUnit()),
- distanceUnit: unitUtils.getDefaultDistanceUnit(),
+ unitUtils.getDefaultDistanceUnit(unitUtils.detectDefaultUnitSystem())),
+ distanceUnit: unitUtils.getDefaultDistanceUnit(unitUtils.detectDefaultUnitSystem()),
time: 2460,
result: 'distance',
});