updated to vue3

initial work on more reactive EventSource wrapper
This commit is contained in:
2021-05-15 22:43:06 +00:00
parent fdbd14a2b2
commit 7b26672963
14 changed files with 2144 additions and 1531 deletions
+1938 -1352
View File
File diff suppressed because it is too large Load Diff
+11 -12
View File
@@ -9,21 +9,20 @@
}, },
"dependencies": { "dependencies": {
"bulma": "^0.9.2", "bulma": "^0.9.2",
"core-js": "^3.12.0", "core-js": "^3.6.5",
"vue": "^2.6.12", "vue": "^3.0.0",
"vue-router": "^3.5.1" "vue-router": "^4.0.8"
}, },
"devDependencies": { "devDependencies": {
"@vue/cli-plugin-babel": "~4.4.0", "@vue/cli-plugin-babel": "~4.5.0",
"@vue/cli-plugin-eslint": "~4.4.0", "@vue/cli-plugin-eslint": "~4.5.0",
"@vue/cli-plugin-router": "^4.5.13", "@vue/cli-service": "~4.5.0",
"@vue/cli-service": "^4.5.13", "@vue/compiler-sfc": "^3.0.0",
"babel-eslint": "^10.1.0", "babel-eslint": "^10.1.0",
"eslint": "^6.7.2", "eslint": "^6.7.2",
"eslint-plugin-vue": "^6.2.2", "eslint-plugin-vue": "^7.0.0",
"node-sass": "^4.14.1", "node-sass": "^6.0.0",
"sass-loader": "^9.0.3", "sass-loader": "^10.0.0"
"vue-template-compiler": "^2.6.12"
}, },
"eslintConfig": { "eslintConfig": {
"root": true, "root": true,
@@ -31,7 +30,7 @@
"node": true "node": true
}, },
"extends": [ "extends": [
"plugin:vue/essential", "plugin:vue/vue3-essential",
"eslint:recommended" "eslint:recommended"
], ],
"parserOptions": { "parserOptions": {
+22 -8
View File
@@ -1,18 +1,16 @@
<template> <template>
<div id="app"> <div>
<nav class="navbar" role="navigation" aria-label="main navigation"> <nav class="navbar" role="navigation" aria-label="main navigation">
<div class="container"> <div class="container">
<div class="navbar-brand"> <div class="navbar-brand">
<a class="navbar-item" href="https://bulma.io"> <router-link class="navbar-item" to="/">Home</router-link>
<img src="https://bulma.io/images/bulma-logo.png" width="112" height="28" />
</a>
<a <a
role="button" role="button"
class="navbar-burger burger" class="navbar-burger burger"
aria-label="menu" aria-label="menu"
aria-expanded="false" aria-expanded="false"
data-target="navbarBasicExample" data-target="navbar"
> >
<span aria-hidden="true"></span> <span aria-hidden="true"></span>
<span aria-hidden="true"></span> <span aria-hidden="true"></span>
@@ -20,14 +18,30 @@
</a> </a>
</div> </div>
<div id="navbarBasicExample" class="navbar-menu"> <div id="navbar" class="navbar-menu">
<div class="navbar-start"> <div class="navbar-start">
<a class="navbar-item">Home</a> <router-link class="navbar-item" to="/connect/blubber">
Connect
</router-link>
<router-link class="navbar-item" to="/about">About</router-link>
</div>
<div class="navbar-end">
<router-view name="navbar" />
</div> </div>
<div class="navbar-end"></div>
</div> </div>
</div> </div>
</nav> </nav>
<div class="container">
<router-view /> <router-view />
</div> </div>
</div>
</template> </template>
<script>
export default {
name: "App",
};
</script>
<style>
</style>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

+7 -3
View File
@@ -1,7 +1,11 @@
@import "~bulma/sass/utilities/initial-variables"; @import "~bulma/sass/utilities/initial-variables";
$scheme-main: $black-ter; //$scheme-main: $black-ter;
$scheme-invert: $white-ter; //$scheme-invert: $white-ter;
$text: $grey-lightest; //$text: $grey-lightest;
@import "~bulma/bulma"; @import "~bulma/bulma";
.navbar-item .notification {
padding: inherit;
}
+12 -10
View File
@@ -1,23 +1,25 @@
<template> <template>
<div class="notification" v-bind:class="active ? 'is-success' : 'is-danger'"> <div class="navbar-item">
<span v-if="active">Connected as {{ channel }}</span> <div class="notification" :class="{'is-success': test.connected, 'is-danger': !test.connected && !test.reconnecting, 'is-warning': test.reconnecting}">
<span v-if="test.connected">Connected as {{ hash }}</span>
<span v-else-if="test.reconnecting">Reconnecting</span>
<span v-else>Disconnected</span> <span v-else>Disconnected</span>
</div> </div>
</div>
</template> </template>
<script> <script>
import eventSource from "@/eventsource"; import { getEventSourceInstance } from "@/eventsource";
export default { export default {
name: "Connection", name: "Connection",
computed: {
active() {
return eventSource.isConnected()
},
},
props: { props: {
channel: String, hash: String
},
data() {
return {
test: getEventSourceInstance("/feed/updates/" + this.hash).connectionStatus
};
}, },
}; };
</script> </script>
-14
View File
@@ -1,14 +0,0 @@
<template>
<div class="hello">
<h1>{{ msg }}</h1>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
props: {
msg: String
}
}
</script>
+71 -48
View File
@@ -1,56 +1,79 @@
import store from "../store" //import store from "@/store"
import handler from './handlers' //import handler from './handlers'
import { reactive } from "vue";
var connection = null let eventSources = {};
var onOpenCallback = null
var onCloseCallback = null
const eventSource = { const createEventSource = (url, callbacks) => {
connect(channel) {
if(connection != null) { let connection = null
let backoffSeconds = 1
let connectionStatus = reactive({
connected: false,
reconnecting: false,
})
let eventSource = {
open() {
if (connection === null) {
connection = new EventSource(url)
connection.addEventListener('message', (message) => {
if (typeof callbacks.onMessage === 'function') {
callbacks.onMessage(message)
}
})
connection.addEventListener('open', () => {
connectionStatus.connected = true
connectionStatus.reconnecting = false
backoffSeconds = 1
if (typeof callbacks.onOpen === 'function') {
callbacks.onOpen()
}
})
connection.addEventListener('error', () => {
connectionStatus.connected = false
connectionStatus.reconnecting = true
connection.close()
connection = null
setTimeout(this.open.bind(this), backoffSeconds * 1000)
if (backoffSeconds < 128) {
backoffSeconds *= 2
}
})
}
},
close() {
if (connection !== null) {
connectionStatus.connected = false
connectionStatus.reconnecting = false
connection.close(); connection.close();
connection = null
if (typeof callbacks.onClose === 'function') {
callbacks.onClose();
}
}
}
} }
connection = new EventSource('/feed/updates/' + channel) Object.defineProperty(eventSource, 'connectionStatus', {
get: function () {
return connectionStatus
}
});
connection.addEventListener("message", function(message) { return eventSource
var data = JSON.parse(message.data)
handler.handle(data)
store.setRawMessageAction(message.data)
})
connection.addEventListener("open", function () {
if(typeof onOpenCallback === 'function') {
onOpenCallback()
}
})
connection.addEventListener("close", function () {
if(typeof onCloseCallback === 'function') {
onCloseCallback()
}
})
connection.addEventListener("error", function () {
if(connection.readyState !== EventSource.CONNECTING) {
if(typeof onCloseCallback === 'function') {
onCloseCallback()
}
}
})
},
isConnected() {
return connection.readyState === EventSource.OPEN
},
isConnecting() {
return connection.readyState === EventSource.CONNECTING
},
onOpen(callback) {
onOpenCallback = callback
},
onClose(callback) {
onCloseCallback = callback
}
} }
export default eventSource const getEventSourceInstance = (url, callbacks = {}) => {
if (!eventSources[url]) {
let eventSource = createEventSource(url, callbacks)
eventSources[url] = eventSource
}
return eventSources[url];
}
export { getEventSourceInstance }
+4 -11
View File
@@ -1,17 +1,10 @@
import Vue from 'vue' import { createApp } from 'vue'
import VueRouter from 'vue-router'
import App from './App.vue' import App from './App.vue'
import store from './store' import store from './store'
import router from './router' import router from './router'
import './assets/main.scss' import './assets/main.scss'
Vue.config.productionTip = false createApp(App, store.state)
.use(router)
Vue.use(VueRouter) .mount('#app')
new Vue({
data: store.state,
router,
render: h => h(App)
}).$mount('#app')
+33 -19
View File
@@ -1,27 +1,41 @@
import Vue from 'vue' import { createWebHashHistory , createRouter } from 'vue-router';
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
Vue.use(VueRouter) import Home from '@/views/Home.vue';
import Connect from '@/views/Connect.vue';
import Connection from '@/components/Connection.vue';
import About from '@/views/About.vue';
import NotFound from '@/views/NotFound.vue';
const routes = [ const routes = [
{ {
path: '/:channel?', path: "/",
name: 'Home', name: "Home",
component: Home component: Home
},
{
path: "/connect/:hash",
name: "Connect",
components: {
default: Connect,
"navbar": Connection
},
props: true
},
{
path: "/about",
name: "About",
component: About
},
{
path: "/:catchall(.*)",
component: NotFound
} }
// { ];
// path: '/about',
// name: 'About',
// // route level code-splitting
// // this generates a separate chunk (about.[hash].js) for this route
// // which is lazy-loaded when the route is visited.
// component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
// }
]
const router = new VueRouter({ const router = createRouter({
history: createWebHashHistory(),
linkActiveClass: "is-active",
routes routes
}) });
export default router export default router;
+3
View File
@@ -0,0 +1,3 @@
<template>
<h1>About Page</h1>
</template>
+44
View File
@@ -0,0 +1,44 @@
<template>
<div>
<h1>Connect Page - {{ hash }}</h1>
<button v-on:click="disconnect">Disconnect</button>
<button v-on:click="connect">Connect</button>
</div>
</template>
<script>
import { getEventSourceInstance } from "@/eventsource";
import store from '@/store'
export default {
props: {
hash: String,
},
data() {
return {
currentChannel: this.hash,
};
},
created() {
this.$data.blumm = getEventSourceInstance("/feed/updates/" + this.hash, {
onOpen: () => {
store.setConnectedAction(true)
},
onClose: () => {
store.setConnectedAction(false)
},
});
if (!this.$data.blumm.isOpen) {
this.$data.blumm.open();
}
},
methods: {
disconnect() {
this.$data.blumm.close();
},
connect() {
this.$data.blumm.open();
},
},
};
</script>
+1 -59
View File
@@ -1,61 +1,3 @@
<template> <template>
<div class="home"> <h1>Home Page</h1>
<Connection v-bind:active="active" v-bind:channel="currentChannel" />
<HelloWorld v-bind:msg="message" />
<div>
Credits: {{ credits }}
</div>
</div>
</template> </template>
<script>
// @ is an alias to /src
import HelloWorld from "@/components/HelloWorld.vue";
import Connection from "@/components/Connection.vue";
import eventSource from "@/eventsource";
var connect = function (channel) {
if (channel != "undefined" && channel != data.currentChannel) {
data.currentChannel = channel;
eventSource.connect(channel);
}
};
var data = {
active: false,
currentChannel: "",
};
export default {
name: "Home",
data() {
return data;
},
computed: {
message() {
return this.$root.message;
},
credits() {
return this.$root.credits;
}
},
watch: {
$route(to) {
connect(to.params.channel);
},
},
created() {
eventSource.onOpen(function () {
data.active = true;
});
eventSource.onClose(function () {
data.active = false;
});
connect(this.$route.params.channel);
},
components: {
HelloWorld,
Connection,
},
};
</script>
+3
View File
@@ -0,0 +1,3 @@
<template>
<h1>404</h1>
</template>