Compare commits

...

26 Commits

Author SHA1 Message Date
stingl d8ed85792a repair stupidity; 3 years ago
stingl b9d82dbf93 update version; 3 years ago
stingl 0f08919318 automatically create multiple tasks if seperated by semicolons; 3 years ago
stingl 21bf3a7035 save on delete; 3 years ago
stingl 3824776c7e responsiveness adjustments; 3 years ago
stingl 075e3a37e1 responsiveness adjustments; 3 years ago
stingl 4a5f06cc4a make notes own page; grid for notes; show version on app; 3 years ago
1nicerOli d6053fb205 Remove classes for responsiveness due to canvas-card; 3 years ago
Nero Ignis b8860afe93 Fix Icons for Task-Components; 3 years ago
Nero Ignis cc91919da1 Show message if no notes match the filter; 3 years ago
Nero Ignis 1be7efaff7 Change notes to canvas instead of own page; 3 years ago
Nero Ignis 9ab4122bd6 Fix box-model; 3 years ago
Nero Ignis 6fb5ba4220 Move filter and only show it if notes are present; 3 years ago
Nero Ignis c636bb6f82 Add filter for colors; 3 years ago
Nero Ignis 287a335f21 Fix saving colors for notes; 3 years ago
Nero Ignis 0c2cb6c44a Add notes-module; 3 years ago
stingl 5e25410897 make page scrollable; 3 years ago
stingl e1ecf56258 change heading; 3 years ago
stingl c5671f0fc7 Fix text-color; 3 years ago
stingl f7605e8084 fix typo; 3 years ago
stingl ed32f4ba13 add general tasks; 3 years ago
stingl d97dce6905 save settings in store; 4 years ago
stingl d3c13a37b2 fix with method; 4 years ago
stingl b449678ace Fix; 4 years ago
stingl fd3a7b6911 show day for history; 4 years ago
stingl 35b605a8f8 don't show today if empty; shot start time in tracking-info; 4 years ago
  1. 62
      package-lock.json
  2. BIN
      public/fonts/NotePaper-regular.otf
  3. 19
      src/App.vue
  4. 10
      src/css/app.scss
  5. 6
      src/router/index.js
  6. 35
      src/store/index.js
  7. 6
      src/views/History.vue
  8. 25
      src/views/Menu.vue
  9. 190
      src/views/Notes.vue
  10. 7
      src/views/Settings.vue
  11. 120
      src/views/Tasks.vue
  12. 14
      src/views/TasksForTracker.vue
  13. 16
      src/views/Trackers.vue

62
package-lock.json generated

@ -5,6 +5,7 @@
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "ttrack",
"version": "0.1.0", "version": "0.1.0",
"dependencies": { "dependencies": {
"@popperjs/core": "^2.11.0", "@popperjs/core": "^2.11.0",
@ -17,7 +18,8 @@
"moment": "^2.29.1", "moment": "^2.29.1",
"vue": "^3.0.0", "vue": "^3.0.0",
"vue-router": "^4.0.0-0", "vue-router": "^4.0.0-0",
"vuex": "^4.0.0-0" "vuex": "^4.0.0-0",
"vuex-persist": "^3.1.3"
}, },
"devDependencies": { "devDependencies": {
"@vue/cli-plugin-babel": "~4.5.0", "@vue/cli-plugin-babel": "~4.5.0",
@ -2375,7 +2377,6 @@
"thread-loader": "^2.1.3", "thread-loader": "^2.1.3",
"url-loader": "^2.2.0", "url-loader": "^2.2.0",
"vue-loader": "^15.9.2", "vue-loader": "^15.9.2",
"vue-loader-v16": "npm:vue-loader@^16.1.0",
"vue-style-loader": "^4.1.2", "vue-style-loader": "^4.1.2",
"webpack": "^4.0.0", "webpack": "^4.0.0",
"webpack-bundle-analyzer": "^3.8.0", "webpack-bundle-analyzer": "^3.8.0",
@ -2536,7 +2537,6 @@
"merge-source-map": "^1.1.0", "merge-source-map": "^1.1.0",
"postcss": "^7.0.36", "postcss": "^7.0.36",
"postcss-selector-parser": "^6.0.2", "postcss-selector-parser": "^6.0.2",
"prettier": "^1.18.2 || ^2.0.0",
"source-map": "~0.6.1", "source-map": "~0.6.1",
"vue-template-es2015-compiler": "^1.9.0" "vue-template-es2015-compiler": "^1.9.0"
}, },
@ -4103,7 +4103,6 @@
"dependencies": { "dependencies": {
"anymatch": "~3.1.2", "anymatch": "~3.1.2",
"braces": "~3.0.2", "braces": "~3.0.2",
"fsevents": "~2.3.2",
"glob-parent": "~5.1.2", "glob-parent": "~5.1.2",
"is-binary-path": "~2.1.0", "is-binary-path": "~2.1.0",
"is-glob": "~4.0.1", "is-glob": "~4.0.1",
@ -9140,9 +9139,6 @@
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
"integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
"dev": true, "dev": true,
"dependencies": {
"graceful-fs": "^4.1.6"
},
"optionalDependencies": { "optionalDependencies": {
"graceful-fs": "^4.1.6" "graceful-fs": "^4.1.6"
} }
@ -15514,16 +15510,39 @@
"vue": "^3.0.2" "vue": "^3.0.2"
} }
}, },
"node_modules/vuex-persist": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/vuex-persist/-/vuex-persist-3.1.3.tgz",
"integrity": "sha512-QWOpP4SxmJDC5Y1+0+Yl/F4n7z27syd1St/oP+IYCGe0X0GFio0Zan6kngZFufdIhJm+5dFGDo3VG5kdkCGeRQ==",
"dependencies": {
"deepmerge": "^4.2.2",
"flatted": "^3.0.5"
},
"peerDependencies": {
"vuex": ">=2.5"
}
},
"node_modules/vuex-persist/node_modules/deepmerge": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz",
"integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/vuex-persist/node_modules/flatted": {
"version": "3.2.5",
"resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz",
"integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg=="
},
"node_modules/watchpack": { "node_modules/watchpack": {
"version": "1.7.5", "version": "1.7.5",
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.5.tgz", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.5.tgz",
"integrity": "sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ==", "integrity": "sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"chokidar": "^3.4.1",
"graceful-fs": "^4.1.2", "graceful-fs": "^4.1.2",
"neo-async": "^2.5.0", "neo-async": "^2.5.0"
"watchpack-chokidar2": "^2.0.1"
}, },
"optionalDependencies": { "optionalDependencies": {
"chokidar": "^3.4.1", "chokidar": "^3.4.1",
@ -15585,7 +15604,6 @@
"anymatch": "^2.0.0", "anymatch": "^2.0.0",
"async-each": "^1.0.1", "async-each": "^1.0.1",
"braces": "^2.3.2", "braces": "^2.3.2",
"fsevents": "^1.2.7",
"glob-parent": "^3.1.0", "glob-parent": "^3.1.0",
"inherits": "^2.0.3", "inherits": "^2.0.3",
"is-binary-path": "^1.0.0", "is-binary-path": "^1.0.0",
@ -15892,7 +15910,6 @@
"anymatch": "^2.0.0", "anymatch": "^2.0.0",
"async-each": "^1.0.1", "async-each": "^1.0.1",
"braces": "^2.3.2", "braces": "^2.3.2",
"fsevents": "^1.2.7",
"glob-parent": "^3.1.0", "glob-parent": "^3.1.0",
"inherits": "^2.0.3", "inherits": "^2.0.3",
"is-binary-path": "^1.0.0", "is-binary-path": "^1.0.0",
@ -28964,6 +28981,27 @@
"@vue/devtools-api": "^6.0.0-beta.11" "@vue/devtools-api": "^6.0.0-beta.11"
} }
}, },
"vuex-persist": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/vuex-persist/-/vuex-persist-3.1.3.tgz",
"integrity": "sha512-QWOpP4SxmJDC5Y1+0+Yl/F4n7z27syd1St/oP+IYCGe0X0GFio0Zan6kngZFufdIhJm+5dFGDo3VG5kdkCGeRQ==",
"requires": {
"deepmerge": "^4.2.2",
"flatted": "^3.0.5"
},
"dependencies": {
"deepmerge": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz",
"integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg=="
},
"flatted": {
"version": "3.2.5",
"resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz",
"integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg=="
}
}
},
"watchpack": { "watchpack": {
"version": "1.7.5", "version": "1.7.5",
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.5.tgz", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.5.tgz",

BIN
public/fonts/NotePaper-regular.otf

Binary file not shown.

19
src/App.vue

@ -4,6 +4,9 @@
<Menu/> <Menu/>
<div class="col" id="page-wrapper"> <div class="col" id="page-wrapper">
<router-view/> <router-view/>
<span id="version">
v{{ version }}
</span>
</div> </div>
</div> </div>
</div> </div>
@ -11,6 +14,7 @@
<HistoryForTracker/> <HistoryForTracker/>
<CustomBookForTracker/> <CustomBookForTracker/>
<TasksForTracker/> <TasksForTracker/>
<Tasks/>
<History/> <History/>
<Settings/> <Settings/>
</template> </template>
@ -25,19 +29,22 @@ import TasksForTracker from "./views/TasksForTracker";
import HistoryForTracker from "./views/HistoryForTracker"; import HistoryForTracker from "./views/HistoryForTracker";
import CustomBookForTracker from "./views/CustomBookForTracker"; import CustomBookForTracker from "./views/CustomBookForTracker";
import Settings from "./views/Settings"; import Settings from "./views/Settings";
import Tasks from "./views/Tasks";
export default { export default {
el: '#root', el: '#root',
components: { components: {
Tasks,
Settings, Settings,
CustomBookForTracker, CustomBookForTracker,
HistoryForTracker, HistoryForTracker,
TasksForTracker, TasksForTracker,
History, History,
Menu Menu,
}, },
data() { data() {
return { return {
version: '0.8.24.1',
sounds: { sounds: {
bad: [ bad: [
'alert', 'alert',
@ -50,7 +57,7 @@ export default {
theme: 'materia', theme: 'materia',
customBookingValue: '', customBookingValue: '',
customDateForPastDays: '', customDateForPastDays: '',
newTaskInput: '' newTaskInput: '',
} }
}, },
mounted() { mounted() {
@ -225,4 +232,12 @@ export default {
#page-wrapper { #page-wrapper {
padding-top: 15px; padding-top: 15px;
} }
#version {
position: fixed;
bottom: 1em;
right: 2em;
z-index: -1;
color: lightgrey;
}
</style> </style>

10
src/css/app.scss

@ -1,10 +1,20 @@
@import '~izitoast/dist/css/iziToast.min.css'; @import '~izitoast/dist/css/iziToast.min.css';
@import "~bootswatch/dist/materia/bootstrap.min.css"; @import "~bootswatch/dist/materia/bootstrap.min.css";
@font-face {
font-family: 'NotePaper';
src: url('/fonts/NotePaper-regular.otf');
}
body { body {
background-color: #e7e7e7; background-color: #e7e7e7;
} }
#page-wrapper {
max-height: 100vh;
overflow-y: scroll;
}
.tracker-action-button { .tracker-action-button {
margin-top: 10px; margin-top: 10px;
padding: 1px 5px 1px 5px; padding: 1px 5px 1px 5px;

6
src/router/index.js

@ -3,6 +3,7 @@ import Trackers from "../views/Trackers";
import Settings from "../views/Settings"; import Settings from "../views/Settings";
import TrackersDetail from "../views/TrackersDetail"; import TrackersDetail from "../views/TrackersDetail";
import Archive from "../views/Archive"; import Archive from "../views/Archive";
import Notes from "../views/Notes";
Array.prototype.pushToBeginning = function (toPush) { Array.prototype.pushToBeginning = function (toPush) {
return this.unshift.apply(this, [toPush]); return this.unshift.apply(this, [toPush]);
@ -24,6 +25,11 @@ const routes = [
name: 'Archive', name: 'Archive',
component: Archive component: Archive
}, },
{
path: '/notes',
name: 'Notes',
component: Notes
},
{ {
path: '/settings', path: '/settings',
name: 'Settings', name: 'Settings',

35
src/store/index.js

@ -1,4 +1,5 @@
import {createStore} from 'vuex' import {createStore} from 'vuex'
import moment from "moment";
export default createStore({ export default createStore({
state: { state: {
@ -8,7 +9,9 @@ export default createStore({
theme: 'materia' theme: 'materia'
}, },
trashed: {}, trashed: {},
selectedTracker: {} selectedTracker: {},
tasks: [],
notes: []
}, },
mutations: { mutations: {
loadSavedData(state) { loadSavedData(state) {
@ -22,6 +25,16 @@ export default createStore({
state.archive = JSON.parse(storedArchive); state.archive = JSON.parse(storedArchive);
} }
let storedTasks = localStorage.getItem('tasks');
if (storedTasks !== null && storedTasks !== undefined) {
state.tasks = JSON.parse(storedTasks);
}
let storedNotes = localStorage.getItem('notes');
if (storedNotes !== null && storedNotes !== undefined) {
state.notes = JSON.parse(storedNotes);
}
let storedSettings = localStorage.getItem('settings'); let storedSettings = localStorage.getItem('settings');
state.settings = storedSettings == null ? { state.settings = storedSettings == null ? {
theme: '', theme: '',
@ -55,6 +68,12 @@ export default createStore({
localStorage.setItem('trackers', JSON.stringify(state.trackers)); localStorage.setItem('trackers', JSON.stringify(state.trackers));
localStorage.setItem('archive', JSON.stringify(state.archive)); localStorage.setItem('archive', JSON.stringify(state.archive));
}, },
saveTasks(state) {
localStorage.setItem('tasks', JSON.stringify(state.tasks));
},
saveSettings(state) {
localStorage.setItem('settings', JSON.stringify(state.settings));
},
deleteTracker(state, index, archive) { deleteTracker(state, index, archive) {
let message = ''; let message = '';
@ -85,6 +104,20 @@ export default createStore({
}, },
selectTracker(state, tracker) { selectTracker(state, tracker) {
state.selectedTracker = tracker; state.selectedTracker = tracker;
},
saveNotes(state) {
localStorage.setItem('notes', JSON.stringify(state.notes));
},
createNote(state, content = '') {
state.notes.pushToBeginning({
body: content,
color: '#ffea77',
created: moment()
});
},
deleteNote(state, index) {
state.notes.splice(index, 1);
localStorage.setItem('notes', JSON.stringify(state.notes));
} }
} }
}) })

6
src/views/History.vue

@ -13,6 +13,9 @@
<h6>Datum</h6> <h6>Datum</h6>
<input id="date" type="date" class="form-control" v-model="customDateForPastDays"> <input id="date" type="date" class="form-control" v-model="customDateForPastDays">
</div> </div>
<div>
{{ showWeekday(customDateForPastDays) }}
</div>
<ul class="list-group"> <ul class="list-group">
<li class="list-group-item" <li class="list-group-item"
:style="entry.archive ? 'background-color: lightgrey;' : ''" :style="entry.archive ? 'background-color: lightgrey;' : ''"
@ -119,6 +122,9 @@ export default {
return time + postFix + plural; return time + postFix + plural;
}, },
showWeekday(date) {
return moment(date).format('dddd');
}
} }
} }
</script> </script>

25
src/views/Menu.vue

@ -45,6 +45,16 @@
<i class="fas fa-archive"></i> <i class="fas fa-archive"></i>
</router-link> </router-link>
</div> </div>
<div class="left-menu-item">
<router-link to="/notes"
type="button"
class="btn btn-info text-light bottom-menu-item"
style="background-color: #ffea77;"
data-bs-placement="left"
title="Notizen">
<i class="fas fa-pen"></i>
</router-link>
</div>
<div class="left-menu-item" v-if="($store.state.trackers.length + $store.state.archive.length) > 0"> <div class="left-menu-item" v-if="($store.state.trackers.length + $store.state.archive.length) > 0">
<a type="button" <a type="button"
class="btn btn-info text-light bottom-menu-item" class="btn btn-info text-light bottom-menu-item"
@ -55,6 +65,17 @@
<i class="fas fa-history"></i> <i class="fas fa-history"></i>
</a> </a>
</div> </div>
<div class="left-menu-item">
<a type="button"
class="btn text-dark bottom-menu-item"
data-bs-toggle="offcanvas"
data-bs-target="#tasksCanvas"
data-bs-placement="top"
style="background-color: beige;"
title="Tasks">
<i class="fas fa-tasks"></i>
</a>
</div>
<div class="left-menu-item"> <div class="left-menu-item">
<a type="button" <a type="button"
class="btn btn-dark text-light bottom-menu-item" class="btn btn-dark text-light bottom-menu-item"
@ -101,4 +122,8 @@ export default {
margin-bottom: 1em; margin-bottom: 1em;
} }
.fas {
text-shadow: 1px 1px grey;
}
</style> </style>

190
src/views/Notes.vue

@ -0,0 +1,190 @@
<template>
<div class="row">
<div class="col-md-12">
<div class="float-end">
<div v-if="$store.state.notes.length > 0" class="filter-wrapper">
<a href="javascript:"
v-if="colorToFilter !== ''"
v-on:click="colorToFilter = ''"
class="color-change-button disable-filter-button"
:style="'background-color: '+colorToFilter">
Filter aus
</a>
<span v-for="color in noteColors"
v-bind:key="color">
<a href="javascript:"
v-if="colorToFilter !== color"
v-on:click="colorToFilter = color"
class="color-change-button"
:style="'background-color: ' + color">
<i class="fas fa-filter filter-icon"></i>
</a>
</span>
</div>
<a href="javascript:" v-on:click="createNote()" class="btn btn-sm btn-success">Neue Notiz</a>
</div>
<h5><i class="fa fa-pen"></i> Notizen</h5>
</div>
<template v-for="(note, noteIndex) in $store.state.notes" v-bind:key="noteIndex">
<div v-if="colorToFilter === '' || note.color === colorToFilter" class="col-sm-6 col-md-4 col-lg-3 card-box">
<div class="card">
<div class="card-body note"
:style="'background-color:' + note.color ?? '#ffea77'">
<textarea v-model="note.body" spellcheck="false"
@keydown="this.$store.commit('saveNotes')"></textarea>
<div class="color-changer">
<span v-for="color in noteColors" v-bind:key="color">
<span href="javascript:"
@click="changeColor(note, color);"
class="color-change-button"
v-if="color !== note.color"
:style="'background-color: ' + color">
</span>
</span>
</div>
<div class="float-end">
<a href="javascript:" class="delete-button"
@click="$store.commit('deleteNote', noteIndex)"><i
class="fas fa-trash"></i></a>
</div>
</div>
</div>
</div>
</template>
<span v-if="colorToFilter !== '' && !notesExistInFilteredColor">
Keine Notizen mit gewählter Farbe vorhanden<br>
<a href="javascript:"
class="color-change-button disable-filter-button"
:style="'background-color: '+colorToFilter"
v-on:click="colorToFilter = ''">
Filter ausschalten
</a>
</span>
</div>
</template>
<script>
import axios from "axios";
export default {
name: "Notes",
data() {
return {
noteColors: ['#ffea77', '#ee6352', '#59cd90', '#3fa7d6', '#fac05e', '#f79d84'],
colorToFilter: ''
}
},
methods: {
createNote() {
let component = this;
axios.get(
'https://api.quotable.io/random'
).then((response) => {
component.$store.commit('createNote', response.data.content + '\n - ' + response.data.author);
component.$store.commit('saveNotes');
}).catch(() => {
component.$store.commit('createNote', '');
component.$store.commit('saveNotes');
})
},
changeColor(note, color) {
note.color = color;
this.$store.commit('saveNotes');
}
},
computed: {
notesExistInFilteredColor() {
let component = this;
return this.$store.state.notes.filter((note) => {
return note.color === component.colorToFilter;
}).length;
}
}
}
</script>
<style scoped>
.card-body {
font-family: NotePaper, sans-serif;
}
#note-container {
margin-top: 1em;
}
textarea {
width: 100%;
height: 100%;
padding: 0;
margin: 0;
background-color: transparent;
border: 0 solid transparent;
min-height: 10em;
}
textarea:focus {
outline: none;
}
.color-changer {
position: absolute;
bottom: -0.8em;
z-index: 1000;
}
.color-change-button {
margin-right: 0.2em;
background-color: red;
border-radius: 25px;
padding: 0.2em 0.7em;
text-decoration: none;
}
.color-change-button:hover {
opacity: 0.9;
cursor: pointer;
}
.delete-button {
position: absolute;
bottom: -1.5em;
right: 0.5em;
text-align: right;
background-color: red;
border-radius: 25px;
z-index: 1000;
}
.delete-button i {
margin: 1em;
color: black;
}
.delete-button:hover * {
color: white;
}
.filter-icon {
color: white;
font-size: 0.7em;
}
.disable-filter-button {
color: white;
background-color: grey;
}
.filter-wrapper {
display: inline-block;
margin: 0.3em 1em;
}
.card-box {
margin-top: 0.5em;
margin-bottom: 0.5em;
}
</style>

7
src/views/Settings.vue

@ -3,7 +3,6 @@
aria-hidden="true"> aria-hidden="true">
<div class="offcanvas-header"> <div class="offcanvas-header">
<h5><i class="fas fa-sliders-h"></i> Einstellungen</h5> <h5><i class="fas fa-sliders-h"></i> Einstellungen</h5>
<button type="button" v-on:click="updateStorage()" class="btn-close" data-bs-dismiss="offcanvas" aria-label="Close"></button>
</div> </div>
<div class="offcanvas-body"> <div class="offcanvas-body">
<div class="row"> <div class="row">
@ -11,19 +10,19 @@
<h5>Allgemeine Einstellungen</h5> <h5>Allgemeine Einstellungen</h5>
<div class="form-group"> <div class="form-group">
<label>Ticket-Link <small>Link zu einem Ticket ohne Ticketnummer</small></label> <label>Ticket-Link <small>Link zu einem Ticket ohne Ticketnummer</small></label>
<input type="text" v-model="trackerSystemUrl" class="form-control"> <input type="text" v-model="$store.state.settings.trackerSystemUrl" v-on:input="$store.commit('saveSettings')" class="form-control">
</div> </div>
<br/> <br/>
<div class="form-group"> <div class="form-group">
<label> <label>
<input type="checkbox" class="form-control-checkbox" v-model="$store.state.settings.showPT"> <input type="checkbox" v-on:input="$store.commit('saveSettings')" class="form-control-checkbox" v-model="$store.state.settings.showPT">
Ab 8 Stunden nurmehr PT anzeigen Ab 8 Stunden nurmehr PT anzeigen
</label> </label>
</div> </div>
<br/> <br/>
<div class="form-group"> <div class="form-group">
<label> <label>
<input type="checkbox" class="form-control-checkbox" <input type="checkbox" v-on:input="$store.commit('saveSettings')" class="form-control-checkbox"
v-model="$store.state.settings.dontShowMinutes"> v-model="$store.state.settings.dontShowMinutes">
Zeit immer in Stunden anzeigen Zeit immer in Stunden anzeigen
</label> </label>

120
src/views/Tasks.vue

@ -0,0 +1,120 @@
<template>
<div class="offcanvas offcanvas-end"
id="tasksCanvas"
tabindex="-1"
role="dialog"
aria-labelledby="showTasksCanvas"
aria-hidden="true">
<div class="offcanvas-header">
<h5><i class="fas fa-clipboard"></i> Tasks</h5>
</div>
<div class="offcanvas-body">
<div class="form-group">
<input type="text" id="newTaskInput" class="form-control"
v-model="newTaskInput" placeholder="Neuer Task" v-on:keyup.enter="addTask()"/>
</div>
<ul class="list-group" v-if="$store.state.tasks && $store.state.tasks.length > 0">
<template v-for="(task, taskIndex) in $store.state.tasks" v-bind:key="taskIndex">
<li class="list-group-item" v-if="!task.done">
<span class="float-end">
<a href="javascript:">
<i class="fas fa-trash" @click="deleteTask(taskIndex)"></i>
</a>
</span>
<a href="javascript:" @click="toggleTask(task)">
<i class="far fa-square"></i>
</a> {{ task.name }}
<div class="form-group">
<div class="float-end">
{{ task.percentDone }}% erledigt
</div>
<input type="range"
class="range range-success range-tasks"
min="0"
max="100"
step="5"
v-model="task.percentDone"
@change="checkForCompletionOfTask(task)">
</div>
</li>
</template>
</ul>
<br/>
<ul class="list-group" v-if="$store.state.tasks && $store.state.tasks.length > 0">
<template v-for="(task, taskIndex) in $store.state.tasks" v-bind:key="taskIndex">
<li class="list-group-item" v-if="task.done">
<span class="float-end">
<a href="javascript:">
<i class="fas fa-trash" @click="deleteTask(taskIndex)"></i>
</a>
</span>
<a href="javascript:" @click="toggleTask(task)">
<i class="far fa-check-square"></i>
</a> <span class="finished-task">{{ task.name }}</span>
</li>
</template>
</ul>
</div>
</div>
</template>
<script>
import moment from "moment";
export default {
name: "Tasks",
data() {
return {
newTaskInput: ''
}
},
methods: {
deleteTask(taskIndex) {
this.$store.state.tasks.splice(taskIndex, 1)
this.$store.commit('saveTasks');
},
addTask() {
if (this.newTaskInput.length <= 0 || this.newTaskInput.trim() === '') {
return false;
}
if (!this.$store.state.tasks) {
this.$store.state.tasks = [];
}
this.$store.state.tasks.pushToBeginning({
name: this.newTaskInput,
done: false,
created: moment(),
percentDone: 0,
finished: null
});
this.newTaskInput = '';
this.$store.commit('saveTasks');
},
toggleTask(task) {
task.done = !task.done;
if (task.done) {
task.finished = moment();
task.percentDone = 100;
} else {
task.finished = null;
task.percentDone = 0;
}
this.$store.commit('saveTasks');
},
checkForCompletionOfTask(task) {
task.done = task.percentDone === 100;
this.$forceUpdate();
this.$store.commit('saveTasks');
},
}
}
</script>
<style scoped>
</style>

14
src/views/TasksForTracker.vue

@ -7,7 +7,7 @@
aria-labelledby="showTrackerCanvasCanvas" aria-labelledby="showTrackerCanvasCanvas"
aria-hidden="true"> aria-hidden="true">
<div class="offcanvas-header"> <div class="offcanvas-header">
<h5><i class="fas fa-clock"></i> Tasks für {{ $store.state.selectedTracker.number }}</h5> <h5><i class="fas fa-clipboard"></i> Tasks für {{ $store.state.selectedTracker.number }}</h5>
</div> </div>
<div class="offcanvas-body"> <div class="offcanvas-body">
<div class="form-group"> <div class="form-group">
@ -83,13 +83,23 @@ export default {
this.$store.state.selectedTracker.tasks = []; this.$store.state.selectedTracker.tasks = [];
} }
let newTasks = [];
if (this.newTaskInput.split(';').length > 3) {
newTasks = this.newTaskInput.split(';').reverse().map((task) => task.trim());
} else {
newTasks.push(this.newTaskInput);
}
newTasks.forEach((task) => {
this.$store.state.selectedTracker.tasks.pushToBeginning({ this.$store.state.selectedTracker.tasks.pushToBeginning({
name: this.newTaskInput, name: task,
done: false, done: false,
created: moment(), created: moment(),
percentDone: 0, percentDone: 0,
finished: null finished: null
}); });
})
this.newTaskInput = ''; this.newTaskInput = '';
this.$store.commit('saveTrackers'); this.$store.commit('saveTrackers');

16
src/views/Trackers.vue

@ -19,16 +19,16 @@
<div class="spinner-grow spinner-grow-sm" role="status"> <div class="spinner-grow spinner-grow-sm" role="status">
<span class="sr-only">Tracking...</span> <span class="sr-only">Tracking...</span>
</div> </div>
Tracking Tracking (<i class="fas fa-play"></i> {{ getTrackingStartTime(tracker) }})
</div> </div>
</div> </div>
</div> </div>
<template v-if="!tracker.isTimeBox"> <template v-if="!tracker.isTimeBox">
<div v-if="tracker.tracking === true"> <div v-if="tracker.tracking === true">
<span class="float-end">{{ getTrackingStartTime(tracker) }}</span> <!-- <span class="float-end">{{ getTrackingStartTime(tracker) }}</span>-->
<span v-if="tracker.tracking === true">Gestartet: </span> <!-- <span v-if="tracker.tracking === true">Gestartet: </span>-->
<br/> <!-- <br/>-->
<span class="float-end">{{ currentTrackingRunningFor(tracker) }}</span> <span class="float-end">{{ currentTrackingRunningFor(tracker) }}</span>
<span v-if="tracker.tracking === true">Läuft seit: </span> <span v-if="tracker.tracking === true">Läuft seit: </span>
</div> </div>
@ -38,8 +38,10 @@
<span class="current-tracker-info">Gesamt: </span> <span class="current-tracker-info">Gesamt: </span>
</div> </div>
<div v-if="getTotalTimeToday(tracker, true) > 1">
<span class="float-end">{{ getTotalTimeToday(tracker) }}</span> <span class="float-end">{{ getTotalTimeToday(tracker) }}</span>
<span class="">Heute: </span> <span class="">Heute: </span>
</div>
<div class="row"> <div class="row">
<div class="col-md-6" v-if="!tracker.tracking"> <div class="col-md-6" v-if="!tracker.tracking">
@ -241,7 +243,7 @@ export default {
return this.timeWithPostFix(totalTime); return this.timeWithPostFix(totalTime);
} }
}, },
getTotalTimeToday(tracker) { getTotalTimeToday(tracker, raw = false) {
let totalTime = 0; let totalTime = 0;
if (tracker.history.length > 0) { if (tracker.history.length > 0) {
@ -256,6 +258,10 @@ export default {
totalTime += Math.round(moment.duration(moment().diff(tracker.trackingStarted)).as('minutes')); totalTime += Math.round(moment.duration(moment().diff(tracker.trackingStarted)).as('minutes'));
} }
if (raw) {
return totalTime;
}
return this.timeWithPostFix(totalTime); return this.timeWithPostFix(totalTime);
}, },
timeWithPostFix(time) { timeWithPostFix(time) {

Loading…
Cancel
Save