Added manage structure page
This commit is contained in:
parent
e1154ec33b
commit
37701a0484
17 changed files with 818 additions and 5 deletions
29
public/api/removeProject.php
Normal file
29
public/api/removeProject.php
Normal file
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
session_start();
|
||||
require_once(__DIR__ . "/services/apiBranch.inc.php");
|
||||
require_once(__DIR__ . "/services/responses.inc.php");
|
||||
require_once(__DIR__ . "/services/jugglDbApi.inc.php");
|
||||
|
||||
class RemoveProjectBranch extends ApiBranch
|
||||
{
|
||||
function get(ParamCleaner $params)
|
||||
{
|
||||
respondStatus(405);
|
||||
}
|
||||
|
||||
function post(ParamCleaner $params)
|
||||
{
|
||||
$user_id = $params->get("user_id");
|
||||
|
||||
if ($params->exists(["project_id"]) == false) {
|
||||
respondStatus(400, "Missing parameter");
|
||||
}
|
||||
|
||||
removeProject($user_id, $params);
|
||||
|
||||
respondStatus(200);
|
||||
}
|
||||
}
|
||||
|
||||
$branch = new RemoveProjectBranch();
|
||||
$branch->execute();
|
29
public/api/removeRecordTag.php
Normal file
29
public/api/removeRecordTag.php
Normal file
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
session_start();
|
||||
require_once(__DIR__ . "/services/apiBranch.inc.php");
|
||||
require_once(__DIR__ . "/services/responses.inc.php");
|
||||
require_once(__DIR__ . "/services/jugglDbApi.inc.php");
|
||||
|
||||
class RemoveRecordTagBranch extends ApiBranch
|
||||
{
|
||||
function get(ParamCleaner $params)
|
||||
{
|
||||
respondStatus(405);
|
||||
}
|
||||
|
||||
function post(ParamCleaner $params)
|
||||
{
|
||||
$user_id = $params->get("user_id");
|
||||
|
||||
if ($params->exists(["record_tag_id"]) == false) {
|
||||
respondStatus(400, "Missing parameter");
|
||||
}
|
||||
|
||||
removeRecordTag($user_id, $params);
|
||||
|
||||
respondStatus(200);
|
||||
}
|
||||
}
|
||||
|
||||
$branch = new RemoveRecordTagBranch();
|
||||
$branch->execute();
|
|
@ -222,6 +222,46 @@ function updateRecord($user_id, $record)
|
|||
$db->execute();
|
||||
}
|
||||
|
||||
function updateProject($user_id, $project)
|
||||
{
|
||||
$project_id = $project["project_id"];
|
||||
|
||||
// Update given parameters
|
||||
$data = [];
|
||||
$props = ["name", "start_date"];
|
||||
foreach ($props as $p) {
|
||||
if (array_key_exists ($p, $project)) {
|
||||
$data[$p] = $project[$p];
|
||||
}
|
||||
}
|
||||
|
||||
$db = new DbOperations();
|
||||
$db->update("projects", $data);
|
||||
$db->where("user_id", Comparison::EQUAL, $user_id);
|
||||
$db->where("project_id", Comparison::EQUAL, $project_id);
|
||||
$db->execute();
|
||||
}
|
||||
|
||||
function updateRecordTag($user_id, $tag)
|
||||
{
|
||||
$record_tag_id = $tag["record_tag_id"];
|
||||
|
||||
// Update given parameters
|
||||
$data = [];
|
||||
$props = ["name"];
|
||||
foreach ($props as $p) {
|
||||
if (array_key_exists ($p, $tag)) {
|
||||
$data[$p] = $tag[$p];
|
||||
}
|
||||
}
|
||||
|
||||
$db = new DbOperations();
|
||||
$db->update("record_tags", $data);
|
||||
$db->where("user_id", Comparison::EQUAL, $user_id);
|
||||
$db->where("record_tag_id", Comparison::EQUAL, $record_tag_id);
|
||||
$db->execute();
|
||||
}
|
||||
|
||||
function removeRecord($user_id, $params)
|
||||
{
|
||||
$record_id = $params->get("record_id");
|
||||
|
@ -233,6 +273,49 @@ function removeRecord($user_id, $params)
|
|||
$db->execute();
|
||||
}
|
||||
|
||||
function removeProject($user_id, $params)
|
||||
{
|
||||
$project_id = $params->get("project_id");
|
||||
|
||||
$db = new DbOperations();
|
||||
$db->delete("projects");
|
||||
$db->where("user_id", Comparison::EQUAL, $user_id);
|
||||
$db->where("project_id", Comparison::EQUAL, $project_id);
|
||||
$db->execute();
|
||||
|
||||
removeRecordsOfProject($user_id, $project_id);
|
||||
}
|
||||
|
||||
function removeRecordsOfProject($user_id, $project_id)
|
||||
{
|
||||
$db = new DbOperations();
|
||||
$db->delete("time_records");
|
||||
$db->where("user_id", Comparison::EQUAL, $user_id);
|
||||
$db->where("project_id", Comparison::EQUAL, $project_id);
|
||||
$db->execute();
|
||||
}
|
||||
|
||||
function removeRecordTag($user_id, $params)
|
||||
{
|
||||
$record_tag_id = $params->get("record_tag_id");
|
||||
|
||||
$db = new DbOperations();
|
||||
$db->delete("record_tags");
|
||||
$db->where("user_id", Comparison::EQUAL, $user_id);
|
||||
$db->where("record_tag_id", Comparison::EQUAL, $record_tag_id);
|
||||
$db->execute();
|
||||
|
||||
removeRecordTagFromAssociations($record_tag_id);
|
||||
}
|
||||
|
||||
function removeRecordTagFromAssociations($record_tag_id)
|
||||
{
|
||||
$db = new DbOperations();
|
||||
$db->delete("tags_on_records");
|
||||
$db->where("record_tag_id", Comparison::EQUAL, $record_tag_id);
|
||||
$db->execute();
|
||||
}
|
||||
|
||||
function updateTimeRecord($user_id, $params)
|
||||
{
|
||||
$data = [];
|
||||
|
|
29
public/api/updateProject.php
Normal file
29
public/api/updateProject.php
Normal file
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
session_start();
|
||||
require_once(__DIR__ . "/services/apiBranch.inc.php");
|
||||
require_once(__DIR__ . "/services/responses.inc.php");
|
||||
require_once(__DIR__ . "/services/jugglDbApi.inc.php");
|
||||
|
||||
class UpdateProjectBranch extends ApiBranch
|
||||
{
|
||||
function get(ParamCleaner $params)
|
||||
{
|
||||
respondStatus(405);
|
||||
}
|
||||
|
||||
function post(ParamCleaner $params)
|
||||
{
|
||||
$user_id = $params->get("user_id");
|
||||
|
||||
if ($params->exists(["project"]) == false) {
|
||||
respondStatus(400, "Missing parameter");
|
||||
}
|
||||
|
||||
updateProject($user_id, $params->get("project"));
|
||||
|
||||
respondStatus(200);
|
||||
}
|
||||
}
|
||||
|
||||
$branch = new UpdateProjectBranch();
|
||||
$branch->execute();
|
29
public/api/updateRecordTag.php
Normal file
29
public/api/updateRecordTag.php
Normal file
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
session_start();
|
||||
require_once(__DIR__ . "/services/apiBranch.inc.php");
|
||||
require_once(__DIR__ . "/services/responses.inc.php");
|
||||
require_once(__DIR__ . "/services/jugglDbApi.inc.php");
|
||||
|
||||
class UpdateRecordTagBranch extends ApiBranch
|
||||
{
|
||||
function get(ParamCleaner $params)
|
||||
{
|
||||
respondStatus(405);
|
||||
}
|
||||
|
||||
function post(ParamCleaner $params)
|
||||
{
|
||||
$user_id = $params->get("user_id");
|
||||
|
||||
if ($params->exists(["record_tag"]) == false) {
|
||||
respondStatus(400, "Missing parameter");
|
||||
}
|
||||
|
||||
updateRecordTag($user_id, $params->get("record_tag"));
|
||||
|
||||
respondStatus(200);
|
||||
}
|
||||
}
|
||||
|
||||
$branch = new UpdateRecordTagBranch();
|
||||
$branch->execute();
|
72
src/components/base/BaseConfirmButton.vue
Normal file
72
src/components/base/BaseConfirmButton.vue
Normal file
|
@ -0,0 +1,72 @@
|
|||
<template>
|
||||
<div>
|
||||
<b-button
|
||||
:pressed.sync="triggered"
|
||||
:size="size"
|
||||
class="inline"
|
||||
:variant="variant"
|
||||
>
|
||||
<slot />
|
||||
</b-button>
|
||||
|
||||
<div id="confirm-popover" v-if="triggered" class="inline">
|
||||
<div class="inline">{{ msg }}</div>
|
||||
<b-button
|
||||
@click="triggered = false"
|
||||
:size="size"
|
||||
class="inline"
|
||||
variant="outline-secondary"
|
||||
>
|
||||
Cancel
|
||||
</b-button>
|
||||
<b-button
|
||||
@click="() => confirm()"
|
||||
:size="size"
|
||||
class="inline"
|
||||
variant="outline-danger"
|
||||
>
|
||||
Yes
|
||||
</b-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "BaseConfirmButton",
|
||||
props: {
|
||||
size: {
|
||||
required: false,
|
||||
type: String
|
||||
},
|
||||
variant: {
|
||||
required: false,
|
||||
type: String,
|
||||
default: "outline-danger"
|
||||
},
|
||||
msg: {
|
||||
required: false,
|
||||
type: String,
|
||||
default: "Sure?"
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
triggered: false
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
confirm: function() {
|
||||
this.$emit("click");
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="sass" scoped>
|
||||
.inline
|
||||
display: inline-block
|
||||
|
||||
#confirm-popover *
|
||||
margin-left: 1rem
|
||||
</style>
|
111
src/components/forms/FormProjectDetails.vue
Normal file
111
src/components/forms/FormProjectDetails.vue
Normal file
|
@ -0,0 +1,111 @@
|
|||
<template>
|
||||
<b-form @submit="submitForm">
|
||||
<b-form-group id="id-group" label-for="id" label="Record ID">
|
||||
<b-form-input id="id" v-model="form.project_id" required trim disabled>
|
||||
</b-form-input>
|
||||
</b-form-group>
|
||||
<b-form-group id="name-group" label-for="name" label="Name">
|
||||
<b-form-input id="name" v-model="form.name" required trim> </b-form-input>
|
||||
</b-form-group>
|
||||
<b-form-group id="startdate-group" label="Start date" label-for="startdate">
|
||||
<b-form-datepicker
|
||||
id="startdate"
|
||||
v-model="form.start_date"
|
||||
required
|
||||
placeholder="Choose a start date"
|
||||
dark
|
||||
>
|
||||
</b-form-datepicker>
|
||||
</b-form-group>
|
||||
<b-form-invalid-feedback :state="!failed">
|
||||
Something went wrong.
|
||||
</b-form-invalid-feedback>
|
||||
<b-button variant="primary" type="submit" class="right" :disabled="working">
|
||||
<b-spinner v-if="working" small />
|
||||
Save
|
||||
</b-button>
|
||||
<b-button variant="outline-secondary" @click="() => cancel()" class="left">
|
||||
Cancel
|
||||
</b-button>
|
||||
<BaseConfirmButton
|
||||
class="left"
|
||||
@click="() => deleteProject()"
|
||||
variant="outline-danger"
|
||||
>
|
||||
<b-icon class="icon-btn" icon="trash" />
|
||||
</BaseConfirmButton>
|
||||
</b-form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import BaseConfirmButton from "@/components/base/BaseConfirmButton";
|
||||
import store from "@/store";
|
||||
|
||||
export default {
|
||||
name: "FormProjectDetails",
|
||||
components: {
|
||||
BaseConfirmButton
|
||||
},
|
||||
props: {
|
||||
project: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
failed: false,
|
||||
working: false,
|
||||
form: {
|
||||
project_id: undefined,
|
||||
start_date: undefined,
|
||||
name: undefined
|
||||
}
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* Submits the form. Assupmtion: Form is valid, based on required flags.
|
||||
*/
|
||||
submitForm: function(e) {
|
||||
e.preventDefault();
|
||||
this.failed = false;
|
||||
this.working = true;
|
||||
|
||||
store
|
||||
.dispatch("updateProject", this.form)
|
||||
.then(() => {
|
||||
this.working = false;
|
||||
this.$emit("submit");
|
||||
})
|
||||
.catch(() => {
|
||||
this.failed = true;
|
||||
this.working = false;
|
||||
});
|
||||
|
||||
return false;
|
||||
},
|
||||
cancel: function() {
|
||||
this.$emit("cancel");
|
||||
},
|
||||
deleteProject: function() {
|
||||
store.dispatch("removeProject", this.form.project_id);
|
||||
}
|
||||
},
|
||||
created: function() {
|
||||
this.form.project_id = this.project.project_id;
|
||||
this.form.name = this.project.name;
|
||||
this.form.start_date = this.project.start_date;
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="sass">
|
||||
.left
|
||||
float: left !important
|
||||
margin-right: 1rem
|
||||
|
||||
.right
|
||||
float: right !important
|
||||
margin-left: 1rem
|
||||
</style>
|
|
@ -106,22 +106,26 @@
|
|||
<b-button variant="outline-secondary" @click="() => cancel()" class="left">
|
||||
Cancel
|
||||
</b-button>
|
||||
<b-button
|
||||
<BaseConfirmButton
|
||||
class="left"
|
||||
@click="() => deleteRecord()"
|
||||
variant="outline-danger"
|
||||
>
|
||||
<b-icon class="icon-btn" icon="trash" />
|
||||
</b-button>
|
||||
</BaseConfirmButton>
|
||||
</b-form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { helperService } from "@/services/helper.service.js";
|
||||
import BaseConfirmButton from "@/components/base/BaseConfirmButton";
|
||||
import store from "@/store";
|
||||
|
||||
export default {
|
||||
name: "FormRecordDetails",
|
||||
components: {
|
||||
BaseConfirmButton
|
||||
},
|
||||
props: {
|
||||
record: {
|
||||
type: Object,
|
||||
|
|
99
src/components/forms/FormTagDetails.vue
Normal file
99
src/components/forms/FormTagDetails.vue
Normal file
|
@ -0,0 +1,99 @@
|
|||
<template>
|
||||
<b-form @submit="submitForm">
|
||||
<b-form-group id="id-group" label-for="id" label="Record ID">
|
||||
<b-form-input id="id" v-model="form.record_tag_id" required trim disabled>
|
||||
</b-form-input>
|
||||
</b-form-group>
|
||||
<b-form-group id="name-group" label-for="name" label="Name">
|
||||
<b-form-input id="name" v-model="form.name" required trim> </b-form-input>
|
||||
</b-form-group>
|
||||
<b-form-invalid-feedback :state="!failed">
|
||||
Something went wrong.
|
||||
</b-form-invalid-feedback>
|
||||
<b-button variant="primary" type="submit" class="right" :disabled="working">
|
||||
<b-spinner v-if="working" small />
|
||||
Save
|
||||
</b-button>
|
||||
<b-button variant="outline-secondary" @click="() => cancel()" class="left">
|
||||
Cancel
|
||||
</b-button>
|
||||
<BaseConfirmButton
|
||||
class="left"
|
||||
@click="() => deleteTag()"
|
||||
variant="outline-danger"
|
||||
>
|
||||
<b-icon class="icon-btn" icon="trash" />
|
||||
</BaseConfirmButton>
|
||||
</b-form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import BaseConfirmButton from "@/components/base/BaseConfirmButton";
|
||||
import store from "@/store";
|
||||
|
||||
export default {
|
||||
name: "FormTagDetails",
|
||||
components: {
|
||||
BaseConfirmButton
|
||||
},
|
||||
props: {
|
||||
tag: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
failed: false,
|
||||
working: false,
|
||||
form: {
|
||||
record_tag_id: undefined,
|
||||
name: undefined
|
||||
}
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* Submits the form. Assupmtion: Form is valid, based on required flags.
|
||||
*/
|
||||
submitForm: function(e) {
|
||||
e.preventDefault();
|
||||
this.failed = false;
|
||||
this.working = true;
|
||||
|
||||
store
|
||||
.dispatch("updateTag", this.form)
|
||||
.then(() => {
|
||||
this.working = false;
|
||||
this.$emit("submit");
|
||||
})
|
||||
.catch(() => {
|
||||
this.failed = true;
|
||||
this.working = false;
|
||||
});
|
||||
|
||||
return false;
|
||||
},
|
||||
cancel: function() {
|
||||
this.$emit("cancel");
|
||||
},
|
||||
deleteTag: function() {
|
||||
store.dispatch("removeTag", this.form.record_tag_id);
|
||||
}
|
||||
},
|
||||
created: function() {
|
||||
this.form.record_tag_id = this.tag.record_tag_id;
|
||||
this.form.name = this.tag.name;
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="sass">
|
||||
.left
|
||||
float: left !important
|
||||
margin-right: 1rem
|
||||
|
||||
.right
|
||||
float: right !important
|
||||
margin-left: 1rem
|
||||
</style>
|
|
@ -33,6 +33,9 @@
|
|||
<hr />
|
||||
|
||||
<FormTagAdd @submit="() => reloadTags()" />
|
||||
<b-link to="/manage">
|
||||
Manage tags
|
||||
</b-link>
|
||||
</div>
|
||||
</b-popover>
|
||||
</div>
|
||||
|
|
|
@ -5,6 +5,7 @@ import Login from "../views/Login.vue";
|
|||
import NotFound from "../views/NotFound.vue";
|
||||
import Home from "../views/Home.vue";
|
||||
import History from "../views/History.vue";
|
||||
import Manage from "../views/Manage.vue";
|
||||
|
||||
Vue.use(VueRouter);
|
||||
|
||||
|
@ -24,6 +25,12 @@ const routes = [
|
|||
component: History,
|
||||
beforeEnter: requireAuth
|
||||
},
|
||||
{
|
||||
path: "/manage",
|
||||
name: "Manage",
|
||||
component: Manage,
|
||||
beforeEnter: requireAuth
|
||||
},
|
||||
{
|
||||
path: "/home",
|
||||
name: "Home",
|
||||
|
|
|
@ -63,6 +63,32 @@ export const jugglService = {
|
|||
});
|
||||
},
|
||||
|
||||
removeProject(projectId) {
|
||||
return apiService
|
||||
.post("/removeProject.php", {
|
||||
project_id: projectId
|
||||
})
|
||||
.then(r => {
|
||||
return {
|
||||
data: r.data,
|
||||
msg: ""
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
removeRecordTag(tagId) {
|
||||
return apiService
|
||||
.post("/removeRecordTag.php", {
|
||||
record_tag_id: tagId
|
||||
})
|
||||
.then(r => {
|
||||
return {
|
||||
data: r.data,
|
||||
msg: ""
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
getRecords(options = {}) {
|
||||
var payload = {};
|
||||
|
||||
|
@ -94,6 +120,32 @@ export const jugglService = {
|
|||
});
|
||||
},
|
||||
|
||||
updateProject(project) {
|
||||
var payload = {
|
||||
project: project
|
||||
};
|
||||
|
||||
return apiService.post("/updateProject.php", payload).then(r => {
|
||||
return {
|
||||
data: r.data,
|
||||
msg: ""
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
updateRecordTag(tag) {
|
||||
var payload = {
|
||||
record_tag: tag
|
||||
};
|
||||
|
||||
return apiService.post("/updateRecordTag.php", payload).then(r => {
|
||||
return {
|
||||
data: r.data,
|
||||
msg: ""
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
getRunningRecords() {
|
||||
return apiService.post("/getRunningRecords.php").then(r => {
|
||||
return {
|
||||
|
|
|
@ -101,6 +101,16 @@ export const juggl = {
|
|||
return Object.values(getters.records).filter(
|
||||
record => record.record_id !== id
|
||||
);
|
||||
},
|
||||
getProjectsExceptId: (state, getters) => id => {
|
||||
return Object.values(getters.projects).filter(
|
||||
project => project.project_id !== id
|
||||
);
|
||||
},
|
||||
getTagsExceptId: (state, getters) => id => {
|
||||
return Object.values(getters.tags).filter(
|
||||
tag => tag.record_tag_id !== id
|
||||
);
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
|
@ -272,6 +282,36 @@ export const juggl = {
|
|||
return true;
|
||||
});
|
||||
},
|
||||
removeProject({ commit, getters }, projectId) {
|
||||
if (projectId === undefined) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return jugglService
|
||||
.removeProject(projectId)
|
||||
.catch(() => {
|
||||
return false;
|
||||
})
|
||||
.then(() => {
|
||||
commit("setProjects", getters.getProjectsExceptId(projectId));
|
||||
return true;
|
||||
});
|
||||
},
|
||||
removeTag({ commit, getters }, tagId) {
|
||||
if (tagId === undefined) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return jugglService
|
||||
.removeRecordTag(tagId)
|
||||
.catch(() => {
|
||||
return false;
|
||||
})
|
||||
.then(() => {
|
||||
commit("setTags", getters.getTagsExceptId(tagId));
|
||||
return true;
|
||||
});
|
||||
},
|
||||
loadSavedLogin() {
|
||||
var userId = localStorage.getItem("userId");
|
||||
var apiKey = localStorage.getItem("apiKey");
|
||||
|
@ -302,6 +342,42 @@ export const juggl = {
|
|||
commit("setRecords", records);
|
||||
return true;
|
||||
});
|
||||
},
|
||||
updateTag({ commit, getters }, tag) {
|
||||
if (tag.record_tag_id === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
return jugglService
|
||||
.updateRecordTag(tag)
|
||||
.catch(() => {
|
||||
return false;
|
||||
})
|
||||
.then(() => {
|
||||
// TODO: Return updated tag from API
|
||||
var tags = getters.getTagsExceptId(tag.record_tag_id);
|
||||
tags.push(tag);
|
||||
commit("setTags", tags);
|
||||
return true;
|
||||
});
|
||||
},
|
||||
updateProject({ commit, getters }, project) {
|
||||
if (project.project_id === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
return jugglService
|
||||
.updateProject(project)
|
||||
.catch(() => {
|
||||
return false;
|
||||
})
|
||||
.then(() => {
|
||||
// TODO: Return updated project from API
|
||||
var projects = getters.getProjectsExceptId(project.project_id);
|
||||
projects.push(project);
|
||||
commit("setProjects", projects);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -55,8 +55,11 @@ body
|
|||
a
|
||||
color: $font-link !important
|
||||
|
||||
&:hover
|
||||
&.btn:hover
|
||||
color: $background-primary !important
|
||||
|
||||
&:hover
|
||||
color: $primary !important
|
||||
|
||||
.b-dropdown, .dropdown
|
||||
border-radius: 0
|
||||
|
|
|
@ -5,7 +5,14 @@
|
|||
</div>
|
||||
<section v-if="!working">
|
||||
<div class="controls">
|
||||
<b-button :download="downloadFilename" :href="'data:text/plain;charset=utf-8,' + encodeURIComponent(fileOutput)" variant="outline-secondary">Download data</b-button>
|
||||
<b-button
|
||||
:download="downloadFilename"
|
||||
:href="
|
||||
'data:text/plain;charset=utf-8,' + encodeURIComponent(fileOutput)
|
||||
"
|
||||
variant="outline-secondary"
|
||||
>Download data</b-button
|
||||
>
|
||||
</div>
|
||||
<JugglRecordsList :records="finishedRecords" />
|
||||
</section>
|
||||
|
@ -34,7 +41,9 @@ export default {
|
|||
return store.getters.finishedRecords;
|
||||
},
|
||||
downloadFilename: function() {
|
||||
return "juggl_data_" + helperService.dateAsFilenameString(new Date()) + ".json";
|
||||
return (
|
||||
"juggl_data_" + helperService.dateAsFilenameString(new Date()) + ".json"
|
||||
);
|
||||
},
|
||||
fileOutput: function() {
|
||||
var content = {
|
||||
|
|
|
@ -11,6 +11,9 @@
|
|||
</div>
|
||||
<div id="add-project-form">
|
||||
<FormProjectAdd />
|
||||
<b-link to="/manage">
|
||||
Manage projects
|
||||
</b-link>
|
||||
</div>
|
||||
</section>
|
||||
<section v-if="finishedRecords.length > 0">
|
||||
|
|
175
src/views/Manage.vue
Normal file
175
src/views/Manage.vue
Normal file
|
@ -0,0 +1,175 @@
|
|||
<template>
|
||||
<LayoutNavbarPrivate title="Manage structures">
|
||||
<section id="projects">
|
||||
<h1>Projects</h1>
|
||||
<FormProjectAdd class="bottom-space" />
|
||||
<b-table
|
||||
:items="allProjects"
|
||||
hover
|
||||
:busy="working"
|
||||
:fields="project_fields"
|
||||
sort-by="name"
|
||||
>
|
||||
<template #table-busy>
|
||||
<div class="text-center">
|
||||
<b-spinner></b-spinner>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- Custom data -->
|
||||
<template #cell(duration)="data">
|
||||
{{ getDurationTimestamp(data.item.duration) }}
|
||||
</template>
|
||||
|
||||
<template #cell(details)="data">
|
||||
<b-button
|
||||
size="sm"
|
||||
@click="data.toggleDetails"
|
||||
variant="outline-secondary"
|
||||
>
|
||||
<b-icon class="icon-btn" icon="gear" />
|
||||
</b-button>
|
||||
</template>
|
||||
|
||||
<template #row-details="data">
|
||||
<b-card>
|
||||
<FormProjectDetails
|
||||
:project="data.item"
|
||||
@cancel="data.toggleDetails"
|
||||
@submit="data.toggleDetails"
|
||||
/>
|
||||
</b-card>
|
||||
</template>
|
||||
</b-table>
|
||||
</section>
|
||||
<section id="tags">
|
||||
<h1>Tags</h1>
|
||||
<FormTagAdd class="bottom-space" />
|
||||
<b-table
|
||||
:items="allTags"
|
||||
hover
|
||||
:busy="working"
|
||||
:fields="tag_fields"
|
||||
sort-by="name"
|
||||
>
|
||||
<template #table-busy>
|
||||
<div class="text-center">
|
||||
<b-spinner></b-spinner>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- Custom data -->
|
||||
<template #cell(details)="data">
|
||||
<b-button
|
||||
size="sm"
|
||||
@click="data.toggleDetails"
|
||||
variant="outline-secondary"
|
||||
>
|
||||
<b-icon class="icon-btn" icon="gear" />
|
||||
</b-button>
|
||||
</template>
|
||||
|
||||
<template #row-details="data">
|
||||
<b-card>
|
||||
<FormTagDetails
|
||||
:tag="data.item"
|
||||
@cancel="data.toggleDetails"
|
||||
@submit="data.toggleDetails"
|
||||
/>
|
||||
</b-card>
|
||||
</template>
|
||||
</b-table>
|
||||
</section>
|
||||
</LayoutNavbarPrivate>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import LayoutNavbarPrivate from "@/components/layout/LayoutNavbarPrivate";
|
||||
import FormProjectDetails from "@/components/forms/FormProjectDetails";
|
||||
import FormProjectAdd from "@/components/forms/FormProjectAdd";
|
||||
import FormTagDetails from "@/components/forms/FormTagDetails";
|
||||
import { helperService } from "@/services/helper.service.js";
|
||||
import FormTagAdd from "@/components/forms/FormTagAdd";
|
||||
import store from "@/store";
|
||||
|
||||
export default {
|
||||
name: "Home",
|
||||
components: {
|
||||
LayoutNavbarPrivate,
|
||||
FormProjectDetails,
|
||||
FormProjectAdd,
|
||||
FormTagDetails,
|
||||
FormTagAdd
|
||||
},
|
||||
data: () => {
|
||||
return {
|
||||
working: true,
|
||||
project_fields: [
|
||||
{
|
||||
key: "name",
|
||||
label: "Name"
|
||||
},
|
||||
{
|
||||
key: "start_date",
|
||||
label: "Start date"
|
||||
},
|
||||
{
|
||||
key: "duration",
|
||||
label: "Duration"
|
||||
},
|
||||
{
|
||||
key: "record_count",
|
||||
label: "Records"
|
||||
},
|
||||
{
|
||||
key: "details",
|
||||
label: "Details"
|
||||
}
|
||||
],
|
||||
tag_fields: [
|
||||
{
|
||||
key: "name",
|
||||
label: "Name"
|
||||
},
|
||||
{
|
||||
key: "details",
|
||||
label: "Details"
|
||||
}
|
||||
]
|
||||
};
|
||||
},
|
||||
created: function() {
|
||||
store.dispatch("loadProjects");
|
||||
store
|
||||
.dispatch("loadTags")
|
||||
.then(() => {
|
||||
this.working = false;
|
||||
})
|
||||
.catch(() => {
|
||||
this.working = false;
|
||||
});
|
||||
},
|
||||
computed: {
|
||||
allTags: function() {
|
||||
return Object.values(store.getters.tags);
|
||||
},
|
||||
allProjects: function() {
|
||||
return Object.values(store.getters.projects);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getDurationTimestamp: helperService.getDurationTimestamp
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="sass">
|
||||
.center
|
||||
text-align: center
|
||||
|
||||
.bottom-space
|
||||
margin-bottom: 1rem
|
||||
|
||||
section
|
||||
margin-bottom: 4rem
|
||||
</style>
|
Loading…
Reference in a new issue