add start point of panel
This commit is contained in:
parent
9d9589f9a0
commit
1cd64aa9f2
|
|
@ -6,6 +6,8 @@ use App\Http\Resources\ScheduleResource;
|
|||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Schedule;
|
||||
use App\Client;
|
||||
use Carbon\Carbon;
|
||||
|
||||
class ScheduleController extends Controller
|
||||
{
|
||||
|
|
@ -13,4 +15,58 @@ class ScheduleController extends Controller
|
|||
{
|
||||
return ScheduleResource::collection(Schedule::all());
|
||||
}
|
||||
|
||||
public function success(){
|
||||
$count = $this->statusCount();
|
||||
$schedules = Schedule::where('last_backup_status', 'Success')->orderBy('updated_at', 'desc')->paginate(10);
|
||||
return ScheduleResource::collection($schedules)->additional(['count' =>
|
||||
$count
|
||||
]);
|
||||
}
|
||||
|
||||
public function warnings(){
|
||||
$count = $this->statusCount();
|
||||
$data = ScheduleResource::collection(Schedule::all()->where('last_backup_status', 'Warning')->sortByDesc('updated_at'));
|
||||
return compact('count','data');
|
||||
}
|
||||
|
||||
public function errors(){
|
||||
$count = $this->statusCount();
|
||||
$data = ScheduleResource::collection(Schedule::all()->where('last_backup_status', 'Error')->sortByDesc('updated_at'));
|
||||
return compact('count','data');
|
||||
}
|
||||
|
||||
public function noschedules(){
|
||||
$count = $this->statusCount();
|
||||
// $data = ScheduleResource::collection(Schedule::all()->where('last_backup_status', 'Errors')->sortByDesc('updated_at'));
|
||||
$data = Client::whereDoesntHave('schedules')->get();
|
||||
return compact('count','data');
|
||||
}
|
||||
|
||||
public function norecent(){
|
||||
$count = $this->statusCount();
|
||||
$data = ScheduleResource::collection(Schedule::where('last_backup_time', '<=', Carbon::now()
|
||||
->subHours(48)
|
||||
->toDateTimeString())
|
||||
->get()->sortByDesc('updated_at'));
|
||||
return compact('count','data');
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function statusCount()
|
||||
{
|
||||
// $results= DB::table('backup_schedules')->select('last_backup_status', DB::raw('count(*) as count'))->groupBy('last_backup_status')->get();
|
||||
$noschedules = Client::whereDoesntHave('schedules')->count();
|
||||
$norecent = Schedule::where('last_backup_time', '<=', Carbon::now()
|
||||
->subHours(48)
|
||||
->toDateTimeString())
|
||||
->count();
|
||||
$errors = Schedule::where('last_backup_status' , 'Error')->count();
|
||||
$successful = Schedule::where('last_backup_status' , 'Success')->count();
|
||||
$warnings = Schedule::where('last_backup_status' , 'Warning')->count();
|
||||
|
||||
return compact('noschedules','norecent','errors','successful','warnings');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@ class ScheduleResource extends JsonResource
|
|||
'id' => $this->id,
|
||||
'name' => $this->name,
|
||||
'last_backup_status' => $this->last_backup_status,
|
||||
'updated_at' => $this->updated_at,
|
||||
'date' => \Carbon\Carbon::parse($this->updated_at)->diffForHumans(),
|
||||
'client' => $this->client->client_name,
|
||||
'client_id' => $this->client->id,
|
||||
];
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -18,5 +18,10 @@
|
|||
"lodash": "^4.17.5",
|
||||
"popper.js": "^1.12",
|
||||
"vue": "^2.5.7"
|
||||
},
|
||||
"dependencies": {
|
||||
"bulma": "^0.7.2",
|
||||
"bulma-badge": "^2.0.0",
|
||||
"vue-router": "^3.0.1"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"/js/app.js": "/js/app.js",
|
||||
"/css/app.css": "/css/app.css"
|
||||
}
|
||||
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
/**
|
||||
* First we will load all of this project's JavaScript dependencies which
|
||||
* includes Vue and other libraries. It is a great starting point when
|
||||
|
|
@ -7,7 +6,9 @@
|
|||
|
||||
require('./bootstrap');
|
||||
|
||||
window.Vue = require('vue');
|
||||
import Vue from 'vue'
|
||||
import VueRouter from 'vue-router'
|
||||
Vue.use(VueRouter)
|
||||
|
||||
/**
|
||||
* Next, we will create a fresh Vue application instance and attach it to
|
||||
|
|
@ -15,8 +16,58 @@ window.Vue = require('vue');
|
|||
* or customize the JavaScript scaffolding to fit your unique needs.
|
||||
*/
|
||||
|
||||
Vue.component('example-component', require('./components/ExampleComponent.vue'));
|
||||
Vue.component('scheduletabs', require('./components/schedules/Tabs.vue'));
|
||||
Vue.component('headernav', require('./components/HeaderNav.vue'));
|
||||
Vue.component('pagination', require('./components/PaginationComponent.vue'));
|
||||
// let headernav = require('./components/HeaderNav.vue');
|
||||
let sidebar = require('./components/SideBar.vue');
|
||||
// let scheduletabs = require('./components/schedules/Tabs.vue')
|
||||
|
||||
let SchedulesSuccessfull = require('./components/schedules/Successfull.vue');
|
||||
let SchedulesNoSchedules = require('./components/schedules/NoSchedules.vue');
|
||||
let SchedulesWarnings = require('./components/schedules/Warnings.vue');
|
||||
let SchedulesErrors = require('./components/schedules/Errors.vue');
|
||||
let SchedulesNoRecent = require('./components/schedules/NoRecent.vue');
|
||||
|
||||
const routes = [
|
||||
{
|
||||
path: '/schedules',
|
||||
redirect: '/schedules/successfull'
|
||||
// component: SchedulesSuccessfull
|
||||
},
|
||||
{
|
||||
path: '/schedules/successfull',
|
||||
component: SchedulesSuccessfull
|
||||
},
|
||||
{
|
||||
path: '/schedules/noschedules',
|
||||
component: SchedulesNoSchedules
|
||||
},
|
||||
{
|
||||
path: '/schedules/norecent',
|
||||
component: SchedulesNoRecent
|
||||
},
|
||||
{
|
||||
path: '/schedules/warnings',
|
||||
component: SchedulesWarnings
|
||||
},
|
||||
{
|
||||
path: '/schedules/errors',
|
||||
component: SchedulesErrors
|
||||
}
|
||||
]
|
||||
|
||||
const router = new VueRouter({
|
||||
mode: 'history',
|
||||
routes // short for `routes: routes`
|
||||
})
|
||||
|
||||
const app = new Vue({
|
||||
el: '#app'
|
||||
el: '#app',
|
||||
router,
|
||||
components: {
|
||||
sidebar,
|
||||
// headernav,
|
||||
// scheduletabs,
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ window.Popper = require('popper.js').default;
|
|||
try {
|
||||
window.$ = window.jQuery = require('jquery');
|
||||
|
||||
require('bootstrap');
|
||||
// require('bootstrap');
|
||||
} catch (e) {}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -0,0 +1,34 @@
|
|||
<template>
|
||||
<nav class="level">
|
||||
<div class="level-item level-left">
|
||||
<div>
|
||||
<p class="title is-4">{{ section }}</p>
|
||||
<p class="heading is-4">{{ subsection }}</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="level-item level-right">
|
||||
|
||||
<div class="feh-actions">
|
||||
<span class="icon">
|
||||
<i class="mdi mdi-24px mdi-tune"></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
section: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
subsection: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
<template>
|
||||
<nav class="navbar" role="navigation" aria-label="main navigation">
|
||||
<div class="navbar-brand">
|
||||
<a class="navbar-item" href="https://bulma.io">
|
||||
<img src="https://bulma.io/images/bulma-logo.png" width="112" height="28">
|
||||
</a>
|
||||
|
||||
<a role="button" class="navbar-burger burger" aria-label="menu" aria-expanded="false" data-target="navbarBasicExample">
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div id="navbarBasicExample" class="navbar-menu">
|
||||
<div class="navbar-start">
|
||||
<a class="navbar-item">
|
||||
Home
|
||||
</a>
|
||||
|
||||
<a class="navbar-item">
|
||||
Documentation
|
||||
</a>
|
||||
|
||||
<div class="navbar-item has-dropdown is-hoverable">
|
||||
<a class="navbar-link">
|
||||
More
|
||||
</a>
|
||||
|
||||
<div class="navbar-dropdown">
|
||||
<a class="navbar-item">
|
||||
About
|
||||
</a>
|
||||
<a class="navbar-item">
|
||||
Jobs
|
||||
</a>
|
||||
<a class="navbar-item">
|
||||
Contact
|
||||
</a>
|
||||
<hr class="navbar-divider">
|
||||
<a class="navbar-item">
|
||||
Report an issue
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="navbar-end">
|
||||
<div class="navbar-item">
|
||||
<div class="buttons">
|
||||
<a class="button is-primary">
|
||||
<strong>Sign up</strong>
|
||||
</a>
|
||||
<a class="button is-light">
|
||||
Log in
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
<template>
|
||||
<nav class="pagination is-centered is-rounded" role="navigation" aria-label="pagination">
|
||||
<a class="pagination-previous" @click.prevent="changePage(1)" :disabled="pagination.current_page <= 1">First page</a>
|
||||
<a class="pagination-previous" @click.prevent="changePage(pagination.current_page - 1)" :disabled="pagination.current_page <= 1">Previous</a>
|
||||
<a class="pagination-next" @click.prevent="changePage(pagination.current_page + 1)" :disabled="pagination.current_page >= pagination.last_page">Next page</a>
|
||||
<a class="pagination-next" @click.prevent="changePage(pagination.last_page)" :disabled="pagination.current_page >= pagination.last_page">Last page</a>
|
||||
<ul class="pagination-list">
|
||||
<li v-for="page in pages">
|
||||
<a class="pagination-link" :class="isCurrentPage(page) ? 'is-current' : ''" @click.prevent="changePage(page)">{{ page }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.pagination {
|
||||
margin-top: 40px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: ['pagination', 'offset'],
|
||||
|
||||
methods: {
|
||||
isCurrentPage(page) {
|
||||
return this.pagination.current_page === page;
|
||||
},
|
||||
|
||||
changePage(page) {
|
||||
if (page > this.pagination.last_page) {
|
||||
page = this.pagination.last_page;
|
||||
}
|
||||
|
||||
this.pagination.current_page = page;
|
||||
this.$emit('paginate');
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
pages() {
|
||||
let pages = [];
|
||||
|
||||
let from = this.pagination.current_page - Math.floor(this.offset / 2);
|
||||
|
||||
if (from < 1) {
|
||||
from = 1;
|
||||
}
|
||||
|
||||
let to = from + this.offset - 1;
|
||||
|
||||
if (to > this.pagination.last_page) {
|
||||
to = this.pagination.last_page;
|
||||
}
|
||||
|
||||
while (from <= to) {
|
||||
pages.push(from);
|
||||
from++;
|
||||
}
|
||||
|
||||
return pages;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
<template>
|
||||
|
||||
<aside class="column is-3 menu sidebar">
|
||||
<div class="logo">
|
||||
<img src="/images/logo.png" alt=""><strong>MDB</strong> Panel
|
||||
</div>
|
||||
<p class="menu-label">
|
||||
General
|
||||
</p>
|
||||
<ul class="menu-list">
|
||||
<li>
|
||||
<a><span class="icon">
|
||||
<i class="mdi mdi-18px mdi-monitor-dashboard"></i>
|
||||
</span>Dashboard</a></li>
|
||||
</ul>
|
||||
<p class="menu-label">
|
||||
Backups
|
||||
</p>
|
||||
<ul class="menu-list">
|
||||
<li>
|
||||
|
||||
<router-link to="/schedules">
|
||||
<span class="icon">
|
||||
<i class="mdi mdi-18px mdi-clock-outline"></i>
|
||||
</span>
|
||||
Schedules
|
||||
</router-link>
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<router-link to="/backups">
|
||||
<span class="icon">
|
||||
<i class="mdi mdi-18px mdi-upload-network"></i>
|
||||
</span>
|
||||
Backups
|
||||
</router-link>
|
||||
</li>
|
||||
</ul>
|
||||
<p class="menu-label">
|
||||
Clients
|
||||
</p>
|
||||
<ul class="menu-list">
|
||||
<li><a>
|
||||
<span class="icon">
|
||||
<i class="mdi mdi-18px mdi-account-details"></i>
|
||||
</span>
|
||||
Client list</a></li>
|
||||
<li><a>
|
||||
<span class="icon">
|
||||
<i class="mdi mdi-18px mdi-account-plus-outline"></i>
|
||||
</span>
|
||||
Add new client</a></li>
|
||||
</ul>
|
||||
|
||||
</aside>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
<template v-cloak>
|
||||
<div>
|
||||
<headernav :section="section" :subsection="subsection"></headernav>
|
||||
<scheduletabs :statusCount="statusCount"></scheduletabs>
|
||||
<table class="table is-fullwidth is-striped is-hoverable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Client</th>
|
||||
<th>Schedule</th>
|
||||
<th>When <span class="icon"><i class="mdi mdi-18px mdi-chevron-up" aria-hidden="true"></i></span>
|
||||
<span class="icon"><i class="mdi mdi-28px mdi-chevron-down" aria-hidden="true"></i></span>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="schedule in schedules" :key="schedule.id">
|
||||
<td><span class="icon tbl-icon"><i class="mdi mdi-24px mdi-close has-text-danger" aria-hidden="true"></i></span>
|
||||
{{ schedule.client }}</td>
|
||||
<td>{{ schedule.name }}</td>
|
||||
<td>{{ schedule.date }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
schedules: null,
|
||||
statusCount: {},
|
||||
section: 'Schedules',
|
||||
subsection: "errors"
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
axios
|
||||
.get('/api/v1/schedule/errors')
|
||||
.then(response => (this.schedules = response.data.data, this.statusCount = response.data.count))
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
<template v-cloak>
|
||||
<div>
|
||||
<headernav :section="section" :subsection="subsection"></headernav>
|
||||
<scheduletabs :statusCount="statusCount"></scheduletabs>
|
||||
<table class="table is-fullwidth is-striped is-hoverable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Client</th>
|
||||
<th>Schedule</th>
|
||||
<th>When <span class="icon"><i class="mdi mdi-18px mdi-chevron-up" aria-hidden="true"></i></span>
|
||||
<span class="icon"><i class="mdi mdi-28px mdi-chevron-down" aria-hidden="true"></i></span>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="schedule in schedules" :key="schedule.id">
|
||||
<td>
|
||||
<span class="icon tbl-icon">
|
||||
<i v-bind:class="{ 'has-text-success mdi-check': schedule.last_backup_status=='Success',
|
||||
'has-text-warning mdi-exclamation': schedule.last_backup_status=='Warning',
|
||||
'has-text-danger mdi-close': schedule.last_backup_status=='Error'
|
||||
|
||||
}" class="mdi mdi-24px" aria-hidden="true"></i>
|
||||
</span>
|
||||
{{ schedule.client }}</td>
|
||||
<td>{{ schedule.name }}</td>
|
||||
<td>{{ schedule.date }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
schedules: null,
|
||||
statusCount: {},
|
||||
section: 'Schedules',
|
||||
subsection: "no recent"
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
axios
|
||||
.get('/api/v1/schedule/norecent')
|
||||
.then(response => (this.schedules = response.data.data, this.statusCount = response.data.count))
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
<template v-cloak>
|
||||
<div>
|
||||
<headernav :section="section" :subsection="subsection"></headernav>
|
||||
<scheduletabs :statusCount="statusCount"></scheduletabs>
|
||||
<table class="table is-fullwidth is-striped is-hoverable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Client</th>
|
||||
<th>Schedule</th>
|
||||
<th>When <span class="icon"><i class="mdi mdi-18px mdi-chevron-up" aria-hidden="true"></i></span>
|
||||
<span class="icon"><i class="mdi mdi-28px mdi-chevron-down" aria-hidden="true"></i></span>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="schedule in schedules" :key="schedule.id">
|
||||
<td><span class="icon tbl-icon"><i class="mdi mdi-24px mdi-minus has-text-info" aria-hidden="true"></i></span>
|
||||
{{ schedule.client_name }}</td>
|
||||
<td>none</td>
|
||||
<td>never</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
schedules: null,
|
||||
statusCount: {},
|
||||
section: 'Schedules',
|
||||
subsection: "no schedules"
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
axios
|
||||
.get('/api/v1/schedule/noschedules')
|
||||
.then(response => (this.schedules = response.data.data, this.statusCount = response.data.count))
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
<template v-cloak>
|
||||
<div>
|
||||
<headernav :section="section" :subsection="subsection"></headernav>
|
||||
<scheduletabs :statusCount="statusCount"></scheduletabs>
|
||||
<table class="table is-fullwidth is-striped is-hoverable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Client</th>
|
||||
<th>Schedule</th>
|
||||
<th>When <span class="icon"><i class="mdi mdi-18px mdi-chevron-up" aria-hidden="true"></i></span>
|
||||
<span class="icon"><i class="mdi mdi-28px mdi-chevron-down" aria-hidden="true"></i></span>
|
||||
</th>
|
||||
<th><span class="is-pulled-right">Actions</span></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="schedule in schedules" :key="schedule.id">
|
||||
<td><span class="icon tbl-icon"><i class="mdi mdi-24px mdi-check has-text-success" aria-hidden="true"></i></span>
|
||||
{{ schedule.client }}</td>
|
||||
<td>{{ schedule.name }}</td>
|
||||
<td>{{ schedule.date }}</td>
|
||||
<td><i class="mdi mdi-24px mdi-magnify is-pulled-right" aria-hidden="true"></i></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<pagination v-if="pagination.last_page > 1" :pagination="pagination" :offset="5" @paginate="fetchSchedules()"></pagination>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
schedules: null,
|
||||
statusCount: {},
|
||||
section: 'Schedules',
|
||||
subsection: "success",
|
||||
pagination: {
|
||||
'current_page': 1
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
fetchSchedules() {
|
||||
axios.get('/api/v1/schedule/success?page=' + this.pagination.current_page)
|
||||
.then(response => {
|
||||
this.schedules = response.data.data,
|
||||
this.statusCount = response.data.count,
|
||||
this.pagination = response.data.meta;
|
||||
})
|
||||
.catch(error => {
|
||||
console.log(error.response.data);
|
||||
});
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.fetchSchedules();
|
||||
setInterval(() => this.fetchSchedules(), 10000);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
<template>
|
||||
<div class="tabs is-fullwidth">
|
||||
<ul>
|
||||
<li>
|
||||
<router-link to="/schedules/successfull">
|
||||
<span class="icon"><i class="mdi mdi-18px mdi-check-circle has-text-success" aria-hidden="true"></i></span>
|
||||
<span>Successful <span class="tag">{{ statusCount.successful}}</span></span>
|
||||
</router-link>
|
||||
</li>
|
||||
<li>
|
||||
<router-link to="/schedules/norecent">
|
||||
<span class="icon"><i class="mdi mdi-18px mdi-help-circle has-text-link" aria-hidden="true"></i></span>
|
||||
<span>No Recent <span class="tag">{{ statusCount.norecent}}</span></span>
|
||||
</router-link>
|
||||
</li>
|
||||
<li>
|
||||
<router-link to="/schedules/warnings">
|
||||
<span class="icon"><i class="mdi mdi-18px mdi-alert-circle has-text-warning" aria-hidden="true"></i></span>
|
||||
<span>Warnings <span class="tag">{{ statusCount.warnings}}</span></span>
|
||||
</router-link>
|
||||
</li>
|
||||
<li>
|
||||
<router-link to="/schedules/errors">
|
||||
<span class="icon"><i class="mdi mdi-18px mdi-close-circle has-text-danger" aria-hidden="true"></i></span>
|
||||
<span>Errors <span class="tag">{{ statusCount.errors }}</span></span>
|
||||
</router-link>
|
||||
</li>
|
||||
<li>
|
||||
<router-link to="/schedules/noschedules">
|
||||
<span class="icon"><i class="mdi mdi-18px mdi-minus-circle has-text-info" aria-hidden="true"></i></span>
|
||||
<span>No Schedules <span class="tag">{{ statusCount.noschedules }}</span></span>
|
||||
</router-link>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
statusCount: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
<template v-cloak>
|
||||
<div>
|
||||
<headernav :section="section" :subsection="subsection"></headernav>
|
||||
<scheduletabs :statusCount="statusCount"></scheduletabs>
|
||||
<table class="table is-fullwidth is-striped is-hoverable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Client</th>
|
||||
<th>Schedule</th>
|
||||
<th>When <span class="icon"><i class="mdi mdi-18px mdi-chevron-up" aria-hidden="true"></i></span>
|
||||
<span class="icon"><i class="mdi mdi-28px mdi-chevron-down" aria-hidden="true"></i></span>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="schedule in schedules" :key="schedule.id">
|
||||
<td><span class="icon tbl-icon"><i class="mdi mdi-24px mdi-exclamation has-text-warning" aria-hidden="true"></i></span>
|
||||
{{ schedule.client }}</td>
|
||||
<td>{{ schedule.name }}</td>
|
||||
<td>{{ schedule.date }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
schedules: null,
|
||||
statusCount: {},
|
||||
section: 'Schedules',
|
||||
subsection: "warnings"
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
axios
|
||||
.get('/api/v1/schedule/warnings')
|
||||
.then(response => (this.schedules = response.data.data, this.statusCount = response.data.count))
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
@ -1,20 +1,26 @@
|
|||
|
||||
// Body
|
||||
$body-bg: #f8fafc;
|
||||
// Links
|
||||
// $link: white;
|
||||
|
||||
// Typography
|
||||
$font-family-sans-serif: "Nunito", sans-serif;
|
||||
$font-size-base: 0.9rem;
|
||||
$line-height-base: 1.6;
|
||||
|
||||
// Colors
|
||||
$blue: #3490dc;
|
||||
$indigo: #6574cd;
|
||||
$purple: #9561e2;
|
||||
$pink: #f66D9b;
|
||||
$red: #e3342f;
|
||||
$orange: #f6993f;
|
||||
$yellow: #ffed4a;
|
||||
$green: #38c172;
|
||||
$teal: #4dc0b5;
|
||||
$cyan: #6cb2eb;
|
||||
// // Body
|
||||
// $body-bg: #f8fafc;
|
||||
|
||||
// // Typography
|
||||
// $font-family-sans-serif: "Nunito", sans-serif;
|
||||
// $font-size-base: 0.9rem;
|
||||
// $line-height-base: 1.6;
|
||||
|
||||
// // Colors
|
||||
// $blue: #3490dc;
|
||||
// $indigo: #6574cd;
|
||||
// $purple: #9561e2;
|
||||
// $pink: #f66D9b;
|
||||
// $red: #e3342f;
|
||||
// $orange: #f6993f;
|
||||
// $yellow: #ffed4a;
|
||||
// $green: #38c172;
|
||||
// $teal: #4dc0b5;
|
||||
// $cyan: #6cb2eb;
|
||||
$table-cell-border: 0px solid #dbdbdb;
|
||||
$table-head-cell-border-width: 0 0 1px;
|
||||
|
|
@ -5,10 +5,146 @@
|
|||
// Variables
|
||||
@import 'variables';
|
||||
|
||||
// Bootstrap
|
||||
@import '~bootstrap/scss/bootstrap';
|
||||
// Bulma
|
||||
@import '~bulma/bulma';
|
||||
@import '~bulma-badge/dist/css/bulma-badge';
|
||||
|
||||
.navbar-laravel {
|
||||
background-color: #fff;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.04);
|
||||
// html, body, #app {
|
||||
// height: 100%;
|
||||
// }
|
||||
// #app {
|
||||
// min-height: 100%;
|
||||
// //display: flex;
|
||||
// //flex-direction: column;
|
||||
// }
|
||||
|
||||
|
||||
tr{
|
||||
line-height: 2rem;
|
||||
}
|
||||
|
||||
.sidebar{
|
||||
display: block;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
position: fixed;
|
||||
overflow-y: auto;
|
||||
background-color: #32393F;
|
||||
padding: 0px;
|
||||
padding-top: 30px;
|
||||
}
|
||||
.sidebar a{
|
||||
color:#cacaca;
|
||||
}
|
||||
|
||||
.sidebar .icon{
|
||||
padding-right: 20px;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.menu-label {
|
||||
padding-left: 4em;
|
||||
}
|
||||
|
||||
.menu-list a {
|
||||
border-radius: 0px;
|
||||
padding: 0.5em 4em;
|
||||
}
|
||||
.menu-list a:hover, .menu-list .router-link-exact-active, .menu-list .router-link-active{
|
||||
background-color:#282e32;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.tabs li .router-link-exact-active, .tabs li .router-link-active {
|
||||
border-bottom-color: #3273dc !important;
|
||||
color: #3273dc !important;
|
||||
}
|
||||
|
||||
.logo {
|
||||
padding-left: 50px;
|
||||
font-size: 1.7rem;
|
||||
color: white;
|
||||
font-weight: 200;
|
||||
}
|
||||
|
||||
.logo strong{
|
||||
color:white;
|
||||
}
|
||||
|
||||
.maincontent{
|
||||
padding-left: 25%;
|
||||
padding-top: 50px;
|
||||
}
|
||||
.feh-actions {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
padding-top:10px;
|
||||
margin: 0;
|
||||
// margin-top:-10px;
|
||||
position: absolute;
|
||||
right: 0px;
|
||||
top: -5px;
|
||||
height: 45px;
|
||||
min-width: 45px;
|
||||
text-align: center;
|
||||
border-radius: 50%;
|
||||
z-index: 11;
|
||||
transition: ease-in-out;
|
||||
transition-duration: .3s;
|
||||
background: whitesmoke;
|
||||
}
|
||||
.feh-actions:hover {
|
||||
border: 0;
|
||||
background: grey;
|
||||
color:white;
|
||||
}
|
||||
|
||||
.table td, .table th {
|
||||
padding-left: 30px;
|
||||
}
|
||||
|
||||
.tbl-icon {
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
background-color: #f5f5f5;
|
||||
padding-left: 6px;
|
||||
padding-top: 2px;
|
||||
margin-right: 10px;
|
||||
border-radius: 50%;
|
||||
width: 35px;
|
||||
height: 35px;
|
||||
transition: background-color;
|
||||
transition-duration: .25s;
|
||||
}
|
||||
tr:hover span.icon.tbl-icon:first-child {
|
||||
/* code */
|
||||
background-color:grey !important;
|
||||
}
|
||||
|
||||
tr:hover i{
|
||||
/* code */
|
||||
color:white !important;
|
||||
}
|
||||
|
||||
.fade-enter-active,
|
||||
.fade-leave-active {
|
||||
transition-duration: 0.2s;
|
||||
transition-property: opacity;
|
||||
transition-timing-function: ease;
|
||||
}
|
||||
|
||||
.fade-enter,
|
||||
.fade-leave-active {
|
||||
opacity: 0
|
||||
}
|
||||
// .content{
|
||||
// min-height:100%;
|
||||
// float:left;
|
||||
// overflow-y:auto;
|
||||
// margin: 0 auto;
|
||||
// position: relative;
|
||||
// }
|
||||
|
||||
[v-cloak] {
|
||||
display:none;
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||
<meta name="csrf-token" content="{{ csrf_token() }}">
|
||||
<title>Document</title>
|
||||
<link rel="stylesheet" href="{{ asset('/css/app.css') }}">
|
||||
<link rel="stylesheet" href="https://cdn.materialdesignicons.com/2.8.94/css/materialdesignicons.min.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="app">
|
||||
<section>
|
||||
<div class="columns">
|
||||
<sidebar></sidebar>
|
||||
<div class="column maincontent">
|
||||
<div class="container is-fluid">
|
||||
{{-- <headernav></headernav> --}}
|
||||
<transition name="fade" mode="out-in">
|
||||
<router-view></router-view>
|
||||
</transition>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
<script src="{{ asset('/js/app.js') }}"></script>
|
||||
<script defer src="https://use.fontawesome.com/releases/v5.3.1/js/all.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
|
@ -22,4 +22,9 @@ Route::middleware('auth:api')->get('/user', function (Request $request) {
|
|||
Route::apiResources(['v1/client' => 'API\v1\ClientController']);
|
||||
Route::post('v1/backup/{client_id}/{schedule_name}', 'API\v1\BackupController@store');
|
||||
// Route::get('v1/test', 'API\v1\BackupController@test');
|
||||
Route::get('v1/schedule', 'API\v1\ScheduleController@index');
|
||||
Route::get('v1/schedule', 'API\v1\ScheduleController@index');
|
||||
Route::get('v1/schedule/success', 'API\v1\ScheduleController@success');
|
||||
Route::get('v1/schedule/warnings', 'API\v1\ScheduleController@warnings');
|
||||
Route::get('v1/schedule/errors', 'API\v1\ScheduleController@errors');
|
||||
Route::get('v1/schedule/noschedules', 'API\v1\ScheduleController@noschedules');
|
||||
Route::get('v1/schedule/norecent', 'API\v1\ScheduleController@norecent');
|
||||
|
|
@ -1,16 +1,8 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Web Routes
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here is where you can register web routes for your application. These
|
||||
| routes are loaded by the RouteServiceProvider within a group which
|
||||
| contains the "web" middleware group. Now create something great!
|
||||
|
|
||||
*/
|
||||
|
||||
Route::get('/', function () {
|
||||
return view('welcome');
|
||||
});
|
||||
// Route::get('/', function () {
|
||||
// return view('index');
|
||||
// });
|
||||
Route::get('/{any}', function(){
|
||||
return view('index');
|
||||
})->where('any', '.*');
|
||||
23
test.sh
23
test.sh
|
|
@ -1,23 +0,0 @@
|
|||
#!/bin/bash
|
||||
# call this with normal curl arguments, especially url argument, e.g.
|
||||
# safecurl.sh "http://example.com:8080/something/"
|
||||
# separating the (verbose) curl options into an array for readability
|
||||
curl_args=(
|
||||
-H 'Accept:application/json'
|
||||
-H 'Content-Type:application/json'
|
||||
--write '\n%{http_code}\n'
|
||||
--fail
|
||||
--silent
|
||||
-k
|
||||
)
|
||||
echo "${curl_args[@]}"
|
||||
# prepend some arguments, but pass on whatever arguments this script was called with
|
||||
output=$(curl "${curl_args[@]}" "$@")
|
||||
return_code=$?
|
||||
if [ 0 -eq $return_code ]; then
|
||||
# remove the "http_code" line from the end of the output, and parse it
|
||||
echo "$output" | sed '$d' | jq .
|
||||
else
|
||||
# echo to stderr so further piping to jq will process empty output
|
||||
>&2 echo "Failure: code=$output"
|
||||
fi
|
||||
Loading…
Reference in New Issue