Fucking navbar

This commit is contained in:
Fergal Moran
2020-09-11 17:21:58 +01:00
parent 1a9ef9fcf8
commit 57c34c3fee
18 changed files with 278 additions and 195 deletions

View File

@@ -1,55 +1,40 @@
module.exports = {
root: true,
env: {
node: true
node: true,
},
extends: [
'plugin:vue/essential',
'eslint:recommended',
'@vue/typescript/recommended'
],
extends: ['plugin:vue/essential', 'eslint:recommended', '@vue/typescript/recommended'],
parserOptions: {
ecmaVersion: 2020
ecmaVersion: 2020,
project: ['./tsconfig.json', './tsconfig.eslint.json'],
},
rules: {
/*
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
quotes: [2, 'single', { avoidEscape: true }],
'@typescript-eslint/quotes': [2, 'single', { avoidEscape: true }],
'prettier/prettier': 'error',
'max-len': [
'error',
{
'code': 80
}
], 'indent': [
'error',
2
]
*/
code: 120,
},
],
indent: [2, 4],
},
overrides: [
{
files: [
'**/__tests__/*.{j,t}s?(x)',
'**/tests/unit/**/*.spec.{j,t}s?(x)'
],
files: ['**/__tests__/*.{j,t}s?(x)', '**/tests/unit/**/*.spec.{j,t}s?(x)'],
env: {
mocha: true
}
mocha: true,
},
},
{
files: [
'**/__tests__/*.{j,t}s?(x)',
'**/tests/unit/**/*.spec.{j,t}s?(x)'
],
files: ['**/__tests__/*.{j,t}s?(x)', '**/tests/unit/**/*.spec.{j,t}s?(x)'],
env: {
mocha: true
}
}
]
mocha: true,
},
},
],
};

1
client/externals.d.ts vendored Normal file
View File

@@ -0,0 +1 @@
declare module 'vue-web-cam';

View File

@@ -1,7 +1,7 @@
<template>
<v-app id="bitchmin">
<TopBarNav v-if="isAuthenticated"/>
<SideBarNav v-if="isAuthenticated" />
<TopBarNav v-on:toggle-sidebar="drawerOpen = !drawerOpen" v-if="isAuthenticated" />
<SideBarNav v-if="isAuthenticated" v-model="drawerOpen" />
<v-main>
<v-container fluid>
<router-view></router-view>
@@ -25,6 +25,8 @@ import Footer from '@/components/Footer.vue'; // @ is an alias to /src
},
})
export default class App extends Vue {
drawerOpen = true;
async mounted() {
this.$store.dispatch('loadInitialState');
}

View File

@@ -1,12 +1,15 @@
<template>
<v-card outlined>
<template slot="progress">
<v-progress-linear color="deep-purple" height="10" indeterminate></v-progress-linear>
<v-progress-linear color="deep-purple" height="10" indeterminate>
</v-progress-linear>
</template>
<v-card-title>Existing records</v-card-title>
<v-card-text>
<v-row>
<v-alert type="error" v-if="errorMessage">{{errorMessage}}</v-alert>
<v-alert type="error" v-if="errorMessage">
{{errorMessage}}
</v-alert>
<v-simple-table>
<template v-slot:default>
<thead>
@@ -23,14 +26,21 @@
<td>{{host.ip}}</td>
<td>{{host.created_on | formatDate}}</td>
<td>
<v-btn-toggle dense background-color="pink" rounded>
<v-btn icon color="pink" @click="refreshRecord(host)">
<v-btn-toggle dense
background-color="pink"
rounded>
<v-btn icon color="pink"
@click="refreshRecord(host)">
<v-icon dark>mdi-refresh</v-icon>
</v-btn>
<v-btn icon color="pink" @click="verifyRecord(host)">
<v-btn icon
color="pink"
@click="verifyRecord(host)">
<v-icon dark>mdi-eye-check</v-icon>
</v-btn>
<v-btn icon color="pink" @click="deleteRecord(host)">
<v-btn icon
color="pink"
@click="deleteRecord(host)">
<v-icon dark>mdi-delete</v-icon>
</v-btn>
</v-btn-toggle>
@@ -45,9 +55,7 @@
</template>
<script lang="ts">
import {
Component, Prop, PropSync, Vue,
} from 'vue-property-decorator';
import { Component, PropSync, Vue } from 'vue-property-decorator';
import { dnsApi } from '@/api';
import { DnsRecord } from '@/models/dnsRecord';
import dayjs from 'dayjs';

View File

@@ -49,17 +49,20 @@ export default class DnsUpdateForm extends Vue {
hostNameRules = [
(v: string) => !!v || 'Host name is required',
(v: string) => (v && v.length < 253) || 'Hostname cannot exceed 253 characters',
(v: string) =>
(v && v.length < 253) || 'Hostname cannot exceed 253 characters',
];
ipAddress = '';
ipAddressRules = [
(v: string) => !!v || 'IP address is required',
(v: string) => /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/.test(
v,
(v: string) =>
/^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/.test(
v
) || 'Invalid IP Address',
(v: string) => (v && v.length < 16) || 'IP address cannot exceed 16 characters',
(v: string) =>
(v && v.length < 16) || 'IP address cannot exceed 16 characters',
];
@PropSync('inrecords')

View File

@@ -0,0 +1,47 @@
<template>
<div id="container">
<video id="video" width="640" height="480" autoplay></video>
<button id="snap"></button>
<canvas id="canvas" width="640" height="480"></canvas>
</div>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
@Component({
components: {},
})
export default class VideoTest extends Vue {
async mounted() {
console.log('VideoTest', 'mounted');
const video = document.getElementById('video') as HTMLVideoElement;
if (video !== null) {
if (navigator.mediaDevices.getUserMedia) {
navigator.mediaDevices
.getUserMedia({ video: true })
.then(function (stream) {
video.srcObject = stream;
})
.catch(function (err0r) {
console.log('Something went wrong!');
});
}
}
}
}
</script>
<style scoped=true>
#container {
margin: 0px auto;
width: 500px;
height: 375px;
border: 10px #333 solid;
}
#videoElement {
width: 500px;
height: 375px;
background-color: #666;
}
</style>

View File

@@ -1,5 +1,8 @@
<template>
<v-navigation-drawer v-model="drawer" app clipped color="grey lighten-4">
<v-navigation-drawer
v-bind:value="value"
v-on:input="$emit('input', $event)"
app clipped color="grey lighten-4">
<v-list dense class="grey lighten-4">
<template v-for="(item, i) in items">
<v-row v-if="item.heading" :key="i" align="center">
@@ -24,16 +27,18 @@
</v-navigation-drawer>
</template>
<script>
import { Component, Vue } from 'vue-property-decorator';
<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator';
@Component
export default class SideBarNav extends Vue {
drawer = null;
@Prop({ required: true, default: true })
value = true;
items = [
{ title: 'Debug', icon: 'mdi-bug', route: 'debug' },
{ title: 'DNS Config', icon: 'mdi-dns', route: 'bitchns' },
{ title: 'Media Stuff', icon: 'mdi-filmstrip', route: 'media' },
{ title: 'IP Tools', icon: 'mdi-ip', route: 'myip' },
{ title: 'JWT Decoder', icon: 'mdi-code-array', route: 'jwt' },
{ title: 'Lights', icon: 'mdi-lightbulb', route: 'lights' },

View File

@@ -1,6 +1,6 @@
<template>
<v-app-bar app clipped-left color="#90CAF9">
<v-app-bar-nav-icon @click="drawer = !drawer"></v-app-bar-nav-icon>
<v-app-bar-nav-icon @click="$emit('toggle-sidebar')"></v-app-bar-nav-icon>
<span class="title ml-3 mr-5">
Bitch&nbsp;
<span class="font-weight-light">Mints</span>
@@ -11,7 +11,7 @@
</v-btn>
</v-app-bar>
</template>
<script>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
@Component

View File

@@ -4,10 +4,12 @@ import store from '@/store';
import Home from '../views/Home.vue';
import Login from '../views/Login.vue';
import Lights from '../views/Lights.vue';
import About from '../views/About.vue';
import Debug from '../views/Debug.vue';
import BitchNS from '../views/BitchNS.vue';
import JwtDecoder from '../views/JwtDecoder.vue';
import MyIp from '../views/MyIp.vue';
import Media from '../views/Media.vue';
Vue.use(VueRouter);
@@ -28,6 +30,14 @@ const routes: Array<RouteConfig> = [
requiresAuth: false,
},
},
{
path: '/media',
name: 'Media',
component: Media,
meta: {
requiresAuth: false,
},
},
{
path: '/bitchns',
name: 'BitchNS',
@@ -66,7 +76,7 @@ const routes: Array<RouteConfig> = [
{
path: '/about',
name: 'About',
component: () => import(/* webpackChunkName: "about" */ '../views/About.vue'),
component: About,
meta: {
requiresAuth: true,
},

View File

@@ -9,16 +9,6 @@
</v-col>
</v-row>
</v-container>
<!-- <v-container fluid grid-list-xl>
<v-layout row wrap>
<v-flex sm4 xs4>
<DnsUpdateForm :inrecords="dnsRecords" />
</v-flex>
<v-flex d-flex lg4 sm6 xs12>
<DnsRecordsList :inrecords="dnsRecords" />
</v-flex>
</v-layout>
</v-container>-->
</template>
<script lang="ts">

0
client/src/views/CnsViwq Normal file
View File

View File

@@ -0,0 +1,17 @@
<template>
<div class="about">
<h1>Media Stuff</h1>
<VideoTest />
</div>
</template>
<script>
import { Component, Vue } from 'vue-property-decorator';
import VideoTest from '@/components/Media/VideoTest';
@Component({
components: {
VideoTest
}
})
export default class Media extends Vue{}
</script>

View File

@@ -0,0 +1,12 @@
{
"extends": "./tsconfig.json",
"include": [
".eslintrc.js",
"babel.config.js"
],
"compilerOptions": {
"allowJs": true,
"checkJs": true,
"noEmit": true
}
}

View File

@@ -10,6 +10,7 @@
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"noImplicitAny": false,
"sourceMap": true,
"baseUrl": ".",
"types": ["webpack-env", "mocha", "chai", "vuetify"],

View File

@@ -10,5 +10,5 @@ module.exports = {
},
configureWebpack: {
devtool: 'source-map'
}
},
};

View File

@@ -24,7 +24,7 @@ migrate = Migrate()
CELERY_TASK_LIST = [
'app.tasks.hosts',
]
import flask_monitoringdashboard as dashboard
def create_app(app_name='bitchmin', config_class=Config):
logger.info('Creating app {}'.format(app_name))

View File

@@ -26,7 +26,7 @@ def check_host_records():
except NoResultFound:
bind_state = BindState(
nameserver_1_ip=platform_ip,
nameserver_1_host=os.getenv('DNS_SERVER')
nameserver_1_host=os.getenv('DNSro_SERVER')
)
db.session.add(bind_state)
db.session.commit()

View File

@@ -18,4 +18,6 @@ flower
requests
IPy
pydig
tinder
twilio
flask_monitoringdashboard