Fix all the things!

This commit is contained in:
Julius 2019-07-07 23:09:35 +02:00
parent ba4ee10a2a
commit c8307e58bd
14 changed files with 368 additions and 50 deletions

1
.dockerignore Normal file
View file

@ -0,0 +1 @@
node_modules/

3
.env.development Normal file
View file

@ -0,0 +1,3 @@
VUE_APP_API_URL=localhost:8000
VUE_APP_API_PROTOCOL=http://
VUE_APP_WS_PROTOCOL=ws://

3
.env.production Normal file
View file

@ -0,0 +1,3 @@
VUE_APP_API_URL=caiapi.voidcorp.nl
VUE_APP_API_PROTOCOL=https://
VUE_APP_WS_PROTOCOL=wss://

22
Dockerfile Normal file
View file

@ -0,0 +1,22 @@
FROM node:alpine as build
# Set work dir
WORKDIR /app/
# Copy package files
COPY package.json ./
COPY yarn.lock ./
RUN yarn install
COPY . .
RUN yarn build
FROM nginx:alpine as production-stage
RUN apk add curl --no-cache
WORKDIR /usr/share/nginx/html
COPY --from=build /app/dist .

View file

@ -8,8 +8,10 @@
"lint": "vue-cli-service lint" "lint": "vue-cli-service lint"
}, },
"dependencies": { "dependencies": {
"@chenfengyuan/vue-qrcode": "^1.0.1",
"axios": "^0.19.0", "axios": "^0.19.0",
"core-js": "^2.6.5", "core-js": "^2.6.5",
"qrcode.vue": "^1.6.2",
"register-service-worker": "^1.6.2", "register-service-worker": "^1.6.2",
"vue": "^2.6.10", "vue": "^2.6.10",
"vue-class-component": "^7.0.2", "vue-class-component": "^7.0.2",

View file

@ -4,12 +4,13 @@
<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">
<script src="https://kit.fontawesome.com/b1ff873bb7.js"></script>
<link rel="icon" href="<%= BASE_URL %>favicon.ico"> <link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title>cards-frontend</title> <title>Cards Against Idiots</title>
</head> </head>
<body> <body>
<noscript> <noscript>
<strong>We're sorry but cards-frontend doesn't work properly without JavaScript enabled. Please enable it to continue.</strong> <strong>We're sorry but almost everything 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 -->

View file

@ -1,9 +1,10 @@
<template> <template>
<div id="app"> <div id="app">
<div id="nav"> <h1>Cards Against Idiots</h1>
<!-- <div id="nav">
<router-link to="/">Start</router-link> | <router-link to="/">Start</router-link> |
<router-link to="/about">About</router-link> <router-link to="/about">About</router-link>
</div> </div> -->
<router-view/> <router-view/>
</div> </div>
</template> </template>

View file

@ -1,6 +1,6 @@
<template> <template>
<div class="card" :class="{black: !isBlack}"> <div class="card" :class="{black: isBlack}">
<span class="text">{{ text }}</span> <span class="text" v-html="text">}</span>
<span class="bottom-text">Cards Against Idiots</span> <span class="bottom-text">Cards Against Idiots</span>
</div> </div>
</template> </template>
@ -20,6 +20,7 @@
<style scoped> <style scoped>
.card{ .card{
position: relative;
width: 13em; width: 13em;
height: 17em; height: 17em;
border: solid black; border: solid black;
@ -30,8 +31,9 @@
.bottom-text { .bottom-text {
display: block; display: block;
position: relative; position: absolute;
top: 13em; bottom: 1em;
left: 2em;
font-style: italic; font-style: italic;
} }

View file

@ -1,8 +1,8 @@
<template> <template>
<div> <div @click="$emit('clicked')" class="stack">
<card-component :text="text[0]" class="c1" isBlack="false" /> <card-component :text="text[0]" class="c1" :isBlack="false" :class="{hover: showhover}"/>
<card-component :text="text[1]" class="c2" v-if="this.text.length > 1" isBlack="false"/> <card-component :text="text[1]" class="c2" v-if="this.text.length > 1" :isBlack="false" :class="{hover: showhover}"/>
<card-component :text="text[2]" class="c3" v-if="this.text.length > 2" isBlack="false"/> <card-component :text="text[2]" class="c3" v-if="this.text.length > 2" :isBlack="false" :class="{hover: showhover}"/>
</div> </div>
</template> </template>
@ -16,10 +16,13 @@ export default class StackedCards extends Vue {
@Prop() @Prop()
private text!: string[]; private text!: string[];
@Prop()
private showhover!: boolean;
} }
</script> </script>
<style scoped> <style scoped lang="scss">
.c2{ .c2{
position: relative; position: relative;
top: -15em; top: -15em;
@ -31,4 +34,9 @@ export default class StackedCards extends Vue {
top: -30em; top: -30em;
left: 0.6em; left: 0.6em;
} }
.stack:hover .hover {
background-color: #b5b5b5;
}
</style> </style>

View file

@ -2,8 +2,10 @@ import axios from "axios";
import { Message, MessageType } from "../models/Message"; import { Message, MessageType } from "../models/Message";
import { Answer } from "../models/Answer"; import { Answer } from "../models/Answer";
const webProt = "http://"; export const webProt = process.env.VUE_APP_API_PROTOCOL;
const baseURL = "localhost:8000"; export const baseURL = process.env.VUE_APP_API_URL;
export const fullURL = webProt + baseURL;
export const wsProt = process.env.VUE_APP_WS_PROTOCOL;
export const axios_api = axios.create({ export const axios_api = axios.create({
baseURL: webProt + baseURL, baseURL: webProt + baseURL,
@ -21,8 +23,8 @@ export class Game {
private sub: WebSocket; private sub: WebSocket;
constructor(code: string, name: string, message_callback: (message: Message) => void) { constructor(code: string, name: string, message_callback: (message: Message) => void) {
this.pub = new WebSocket(`ws://${baseURL}/ws/room/${code}/pub`); this.pub = new WebSocket(`${wsProt}${baseURL}/ws/room/${code}/pub`);
this.sub = new WebSocket(`ws://${baseURL}/ws/room/${code}/sub`); this.sub = new WebSocket(`${wsProt}${baseURL}/ws/room/${code}/sub`);
this.pub.addEventListener("open", (event) => { this.pub.addEventListener("open", (event) => {
console.info("pub-ws connected"); console.info("pub-ws connected");

View file

@ -1,5 +1,207 @@
<template> <template>
<div class="about"> <div class="about">
<h1>yeet</h1> <h1>yeet</h1>
<pre>
</pre>
<h2>What did you expect?</h2>
</div> </div>
</template> </template>

View file

@ -1,8 +1,7 @@
<template> <template>
<div id="game"> <div id="game">
<h1> <h1>
Room: Room: {{ this.$route.params.code }}
<a>{{ this.$route.params.code }}</a>
</h1> </h1>
<h2>Your name is: {{ this.name }}</h2> <h2>Your name is: {{ this.name }}</h2>
<ul> <ul>
@ -11,56 +10,70 @@
<button v-if="this.game.owner && !this.room.started" @click="this.start_game">Stort</button> <button v-if="this.game.owner && !this.room.started" @click="this.start_game">Stort</button>
<span v-show="this.card" v-html="this.card.text" /> <card-component v-if="this.room.started" :text="this.card.text" :isBlack="true" />
<ul v-show="this.card && !this.czar()"> <ul v-show="this.card && !this.czar()">
<li v-for="blank in this.card.pick"> <li v-for="blank in this.card.pick">
Card {{blank}}: Card {{blank}}:
<input type="text" v-model="inputs[blank - 1]" :disabled="input_blocked" /> <input type="text" v-model="inputs[blank - 1]" :disabled="input_blocked" />
</li> </li>
<li> <li v-show="!input_blocked && room.started">
<button @click="this.send_answers" v-show="!input_blocked && room.started">Submit Answers</button> <button @click="this.send_answers">Submit Answers</button>
</li> </li>
</ul> </ul>
<ul> <div class="cards">
<li v-for="ans in this.answers"> <stacked-cards
<span v-for="t in ans.text">{{ t }},&nbsp;</span> class="card"
<button @click="pick(ans)" v-show="czar()">Pick</button> v-for="ans in this.answers"
</li> :key="ans.index"
</ul> :text="ans.text"
:showhover="czar()"
v-on:clicked="pick(ans)"
/>
</div>
<qrcode-vue v-if="!this.room.started" :value="gameURL" :size="300"></qrcode-vue>
</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 { Game, axios_api } from "../util/api"; import { Game, axios_api, fullURL } from "../util/api";
import { Message, MessageType } from "../models/Message"; import { Message, MessageType } from "../models/Message";
import { Room } from "../models/Room"; import { Room } from "../models/Room";
import { Card } from "../models/Card"; import { Card } from "../models/Card";
import { Answer } from "../models/Answer"; import { Answer } from "../models/Answer";
import CardComponent from "../components/CardComponent.vue";
import StackedCards from "../components/StackedCards.vue";
import QrcodeVue from "qrcode.vue";
@Component({ @Component({
components: {Card}, components: { CardComponent, StackedCards, QrcodeVue },
}) })
export default class GameVueView extends Vue { export default class GameVueView extends Vue {
private game: Game = {}; private game: Game = new Game("", "", () => {console.error("OwO we did an oopsie woopsie"); });
private room: Room = {}; private room: Room = new Room("");
private card: Card = {}; private card: Card = new Card("", 0, "", "");
private inputs: string[] = []; private inputs: string[] = [];
private input_blocked: boolean = false; private input_blocked: boolean = false;
private answers: Answer[] = []; private answers: Answer[] = [];
private name: string; private name: string = "";
private gameURL: string = "";
/** /**
* Lifecycle hooks * Lifecycle hooks
*/ */
private async mounted() { private async mounted() {
this.name = this.$route.query.name || prompt("What is your nickname?"); this.gameURL = `${fullURL}/?code=${this.$route.params.code}`;
if (name && this.$route.params.code.length > 3) {
this.name = name as string;
const room = await axios_api.get(`/room/${this.$route.params.code}`);
if (room.status === 200 && !room.data.started) { this.name = (this.$route.query.name || prompt("What is your nickname?")) as string;
this.game = new Game(this.$route.params.code, name, this.on_message); if (this.name && this.$route.params.code.length > 3) {
this.name = this.name as string;
const room = await axios_api.get(`/room/${this.$route.params.code}`);
if (room.status === 200) {
this.game = new Game(
this.$route.params.code,
this.name,
this.on_message,
);
} }
} }
} }
@ -79,10 +92,12 @@ export default class GameVueView extends Vue {
} }
private pick(ans: Answer) { private pick(ans: Answer) {
if (this.czar()) {
this.game.pick_answer(ans); this.game.pick_answer(ans);
} }
}
private on_message(message: Message) { private async on_message(message: Message) {
switch (message.msgtype) { switch (message.msgtype) {
case MessageType.JOIN: case MessageType.JOIN:
break; break;
@ -106,4 +121,24 @@ export default class GameVueView extends Vue {
} }
</script> </script>
<style lang="scss"> <style lang="scss">
#game {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.cards {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
flex-wrap: wrap;
}
.card {
margin-left: 5px;
margin-right: 5px;
margin-top: 5px;
}
</style> </style>

View file

@ -14,25 +14,24 @@
<input id="code" type="text" v-model="code" placeholder="Optional room code" minlength="4" /> <input id="code" type="text" v-model="code" placeholder="Optional room code" minlength="4" />
<button @click="checkRoom" id="join">Join!</button> <button @click="checkRoom" id="join">Join!</button>
<stacked-cards :text="texts" />
</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 { axios_api } from "../util/api"; import { axios_api } from "../util/api";
import { Room } from "../models/Room"; import { Room } from "../models/Room";
import CardComponent from "@/components/CardComponent.vue";
import StackedCards from "@/components/StackedCards.vue";
@Component({ @Component({
name: "JoinRoom", name: "JoinRoom",
components: {StackedCards, CardComponent},
}) })
export default class JoinRoom extends Vue { export default class JoinRoom extends Vue {
private code: string = ""; private code: string = "";
private name: string = ""; private name: string = "";
private texts: string[] = ["a", "b", "c"];
private mounted() {
this.code = (this.$route.query.code || "") as string;
}
private checkRoom() { private checkRoom() {
if (this.name.length < 1 || this.name.length > 25) { if (this.name.length < 1 || this.name.length > 25) {

View file

@ -670,6 +670,13 @@
lodash "^4.17.11" lodash "^4.17.11"
to-fast-properties "^2.0.0" to-fast-properties "^2.0.0"
"@chenfengyuan/vue-qrcode@^1.0.1":
version "1.0.1"
resolved "https://registry.yarnpkg.com/@chenfengyuan/vue-qrcode/-/vue-qrcode-1.0.1.tgz#e6f757103c36630dc7c9f385494c5d9796c24d47"
integrity sha512-D5d8U3zFc8zDlrqVOWkarYz4qDTrGLfCOeGkODpQxq6KcAamOhvZ0B8V9qxdkXjUUPjOO3L8pLLnIo6xYoEpMw==
dependencies:
qrcode "^1.3.3"
"@hapi/address@2.x.x": "@hapi/address@2.x.x":
version "2.0.0" version "2.0.0"
resolved "https://registry.yarnpkg.com/@hapi/address/-/address-2.0.0.tgz#9f05469c88cb2fd3dcd624776b54ee95c312126a" resolved "https://registry.yarnpkg.com/@hapi/address/-/address-2.0.0.tgz#9f05469c88cb2fd3dcd624776b54ee95c312126a"
@ -2804,6 +2811,11 @@ diffie-hellman@^5.0.0:
miller-rabin "^4.0.0" miller-rabin "^4.0.0"
randombytes "^2.0.0" randombytes "^2.0.0"
dijkstrajs@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/dijkstrajs/-/dijkstrajs-1.0.1.tgz#d3cd81221e3ea40742cfcde556d4e99e98ddc71b"
integrity sha1-082BIh4+pAdCz83lVtTpnpjdxxs=
dir-glob@^2.0.0, dir-glob@^2.2.2: dir-glob@^2.0.0, dir-glob@^2.2.2:
version "2.2.2" version "2.2.2"
resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-2.2.2.tgz#fa09f0694153c8918b18ba0deafae94769fc50c4" resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-2.2.2.tgz#fa09f0694153c8918b18ba0deafae94769fc50c4"
@ -4412,6 +4424,11 @@ isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0:
resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=
isarray@^2.0.1:
version "2.0.4"
resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.4.tgz#38e7bcbb0f3ba1b7933c86ba1894ddfc3781bbb7"
integrity sha512-GMxXOiUirWg1xTKRipM0Ek07rX+ubx4nNVElTJdNLYmNO/2YrDkgJGw9CljXn+r4EWiDQg/8lsRdHyg2PJuUaA==
isemail@3.x.x: isemail@3.x.x:
version "3.2.0" version "3.2.0"
resolved "https://registry.yarnpkg.com/isemail/-/isemail-3.2.0.tgz#59310a021931a9fb06bbb51e155ce0b3f236832c" resolved "https://registry.yarnpkg.com/isemail/-/isemail-3.2.0.tgz#59310a021931a9fb06bbb51e155ce0b3f236832c"
@ -5824,6 +5841,11 @@ please-upgrade-node@^3.0.2:
dependencies: dependencies:
semver-compare "^1.0.0" semver-compare "^1.0.0"
pngjs@^3.3.0:
version "3.4.0"
resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-3.4.0.tgz#99ca7d725965fb655814eaf65f38f12bbdbf555f"
integrity sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==
portfinder@^1.0.20: portfinder@^1.0.20:
version "1.0.20" version "1.0.20"
resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.20.tgz#bea68632e54b2e13ab7b0c4775e9b41bf270e44a" resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.20.tgz#bea68632e54b2e13ab7b0c4775e9b41bf270e44a"
@ -6309,6 +6331,21 @@ q@^1.1.2:
resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7"
integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc= integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=
qrcode.vue@^1.6.2:
version "1.6.2"
resolved "https://registry.yarnpkg.com/qrcode.vue/-/qrcode.vue-1.6.2.tgz#56446818a4103fac652180fa4a761ff2f39cd0a9"
integrity sha512-zlQ7btO//ACLv2FT4PJGumecXQ2SMtajkR7FuKscD1dR9u0/AnttOamfADVf6Ha7oeHb1b/27JkzQ+VkSAkKPA==
qrcode@^1.3.3:
version "1.3.4"
resolved "https://registry.yarnpkg.com/qrcode/-/qrcode-1.3.4.tgz#1e5358050a5184cca3d0b7ed7f76769a8d3557d1"
integrity sha512-wCfIu6sA0bXisSDT/ehgSC1v1uRoW8xGu5y18zyOV8D1J/ciz3xC+48LkLupqk0uqyBKxKq3eImuVgfrzFAdrg==
dependencies:
dijkstrajs "^1.0.1"
isarray "^2.0.1"
pngjs "^3.3.0"
yargs "^13.2.4"
qs@6.7.0: qs@6.7.0:
version "6.7.0" version "6.7.0"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc"
@ -8322,7 +8359,7 @@ yargs@12.0.5:
y18n "^3.2.1 || ^4.0.0" y18n "^3.2.1 || ^4.0.0"
yargs-parser "^11.1.1" yargs-parser "^11.1.1"
yargs@^13.0.0: yargs@^13.0.0, yargs@^13.2.4:
version "13.2.4" version "13.2.4"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.2.4.tgz#0b562b794016eb9651b98bd37acf364aa5d6dc83" resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.2.4.tgz#0b562b794016eb9651b98bd37acf364aa5d6dc83"
integrity sha512-HG/DWAJa1PAnHT9JAhNa8AbAv3FPaiLzioSjCcmuXXhP8MlpHO5vwls4g4j6n30Z74GVQj8Xa62dWVx1QCGklg== integrity sha512-HG/DWAJa1PAnHT9JAhNa8AbAv3FPaiLzioSjCcmuXXhP8MlpHO5vwls4g4j6n30Z74GVQj8Xa62dWVx1QCGklg==