mirror of
https://github.com/owntracks/frontend.git
synced 2026-04-19 01:56:38 +00:00
Implement new date/time range picker
Co-authored-by: Christophe Chapuis <chris.chapuis@gmail.com>
This commit is contained in:
131
package-lock.json
generated
131
package-lock.json
generated
@@ -14,13 +14,13 @@
|
||||
"leaflet.heat": "^0.2.0",
|
||||
"moment": "^2.30.1",
|
||||
"vue": "^2.7.16",
|
||||
"vue-ctk-date-time-picker": "^2.5.0",
|
||||
"vue-feather-icons": "^5.1.0",
|
||||
"vue-i18n": "^8.28.2",
|
||||
"vue-js-modal": "^2.0.1",
|
||||
"vue-mq": "^1.0.1",
|
||||
"vue-outside-events": "^1.1.3",
|
||||
"vue-router": "^3.6.5",
|
||||
"vue2-datepicker": "^3.11.1",
|
||||
"vue2-leaflet": "^2.7.1",
|
||||
"vuex": "^3.6.2"
|
||||
},
|
||||
@@ -1720,18 +1720,6 @@
|
||||
"version": "3.1.3",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/d": {
|
||||
"version": "1.0.1",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"es5-ext": "^0.10.50",
|
||||
"type": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/d/node_modules/type": {
|
||||
"version": "1.2.0",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/data-urls": {
|
||||
"version": "5.0.0",
|
||||
"dev": true,
|
||||
@@ -1752,6 +1740,11 @@
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/date-format-parse": {
|
||||
"version": "0.2.7",
|
||||
"resolved": "https://registry.npmjs.org/date-format-parse/-/date-format-parse-0.2.7.tgz",
|
||||
"integrity": "sha512-/+lyMUKoRogMuTeOVii6lUwjbVlesN9YRYLzZT/g3TEZ3uD9QnpjResujeEqUW+OSNbT7T1+SYdyEkTcRv+KDQ=="
|
||||
},
|
||||
"node_modules/debug": {
|
||||
"version": "4.3.4",
|
||||
"dev": true,
|
||||
@@ -1862,37 +1855,6 @@
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/es5-ext": {
|
||||
"version": "0.10.63",
|
||||
"hasInstallScript": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"es6-iterator": "^2.0.3",
|
||||
"es6-symbol": "^3.1.3",
|
||||
"esniff": "^2.0.1",
|
||||
"next-tick": "^1.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/es6-iterator": {
|
||||
"version": "2.0.3",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"d": "1",
|
||||
"es5-ext": "^0.10.35",
|
||||
"es6-symbol": "^3.1.1"
|
||||
}
|
||||
},
|
||||
"node_modules/es6-symbol": {
|
||||
"version": "3.1.3",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"d": "^1.0.1",
|
||||
"ext": "^1.1.2"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild": {
|
||||
"version": "0.20.2",
|
||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz",
|
||||
@@ -2245,19 +2207,6 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/esniff": {
|
||||
"version": "2.0.1",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"d": "^1.0.1",
|
||||
"es5-ext": "^0.10.62",
|
||||
"event-emitter": "^0.3.5",
|
||||
"type": "^2.7.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/espree": {
|
||||
"version": "9.6.1",
|
||||
"dev": true,
|
||||
@@ -2322,14 +2271,6 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/event-emitter": {
|
||||
"version": "0.3.5",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"d": "1",
|
||||
"es5-ext": "~0.10.14"
|
||||
}
|
||||
},
|
||||
"node_modules/eventemitter3": {
|
||||
"version": "1.2.0",
|
||||
"dev": true,
|
||||
@@ -2344,13 +2285,6 @@
|
||||
"node": ">=0.8.x"
|
||||
}
|
||||
},
|
||||
"node_modules/ext": {
|
||||
"version": "1.7.0",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"type": "^2.7.2"
|
||||
}
|
||||
},
|
||||
"node_modules/fast-deep-equal": {
|
||||
"version": "3.1.3",
|
||||
"dev": true,
|
||||
@@ -3337,19 +3271,6 @@
|
||||
"webpack": "^1 || ^2 || ^3 || ^4 || ^5"
|
||||
}
|
||||
},
|
||||
"node_modules/moment-range": {
|
||||
"version": "4.0.2",
|
||||
"license": "Unlicense",
|
||||
"dependencies": {
|
||||
"es6-symbol": "^3.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"moment": ">= 2"
|
||||
}
|
||||
},
|
||||
"node_modules/nanoid": {
|
||||
"version": "3.3.7",
|
||||
"funding": [
|
||||
@@ -3377,10 +3298,6 @@
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/next-tick": {
|
||||
"version": "1.1.0",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/node-fetch": {
|
||||
"version": "2.7.0",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
|
||||
@@ -4299,10 +4216,6 @@
|
||||
"dev": true,
|
||||
"license": "0BSD"
|
||||
},
|
||||
"node_modules/type": {
|
||||
"version": "2.7.2",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/type-check": {
|
||||
"version": "0.4.0",
|
||||
"dev": true,
|
||||
@@ -4409,13 +4322,6 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/v-click-outside": {
|
||||
"version": "2.1.5",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/vite": {
|
||||
"version": "5.2.13",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-5.2.13.tgz",
|
||||
@@ -4685,20 +4591,6 @@
|
||||
"csstype": "^3.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/vue-ctk-date-time-picker": {
|
||||
"version": "2.5.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"moment": "^2.24.0",
|
||||
"moment-range": "^4.0.1",
|
||||
"v-click-outside": "^2.0.2",
|
||||
"vue": "^2.6.9"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6.0.0",
|
||||
"npm": ">= 3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/vue-eslint-parser": {
|
||||
"version": "9.4.3",
|
||||
"resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.4.3.tgz",
|
||||
@@ -4803,6 +4695,17 @@
|
||||
"version": "3.6.5",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/vue2-datepicker": {
|
||||
"version": "3.11.1",
|
||||
"resolved": "https://registry.npmjs.org/vue2-datepicker/-/vue2-datepicker-3.11.1.tgz",
|
||||
"integrity": "sha512-6PU/+pnp2mgZAfnSXmbdwj9516XsEvTiw61Q5SNrvvdy8W/FCxk1GAe9UZn/m9YfS5A47yK6XkcjMHbp7aFApA==",
|
||||
"dependencies": {
|
||||
"date-format-parse": "^0.2.7"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"vue": "^2.5.0"
|
||||
}
|
||||
},
|
||||
"node_modules/vue2-leaflet": {
|
||||
"version": "2.7.1",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -30,13 +30,13 @@
|
||||
"leaflet.heat": "^0.2.0",
|
||||
"moment": "^2.30.1",
|
||||
"vue": "^2.7.16",
|
||||
"vue-ctk-date-time-picker": "^2.5.0",
|
||||
"vue-feather-icons": "^5.1.0",
|
||||
"vue-i18n": "^8.28.2",
|
||||
"vue-js-modal": "^2.0.1",
|
||||
"vue-mq": "^1.0.1",
|
||||
"vue-outside-events": "^1.1.3",
|
||||
"vue-router": "^3.6.5",
|
||||
"vue2-datepicker": "^3.11.1",
|
||||
"vue2-leaflet": "^2.7.1",
|
||||
"vuex": "^3.6.2"
|
||||
},
|
||||
|
||||
@@ -53,35 +53,31 @@
|
||||
</div>
|
||||
<div class="nav-item">
|
||||
<CalendarIcon size="1x" aria-hidden="true" role="img" />
|
||||
<VueCtkDateTimePicker
|
||||
v-model="startDateTime"
|
||||
:format="DATE_TIME_FORMAT"
|
||||
:color="$config.primaryColor"
|
||||
:locale="$config.locale"
|
||||
:max-date="endDateTime"
|
||||
:button-now-translation="$t('Now')"
|
||||
<date-picker
|
||||
v-model="dateTimeRange"
|
||||
type="datetime"
|
||||
format="YYYY-MM-DD HH:mm"
|
||||
:editable="false"
|
||||
:clearable="false"
|
||||
:confirm="true"
|
||||
:show-second="false"
|
||||
:range="true"
|
||||
range-separator=" – "
|
||||
:shortcuts="shortcuts"
|
||||
:show-time-panel="showTimeRangePanel"
|
||||
:disabled-date="(date, _) => date > new Date()"
|
||||
@change="handleDateTimeRangeChange"
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
class="dropdown-button button"
|
||||
:title="$t('Select start date')"
|
||||
/>
|
||||
</VueCtkDateTimePicker>
|
||||
<span>{{ $t("to") }}</span>
|
||||
<VueCtkDateTimePicker
|
||||
v-model="endDateTime"
|
||||
:format="DATE_TIME_FORMAT"
|
||||
:color="$config.primaryColor"
|
||||
:locale="$config.locale"
|
||||
:min-date="startDateTime"
|
||||
:button-now-translation="$t('Now')"
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
class="dropdown-button button"
|
||||
:title="$t('Select end date')"
|
||||
/>
|
||||
</VueCtkDateTimePicker>
|
||||
<template v-slot:footer>
|
||||
<button
|
||||
class="mx-btn toggle-date-btn"
|
||||
type="button"
|
||||
@click="toggleTimeRangePanel"
|
||||
>
|
||||
{{ showTimeRangePanel ? $t("Select date") : $t("Select time") }}
|
||||
</button>
|
||||
</template>
|
||||
</date-picker>
|
||||
</div>
|
||||
<div class="nav-item">
|
||||
<UserIcon size="1x" aria-hidden="true" role="img" />
|
||||
@@ -162,8 +158,9 @@ import {
|
||||
SmartphoneIcon,
|
||||
UserIcon,
|
||||
} from "vue-feather-icons";
|
||||
import VueCtkDateTimePicker from "vue-ctk-date-time-picker";
|
||||
import "vue-ctk-date-time-picker/dist/vue-ctk-date-time-picker.css";
|
||||
|
||||
import DatePicker from "vue2-datepicker";
|
||||
import "vue2-datepicker/index.css";
|
||||
|
||||
import DropdownButton from "@/components/DropdownButton.vue";
|
||||
import { DATE_TIME_FORMAT } from "@/constants";
|
||||
@@ -176,12 +173,12 @@ export default {
|
||||
ArrowUpIcon,
|
||||
CalendarIcon,
|
||||
CrosshairIcon,
|
||||
DatePicker,
|
||||
InfoIcon,
|
||||
LayersIcon,
|
||||
MenuIcon,
|
||||
SmartphoneIcon,
|
||||
UserIcon,
|
||||
VueCtkDateTimePicker,
|
||||
DropdownButton,
|
||||
},
|
||||
data() {
|
||||
@@ -194,6 +191,41 @@ export default {
|
||||
{ layer: "heatmap", label: this.$t("Show location heatmap") },
|
||||
],
|
||||
showMobileNav: false,
|
||||
shortcuts: [
|
||||
{
|
||||
text: this.$t("Today"),
|
||||
onClick() {
|
||||
const end = new Date();
|
||||
end.setHours(23, 59, 59, 0);
|
||||
const start = new Date();
|
||||
start.setHours(0, 0, 0, 0);
|
||||
return [start, end];
|
||||
},
|
||||
},
|
||||
{
|
||||
text: this.$t("7 days"),
|
||||
onClick() {
|
||||
const end = new Date();
|
||||
end.setHours(23, 59, 59, 0);
|
||||
const start = new Date();
|
||||
start.setDate(end.getDate() - 7);
|
||||
start.setHours(0, 0, 0, 0);
|
||||
return [start, end];
|
||||
},
|
||||
},
|
||||
{
|
||||
text: this.$t("30 days"),
|
||||
onClick() {
|
||||
const end = new Date();
|
||||
end.setHours(23, 59, 59, 0);
|
||||
const start = new Date();
|
||||
start.setDate(end.getDate() - 30);
|
||||
start.setHours(0, 0, 0, 0);
|
||||
return [start, end];
|
||||
},
|
||||
},
|
||||
],
|
||||
showTimeRangePanel: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
@@ -221,32 +253,25 @@ export default {
|
||||
this.setSelectedDevice(value);
|
||||
},
|
||||
},
|
||||
startDateTime: {
|
||||
dateTimeRange: {
|
||||
get() {
|
||||
return moment
|
||||
const startDateTime = moment
|
||||
.utc(this.$store.state.startDateTime, DATE_TIME_FORMAT)
|
||||
.local()
|
||||
.format(DATE_TIME_FORMAT);
|
||||
},
|
||||
set(value) {
|
||||
this.setStartDateTime(
|
||||
moment(value, DATE_TIME_FORMAT).utc().format(DATE_TIME_FORMAT)
|
||||
);
|
||||
},
|
||||
},
|
||||
endDateTime: {
|
||||
get() {
|
||||
return moment
|
||||
.toDate();
|
||||
const endDateTime = moment
|
||||
.utc(this.$store.state.endDateTime, DATE_TIME_FORMAT)
|
||||
.local()
|
||||
.format(DATE_TIME_FORMAT);
|
||||
.toDate();
|
||||
return [startDateTime, endDateTime];
|
||||
},
|
||||
set(value) {
|
||||
set([startDateTime, endDateTime]) {
|
||||
this.setStartDateTime(
|
||||
moment(startDateTime).utc().format(DATE_TIME_FORMAT)
|
||||
);
|
||||
|
||||
this.setEndDateTime(
|
||||
moment(value, DATE_TIME_FORMAT)
|
||||
.set("seconds", 59)
|
||||
.utc()
|
||||
.format(DATE_TIME_FORMAT)
|
||||
moment(endDateTime).set("seconds", 59).utc().format(DATE_TIME_FORMAT)
|
||||
);
|
||||
},
|
||||
},
|
||||
@@ -262,6 +287,13 @@ export default {
|
||||
"setEndDateTime",
|
||||
]),
|
||||
humanReadableDistance,
|
||||
toggleTimeRangePanel() {
|
||||
this.showTimeRangePanel = !this.showTimeRangePanel;
|
||||
},
|
||||
// Resetting to date choice after value change
|
||||
handleDateTimeRangeChange(value, type) {
|
||||
this.showTimeRangePanel = false;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -32,5 +32,10 @@
|
||||
"Battery": "Battery",
|
||||
"Speed": "Speed",
|
||||
"Regions:": "Regions:",
|
||||
"WiFi": "WiFi"
|
||||
"WiFi": "WiFi",
|
||||
"Select date": "Select date",
|
||||
"Select time": "Select time",
|
||||
"Today": "Today",
|
||||
"7 days": "7 days",
|
||||
"30 days": "30 days"
|
||||
}
|
||||
|
||||
@@ -32,5 +32,10 @@
|
||||
"Battery": "Battery",
|
||||
"Speed": "Speed",
|
||||
"Regions:": "Regions:",
|
||||
"WiFi": "WiFi"
|
||||
"WiFi": "WiFi",
|
||||
"Select date": "Select date",
|
||||
"Select time": "Select time",
|
||||
"Today": "Today",
|
||||
"7 days": "7 days",
|
||||
"30 days": "30 days"
|
||||
}
|
||||
|
||||
@@ -101,8 +101,7 @@ pre {
|
||||
min-height: 100%;
|
||||
flex-direction: column;
|
||||
|
||||
// Only select immediate child as the datepicker contains a <header> as well
|
||||
> header {
|
||||
header {
|
||||
display: flex;
|
||||
padding: 20px;
|
||||
white-space: nowrap;
|
||||
@@ -182,19 +181,33 @@ pre {
|
||||
}
|
||||
|
||||
> .button,
|
||||
> .dropdown,
|
||||
> .date-time-picker {
|
||||
> .mx-datepicker,
|
||||
> .mx-input,
|
||||
> .dropdown {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
> .dropdown .dropdown-button,
|
||||
> .date-time-picker .dropdown-button {
|
||||
> .dropdown .dropdown-button {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
> .date-time-picker {
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
.mx-datepicker {
|
||||
display: flex;
|
||||
width: auto;
|
||||
|
||||
.mx-datepicker-range {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.mx-input-wrapper {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
|
||||
.mx-input {
|
||||
font-size: 13px;
|
||||
letter-spacing: -0.6px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
> span {
|
||||
|
||||
@@ -1,10 +1,45 @@
|
||||
.date-time-picker {
|
||||
display: inline-block;
|
||||
width: auto;
|
||||
.mx-datepicker {
|
||||
width: 280px;
|
||||
|
||||
.datepicker {
|
||||
box-shadow: none !important;
|
||||
filter: var(--drop-shadow);
|
||||
margin-top: 5px;
|
||||
.mx-input {
|
||||
border: 0;
|
||||
border-radius: 18px;
|
||||
text-align: center;
|
||||
height: 33px;
|
||||
padding-right: 0px;
|
||||
padding-left: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 400px) {
|
||||
.mx-datepicker-main {
|
||||
display: flex;
|
||||
top: 0 !important;
|
||||
left: 0 !important;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
.mx-datepicker-sidebar {
|
||||
flex: 0.7;
|
||||
}
|
||||
|
||||
.mx-datepicker-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
margin-left: 0px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.mx-time {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.toggle-date-btn {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.mx-icon-calendar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user