We are doing connections now!
This commit is contained in:
parent
05b253a2a2
commit
035dec73dc
13 changed files with 222 additions and 79 deletions
|
@ -1,29 +1,7 @@
|
||||||
# webclient
|
# webclient
|
||||||
|
|
||||||
## Project setup
|
Web-client for browsing, creating and joining rooms on Cardgage servers
|
||||||
```
|
|
||||||
yarn install
|
|
||||||
```
|
|
||||||
|
|
||||||
### Compiles and hot-reloads for development
|
### Shoutouts
|
||||||
```
|
|
||||||
yarn run serve
|
|
||||||
```
|
|
||||||
|
|
||||||
### Compiles and minifies for production
|
- Dark theme by [bulmaswatch/Jenil Gogari](https://github.com/jenil/bulmaswatch)
|
||||||
```
|
|
||||||
yarn run build
|
|
||||||
```
|
|
||||||
|
|
||||||
### Run your tests
|
|
||||||
```
|
|
||||||
yarn run test
|
|
||||||
```
|
|
||||||
|
|
||||||
### Lints and fixes files
|
|
||||||
```
|
|
||||||
yarn run lint
|
|
||||||
```
|
|
||||||
|
|
||||||
### Customize configuration
|
|
||||||
See [Configuration Reference](https://cli.vuejs.org/config/).
|
|
||||||
|
|
|
@ -13,7 +13,8 @@
|
||||||
"vue": "^2.6.10",
|
"vue": "^2.6.10",
|
||||||
"vue-class-component": "^7.0.2",
|
"vue-class-component": "^7.0.2",
|
||||||
"vue-property-decorator": "^8.1.0",
|
"vue-property-decorator": "^8.1.0",
|
||||||
"vuex": "^3.0.1"
|
"vuex": "^3.0.1",
|
||||||
|
"vuex-class": "^0.3.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@vue/cli-plugin-babel": "^4.0.0-alpha.1",
|
"@vue/cli-plugin-babel": "^4.0.0-alpha.1",
|
||||||
|
|
|
@ -1,16 +1,22 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8" />
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
|
||||||
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
|
<link rel="icon" href="<%= BASE_URL %>favicon.ico" />
|
||||||
<link rel="stylesheet" href="//cdn.materialdesignicons.com/2.0.46/css/materialdesignicons.min.css">
|
<link
|
||||||
<title>webclient</title>
|
rel="stylesheet"
|
||||||
|
href="//cdn.materialdesignicons.com/2.0.46/css/materialdesignicons.min.css"
|
||||||
|
/>
|
||||||
|
<title>Cardgage Web Client</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<noscript>
|
<noscript>
|
||||||
<strong>We're sorry but webclient doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
|
<strong
|
||||||
|
>We're sorry but webclient doesn't work properly without
|
||||||
|
JavaScript enabled. Please enable it to continue.</strong
|
||||||
|
>
|
||||||
</noscript>
|
</noscript>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
<!-- built files will be auto injected -->
|
<!-- built files will be auto injected -->
|
||||||
|
|
|
@ -1,12 +1,47 @@
|
||||||
<template>
|
<template>
|
||||||
<div id="app"></div>
|
<div id="app">
|
||||||
|
<section class="hero">
|
||||||
|
<div class="hero-body">
|
||||||
|
<div class="container">
|
||||||
|
<h1 class="title">{{ title }}</h1>
|
||||||
|
<h2 class="subtitle">{{ subtitle }}</h2>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<div class="container">
|
||||||
|
<ConnectForm v-if="!isConnected" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Component, Vue } from "vue-property-decorator";
|
import { Component, Vue } from "vue-property-decorator";
|
||||||
|
import { State } from "vuex-class";
|
||||||
|
import ConnectForm from "@/components/ConnectForm.vue";
|
||||||
|
import RoomList from "@/components/RoomList.vue";
|
||||||
|
import { ServerState } from "./store/server";
|
||||||
|
|
||||||
@Component({})
|
@Component({
|
||||||
export default class App extends Vue {}
|
components: {
|
||||||
|
ConnectForm,
|
||||||
|
RoomList
|
||||||
|
}
|
||||||
|
})
|
||||||
|
export default class App extends Vue {
|
||||||
|
@State("server") private server!: ServerState;
|
||||||
|
|
||||||
|
private title!: string;
|
||||||
|
private subtitle!: string;
|
||||||
|
|
||||||
|
private data() {
|
||||||
|
return {
|
||||||
|
title: "Cardgage web client",
|
||||||
|
subtitle: ""
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private get isConnected() {
|
||||||
|
return this.server.connected;
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss"></style>
|
|
||||||
|
|
0
webclient/src/assets/scss/_overrides.scss
Normal file
0
webclient/src/assets/scss/_overrides.scss
Normal file
|
@ -1,37 +1,10 @@
|
||||||
@import "~bulma/sass/utilities/initial-variables";
|
@import "~bulma/sass/utilities/initial-variables";
|
||||||
@import "~bulma/sass/utilities/functions";
|
@import "~bulma/sass/utilities/functions";
|
||||||
// 1. Set your own initial variables and derived
|
|
||||||
// variables in _variables.scss
|
|
||||||
@import "variables";
|
@import "variables";
|
||||||
|
|
||||||
// 2. Setup your Custom Colors
|
|
||||||
$linkedin: #0077b5;
|
|
||||||
$linkedin-invert: findColorInvert($linkedin);
|
|
||||||
$twitter: #55acee;
|
|
||||||
$twitter-invert: findColorInvert($twitter);
|
|
||||||
$github: #333;
|
|
||||||
$github-invert: findColorInvert($github);
|
|
||||||
|
|
||||||
@import "~bulma/sass/utilities/derived-variables";
|
@import "~bulma/sass/utilities/derived-variables";
|
||||||
|
|
||||||
// 3. Add new color variables to the color map.
|
|
||||||
$addColors: (
|
|
||||||
"twitter": (
|
|
||||||
$twitter,
|
|
||||||
$twitter-invert
|
|
||||||
),
|
|
||||||
"linkedin": (
|
|
||||||
$linkedin,
|
|
||||||
$linkedin-invert
|
|
||||||
),
|
|
||||||
"github": (
|
|
||||||
$github,
|
|
||||||
$github-invert
|
|
||||||
)
|
|
||||||
);
|
|
||||||
$colors: map-merge($colors, $addColors);
|
|
||||||
|
|
||||||
@import "~bulma";
|
@import "~bulma";
|
||||||
@import "~buefy/src/scss/buefy";
|
@import "~buefy/src/scss/buefy";
|
||||||
|
|
||||||
// 4. Provide custom buefy overrides and site styles here
|
@import "overrides";
|
||||||
|
|
48
webclient/src/components/ConnectForm.vue
Normal file
48
webclient/src/components/ConnectForm.vue
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
<template>
|
||||||
|
<section>
|
||||||
|
<form @submit.prevent="tryConnect">
|
||||||
|
<b-notification
|
||||||
|
type="is-danger"
|
||||||
|
aria-close-label="Close notification"
|
||||||
|
role="alert"
|
||||||
|
v-if="server.connectionError"
|
||||||
|
>
|
||||||
|
{{ server.connectionError }}
|
||||||
|
</b-notification>
|
||||||
|
<b-field label="Server address">
|
||||||
|
<b-input size="is-large" v-model="addr"></b-input>
|
||||||
|
</b-field>
|
||||||
|
<b-field>
|
||||||
|
<button type="submit" class="button is-primary">Connect</button>
|
||||||
|
</b-field>
|
||||||
|
<b-loading
|
||||||
|
is-full-page
|
||||||
|
:active.sync="server.connecting"
|
||||||
|
></b-loading>
|
||||||
|
</form>
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { Action, State } from "vuex-class";
|
||||||
|
import { Component, Vue } from "vue-property-decorator";
|
||||||
|
import { ServerState } from "@/store/server";
|
||||||
|
|
||||||
|
@Component({})
|
||||||
|
export default class ConnectForm extends Vue {
|
||||||
|
@State("server") private server!: ServerState;
|
||||||
|
@Action("connect", { namespace: "server" }) private connect: any;
|
||||||
|
private addr!: string;
|
||||||
|
private loading!: boolean;
|
||||||
|
|
||||||
|
private data() {
|
||||||
|
return {
|
||||||
|
addr: "http://192.168.22.22"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private async tryConnect() {
|
||||||
|
this.connect(this.addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
12
webclient/src/components/RoomList.vue
Normal file
12
webclient/src/components/RoomList.vue
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
<template>
|
||||||
|
<div class="container">
|
||||||
|
<h1>Room list</h1>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { Component, Vue } from "vue-property-decorator";
|
||||||
|
|
||||||
|
@Component({})
|
||||||
|
export default class RoomList extends Vue {}
|
||||||
|
</script>
|
|
@ -1,6 +1,6 @@
|
||||||
import Vue from "vue";
|
import Vue from "vue";
|
||||||
import App from "./App.vue";
|
import App from "./App.vue";
|
||||||
import store from "./store";
|
import store from "./store/index";
|
||||||
import Buefy from "buefy";
|
import Buefy from "buefy";
|
||||||
import "./assets/scss/app.scss";
|
import "./assets/scss/app.scss";
|
||||||
|
|
||||||
|
|
|
@ -1,23 +1,26 @@
|
||||||
import Vue from "vue";
|
import Vue from "vue";
|
||||||
import Vuex, { StoreOptions } from "vuex";
|
import Vuex, { StoreOptions } from "vuex";
|
||||||
|
import { server } from "./server";
|
||||||
|
import { room } from "./room";
|
||||||
|
|
||||||
Vue.use(Vuex);
|
Vue.use(Vuex);
|
||||||
|
|
||||||
export interface AppState {
|
export interface AppState {
|
||||||
in_room: boolean;
|
// Client info
|
||||||
room: string;
|
|
||||||
playerName: string;
|
playerName: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const store: StoreOptions<AppState> = {
|
const store: StoreOptions<AppState> = {
|
||||||
state: {
|
state: {
|
||||||
in_room: false,
|
|
||||||
room: "",
|
|
||||||
playerName:
|
playerName:
|
||||||
"webclient-" +
|
"webclient-" +
|
||||||
Math.random()
|
Math.random()
|
||||||
.toString(32)
|
.toString(32)
|
||||||
.slice(2)
|
.slice(2)
|
||||||
|
},
|
||||||
|
modules: {
|
||||||
|
server,
|
||||||
|
room
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
19
webclient/src/store/room.ts
Normal file
19
webclient/src/store/room.ts
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
import { Module } from "vuex";
|
||||||
|
import { AppState } from "@/store/index";
|
||||||
|
|
||||||
|
const namespaced: boolean = true;
|
||||||
|
|
||||||
|
export interface RoomState {
|
||||||
|
in_room: boolean;
|
||||||
|
room: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const state: RoomState = {
|
||||||
|
in_room: false,
|
||||||
|
room: ""
|
||||||
|
};
|
||||||
|
|
||||||
|
export const room: Module<RoomState, AppState> = {
|
||||||
|
namespaced,
|
||||||
|
state
|
||||||
|
};
|
63
webclient/src/store/server.ts
Normal file
63
webclient/src/store/server.ts
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
import { Module, ActionTree, MutationTree, GetterTree } from "vuex";
|
||||||
|
import { AppState } from "@/store/index";
|
||||||
|
|
||||||
|
const namespaced: boolean = true;
|
||||||
|
|
||||||
|
export interface ServerState {
|
||||||
|
server: string;
|
||||||
|
connecting: boolean;
|
||||||
|
connected: boolean;
|
||||||
|
rooms: Object | null;
|
||||||
|
connectionError: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const state: ServerState = {
|
||||||
|
connecting: false,
|
||||||
|
connected: false,
|
||||||
|
server: "",
|
||||||
|
rooms: null,
|
||||||
|
connectionError: ""
|
||||||
|
};
|
||||||
|
|
||||||
|
const mutations: MutationTree<ServerState> = {
|
||||||
|
beginConnection(state: ServerState) {
|
||||||
|
state.connected = false;
|
||||||
|
state.connectionError = "";
|
||||||
|
state.connecting = true;
|
||||||
|
},
|
||||||
|
|
||||||
|
connectionDone(
|
||||||
|
state: ServerState,
|
||||||
|
payload: { addr: string; rooms: Object }
|
||||||
|
) {
|
||||||
|
state.connected = true;
|
||||||
|
state.server = payload.addr;
|
||||||
|
state.rooms = payload.rooms;
|
||||||
|
},
|
||||||
|
|
||||||
|
connectionFailed(state: ServerState, err: Error) {
|
||||||
|
state.connecting = false;
|
||||||
|
state.connectionError = err.message;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const actions: ActionTree<ServerState, AppState> = {
|
||||||
|
connect: async ({ commit }, addr: string) => {
|
||||||
|
commit("beginConnection");
|
||||||
|
// Get room list
|
||||||
|
try {
|
||||||
|
let req = await fetch(`${addr}/api/lobby/room/list`);
|
||||||
|
let data = await req.json();
|
||||||
|
commit("connectionDone", { addr, rooms: data });
|
||||||
|
} catch (err) {
|
||||||
|
commit("connectionFailed", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const server: Module<ServerState, AppState> = {
|
||||||
|
namespaced,
|
||||||
|
state,
|
||||||
|
actions,
|
||||||
|
mutations
|
||||||
|
};
|
|
@ -8191,6 +8191,11 @@ vue@^2.6.10:
|
||||||
resolved "https://registry.yarnpkg.com/vue/-/vue-2.6.10.tgz#a72b1a42a4d82a721ea438d1b6bf55e66195c637"
|
resolved "https://registry.yarnpkg.com/vue/-/vue-2.6.10.tgz#a72b1a42a4d82a721ea438d1b6bf55e66195c637"
|
||||||
integrity sha512-ImThpeNU9HbdZL3utgMCq0oiMzAkt1mcgy3/E6zWC/G6AaQoeuFdsl9nDhTDU3X1R6FK7nsIUuRACVcjI+A2GQ==
|
integrity sha512-ImThpeNU9HbdZL3utgMCq0oiMzAkt1mcgy3/E6zWC/G6AaQoeuFdsl9nDhTDU3X1R6FK7nsIUuRACVcjI+A2GQ==
|
||||||
|
|
||||||
|
vuex-class@^0.3.2:
|
||||||
|
version "0.3.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/vuex-class/-/vuex-class-0.3.2.tgz#c7e96a076c1682137d4d23a8dcfdc63f220e17a8"
|
||||||
|
integrity sha512-m0w7/FMsNcwJgunJeM+wcNaHzK2KX1K1rw2WUQf7Q16ndXHo7pflRyOV/E8795JO/7fstyjH3EgqBI4h4n4qXQ==
|
||||||
|
|
||||||
vuex@^3.0.1:
|
vuex@^3.0.1:
|
||||||
version "3.1.1"
|
version "3.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/vuex/-/vuex-3.1.1.tgz#0c264bfe30cdbccf96ab9db3177d211828a5910e"
|
resolved "https://registry.yarnpkg.com/vuex/-/vuex-3.1.1.tgz#0c264bfe30cdbccf96ab9db3177d211828a5910e"
|
||||||
|
|
Loading…
Reference in a new issue