Skip to content

Commit

Permalink
Update app to use localised timezones everywhere
Browse files Browse the repository at this point in the history
Remove now-unnecessary timezone workaround in app

Update app test with UTC offset

Fix app bug introduced during refactor

Add specific handling of datetime fields in computed getters/setters

Use localized timestamp in UI, thanks to Sweden

Fix UI date display when updated in starting_materials EditPage
  • Loading branch information
ml-evs committed Nov 4, 2024
1 parent 119918f commit fc2cf1b
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 15 deletions.
2 changes: 1 addition & 1 deletion webapp/cypress/e2e/equipment.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ describe("Equipment table page", () => {
expect(body).to.have.property("item_id", "test_e3");
expect(body.item_data).to.have.property("item_id", "test_e3");
expect(body.item_data).to.have.property("name", "my inst");
expect(body.item_data).to.have.property("date", "1990-01-07T00:00:00");
expect(body.item_data).to.have.property("date", "1990-01-07T00:00:00+00:00");
});
});

Expand Down
2 changes: 1 addition & 1 deletion webapp/src/components/StartingMaterialInformation.vue
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
<StyledInput
id="startmat-date-acquired"
v-model="DateAcquired"
type="date"
type="datetime-local"
:readonly="!isEditable"
/>
</div>
Expand Down
73 changes: 66 additions & 7 deletions webapp/src/field_utils.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,53 @@
import store from "@/store/index.js";
//import { debounce } from 'lodash';
import { DATETIME_FIELDS } from "@/resources.js";

/**
* Converts a datetime-local input value to an ISO format string with timezone offset.
*
* @param {string} value - The datetime value from a datetime-local input
* (format: "YYYY-MM-DDThh:mm")
*
* @returns {string} ISO format datetime with timezone offset
* (format: "YYYY-MM-DDThh:mm:ss±hh:mm")
*
*/
export function dateTimeFormatter(value) {
if (!value) return "";
try {
const date = new Date(value);
const tzOffset = date.getTimezoneOffset();
const tzHours = Math.abs(Math.floor(tzOffset / 60));
const tzMinutes = Math.abs(tzOffset % 60);
const tzSign = tzOffset > 0 ? "-" : "+";
const tzString = `${tzSign}${tzHours.toString().padStart(2, "0")}:${tzMinutes
.toString()
.padStart(2, "0")}`;

return `${value}:00${tzString}`;
} catch (err) {
return "";
}
}

/**
* Converts an ISO format datetime string with timezone offset to a datetime-local input value.
*
* @param {string} value - The ISO format datetime with timezone offset (format: "YYYY-MM-DDThh:mm:ss±hh:mm")
* @returns {string} datetime-local input value (format: "YYYY-MM-DDThh:mm")
*
*/
export function dateTimeParser(value) {
if (!value) return "";
try {
const date = new Date(value);
// The Swedes are sensible and use basically the isoformat for their locale string; we take advantage of this
// to get an ISO datetime that does not use UTC; the 'iso' locale itself has slashes and commas for some reason
return date.toLocaleString("sv").replace(" ", "T").slice(0, 16);
} catch (err) {
console.error("Invalid date passed to dateTimeParser", value);
return "";
}
}

// Amazingly (and perhaps dangerously) the this context used here is the this from
// the component which this function is called for.
Expand Down Expand Up @@ -27,17 +75,23 @@ export function createComputedSetterForItemField(item_field) {
return {
get() {
if (this.item_id in store.state.all_item_data) {
return store.state.all_item_data[this.item_id][item_field];
let value = store.state.all_item_data[this.item_id][item_field];
if (DATETIME_FIELDS.has(item_field)) {
value = dateTimeParser(value);
}

return value;
}
},
set(value) {
//set: debounce(function(value) {
console.log(`comp setter called for '${item_field}' with value: '${value}'`);
if (DATETIME_FIELDS.has(item_field)) {
value = dateTimeFormatter(value);
}
store.commit("updateItemData", {
item_id: this.item_id,
item_data: { [item_field]: value === "" ? null : value },
});
//}, 500),
},
};
}
Expand All @@ -46,17 +100,22 @@ export function createComputedSetterForCollectionField(collection_field) {
return {
get() {
if (this.collection_id in store.state.all_collection_data) {
return store.state.all_collection_data[this.collection_id][collection_field];
let value = store.state.all_collection_data[this.collection_id][collection_field];
if (DATETIME_FIELDS.has(collection_field)) {
value = dateTimeParser(value);
}
return value;
}
},
set(value) {
//set: debounce( function(value) {
if (DATETIME_FIELDS.has(collection_field)) {
value = dateTimeFormatter(value);
}
console.log(`collection comp setter called for '${collection_field}' with value: '${value}'`);
store.commit("updateCollectionData", {
collection_id: this.collection_id,
block_data: { [collection_field]: value },
});
//}, 500),
},
};
}
Expand Down
3 changes: 3 additions & 0 deletions webapp/src/resources.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ export const GRAVATAR_STYLE = "identicon";
const editable_inventory = process.env.VUE_APP_EDITABLE_INVENTORY || "false";
export const EDITABLE_INVENTORY = editable_inventory.toLowerCase() == "true";

// Eventually this should be pulled from the schema
export const DATETIME_FIELDS = new Set(["date"]);

export const UPPY_MAX_TOTAL_FILE_SIZE =
Number(process.env.VUE_APP_UPPY_MAX_TOTAL_FILE_SIZE) != null
? process.env.VUE_APP_UPPY_MAX_TOTAL_FILE_SIZE
Expand Down
4 changes: 1 addition & 3 deletions webapp/src/views/CollectionPage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -144,9 +144,7 @@ export default {
if (item_date == null) {
this.lastModified = "Unknown";
} else {
// API dates are in UTC but missing Z suffix
const save_date = new Date(item_date + "Z");
this.lastModified = formatDistanceToNow(save_date, { addSuffix: true });
this.lastModified = formatDistanceToNow(new Date(item_date), { addSuffix: true });
}
},
},
Expand Down
4 changes: 1 addition & 3 deletions webapp/src/views/EditPage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -310,9 +310,7 @@ export default {
if (item_date == null) {
this.lastModified = "Unknown";
} else {
// API dates are in UTC but missing Z suffix
const save_date = new Date(item_date + "Z");
this.lastModified = formatDistanceToNow(save_date, { addSuffix: true });
this.lastModified = formatDistanceToNow(new Date(item_date), { addSuffix: true });
}
},
},
Expand Down

0 comments on commit fc2cf1b

Please sign in to comment.