Commit c24595e9 authored by Dillenn Terumalai's avatar Dillenn Terumalai
Browse files

// WIP

parent 593ea227
......@@ -1132,10 +1132,10 @@
"integrity": "sha512-Fxt+AfXgjMoin2maPIYzFZnQjAXjAL0PHscM5pRTtatFqB+vZxAM9tLp2Optnuw3QOQC40jTNeGYFOMvyf7v9g==",
"dev": true
},
"@mdi/font": {
"@mdi/js": {
"version": "5.9.55",
"resolved": "https://registry.npmjs.org/@mdi/font/-/font-5.9.55.tgz",
"integrity": "sha512-jswRF6q3eq8NWpWiqct6q+6Fg/I7nUhrxYJfiEM8JJpap0wVJLQdbKtyS65GdlK7S7Ytnx3TTi/bmw+tBhkGmg==",
"resolved": "https://registry.npmjs.org/@mdi/js/-/js-5.9.55.tgz",
"integrity": "sha512-BbeHMgeK2/vjdJIRnx12wvQ6s8xAYfvMmEAVsUx9b+7GiQGQ9Za8jpwp17dMKr9CgKRvemlAM4S7S3QOtEbp4A==",
"dev": true
},
"@nodelib/fs.scandir": {
......
......@@ -10,7 +10,7 @@
"production": "mix --production"
},
"devDependencies": {
"@mdi/font": "^5.9.55",
"@mdi/js": "^5.9.55",
"@types/node": "^14.17.3",
"@types/webpack-env": "^1.16.0",
"axios": "^0.21.1",
......
This diff is collapsed.
{
"/app.js": "/app.js?id=e4a8cfac39f40a99f455",
"/app.js": "/app.js?id=4c4d26a3f33229007eb4",
"/img/favicon.ico": "/img/favicon.ico?id=ddf9962d2b7fa394e573"
}
......@@ -54,7 +54,7 @@
</svg>
</v-avatar>
<p class="text-h5 my-auto"><b>SLURM</b> Cluster - {{ appName() }}</p>
<p class="text-h5 my-auto"><b>Laravel</b> - Cluster</p>
</v-container>
</v-app-bar>
......@@ -72,12 +72,12 @@
@click="$router.push({ name: link.route })"
>
<v-list-item-icon class="mr-3">
<v-icon :color="route().current(link.route) ? 'primary' : 'grey'">
<v-icon :color="$router.currentRoute.name.includes(link.route) ? 'primary' : 'grey'">
{{ link.icon }}
</v-icon>
</v-list-item-icon>
<v-list-item-title
:class="route().current(link.route) ? 'primary--text' : 'grey--text'">
:class="$router.currentRoute.name.includes(link.route) ? 'primary--text' : 'grey--text'">
{{ link.label }}
</v-list-item-title>
</v-list-item>
......@@ -86,6 +86,15 @@
</v-col>
<v-col>
<v-alert
text
outlined
type="warning"
:icon="mdiAlertOutline()"
v-if="!assetsAreCurrent()"
>
The published LaravelCluster assets are not up-to-date with the installed version. To update, run:<br/><code>php artisan laravel-cluster:publish</code>
</v-alert>
<router-view></router-view>
</v-col>
</v-row>
......@@ -97,45 +106,62 @@
<script lang="ts">
import 'reflect-metadata'
import { Component, Vue } from 'vue-property-decorator'
import {
mdiCheckCircleOutline,
mdiCloseCircleOutline, mdiDeleteCircleOutline,
mdiHome,
mdiMagnify,
mdiPauseCircleOutline,
mdiTrayFull,
mdiAlertOutline
} from "@mdi/js";
@Component
export default class ClusterLayout extends Vue {
private links: { label: string; icon: string; route: string }[] = [
export default class LaravelCluster extends Vue {
links: { label: string; icon: string; route: string }[] = [
{
label: 'Dashboard',
icon: 'mdi-home',
icon: mdiHome,
route: 'dashboard'
},
{
label: 'Queue',
icon: 'mdi-tray-full',
icon: mdiTrayFull,
route: 'queue'
},
{
label: 'Inspector',
icon: 'mdi-magnify',
icon: mdiMagnify,
route: 'inspector'
},
{
label: 'Pending Jobs',
icon: 'mdi-pause-circle-outline',
icon: mdiPauseCircleOutline,
route: 'pending-jobs'
},
{
label: 'Completed Jobs',
icon: 'mdi-check-circle-outline',
icon: mdiCheckCircleOutline,
route: 'completed-jobs'
},
{
label: 'Failed Jobs',
icon: 'mdi-close-circle-outline',
icon: mdiCloseCircleOutline,
route: 'failed-jobs'
},
{
label: 'Cancelled Jobs',
icon: 'mdi-delete-circle-outline',
icon: mdiDeleteCircleOutline,
route: 'cancelled-jobs'
}
]
mdiAlertOutline() {
return mdiAlertOutline
}
assetsAreCurrent() {
return window.LaravelCluster.assetsAreCurrent
}
}
</script>
......@@ -19,7 +19,7 @@
>
<div class="pa-3">
<a class="primary--text text-subtitle-1"
@click="$router.push({ name: 'cancelled-job-detail', params: {id: item.id}})">{{
@click="$router.push({ name: 'cancelled-jobs-preview', params: {id: item.id}})">{{
item.job_name.toUpperCase()
}}</a>
<p class="text-caption grey--text text--darken-1 mb-0">Partition: {{ item.partition }} | ID:
......@@ -39,7 +39,7 @@ import {Component, Vue} from 'vue-property-decorator'
export default class CancelledJobs extends Vue {
isLoading: boolean = false
items: any
items: any[] = []
headers: any = [
{
......
......@@ -18,7 +18,7 @@
v-slot:item.job="{ item }"
>
<div class="pa-3">
<a class="primary--text text-subtitle-1" @click="$router.push({ name: 'completed-job-detail', params: {id: item.id}})">{{
<a class="primary--text text-subtitle-1" @click="$router.push({ name: 'completed-jobs-preview', params: {id: item.id}})">{{
item.job_name.toUpperCase()
}}</a>
<p class="text-caption grey--text text--darken-1 mb-0">Partition: {{ item.partition }} | ID:
......@@ -38,7 +38,7 @@ import {Component, Vue} from 'vue-property-decorator'
export default class CompletedJobs extends Vue {
isLoading: boolean = false
items: any
items: any[] = []
headers: any = [
{
......
<template>
<div>
<v-card class="mb-10">
<v-card class="mb-10" :loading="isLoading" :disabled="isLoading">
<v-card-title>
<p class="text-h6 mb-0">Overview</p>
</v-card-title>
......@@ -24,11 +24,11 @@
<v-col cols="3" class="grey dark-grey--text lighten-5 pa-5 border">
<p class="text-subtitle-2 font-weight-regular text-uppercase">Status</p>
<p class="text-h5" v-if="isOnline">
<v-icon color="green accent-3" large>mdi-check-circle-outline</v-icon>
<v-icon color="green accent-3" large>{{ mdiCheckCircleOutline() }}</v-icon>
Active
</p>
<p class="text-h5" v-if="!isOnline">
<v-icon color="red accent-3" large>mdi-close-circle-outline</v-icon>
<v-icon color="red accent-3" large>{{ mdiCloseCircleOutline() }}</v-icon>
Inactive
</p>
</v-col>
......@@ -55,16 +55,17 @@
<script lang="ts">
import 'reflect-metadata'
import {Component, Vue} from 'vue-property-decorator'
import {mdiCheckCircleOutline, mdiCloseCircleOutline} from "@mdi/js";
@Component
export default class Dashboard extends Vue {
isLoading: boolean = false
totalJobs: number
jobsPastHour: number
failedJobs: number
isOnline: boolean
nodes: any[]
totalJobs: number = 0
jobsPastHour: number = 0
failedJobs: number = 0
isOnline: boolean = false
nodes: any[] = []
headers: any = [
{
......@@ -118,6 +119,14 @@ export default class Dashboard extends Vue {
mounted() {
document.title = "LaravelCluster - Dashboard"
}
mdiCheckCircleOutline() {
return mdiCheckCircleOutline
}
mdiCloseCircleOutline() {
return mdiCloseCircleOutline
}
}
</script>
......
......@@ -18,7 +18,7 @@
v-slot:item.job="{ item }"
>
<div class="pa-3">
<a class="primary--text text-subtitle-1" @click="$router.push({ name: 'failed-job-detail', params: {id: item.id}})">{{
<a class="primary--text text-subtitle-1" @click="$router.push({ name: 'failed-jobs-preview', params: {id: item.id}})">{{
item.job_name.toUpperCase()
}}</a>
<p class="text-caption grey--text text--darken-1 mb-0">Partition: {{ item.partition }} | ID:
......@@ -38,7 +38,7 @@ import {Component, Vue} from 'vue-property-decorator'
export default class FailedJobs extends Vue {
isLoading: boolean = false
items: any
items: any[] = []
headers: any = [
{
......
......@@ -26,7 +26,7 @@ import {Component, Vue} from 'vue-property-decorator'
export default class Inspector extends Vue {
isLoading: boolean = false
information: string;
information: string = '';
private jobId: string | null = null
......
......@@ -11,13 +11,14 @@
v-if="items.length"
:headers="headers"
:items="items"
:loading="isLoading"
hide-default-footer
>
<template
v-slot:item.job="{ item }"
>
<div class="pa-3">
<a class="primary--text text-subtitle-1" @click="$router.push({ name: 'pending-job-detail', params: {id: item.id}})">{{
<a class="primary--text text-subtitle-1" @click="$router.push({ name: 'pending-jobs-preview', params: {id: item.id}})">{{
item.job_name.toUpperCase()
}}</a>
<p class="text-caption grey--text text--darken-1 mb-0">Partition: {{ item.partition }} | ID: {{ item.id }}</p>
......@@ -36,7 +37,7 @@ import {Component, Vue} from 'vue-property-decorator'
export default class PendingJobs extends Vue {
isLoading: boolean = false
items: any
items: any[] = []
headers: any = [
{
......@@ -55,7 +56,7 @@ export default class PendingJobs extends Vue {
loadJobs() {
this.isLoading = true
this.$http.get(`${window.LaravelCluster.basePath}/api/failed`)
this.$http.get(`${window.LaravelCluster.basePath}/api/pending`)
.then(({data}) => {
this.items = data.jobs
})
......
......@@ -22,7 +22,7 @@ import {Component, Vue} from 'vue-property-decorator'
export default class Queue extends Vue {
isLoading: boolean = false
queues: any[]
queues: any[] = []
headers: any = [
{
......
<template>
<div>
<v-card class="mb-10" :loading="isLoading">
<v-card class="mb-10" :loading="isLoading" v-if="job">
<v-card-title>
<p class="text-h6 mb-0">{{ job.job_name }}</p>
</v-card-title>
......@@ -24,7 +24,7 @@
</v-card-text>
</v-card>
<v-card class="mb-10">
<v-card class="mb-10" :loading="isLoading" v-if="job">
<v-card-title>
<p class="text-h6 mb-0">Payload</p>
</v-card-title>
......@@ -45,7 +45,7 @@ import {Component, Vue} from 'vue-property-decorator'
export default class ShowCancelledJob extends Vue {
isLoading: boolean = false
job: any
job: any = null
loadJob() {
this.isLoading = true
......
<template>
<div>
<v-card class="mb-10" :loading="isLoading">
<v-card class="mb-10" :loading="isLoading" v-if="job">
<v-card-title>
<p class="text-h6 mb-0">{{ job.job_name }}</p>
</v-card-title>
......@@ -26,7 +26,7 @@
</v-card-text>
</v-card>
<v-card class="mb-10">
<v-card class="mb-10" :loading="isLoading" v-if="job">
<v-card-title>
<p class="text-h6 mb-0">Payload</p>
</v-card-title>
......@@ -37,7 +37,7 @@
</v-card-text>
</v-card>
<v-card class="mb-10">
<v-card class="mb-10" :loading="isLoading" v-if="job">
<v-card-title>
<p class="text-h6 mb-0">Stdout</p>
</v-card-title>
......@@ -48,7 +48,7 @@
</v-card-text>
</v-card>
<v-card class="mb-10">
<v-card class="mb-10" :loading="isLoading" v-if="job">
<v-card-title>
<p class="text-h6 mb-0">Stderr</p>
</v-card-title>
......@@ -59,7 +59,7 @@
</v-card-text>
</v-card>
<v-card class="mb-10">
<v-card class="mb-10" :loading="isLoading" v-if="job">
<v-card-title>
<p class="text-h6 mb-0">Exports</p>
</v-card-title>
......@@ -83,7 +83,7 @@ import {DataTableHeader} from 'vuetify'
export default class ShowCompletedJob extends Vue {
isLoading: boolean = false
job: any
job: any = null
headers: DataTableHeader[] = [
{
......
<template>
<div>
<v-card class="mb-10">
<v-card class="mb-10" :loading="isLoading" v-if="job">
<v-card-title>
<p class="text-h6 mb-0">{{ job.job_name }}</p>
<v-spacer></v-spacer>
......@@ -8,7 +8,7 @@
<template v-slot:activator="{ on, attrs }">
<v-btn @click="retryJob()" class="primary" depressed v-bind="attrs"
v-on="on">
<v-icon>mdi-reload</v-icon>
<v-icon>{{ mdiReload() }}</v-icon>
</v-btn>
</template>
<span>Click to retry</span>
......@@ -36,7 +36,7 @@
</v-card-text>
</v-card>
<v-card class="mb-10">
<v-card class="mb-10" :loading="isLoading" v-if="job">
<v-card-title>
<p class="text-h6 mb-0">Payload</p>
</v-card-title>
......@@ -47,7 +47,7 @@
</v-card-text>
</v-card>
<v-card class="mb-10">
<v-card class="mb-10" :loading="isLoading" v-if="job">
<v-card-title>
<p class="text-h6 mb-0">Stdout</p>
</v-card-title>
......@@ -58,7 +58,7 @@
</v-card-text>
</v-card>
<v-card class="mb-10">
<v-card class="mb-10" :loading="isLoading" v-if="job">
<v-card-title>
<p class="text-h6 mb-0">Stderr</p>
</v-card-title>
......@@ -74,12 +74,13 @@
<script lang="ts">
import 'reflect-metadata'
import {Component, Vue} from 'vue-property-decorator'
import { mdiReload } from '@mdi/js'
@Component
export default class ShowFailedJob extends Vue {
isLoading: boolean = false
job: any
job: any = null
loadJob() {
this.isLoading = true
......@@ -93,6 +94,10 @@ export default class ShowFailedJob extends Vue {
})
}
retryJob() {
// TODO: implement retry functionality
}
mounted() {
document.title = "LaravelCluster - Job Detail"
}
......@@ -100,6 +105,10 @@ export default class ShowFailedJob extends Vue {
created() {
this.loadJob()
}
mdiReload() {
return mdiReload
}
}
</script>
......
<template>
<div>
<v-card class="mb-10">
<v-card class="mb-10" v-if="job">
<v-card-title>
<p class="text-h6 mb-0">{{ job.job_name }}</p>
</v-card-title>
......@@ -22,7 +22,7 @@
</v-card-text>
</v-card>
<v-card class="mb-10">
<v-card class="mb-10" :loading="isLoading" v-if="job">
<v-card-title>
<p class="text-h6 mb-0">Payload</p>
</v-card-title>
......@@ -43,7 +43,7 @@ import {Component, Vue} from 'vue-property-decorator'
export default class ShowPendingJob extends Vue {
isLoading: boolean = false
job: any
job: any = null
loadJob() {
this.isLoading = true
......
<template>
<div>
test
</div>
</template>
<script lang="ts">
import 'reflect-metadata'
import {Component, Vue} from "vue-property-decorator";
@Component
export default class Test extends Vue {
mounted() {
console.log('test')
}
}
</script>
<style lang="scss" scoped>
</style>
import '@mdi/font/css/materialdesignicons.css'
import Vue from 'vue'
import vuetify from './vuetify';
import axios from "axios";
import Routes from './routes'
import VueRouter from "vue-router";
import ClusterLayout from "@/Layouts/ClusterLayout.vue";
import LaravelCluster from "@/LaravelCluster.vue";
let token: any = document.head.querySelector('meta[name="csrf-token"]');
......@@ -41,9 +40,10 @@ const router = new VueRouter({
base: routerBasePath,
});
const el: HTMLElement = document.getElementById('laravel-cluster') || document.createElement('laravel-cluster')
new Vue({
el: '#laravel-cluster',
components: { ClusterLayout },
router,
vuetify,
router
})
render: h => h(LaravelCluster)
}).$mount(el)
......@@ -43,7 +43,7 @@ const routes: RouteConfig[] = [
{
path: '/pending/:id',
name: 'pending-job-preview',
name: 'pending-jobs-preview',
component: ShowPendingJob
},
......@@ -55,7 +55,7 @@ const routes: RouteConfig[] = [
{
path: '/completed/:id',
name: 'completed-job-preview',
name: 'completed-jobs-preview',
component: ShowCompletedJob
},
......@@ -67,7 +67,7 @@ const routes: RouteConfig[] = [
{
path: '/failed/:id',
name: 'failed-job-preview',
name: 'failed-jobs-preview',
component: ShowFailedJob
},
......@@ -79,7 +79,7 @@ const routes: RouteConfig[] = [
{
path: '/cancelled/:id',
name: 'cancelled-job-preview',
name: 'cancelled-jobs-preview',
component: ShowCancelledJob
},
]
......
const Ziggy: {
url: string,
port?: number,
defaults: any,
routes: {
[key: string]: {
uri: string,
methods: string[],
bindings?: {
"clusterJob": "id"
}
}
}
} = {
"url": "http:\/\/localhost", "port": null, "defaults": {}, "routes": {
"cluster.": {"uri": "cluster", "methods": ["GET", "HEAD"]},
"cluster.dashboard": {"uri": "cluster\/dashboard", "methods": ["GET", "HEAD"]},
"cluster.inspector": {"uri": "cluster\/inspector", "methods": ["GET", "HEAD"]},
"cluster.queue": {"uri": "cluster\/queue", "methods": ["GET", "HEAD"]},
"cluster.pending": {"uri": "cluster\/pending", "methods": ["GET", "HEAD"]},
"cluster.pending.show": {
"uri": "cluster\/pending\/{clusterJob}",
"methods": ["GET", "HEAD"],
"bindings": {"clusterJob": "id"}
},
"cluster.completed": {"uri": "cluster\/completed", "methods": ["GET", "HEAD"]},
"cluster.completed.show": {
"uri": "cluster\/completed\/{clusterJob}",
"methods": ["GET", "HEAD"],
"bindings": {"clusterJob": "id"}
},
"cluster.failed": {"uri": "cluster\/failed", "methods": ["GET", "HEAD"]},
"cluster.failed.show": {
"uri": "cluster\/failed\/{clusterJob}",