Time tracking you can host anywhere, built on Django. Full export support in multiple formats and easily extensible.
djangodockerhandcodedpythonself-hostedtime-trackingtimetracker
1<template>
2<div id="app">
3 <transition name="fade">
4 <div v-if="!doneLoading" id="loading" class="progress">
5 <div
6 :style="'width:' + loadingPercent + '%;'"
7 class="progress-bar bg-primary"/>
8 </div>
9 </transition>
10
11 <toast></toast>
12
13 <div class="navbar navbar-dark bg-dark">
14 <router-link :to="timesheet" class="navbar-brand">
15 {{ site.NAME }}
16 </router-link>
17 <ul class="navbar-nav flex-grow-1">
18 <li v-if="$perms.view_entry" class="nav-item">
19 <router-link
20 id="nav-timesheet"
21 :to="timesheet"
22 class="nav-link">
23 <icon :icon="['fas', 'clock']" class="fa-fw mr-1"/>
24 Timesheet
25 </router-link>
26 </li>
27 <li v-if="$perms.view_project" class="nav-item">
28 <router-link
29 id="nav-projects"
30 :to="projects"
31 class="nav-link">
32 <icon :icon="['fas', 'briefcase']" class="fa-fw mr-1"/>
33 Projects
34 </router-link>
35 </li>
36 <li v-if="$perms.view_client" class="nav-item">
37 <router-link
38 id="nav-clients"
39 :to="clients"
40 class="nav-link">
41 <icon :icon="['fas', 'address-book']" class="fa-fw mr-1"/>
42 Clients
43 </router-link>
44 </li>
45 <li v-if="$perms.view_task" class="nav-item">
46 <router-link
47 id="nav-tasks"
48 :to="tasks"
49 class="nav-link">
50 <icon :icon="['fas', 'tasks']" class="fa-fw mr-1"/>
51 Tasks
52 </router-link>
53 </li>
54 <li v-if="$perms.view_entry" class="nav-item">
55 <router-link
56 id="nav-reports"
57 :to="reports"
58 class="nav-link">
59 <icon :icon="['fas', 'book']" class="fa-fw mr-1"/>
60 Reports
61 </router-link>
62 </li>
63 </ul>
64 <ul class="navbar-nav">
65 <li class="nav-item">
66 <a
67 v-if="isStaff"
68 id="nav-user-admin"
69 class="nav-link"
70 :href="admin"
71 target="_blank">
72 <icon :icon="['fas', 'tools']" class="fa-fw mr-1"/>
73 Admin
74 </a>
75 </li>
76 <li class="nav-item">
77 <a
78 id="nav-user-api"
79 class="nav-link"
80 :href="api"
81 target="_blank">
82 <icon :icon="['fas', 'tape']" class="fa-fw mr-1"/>
83 API Browser
84 </a>
85 </li>
86 <li class="nav-item">
87 <a
88 id="nav-user-logout"
89 class="nav-link"
90 :href="logout">
91 <icon :icon="['fas', 'sign-out-alt']" class="fa-fw mr-1"/>
92 Logout
93 </a>
94 </li>
95 </ul>
96 </div>
97
98 <div class="page">
99 <tracker/>
100
101 <router-view :id="'view-' + $route.name"/>
102 </div>
103
104 <div id="github">
105 <a
106 href="https://github.com/overshard/timestrap"
107 target="_blank">
108 <icon
109 :icon="['fas', 'code-branch']"
110 class="mr-1 text-muted"/>
111 </a>
112 </div>
113</div>
114</template>
115
116
117<script>
118import $ from 'jquery';
119
120import {mapGetters} from 'vuex';
121
122import Tracker from './tracker.vue';
123import Toast from './toast.vue';
124
125
126export default {
127 components: {
128 Tracker,
129 Toast,
130 },
131 data() {
132 return {
133 timesheet: timestrapConfig.CORE_URLS.TIMESHEET,
134 projects: timestrapConfig.CORE_URLS.PROJECTS,
135 clients: timestrapConfig.CORE_URLS.CLIENTS,
136 tasks: timestrapConfig.CORE_URLS.TASKS,
137 reports: timestrapConfig.CORE_URLS.REPORTS,
138 username: timestrapConfig.USER.NAME,
139 api: timestrapConfig.CORE_URLS.API,
140 admin: timestrapConfig.CORE_URLS.ADMIN,
141 logout: timestrapConfig.CORE_URLS.LOGOUT,
142 site: timestrapConfig.SITE,
143 isStaff: timestrapConfig.USER.IS_STAFF,
144 };
145 },
146 computed: {
147 ...mapGetters([
148 'loadingPercent',
149 'doneLoading',
150 ]),
151 },
152};
153</script>
154
155
156<style lang="scss">
157body {
158 padding: 0;
159}
160
161.bg-dark {
162 background-color: rgb(27, 22, 16) !important;
163}
164
165.bg-light {
166 background-color: rgb(247, 246, 243) !important;
167}
168
169// Loading styles
170#loading {
171 height: 3px;
172 position: absolute;
173 z-index: 1;
174 top: 0;
175 left: 0;
176 right: 0;
177}
178
179.fade-enter-active,
180.fade-leave-active {
181 transition: opacity .5s;
182}
183
184.fade-enter,
185.fade-leave-to {
186 opacity: 0;
187}
188
189// Fix chrome focus highlight
190input:focus {
191 outline: none !important;
192}
193
194// Github icon
195#github {
196 position: fixed;
197 bottom: 5px;
198 right: 15px;
199 font-size: 2em;
200}
201
202// Remove arrow on the ellipsis icons on rows
203.btn-icon:after {
204 display: none;
205}
206
207.navbar {
208 position: fixed;
209 left: 0;
210 width: 200px;
211 top: 0;
212 bottom: 0;
213 padding: 0;
214 padding-bottom: .25rem;
215 flex-direction: column;
216
217 .navbar-brand {
218 display: flex;
219 align-items: center;
220 padding-left: 1rem;
221 padding-right: 1rem;
222 font-weight: bold;
223 margin-right: 0;
224 width: 200px;
225 height: 54px;
226 }
227
228 .navbar-nav {
229 flex-direction: column !important;
230 }
231
232 .nav-link,
233 .navbar-text {
234 width: 200px;
235 padding-left: 1rem !important;
236 padding-right: 1rem !important;
237 }
238
239 .nav-link.active {
240 background: #222;
241 }
242}
243
244.page {
245 width: calc(100% - 200px);
246 margin-left: 200px;
247}
248</style>