mirror of
https://github.com/owntracks/frontend.git
synced 2026-08-25 20:47:16 +00:00
Implement data copying & download
This commit is contained in:
@@ -9,6 +9,7 @@
|
||||
"cors-proxy": "node scripts/corsProxy.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"clipboard-copy": "^3.1.0",
|
||||
"deepmerge": "^4.0.0",
|
||||
"leaflet": "^1.5.1",
|
||||
"leaflet.heat": "^0.2.0",
|
||||
|
||||
@@ -1,5 +1,102 @@
|
||||
<template>
|
||||
<modal name="download" adaptive>
|
||||
Not implemented.
|
||||
<pre class="data"><code>{{ data }}</code></pre>
|
||||
<div class="options">
|
||||
<input
|
||||
v-model="options.minifyJson"
|
||||
type="checkbox"
|
||||
id="option-minify-json"
|
||||
/>
|
||||
<label for="option-minify-json">
|
||||
Minify JSON
|
||||
</label>
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<button class="button button-outline button-primary" @click="copy">
|
||||
Copy to Clipboard
|
||||
</button>
|
||||
<button class="button button-primary" @click="download">
|
||||
Download
|
||||
</button>
|
||||
</div>
|
||||
</modal>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.data {
|
||||
max-height: 300px;
|
||||
}
|
||||
|
||||
.options {
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
.buttons {
|
||||
display: flex;
|
||||
margin-top: 30px;
|
||||
|
||||
button {
|
||||
flex: 1;
|
||||
|
||||
&:first-child {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import { mapState } from "vuex";
|
||||
import copy from "clipboard-copy";
|
||||
|
||||
import { download } from "@/util";
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
options: {
|
||||
minifyJson: false,
|
||||
},
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapState([
|
||||
"startDate",
|
||||
"endDate",
|
||||
"selectedUser",
|
||||
"selectedDevice",
|
||||
"locationHistory",
|
||||
]),
|
||||
data() {
|
||||
return this.locationHistory;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
copy() {
|
||||
const data = JSON.stringify(
|
||||
this.data,
|
||||
null,
|
||||
this.options.minifyJson ? 0 : 2
|
||||
);
|
||||
copy(data);
|
||||
},
|
||||
download() {
|
||||
const data = JSON.stringify(
|
||||
this.data,
|
||||
null,
|
||||
this.options.minifyJson ? 0 : 2
|
||||
);
|
||||
const start = this.startDate.toISOString().split("T")[0];
|
||||
const end = this.endDate.toISOString().split("T")[0];
|
||||
const user = this.selectedUser ? `_${this.selectedUser}` : "";
|
||||
const device = this.selectedDevice ? `_${this.selectedDevice}` : "";
|
||||
const filename = `data_${start}_${end}${user}${device}.json`;
|
||||
download(data, filename, "application/json");
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
+64
-23
@@ -31,6 +31,22 @@ ul {
|
||||
list-style: inside;
|
||||
}
|
||||
|
||||
pre {
|
||||
background: #000;
|
||||
border-radius: 3px;
|
||||
color: #ddd;
|
||||
display: block;
|
||||
font-family: Consolas, "Andale Mono WT", "Andale Mono", "Lucida Console",
|
||||
"Lucida Sans Typewriter", "DejaVu Sans Mono", "Bitstream Vera Sans Mono",
|
||||
"Liberation Mono", "Nimbus Mono L", Monaco, "Courier New", Courier, monospace;
|
||||
overflow-x: auto;
|
||||
|
||||
code {
|
||||
display: block;
|
||||
margin: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
#app {
|
||||
display: flex;
|
||||
min-height: 100%;
|
||||
@@ -104,7 +120,8 @@ ul {
|
||||
}
|
||||
}
|
||||
|
||||
.button,
|
||||
|
||||
|
||||
.vdp-datepicker input {
|
||||
cursor: pointer;
|
||||
color: var(--color-text);
|
||||
@@ -112,35 +129,59 @@ ul {
|
||||
border: 0;
|
||||
border-radius: 18px;
|
||||
padding: 8px 16px;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.vdp-datepicker input {
|
||||
min-width: 130px;
|
||||
}
|
||||
|
||||
.button-outline {
|
||||
border: 1px solid var(--color-background);
|
||||
color: var(--color-primary-text);
|
||||
background: transparent;
|
||||
}
|
||||
.button {
|
||||
cursor: pointer;
|
||||
color: var(--color-text);
|
||||
background: var(--color-background);
|
||||
border: 0;
|
||||
border-radius: 18px;
|
||||
padding: 8px 16px;
|
||||
text-overflow: ellipsis;
|
||||
|
||||
.button-flat {
|
||||
color: var(--color-primary-text);
|
||||
background: transparent;
|
||||
}
|
||||
&.button-primary {
|
||||
color: var(--color-primary-text);
|
||||
background: var(--color-primary);
|
||||
|
||||
.button-outline,
|
||||
.button-flat {
|
||||
transition: background 0.2s;
|
||||
&:hover,
|
||||
&:focus {
|
||||
background: rgba(0, 0, 0, 0.2);
|
||||
&:focus::-moz-focus-inner {
|
||||
border-color: var(--color-primary-text)e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.button-icon {
|
||||
padding: 8px;
|
||||
&.button-outline {
|
||||
border: 1px solid var(--color-background);
|
||||
color: var(--color-primary-text);
|
||||
background: transparent;
|
||||
|
||||
&.button-primary {
|
||||
border-color: var(--color-primary);
|
||||
color: var(--color-text);
|
||||
}
|
||||
}
|
||||
|
||||
&.button-flat {
|
||||
color: var(--color-primary-text);
|
||||
background: transparent;
|
||||
|
||||
&.button-primary {
|
||||
color: var(--color-text);
|
||||
}
|
||||
}
|
||||
|
||||
&.button-outline,
|
||||
&.button-flat {
|
||||
transition: background 0.2s;
|
||||
&:hover,
|
||||
&:focus {
|
||||
background: rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
}
|
||||
|
||||
&.button-icon {
|
||||
padding: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown {
|
||||
|
||||
+19
@@ -57,3 +57,22 @@ export const distanceBetweenCoordinates = (c1, c2) => {
|
||||
// Return distance in meters
|
||||
return EARTH_RADIUS_IN_KM * c * 1000;
|
||||
};
|
||||
|
||||
/**
|
||||
* Let the user download a string as file.
|
||||
*
|
||||
* @param {String} text Content of the file
|
||||
* @param {String} filename Suggested filename for the browser
|
||||
* @param {String} [mimeType] Content mime type
|
||||
*/
|
||||
export const download = (text, filename, mimeType = "text/plain") => {
|
||||
const dataUrl = `data:${mimeType},${encodeURIComponent(text)}`;
|
||||
console.log(dataUrl);
|
||||
const element = document.createElement("a");
|
||||
element.href = dataUrl;
|
||||
element.download = filename;
|
||||
element.style.display = "none";
|
||||
document.body.appendChild(element);
|
||||
element.click();
|
||||
document.body.removeChild(element);
|
||||
};
|
||||
|
||||
@@ -2585,6 +2585,11 @@ cli-width@^2.0.0:
|
||||
resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639"
|
||||
integrity sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=
|
||||
|
||||
clipboard-copy@^3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/clipboard-copy/-/clipboard-copy-3.1.0.tgz#4c59030a43d4988990564a664baeafba99f78ca4"
|
||||
integrity sha512-Xsu1NddBXB89IUauda5BIq3Zq73UWkjkaQlPQbLNvNsd5WBMnTWPNKYR6HGaySOxGYZ+BKxP2E9X4ElnI3yiPA==
|
||||
|
||||
clipboardy@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/clipboardy/-/clipboardy-2.1.0.tgz#0123a0c8fac92f256dc56335e0bb8be97a4909a5"
|
||||
|
||||
Reference in New Issue
Block a user