Reduce UI artefact size by removing moment.js
Remove moment.js dependency
This commit is contained in:
parent
7b59fb2f52
commit
ebd4b76a85
@ -1,4 +1,4 @@
|
|||||||
# Change the IP address to that of your ESP device to enable local development of the UI.
|
# Change the IP address to that of your ESP device to enable local development of the UI.
|
||||||
# Remember to also enable CORS in platformio.ini before uploading the code to the device.
|
# Remember to also enable CORS in platformio.ini before uploading the code to the device.
|
||||||
REACT_APP_HTTP_ROOT=http://192.168.0.88
|
REACT_APP_HTTP_ROOT=http://192.168.0.24
|
||||||
REACT_APP_WEB_SOCKET_ROOT=ws://192.168.0.88
|
REACT_APP_WEB_SOCKET_ROOT=ws://192.168.0.24
|
||||||
|
10
interface/package-lock.json
generated
10
interface/package-lock.json
generated
@ -10309,11 +10309,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
|
||||||
"integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="
|
"integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="
|
||||||
},
|
},
|
||||||
"moment": {
|
|
||||||
"version": "2.29.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz",
|
|
||||||
"integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ=="
|
|
||||||
},
|
|
||||||
"move-concurrently": {
|
"move-concurrently": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
|
||||||
@ -10984,6 +10979,11 @@
|
|||||||
"lines-and-columns": "^1.1.6"
|
"lines-and-columns": "^1.1.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"parse-ms": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-kHt7kzLoS9VBZfUsiKjv43mr91ea+U05EyKkEtqp7vNbHxmaVuEqN7XxeEVnGrMtYOAxGrDElSi96K7EgO1zCA=="
|
||||||
|
},
|
||||||
"parse5": {
|
"parse5": {
|
||||||
"version": "5.1.1",
|
"version": "5.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz",
|
||||||
|
@ -16,8 +16,8 @@
|
|||||||
"jwt-decode": "^3.1.2",
|
"jwt-decode": "^3.1.2",
|
||||||
"lodash": "^4.17.20",
|
"lodash": "^4.17.20",
|
||||||
"mime-types": "^2.1.28",
|
"mime-types": "^2.1.28",
|
||||||
"moment": "^2.29.1",
|
|
||||||
"notistack": "^1.0.3",
|
"notistack": "^1.0.3",
|
||||||
|
"parse-ms": "^2.1.0",
|
||||||
"react": "^17.0.1",
|
"react": "^17.0.1",
|
||||||
"react-dom": "^17.0.1",
|
"react-dom": "^17.0.1",
|
||||||
"react-dropzone": "^11.2.4",
|
"react-dropzone": "^11.2.4",
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import React, { Component, Fragment } from 'react';
|
import React, { Component, Fragment } from 'react';
|
||||||
import moment from 'moment';
|
|
||||||
|
|
||||||
import { WithTheme, withTheme } from '@material-ui/core/styles';
|
import { WithTheme, withTheme } from '@material-ui/core/styles';
|
||||||
import { Avatar, Divider, List, ListItem, ListItemAvatar, ListItemText, Button } from '@material-ui/core';
|
import { Avatar, Divider, List, ListItem, ListItemAvatar, ListItemText, Button } from '@material-ui/core';
|
||||||
@ -14,7 +13,7 @@ import RefreshIcon from '@material-ui/icons/Refresh';
|
|||||||
|
|
||||||
import { RestFormProps, FormButton, HighlightAvatar } from '../components';
|
import { RestFormProps, FormButton, HighlightAvatar } from '../components';
|
||||||
import { isNtpActive, ntpStatusHighlight, ntpStatus } from './NTPStatus';
|
import { isNtpActive, ntpStatusHighlight, ntpStatus } from './NTPStatus';
|
||||||
import { formatIsoDateTime, formatLocalDateTime } from './TimeFormat';
|
import { formatDuration, formatDateTime, formatLocalDateTime } from './TimeFormat';
|
||||||
import { NTPStatus, Time } from './types';
|
import { NTPStatus, Time } from './types';
|
||||||
import { redirectingAuthorizedFetch, withAuthenticatedContext, AuthenticatedContextProps } from '../authentication';
|
import { redirectingAuthorizedFetch, withAuthenticatedContext, AuthenticatedContextProps } from '../authentication';
|
||||||
import { TIME_ENDPOINT } from '../api';
|
import { TIME_ENDPOINT } from '../api';
|
||||||
@ -39,34 +38,34 @@ class NTPStatusForm extends Component<NTPStatusFormProps, NTPStatusFormState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
updateLocalTime = (event: React.ChangeEvent<HTMLInputElement>) => {
|
updateLocalTime = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
this.setState({ localTime: event.target.value });
|
this.setState({
|
||||||
|
localTime: event.target.value
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
openSetTime = () => {
|
openSetTime = () => {
|
||||||
this.setState({ localTime: formatLocalDateTime(moment()), settingTime: true, });
|
this.setState({
|
||||||
|
localTime: formatLocalDateTime(new Date()),
|
||||||
|
settingTime: true
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
closeSetTime = () => {
|
closeSetTime = () => {
|
||||||
this.setState({ settingTime: false });
|
this.setState({
|
||||||
|
settingTime: false
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
createAdjustedTime = (): Time => {
|
createTime = (): Time => ({
|
||||||
const currentLocalTime = moment(this.props.data.time_local);
|
local_time: formatLocalDateTime(new Date(this.state.localTime))
|
||||||
const newLocalTime = moment(this.state.localTime);
|
});
|
||||||
newLocalTime.subtract(currentLocalTime.utcOffset())
|
|
||||||
newLocalTime.milliseconds(0);
|
|
||||||
newLocalTime.utc();
|
|
||||||
return {
|
|
||||||
time_utc: newLocalTime.format()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
configureTime = () => {
|
configureTime = () => {
|
||||||
this.setState({ processing: true });
|
this.setState({ processing: true });
|
||||||
redirectingAuthorizedFetch(TIME_ENDPOINT,
|
redirectingAuthorizedFetch(TIME_ENDPOINT,
|
||||||
{
|
{
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: JSON.stringify(this.createAdjustedTime()),
|
body: JSON.stringify(this.createTime()),
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
}
|
}
|
||||||
@ -153,7 +152,7 @@ class NTPStatusForm extends Component<NTPStatusFormProps, NTPStatusFormState> {
|
|||||||
<AccessTimeIcon />
|
<AccessTimeIcon />
|
||||||
</Avatar>
|
</Avatar>
|
||||||
</ListItemAvatar>
|
</ListItemAvatar>
|
||||||
<ListItemText primary="Local Time" secondary={formatIsoDateTime(data.time_local)} />
|
<ListItemText primary="Local Time" secondary={formatDateTime(data.local_time)} />
|
||||||
</ListItem>
|
</ListItem>
|
||||||
<Divider variant="inset" component="li" />
|
<Divider variant="inset" component="li" />
|
||||||
<ListItem>
|
<ListItem>
|
||||||
@ -162,7 +161,7 @@ class NTPStatusForm extends Component<NTPStatusFormProps, NTPStatusFormState> {
|
|||||||
<SwapVerticalCircleIcon />
|
<SwapVerticalCircleIcon />
|
||||||
</Avatar>
|
</Avatar>
|
||||||
</ListItemAvatar>
|
</ListItemAvatar>
|
||||||
<ListItemText primary="UTC Time" secondary={formatIsoDateTime(data.time_utc)} />
|
<ListItemText primary="UTC Time" secondary={formatDateTime(data.utc_time)} />
|
||||||
</ListItem>
|
</ListItem>
|
||||||
<Divider variant="inset" component="li" />
|
<Divider variant="inset" component="li" />
|
||||||
<ListItem>
|
<ListItem>
|
||||||
@ -171,7 +170,7 @@ class NTPStatusForm extends Component<NTPStatusFormProps, NTPStatusFormState> {
|
|||||||
<AvTimerIcon />
|
<AvTimerIcon />
|
||||||
</Avatar>
|
</Avatar>
|
||||||
</ListItemAvatar>
|
</ListItemAvatar>
|
||||||
<ListItemText primary="Uptime" secondary={moment.duration(data.uptime, 'seconds').humanize()} />
|
<ListItemText primary="Uptime" secondary={formatDuration(data.uptime)} />
|
||||||
</ListItem>
|
</ListItem>
|
||||||
<Divider variant="inset" component="li" />
|
<Divider variant="inset" component="li" />
|
||||||
</List>
|
</List>
|
||||||
|
@ -1,5 +1,45 @@
|
|||||||
import moment, { Moment } from 'moment';
|
import parseMilliseconds from 'parse-ms';
|
||||||
|
|
||||||
export const formatIsoDateTime = (isoDateString: string) => moment.parseZone(isoDateString).format('ll @ HH:mm:ss');
|
const LOCALE_FORMAT = new Intl.DateTimeFormat(
|
||||||
|
[...window.navigator.languages],
|
||||||
|
{
|
||||||
|
day: 'numeric',
|
||||||
|
month: 'short',
|
||||||
|
year: 'numeric',
|
||||||
|
hour: 'numeric',
|
||||||
|
minute: 'numeric',
|
||||||
|
second: 'numeric',
|
||||||
|
hour12: false
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
export const formatLocalDateTime = (moment: Moment) => moment.format('YYYY-MM-DDTHH:mm');
|
export const formatDateTime = (dateTime: string) => {
|
||||||
|
return LOCALE_FORMAT.format(new Date(dateTime.substr(0, 19)));
|
||||||
|
}
|
||||||
|
|
||||||
|
export const formatLocalDateTime = (date: Date) => {
|
||||||
|
return new Date(date.getTime() - date.getTimezoneOffset() * 60000)
|
||||||
|
.toISOString()
|
||||||
|
.slice(0, -1)
|
||||||
|
.substr(0, 19);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const formatDuration = (duration: number) => {
|
||||||
|
const { days, hours, minutes, seconds } = parseMilliseconds(duration * 1000);
|
||||||
|
var formatted = '';
|
||||||
|
if (days) {
|
||||||
|
formatted += pluralize(days, 'day');
|
||||||
|
}
|
||||||
|
if (formatted || hours) {
|
||||||
|
formatted += pluralize(hours, 'hour');
|
||||||
|
}
|
||||||
|
if (formatted || minutes) {
|
||||||
|
formatted += pluralize(minutes, 'minute');
|
||||||
|
}
|
||||||
|
if (formatted || seconds) {
|
||||||
|
formatted += pluralize(seconds, 'second');
|
||||||
|
}
|
||||||
|
return formatted;
|
||||||
|
}
|
||||||
|
|
||||||
|
const pluralize = (count: number, noun: string, suffix: string = 's') => ` ${count} ${noun}${count !== 1 ? suffix : ''} `;
|
||||||
|
@ -5,8 +5,8 @@ export enum NTPSyncStatus {
|
|||||||
|
|
||||||
export interface NTPStatus {
|
export interface NTPStatus {
|
||||||
status: NTPSyncStatus;
|
status: NTPSyncStatus;
|
||||||
time_utc: string;
|
utc_time: string;
|
||||||
time_local: string;
|
local_time: string;
|
||||||
server: string;
|
server: string;
|
||||||
uptime: number;
|
uptime: number;
|
||||||
}
|
}
|
||||||
@ -19,5 +19,5 @@ export interface NTPSettings {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface Time {
|
export interface Time {
|
||||||
time_utc: string;
|
local_time: string;
|
||||||
}
|
}
|
||||||
|
@ -73,9 +73,9 @@ void NTPSettingsService::configureNTP() {
|
|||||||
|
|
||||||
void NTPSettingsService::configureTime(AsyncWebServerRequest* request, JsonVariant& json) {
|
void NTPSettingsService::configureTime(AsyncWebServerRequest* request, JsonVariant& json) {
|
||||||
if (!sntp_enabled() && json.is<JsonObject>()) {
|
if (!sntp_enabled() && json.is<JsonObject>()) {
|
||||||
String timeUtc = json["time_utc"];
|
|
||||||
struct tm tm = {0};
|
struct tm tm = {0};
|
||||||
char* s = strptime(timeUtc.c_str(), "%Y-%m-%dT%H:%M:%SZ", &tm);
|
String timeLocal = json["local_time"];
|
||||||
|
char* s = strptime(timeLocal.c_str(), "%Y-%m-%dT%H:%M:%S", &tm);
|
||||||
if (s != nullptr) {
|
if (s != nullptr) {
|
||||||
time_t time = mktime(&tm);
|
time_t time = mktime(&tm);
|
||||||
struct timeval now = {.tv_sec = time};
|
struct timeval now = {.tv_sec = time};
|
||||||
|
@ -7,12 +7,25 @@ NTPStatus::NTPStatus(AsyncWebServer* server, SecurityManager* securityManager) {
|
|||||||
AuthenticationPredicates::IS_AUTHENTICATED));
|
AuthenticationPredicates::IS_AUTHENTICATED));
|
||||||
}
|
}
|
||||||
|
|
||||||
String toISOString(tm* time, bool incOffset) {
|
/*
|
||||||
|
* Formats the time using the format provided.
|
||||||
|
*
|
||||||
|
* Uses a 25 byte buffer, large enough to fit an ISO time string with offset.
|
||||||
|
*/
|
||||||
|
String formatTime(tm* time, const char* format) {
|
||||||
char time_string[25];
|
char time_string[25];
|
||||||
strftime(time_string, 25, incOffset ? "%FT%T%z" : "%FT%TZ", time);
|
strftime(time_string, 25, format, time);
|
||||||
return String(time_string);
|
return String(time_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String toUTCTimeString(tm* time) {
|
||||||
|
return formatTime(time, "%FT%TZ");
|
||||||
|
}
|
||||||
|
|
||||||
|
String toLocalTimeString(tm* time) {
|
||||||
|
return formatTime(time, "%FT%T");
|
||||||
|
}
|
||||||
|
|
||||||
void NTPStatus::ntpStatus(AsyncWebServerRequest* request) {
|
void NTPStatus::ntpStatus(AsyncWebServerRequest* request) {
|
||||||
AsyncJsonResponse* response = new AsyncJsonResponse(false, MAX_NTP_STATUS_SIZE);
|
AsyncJsonResponse* response = new AsyncJsonResponse(false, MAX_NTP_STATUS_SIZE);
|
||||||
JsonObject root = response->getRoot();
|
JsonObject root = response->getRoot();
|
||||||
@ -24,10 +37,10 @@ void NTPStatus::ntpStatus(AsyncWebServerRequest* request) {
|
|||||||
root["status"] = sntp_enabled() ? 1 : 0;
|
root["status"] = sntp_enabled() ? 1 : 0;
|
||||||
|
|
||||||
// the current time in UTC
|
// the current time in UTC
|
||||||
root["time_utc"] = toISOString(gmtime(&now), false);
|
root["utc_time"] = toUTCTimeString(gmtime(&now));
|
||||||
|
|
||||||
// local time as ISO String with TZ
|
// local time with offset
|
||||||
root["time_local"] = toISOString(localtime(&now), true);
|
root["local_time"] = toLocalTimeString(localtime(&now));
|
||||||
|
|
||||||
// the sntp server name
|
// the sntp server name
|
||||||
root["server"] = sntp_getservername(0);
|
root["server"] = sntp_getservername(0);
|
||||||
|
Loading…
Reference in New Issue
Block a user