repos
/ timestrap-django master

timestrap-django

mirror archived upstream

Time tracking you can host anywhere, built on Django. Full export support in multiple formats and easily extensible.

djangodockerhandcodedpythonself-hostedtime-trackingtimetracker

4.0 KB · 184 lines · vue Raw History
  1<template>
  2<div :id="'entry-' + entry.id" class="entry row py-2 bg-light small">
  3  <div v-if="entry.project" class="col-sm-3 client-project">
  4    <div class="small">
  5      <icon :icon="['fas', 'address-book']" class="mr-2 text-muted"/>
  6      {{ getClient(getProject(entry.project).client).name }}
  7    </div>
  8    <icon :icon="['fas', 'briefcase']" class="mr-1 text-muted"/>
  9    {{ getProject(entry.project).name }}
 10  </div>
 11  <div :class="['d-flex', 'flex-column', 'align-self-end', 'tasks', 'col-sm-5']">
 12    <div v-if="entry.task" class="small">
 13      <icon :icon="['fas', 'tasks']" class="mr-2 text-muted"/>
 14      {{ getTask(entry.task).name }}
 15    </div>
 16    <div v-if="entry.note" class="entry-note">
 17      <icon :icon="['fas', 'comment']" class="mr-1 text-muted"/>
 18      {{ entry.note }}
 19    </div>
 20  </div>
 21  <div class="col-sm-2 align-items-center display-4 duration">
 22    <icon :icon="['fas', 'clock']" class="mr-2 text-muted small"/>
 23    {{ $moment.duration(entry.duration, 'hours').format('h:mm', {trim: false}) }}
 24  </div>
 25  <div class="col-sm-2 align-self-center datetimes flex-column">
 26    <div class="datetime-start small">
 27      <icon :icon="['fas', 'hourglass-start']" class="mr-1 text-muted"/>
 28      {{ formatDateTime(entry.datetime_start) }}
 29    </div>
 30    <div class="datetime-end small">
 31      <icon :icon="['fas', 'hourglass-end']" class="mr-1 text-muted"/>
 32      {{ formatDateTime(entry.datetime_end) }}
 33    </div>
 34  </div>
 35  <div
 36    v-if="$perms.change_entry || $perms.delete_entry"
 37    class="col-sm-2 d-flex align-self-center justify-content-end">
 38    <button
 39      id="entry-menu"
 40      type="button"
 41      data-toggle="dropdown"
 42      class="btn btn-faded btn-sm btn-icon dropdown-toggle">
 43      <icon :icon="['fas', 'ellipsis-v']"/>
 44    </button>
 45    <div class="dropdown-menu dropdown-menu-right">
 46      <button
 47        id="entry-menu-change"
 48        class="dropdown-item"
 49        v-if="$perms.change_entry"
 50        @click.prevent.exact="$emit('modal')">
 51        Edit
 52      </button>
 53      <button
 54        id="entry-menu-delete"
 55        class="dropdown-item"
 56        v-if="$perms.delete_entry"
 57        @click.prevent.exact="deleteEntry(entry)">
 58        Delete
 59      </button>
 60    </div>
 61  </div>
 62</div>
 63</template>
 64
 65
 66<script>
 67import {mapActions, mapGetters} from 'vuex';
 68
 69
 70export default {
 71  props: [
 72    'entry',
 73    'index',
 74    'editable',
 75  ],
 76  computed: {
 77    ...mapGetters({
 78      getProject: 'projects/getProject',
 79      getClient: 'clients/getClient',
 80      getTask: 'tasks/getTask',
 81    }),
 82  },
 83  methods: {
 84    ...mapActions({
 85      deleteEntry: 'entries/deleteEntry',
 86    }),
 87    formatDateTime(datetime) {
 88      if (datetime) return this.$moment(datetime).format('h:mm a');
 89      else return '-';
 90    },
 91  },
 92};
 93</script>
 94
 95
 96<style lang="scss">
 97#entry-rows {
 98  .row:not(.inset-row) {
 99    border-top: 1px solid #eceeef;
100
101    &:nth-of-type(2n+1) {
102      background-color: #fbf3e5 !important;
103    }
104
105    &:last-child {
106      border-bottom: 1px solid #eceeef;
107    }
108
109    // Fix for override of striping-row-color above
110    &.bg-success {
111      background-color: #28a745 !important;
112    }
113  }
114
115  .duration {
116    display: flex;
117    font-weight: lighter;
118  }
119
120  .datetimes {
121    display: none;
122  }
123
124  .entry-note {
125    overflow: hidden;
126    white-space: nowrap;
127    text-overflow: ellipsis;
128  }
129
130  .entry:hover,
131  .entry:focus {
132    .duration {
133      display: none;
134    }
135
136    .datetimes {
137      display: flex;
138    }
139
140    .tasks .small {
141      display: none;
142    }
143
144    .tasks {
145      align-self: flex-start !important;
146
147      .entry-note {
148        overflow: show !important;
149        white-space: normal !important;
150      }
151    }
152  }
153
154  .duration.display-4 {
155    font-size: 1.7rem;
156  }
157
158  .note {
159    line-height: 1.3;
160    margin-bottom: 3px;
161  }
162
163  .username {
164    overflow-x: hidden;
165  }
166
167  .client-project {
168    overflow-x: hidden;
169    text-overflow: ellipsis;
170    white-space: nowrap;
171  }
172
173  .inset-row {
174    padding: 1rem 0;
175
176    .display-4 {
177      font-size: 1.5rem;
178      font-weight: bold;
179      margin-bottom: 0;
180    }
181  }
182}
183</style>