initial commit
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"presets": ["es2015", "stage-2"],
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"extends": "standard",
|
||||
"plugins": [
|
||||
"html"
|
||||
],
|
||||
"env": {
|
||||
"jasmine": true
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
.DS_Store
|
||||
node_modules
|
||||
dist/build.js
|
||||
dist/build.css
|
||||
yarn-error.log
|
||||
npm-debug.log
|
||||
|
||||
# Editor directories and files
|
||||
.vscode
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
|
@ -0,0 +1,24 @@
|
|||
# vue-dashboard
|
||||
|
||||
> A Vue.js project with Kendo Vue wrappers
|
||||
|
||||
## Build Setup
|
||||
|
||||
``` bash
|
||||
# install dependencies
|
||||
npm install
|
||||
|
||||
# serve with hot reload at localhost:8080
|
||||
npm run dev
|
||||
|
||||
# build for production with minification
|
||||
npm run build
|
||||
|
||||
# lint all *.js and *.vue files
|
||||
npm run lint
|
||||
|
||||
# run unit tests
|
||||
npm test
|
||||
```
|
||||
|
||||
For more information see the [docs for vueify](https://github.com/vuejs/vueify).
|
После Ширина: | Высота: | Размер: 1.2 KiB |
После Ширина: | Высота: | Размер: 1.1 KiB |
После Ширина: | Высота: | Размер: 1.2 KiB |
После Ширина: | Высота: | Размер: 1.1 KiB |
После Ширина: | Высота: | Размер: 34 KiB |
После Ширина: | Высота: | Размер: 39 KiB |
После Ширина: | Высота: | Размер: 5.3 KiB |
|
@ -0,0 +1,15 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Kendo UI for Vue Dashboard Sample App</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" href="dist/build.css">
|
||||
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans" rel="stylesheet">
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script src="dist/build.js"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,63 @@
|
|||
{
|
||||
"name": "vue-dashboard",
|
||||
"version": "0.1.0",
|
||||
"description": "A Vue.js project with Kendo Vue wrappers",
|
||||
"author": "Progress",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"watchify": "watchify -vd -p browserify-hmr -e src/main.js -o dist/build.js",
|
||||
"serve": "http-server -o -c 1 -a localhost",
|
||||
"dev": "npm-run-all --parallel watchify serve",
|
||||
"lint": "eslint --ext .js,.vue src",
|
||||
"build": "cross-env NODE_ENV=production browserify -g envify -p [ vueify/plugins/extract-css -o dist/build.css ] -e src/main.js | uglifyjs -c warnings=false -m > dist/build.js"
|
||||
},
|
||||
"browserify": {
|
||||
"transform": [
|
||||
"babelify",
|
||||
"vueify"
|
||||
]
|
||||
},
|
||||
"browser": {
|
||||
"vue": "vue/dist/vue.common.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"vue": "2.5.2",
|
||||
"vue-router": "3.0.1",
|
||||
"jquery": "3.2.1",
|
||||
"@progress/kendo-ui": "2017.3.1018",
|
||||
"bootstrap": "git://github.com/twbs/bootstrap.git#95f37e4c402df37db16781995ffa1592032df9c8",
|
||||
"@progress/kendo-grid-vue-wrapper": "2017.3.1018",
|
||||
"@progress/kendo-datasource-vue-wrapper": "2017.3.1018",
|
||||
"@progress/kendo-buttons-vue-wrapper": "2017.3.1018",
|
||||
"@progress/kendo-theme-bootstrap": "^2.8.0",
|
||||
"@progress/kendo-theme-default": "^2.40.2",
|
||||
"marked": "^0.3.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"bootstrap": "git://github.com/twbs/bootstrap.git#95f37e4c402df37db16781995ffa1592032df9c8",
|
||||
"@progress/kendo-theme-bootstrap": "^2.8.0",
|
||||
"@progress/kendo-theme-default": "^2.40.2",
|
||||
"babel-core": "^6.0.0",
|
||||
"babel-plugin-transform-runtime": "^6.0.0",
|
||||
"babel-preset-es2015": "^6.0.0",
|
||||
"babel-preset-stage-2": "^6.0.0",
|
||||
"babel-runtime": "^6.0.0",
|
||||
"babelify": "^7.2.0",
|
||||
"browserify": "^13.1.0",
|
||||
"browserify-hmr": "^0.3.1",
|
||||
"cross-env": "^2.0.0",
|
||||
"envify": "^3.4.1",
|
||||
"eslint": "^3.3.0",
|
||||
"eslint-config-standard": "^5.3.5",
|
||||
"eslint-plugin-html": "^1.5.2",
|
||||
"eslint-plugin-promise": "^2.0.1",
|
||||
"eslint-plugin-standard": "^2.0.0",
|
||||
"http-server": "^0.9.0",
|
||||
"node-sass": "^4.5.3",
|
||||
"npm-run-all": "^2.3.0",
|
||||
"proxyquireify": "^3.0.1",
|
||||
"uglify-js": "^2.5.0",
|
||||
"vueify": "^9.0.0",
|
||||
"watchify": "^3.4.0"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
<template>
|
||||
<div id="app" class="app container-fluid">
|
||||
<main-menu></main-menu>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MainMenu from './components/MainMenu.vue'
|
||||
|
||||
export default {
|
||||
name: 'app',
|
||||
components: {
|
||||
MainMenu
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import "./shared/custom";
|
||||
@import './node_modules/bootstrap/scss/bootstrap';
|
||||
@import './node_modules/@progress/kendo-theme-bootstrap/scss/all';
|
||||
@import "./components/dashboard";
|
||||
|
||||
.container {
|
||||
margin:40px;
|
||||
}
|
||||
|
||||
html, body {
|
||||
height: 100%;
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
}
|
||||
|
||||
body {
|
||||
margin:0;
|
||||
}
|
||||
|
||||
span.active {
|
||||
background-color: gray;
|
||||
}
|
||||
|
||||
.col-xs {
|
||||
flex-basis: 0;
|
||||
flex-grow: 1;
|
||||
max-width: 100%
|
||||
}
|
||||
|
||||
.col-xs-12 {
|
||||
flex: 0 0 100%;
|
||||
}
|
||||
|
||||
.nav-toggle .k-i-hamburger {
|
||||
font-size: 32px;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,118 @@
|
|||
<template>
|
||||
<div>
|
||||
<div class="row mb-4">
|
||||
<div class="col-sm">
|
||||
<h2>
|
||||
<span class="small text-uppercase text-muted d-block">Statistics</span>
|
||||
{{ rangeStart.toDateString() }} - {{ today.toDateString() }}
|
||||
{{range}}
|
||||
</h2>
|
||||
|
||||
<kendo-grid :data-source="ghData" :sortable="true" :filterable="true" :pageable-refresh="true" :pageable-page-sizes="true"
|
||||
:pageable-button-count="5" :detail-template="detailTemplate">
|
||||
<kendo-grid-column field="number" title="ID" :width="100" :filterable="false" template="<a href='#: html_url #'>\##: number #</a>">
|
||||
</kendo-grid-column>
|
||||
<kendo-grid-column field="title" title="Title" :filterable="true" template="
|
||||
<span class='issue-status
|
||||
#if (state === 'open') {#
|
||||
issue-open
|
||||
# } else { #
|
||||
issue-closed
|
||||
# } #'></span>
|
||||
#:title#">
|
||||
</kendo-grid-column>
|
||||
<kendo-grid-column field="labels" title="Labels" :width="200" :filterable="false" template="
|
||||
#for (var i = 0; i < labels.length; i++) {#
|
||||
<span class='badge' style='background-color: #: getColor(labels[i].name) #'>#: labels[i].name #</span>
|
||||
#}#">
|
||||
</kendo-grid-column>
|
||||
<kendo-grid-column field="milestone" title="Milestone" :width="150" :filterable="false" template="#: milestone ? milestone.title : '' #">
|
||||
</kendo-grid-column>
|
||||
<kendo-grid-column field="assignee" title="Assignee" :width="150" :filterable="false" template="
|
||||
#if (assignee) { # <img src='#: assignee.avatar_url#'' style='width: 30px; height: 30px' class='img-circle' /> #}#
|
||||
#: assignee ? assignee.login : '' #">
|
||||
</kendo-grid-column>
|
||||
</kendo-grid>
|
||||
</div>
|
||||
<div class="col-sm text-sm-right">
|
||||
<kendo-buttongroup @select="onSelect" :index="selectedIndex">
|
||||
<kendo-buttongroup-button>3 Months</kendo-buttongroup-button>
|
||||
<kendo-buttongroup-button>6 Months</kendo-buttongroup-button>
|
||||
<kendo-buttongroup-button>1 Year</kendo-buttongroup-button>
|
||||
</kendo-buttongroup>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import IssuesDataSource from './IssuesDataSource.vue'
|
||||
export default {
|
||||
name: 'dashboard',
|
||||
created(){
|
||||
this.ghData = new kendo.data.DataSource({
|
||||
transport: {
|
||||
read: {
|
||||
url: 'https://api.github.com/repos/telerik/kendo-ui-core/issues',
|
||||
data: {
|
||||
state: 'all',
|
||||
page: 1,
|
||||
per_page: 100
|
||||
},
|
||||
beforeSend: function (req) {
|
||||
req.setRequestHeader('Authorization', 'token b95116792cba5a8169a1ec10640d8c16535c6419')
|
||||
}
|
||||
}
|
||||
},
|
||||
schema: {
|
||||
model: {
|
||||
fields: {
|
||||
created_at: { type: "Date" }
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
today: new Date(),
|
||||
selectedIndex: 0
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
months () {
|
||||
switch (this.selectedIndex) {
|
||||
case 0:
|
||||
return 3
|
||||
case 1:
|
||||
return 6
|
||||
case 2:
|
||||
return 12
|
||||
default:
|
||||
return 3
|
||||
}
|
||||
},
|
||||
rangeStart () {
|
||||
var since = new Date()
|
||||
since.setMonth(since.getMonth() - this.months)
|
||||
|
||||
return since
|
||||
},
|
||||
range () {
|
||||
return {
|
||||
start: this.rangeStart,
|
||||
end: this.today
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onSelect (ev) {
|
||||
this.selectedIndex = ev.index
|
||||
var today = new Date();
|
||||
var fd = new Date();
|
||||
fd.setDate(today.getDate() - 7);
|
||||
this.ghData.filter({ field: "created_at", operator: "gt", value: fd })
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,61 @@
|
|||
<template>
|
||||
<div id="hello">
|
||||
<img src="http://vuejs.org/images/logo.png">
|
||||
<h1>{{ msg }}</h1>
|
||||
<h2>Essential Links</h2>
|
||||
<ul>
|
||||
<li><a href="https://vuejs.org" target="_blank">Core Docs</a></li>
|
||||
<li><a href="https://forum.vuejs.org" target="_blank">Forum</a></li>
|
||||
<li><a href="https://gitter.im/vuejs/vue" target="_blank">Gitter Chat</a></li>
|
||||
<li><a href="https://twitter.com/vuejs" target="_blank">Twitter</a></li>
|
||||
</ul>
|
||||
<h2>Ecosystem</h2>
|
||||
<ul>
|
||||
<li><a href="http://router.vuejs.org/" target="_blank">vue-router</a></li>
|
||||
<li><a href="http://vuex.vuejs.org/" target="_blank">vuex</a></li>
|
||||
<li><a href="https://github.com/vuejs/vueify" target="_blank">vueify</a></li>
|
||||
<li><a href="https://github.com/vuejs/awesome-vue" target="_blank">awesome-vue</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'hello',
|
||||
data () {
|
||||
return {
|
||||
msg: 'Welcome to Your Vue.js App'
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
#hello {
|
||||
font-family: 'Avenir', Helvetica, Arial, sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
text-align: center;
|
||||
color: #2c3e50;
|
||||
margin-top: 60px;
|
||||
}
|
||||
|
||||
h1, h2 {
|
||||
font-weight: normal;
|
||||
color:red;
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
li {
|
||||
display: inline-block;
|
||||
margin: 0 10px;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #42b983;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,157 @@
|
|||
<template>
|
||||
<div class="issues">
|
||||
<issues-data-source ref="ghDataSourceComponent"
|
||||
url="https://api.github.com/repos/telerik/kendo-ui-core/issues"
|
||||
pagingSettings="{state: 'all', page: 1, per_page: 100}"
|
||||
pageSize="10">
|
||||
</issues-data-source>
|
||||
<kendo-grid ref="issuesGrid" :sortable="true" :filterable="true" :pageable-refresh="true" :pageable-page-sizes="true"
|
||||
:pageable-button-count="5" :detail-template="detailTemplate">
|
||||
<kendo-grid-column field="number" title="ID" :width="100" :filterable="false" template="<a href='#: html_url #'>\##: number #</a>">
|
||||
</kendo-grid-column>
|
||||
<kendo-grid-column field="title" title="Title" :filterable="true" template="
|
||||
<span class='issue-status
|
||||
#if (state === 'open') {#
|
||||
issue-open
|
||||
# } else { #
|
||||
issue-closed
|
||||
# } #'></span>
|
||||
#:title#">
|
||||
</kendo-grid-column>
|
||||
<kendo-grid-column field="labels" title="Labels" :width="200" :filterable="false" template="
|
||||
#for (var i = 0; i < labels.length; i++) {#
|
||||
<span class='badge' style='background-color: #: getColor(labels[i].name) #'>#: labels[i].name #</span>
|
||||
#}#">
|
||||
</kendo-grid-column>
|
||||
<kendo-grid-column field="milestone" title="Milestone" :width="150" :filterable="false" template="#: milestone ? milestone.title : '' #">
|
||||
</kendo-grid-column>
|
||||
<kendo-grid-column field="assignee" title="Assignee" :width="150" :filterable="false" template="
|
||||
#if (assignee) { # <img src='#: assignee.avatar_url#'' style='width: 30px; height: 30px' class='img-circle' /> #}#
|
||||
#: assignee ? assignee.login : '' #">
|
||||
</kendo-grid-column>
|
||||
</kendo-grid>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import marked from 'marked'
|
||||
import IssuesDataSource from './IssuesDataSource.vue'
|
||||
window.mdConverter = marked.setOptions({});
|
||||
|
||||
const DETAIL_TEMPLATE = `
|
||||
<div class="row my-4">
|
||||
<div class="col-sm-12">
|
||||
<span class="badge
|
||||
#if (state === 'open') {#
|
||||
badge-success
|
||||
#}#
|
||||
|
||||
#if (state === 'closed') {#
|
||||
badge-danger
|
||||
#}#
|
||||
">
|
||||
#: state #
|
||||
</span>
|
||||
<h3 class="h1">
|
||||
#: title #
|
||||
<span class="text-muted">\\##: number #</span>
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-4">
|
||||
<div class="col-sm-2">
|
||||
<span class="small d-block text-muted">Created on</span>
|
||||
#: (new Date(created_at)).toDateString() #
|
||||
</div>
|
||||
#if(closed_at){#
|
||||
<div class="col-sm-2">
|
||||
<span class="small d-block text-muted">Closed on</span>
|
||||
#: (new Date(closed_at)).toDateString() #
|
||||
</div>
|
||||
#}#
|
||||
<div class="col-sm-2">
|
||||
<span class="small d-block text-muted">Milestone</span>
|
||||
#: milestone ? milestone.title : '' #
|
||||
</div>
|
||||
<div class="col-sm-2">
|
||||
<span class="small d-block text-muted">Author</span>
|
||||
#: user.login #
|
||||
</div>
|
||||
#if(assignee){#
|
||||
<div class="col-sm-2">
|
||||
<span class="small d-block text-muted">Assignee</span>
|
||||
#if (assignee) { #
|
||||
<img src='#: assignee.avatar_url#'' style='width: 30px; height: 30px' class='img-circle' />
|
||||
#}#
|
||||
#: assignee ? assignee.login : '' #
|
||||
</div>
|
||||
#}#
|
||||
</div>
|
||||
<div class="row my-4">
|
||||
<div class="col-sm-2">
|
||||
<h4 class="small text-muted">Labels</h4>
|
||||
#for (var i = 0; i < labels.length; i++) {#
|
||||
<span class='badge' style='background-color: #: getColor(labels[i].name) #'>#: labels[i].name #</span>
|
||||
#}#
|
||||
</div>
|
||||
<div class="col-sm-8">
|
||||
<h4 class="small text-muted">Description</h4>
|
||||
<div>
|
||||
#= window.mdConverter.parse(body) #
|
||||
</div>
|
||||
</div>
|
||||
</div>`
|
||||
|
||||
/* global kendo */
|
||||
export default {
|
||||
name: 'issues',
|
||||
components: {IssuesDataSource},
|
||||
mounted(){
|
||||
this.ghData = this.$refs["ghDataSourceComponent"].ghData
|
||||
this.$refs["issuesGrid"].kendoWidget().setDataSource(this.ghData)
|
||||
},
|
||||
created() {
|
||||
this.detailTemplate = DETAIL_TEMPLATE;
|
||||
|
||||
//use :data-source="ghData" on the grid component if you use this approach
|
||||
//which does not allow code reuse for the data source component
|
||||
//with this, the mounted() code and the issues data source components are not needed
|
||||
// this.ghData = new kendo.data.DataSource({
|
||||
// pageSize: 10,
|
||||
// transport: {
|
||||
// read: {
|
||||
// url: 'https://api.github.com/repos/telerik/kendo-ui-core/issues',
|
||||
// data: {
|
||||
// state: 'all',
|
||||
// page: 1,
|
||||
// per_page: 100
|
||||
// },
|
||||
// beforeSend: function (req) {
|
||||
// req.setRequestHeader('Authorization', 'token b95116792cba5a8169a1ec10640d8c16535c6419')
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// })
|
||||
}
|
||||
}
|
||||
|
||||
window.getColor = (label) => {
|
||||
var colors = {
|
||||
'SEV: LOW': '#ff9800',
|
||||
'SEV: MEDIUM': '#ff5d2a',
|
||||
'SEV: HIGH': '#d50000',
|
||||
'ENHANCEMENT': '#00c853',
|
||||
'FEATURE': '#2e7d32',
|
||||
'OTHER': '#1ca8dd',
|
||||
'PASSED QA': '#57b45b',
|
||||
'BUG': '#cf3257',
|
||||
'NEEDS QA': '#bc007c',
|
||||
'DOCUMENTATION': '#455a64',
|
||||
'DEMO': '#673ab7',
|
||||
'DELETED': '#f44336',
|
||||
'IN PROGRESS': '#ffd600'
|
||||
}
|
||||
var color = colors[label.toUpperCase()] || colors.OTHER
|
||||
return color
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,24 @@
|
|||
<template>
|
||||
<div></div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'issues-data-source',
|
||||
props: ["url", "pagingSettings", "pageSize"],
|
||||
created () {
|
||||
this.ghData = new kendo.data.DataSource({
|
||||
pageSize: this.$props["pageSize"],
|
||||
transport: {
|
||||
read: {
|
||||
url: this.$props["url"],
|
||||
data: this.$props["pagingSettings"] || {} ,
|
||||
beforeSend: function (req) {
|
||||
req.setRequestHeader('Authorization', 'token b95116792cba5a8169a1ec10640d8c16535c6419')
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,56 @@
|
|||
<template>
|
||||
<div class="row">
|
||||
<div id="top-bar" class="top-bar col-xs-12 bg-inverse d-md-none"></div>
|
||||
<div id="nav"
|
||||
class="col-xs-3 bg-inverse text-white py-5 k-vbox"
|
||||
v-if="this.$route.path !== '/signout'"
|
||||
:class="{expand: navState}">
|
||||
<span id="nav-toggle" class="nav-toggle d-md-none" @click="navState = !navState">
|
||||
<span class="k-icon k-i-hamburger"></span>
|
||||
</span>
|
||||
<h1 id="app-title">Issues</h1>
|
||||
<p id="app-subtitle">Sample Dashboard</p>
|
||||
<hr />
|
||||
<p class="h4 mt-5">Project</p>
|
||||
<ul class="nav nav-pills flex-column">
|
||||
<li class="nav-item" id="dashbaord">
|
||||
<router-link to="/dashboard" class="nav-link">Dashboard</router-link>
|
||||
</li>
|
||||
<li class="nav-item" id="issues">
|
||||
<router-link to="/issues" class="nav-link">Issues</router-link>
|
||||
</li>
|
||||
</ul>
|
||||
<p class="h4 mt-5">Account</p>
|
||||
<ul class="nav nav-pills flex-column">
|
||||
<li class="nav-item" id="profile">
|
||||
<router-link to="/profile" class="nav-link">My Profile</router-link>
|
||||
</li>
|
||||
<li class="nav-item" id="signout">
|
||||
<router-link to="/signout" class="nav-link">Sign Out</router-link>
|
||||
</li>
|
||||
</ul>
|
||||
<hr class="k-flex" />
|
||||
<div id="copy">
|
||||
<p>Copyright © {{year}},<br /><a href="http://www.progress.com">Progress Software Corporation</a> and/or its subsidiaries or affiliates.</p>
|
||||
<p>All Rights Reserved.</p>
|
||||
</div>
|
||||
</div>
|
||||
<main class="col-xs p-4 py-5">
|
||||
<router-view></router-view>
|
||||
</main>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'main-menu',
|
||||
data () {
|
||||
return {
|
||||
year: '2017',
|
||||
transformValue: 'translateX(0)',
|
||||
navState: false
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
@ -0,0 +1,323 @@
|
|||
// Common
|
||||
.k-hbox,
|
||||
.k-vbox {
|
||||
display: flex;
|
||||
}
|
||||
.k-ihbox,
|
||||
.k-ivbox {
|
||||
display: inline-flex;
|
||||
}
|
||||
.k-hbox,
|
||||
.k-ihbox {
|
||||
flex-direction: row;
|
||||
}
|
||||
.k-vbox,
|
||||
.k-ivbox {
|
||||
flex-direction: column;
|
||||
}
|
||||
.k-flex,
|
||||
.k-spacer {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
|
||||
// Undo
|
||||
.k-widget .row,
|
||||
.k-widget [class^="col-"] {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
html .k-widget,
|
||||
html .k-tabstrip .k-content {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.k-chart {
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Ng
|
||||
kendo-tabstrip {
|
||||
position: relative;
|
||||
display: block;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// App
|
||||
#app {
|
||||
display: block;
|
||||
|
||||
> .row {
|
||||
min-height: 100vh;
|
||||
align-items: stretch;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Nav
|
||||
#nav {
|
||||
padding-left: $grid-gutter-width * 1.5;
|
||||
padding-right: $grid-gutter-width * 1.5;
|
||||
width: 320px;
|
||||
box-sizing: border-box;
|
||||
flex-basis: auto;
|
||||
flex-grow: 0;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
transform: translateX(0);
|
||||
|
||||
#app-title { position: relative; }
|
||||
#app-title::after {
|
||||
content: "";
|
||||
width: $spacer * 1.5;
|
||||
border-bottom: 2px solid $brand-primary;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: $font-size-h1 + $font-size-h2 + ( $spacer * 1.5 );
|
||||
}
|
||||
|
||||
hr { border: 0; }
|
||||
.h4 {
|
||||
font-size: $font-size-xs;
|
||||
font-weight: 400;
|
||||
text-transform: uppercase;
|
||||
opacity: .3;
|
||||
}
|
||||
|
||||
.nav-pills {
|
||||
margin-left: -( $grid-gutter-width * 1.5 );
|
||||
margin-right: -( $grid-gutter-width * 1.5 );
|
||||
font-size: 1.125rem;
|
||||
}
|
||||
.nav-pills .nav-link {
|
||||
padding-left: $grid-gutter-width * 1.5;
|
||||
padding-right: $grid-gutter-width * 1.5;
|
||||
}
|
||||
.nav-pills .nav-link:not(.active) {
|
||||
color: inherit;
|
||||
}
|
||||
}
|
||||
#app-title {
|
||||
margin: 0;
|
||||
font-weight: normal;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
#app-subtitle {
|
||||
margin: 0;
|
||||
font-size: $font-size-xs;
|
||||
font-weight: 100;
|
||||
text-transform: uppercase;
|
||||
opacity: .75;
|
||||
}
|
||||
#copy {
|
||||
color: #9195a2;
|
||||
font-size: $font-size-sm;
|
||||
position: relative;
|
||||
}
|
||||
#copy::after {
|
||||
content: "";
|
||||
width: $spacer * 1.5;
|
||||
border-top: 2px solid;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: -( $spacer * 1.5 );
|
||||
}
|
||||
|
||||
.top-bar {
|
||||
padding: .25em;
|
||||
font-size: 32px;
|
||||
line-height: 1;
|
||||
|
||||
&:before { content: "."; display: block; }
|
||||
}
|
||||
.nav-toggle {
|
||||
padding: .25em;
|
||||
background: inherit;
|
||||
font-size: 32px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: absolute;
|
||||
z-index: 1000;
|
||||
top: 0;
|
||||
left: 100%;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@media (max-width: map-get($grid-breakpoints, md) ) {
|
||||
#nav {
|
||||
width: 320px;
|
||||
max-width: none;
|
||||
transform: translateX(-100%);
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
box-shadow: 0 $spacer $spacer rgba( $brand-inverse, .5 );
|
||||
}
|
||||
|
||||
#nav.expand {
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Main
|
||||
main {
|
||||
overflow: auto;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
|
||||
|
||||
// Cards
|
||||
.card {}
|
||||
.card .card-header {}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Dashboard
|
||||
.dashboard {
|
||||
display: block;
|
||||
|
||||
|
||||
.card {
|
||||
margin-top: $spacer * 1.5;
|
||||
}
|
||||
.card-block {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
|
||||
.k-tabstrip {
|
||||
background: none;
|
||||
}
|
||||
.k-tabstrip .k-tabstrip-items {
|
||||
position: absolute;
|
||||
top: calc( 1.75em + 2px );
|
||||
right: 0;
|
||||
z-index: 2;
|
||||
}
|
||||
.k-tabstrip .k-content {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
background: none;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
|
||||
.comp-label {
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
|
||||
strong {
|
||||
font-size: 4em;
|
||||
line-height: 1;
|
||||
font-weight: 100;
|
||||
display: block;
|
||||
}
|
||||
small {
|
||||
font-size: .875em;
|
||||
text-transform: uppercase;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
a {
|
||||
-webkit-user-select: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
||||
.active-issues {}
|
||||
.closed-issues {}
|
||||
.open-issues {}
|
||||
.close-rate {
|
||||
.k-chart {
|
||||
padding-top: 6px;
|
||||
}
|
||||
}
|
||||
|
||||
.issue-types {
|
||||
overflow: hidden;
|
||||
}
|
||||
.issue-types .card-block {
|
||||
max-width: 100%;
|
||||
margin: auto;
|
||||
}
|
||||
.issue-types .chart-label {
|
||||
margin: -1em 0 0;
|
||||
white-space: nowrap;
|
||||
text-align: center;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Issues
|
||||
.issues {
|
||||
display: block;
|
||||
|
||||
|
||||
.badge {
|
||||
margin-right: .5em;
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.issue-status {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
.issue-open { background-image: url( "assets/issue-open.png" ) }
|
||||
.issue-closed { background-image: url( "assets/issue-closed.png" ) }
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Signin
|
||||
.signin {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
box-sizing: border-box;
|
||||
color: #ffffff;
|
||||
background-color: #111111;
|
||||
background-image: url( "assets/login-left-bg.png" ), url( "assets/login-right-bg.png" );
|
||||
background-position: left center, right bottom;
|
||||
background-repeat: no-repeat;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
#app-title { font-size: 4em; }
|
||||
#app-subtitle { font-size: 1em; }
|
||||
}
|
||||
.signin-form {
|
||||
width: 360px;
|
||||
background-color: inherit;
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
// The following line loads the standalone build of Vue instead of the runtime-only build,
|
||||
// so you don't have to do: import Vue from 'vue/dist/vue'
|
||||
// This is done with the browser options. For the config, see package.json
|
||||
import Vue from 'vue'
|
||||
import Router from 'vue-router'
|
||||
import App from './App.vue'
|
||||
import Dashboard from './components/Dashboard.vue'
|
||||
import Issues from './components/Issues.vue'
|
||||
|
||||
import '@progress/kendo-ui'
|
||||
import { KendoButtonGroup, KendoButtonsInstaller } from '@progress/kendo-buttons-vue-wrapper'
|
||||
import { KendoDataSource, KendoDataSourceInstaller } from '@progress/kendo-datasource-vue-wrapper'
|
||||
import { KendoGrid, KendoGridInstaller } from '@progress/kendo-grid-vue-wrapper'
|
||||
|
||||
Vue.use(Router)
|
||||
Vue.use(KendoButtonsInstaller)
|
||||
Vue.use(KendoGridInstaller)
|
||||
Vue.use(KendoDataSourceInstaller)
|
||||
|
||||
const routes = [
|
||||
{ path: '/', component: Dashboard },
|
||||
{ path: '/dashboard', component: Dashboard },
|
||||
{ path: '/issues', component: Issues },
|
||||
{ path: '/profile', component: Issues },
|
||||
{ path: '/signout', component: Issues }
|
||||
]
|
||||
|
||||
const router = new Router({
|
||||
routes,
|
||||
linkActiveClass: 'active'
|
||||
})
|
||||
|
||||
new Vue({ // eslint-disable-line no-new
|
||||
el: '#app',
|
||||
render: (h) => h(App),
|
||||
router,
|
||||
components: {
|
||||
KendoButtonGroup,
|
||||
KendoDataSource,
|
||||
KendoGrid
|
||||
}
|
||||
})
|
|
@ -0,0 +1,106 @@
|
|||
// Options
|
||||
//
|
||||
// Quickly modify global styling by enabling or disabling optional features.
|
||||
|
||||
$enable-flex: true;
|
||||
$enable-rounded: true;
|
||||
$enable-shadows: false;
|
||||
$enable-gradients: false;
|
||||
$enable-transitions: false;
|
||||
$enable-hover-media-query: false;
|
||||
$enable-grid-classes: true;
|
||||
$enable-print-styles: false;
|
||||
|
||||
|
||||
|
||||
|
||||
// Grid columns
|
||||
//
|
||||
// Set the number of columns and specify the width of the gutters.
|
||||
|
||||
$grid-columns: 12;
|
||||
$grid-gutter-width: 20px;
|
||||
|
||||
|
||||
|
||||
|
||||
// Colors
|
||||
//
|
||||
// Grayscale and brand colors for use across Bootstrap.
|
||||
|
||||
$gray-dark: #252830;
|
||||
$gray: #55595c;
|
||||
$gray-light: #818a91;
|
||||
$gray-lighter: #eceeef;
|
||||
$gray-lightest: #f7f7f9;
|
||||
|
||||
$brand-primary: #1ca8dd;
|
||||
$brand-success: #27c46d;
|
||||
$brand-info: #52c3d3;
|
||||
$brand-warning: #ff9966;
|
||||
$brand-danger: #cf3257;
|
||||
$brand-inverse: $gray-dark;
|
||||
|
||||
|
||||
|
||||
|
||||
// Typography
|
||||
//
|
||||
// Font, line-height, and color for body text, headings, and more.
|
||||
|
||||
$font-family-sans-serif: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
||||
$font-family-serif: Georgia, "Times New Roman", Times, serif;
|
||||
$font-family-monospace: Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
||||
$font-family-base: $font-family-sans-serif;
|
||||
|
||||
// Pixel value used to responsively scale all typography. Applied to the `<html>` element.
|
||||
$font-size-root: 14px;
|
||||
|
||||
$font-size-base: 1rem;
|
||||
$font-size-lg: 1.25rem;
|
||||
$font-size-sm: .875rem;
|
||||
$font-size-xs: .75rem;
|
||||
|
||||
$line-height-base: 1.5;
|
||||
|
||||
$font-size-h1: 1.75rem;
|
||||
$font-size-h2: 1.25rem;
|
||||
$font-size-h3: 1.25rem;
|
||||
$font-size-h4: 1.25rem;
|
||||
$font-size-h5: 1.25rem;
|
||||
$font-size-h6: 1rem;
|
||||
|
||||
|
||||
|
||||
|
||||
// Body
|
||||
//
|
||||
// Settings for the `<body>` element.
|
||||
|
||||
$body-bg: #fbfbfb;
|
||||
$body-color: $gray-dark;
|
||||
|
||||
|
||||
// Components
|
||||
//
|
||||
// Define common padding and border radius sizes and more.
|
||||
|
||||
$component-active-color: #fff;
|
||||
$component-active-bg: $brand-primary;
|
||||
|
||||
|
||||
// Navs
|
||||
|
||||
$nav-pills-border-radius: 0;
|
||||
$nav-pills-active-link-color: #111111;
|
||||
$nav-pills-active-link-bg: $component-active-bg;
|
||||
|
||||
|
||||
// Cards
|
||||
|
||||
$card-spacer-x: 1.25rem;
|
||||
$card-spacer-y: .75rem;
|
||||
$card-border-width: 1px;
|
||||
$card-border-color: #e8e8e8;
|
||||
$card-cap-bg: #ffffff;
|
||||
$card-bg: #fff;
|