Merge branch 'master' into feat/ci
commit
3d3204e322
|
@ -0,0 +1,13 @@
|
||||||
|
# build stage
|
||||||
|
FROM node:lts-alpine as build-stage
|
||||||
|
WORKDIR /app
|
||||||
|
COPY package*.json ./
|
||||||
|
RUN npm install
|
||||||
|
COPY . .
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
# production stage
|
||||||
|
FROM nginx:stable-alpine as production-stage
|
||||||
|
COPY --from=build-stage /app/public /usr/share/nginx/html
|
||||||
|
EXPOSE 80
|
||||||
|
CMD ["nginx", "-g", "daemon off;"]
|
|
@ -0,0 +1,46 @@
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name localhost;
|
||||||
|
|
||||||
|
#charset koi8-r;
|
||||||
|
#access_log /var/log/nginx/host.access.log main;
|
||||||
|
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
index index.html;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
try_files $uri /index.html;
|
||||||
|
}
|
||||||
|
|
||||||
|
#error_page 404 /404.html;
|
||||||
|
|
||||||
|
# redirect server error pages to the static page /50x.html
|
||||||
|
#
|
||||||
|
# error_page 500 502 503 504 /50x.html;
|
||||||
|
# location = /50x.html {
|
||||||
|
# root /usr/share/nginx/html;
|
||||||
|
# }
|
||||||
|
|
||||||
|
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
|
||||||
|
#
|
||||||
|
#location ~ \.php$ {
|
||||||
|
# proxy_pass http://127.0.0.1;
|
||||||
|
#}
|
||||||
|
|
||||||
|
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
|
||||||
|
#
|
||||||
|
#location ~ \.php$ {
|
||||||
|
# root html;
|
||||||
|
# fastcgi_pass 127.0.0.1:9000;
|
||||||
|
# fastcgi_index index.php;
|
||||||
|
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
|
||||||
|
# include fastcgi_params;
|
||||||
|
#}
|
||||||
|
|
||||||
|
# deny access to .htaccess files, if Apache's document root
|
||||||
|
# concurs with nginx's one
|
||||||
|
#
|
||||||
|
#location ~ /\.ht {
|
||||||
|
# deny all;
|
||||||
|
#}
|
||||||
|
}
|
|
@ -2120,6 +2120,43 @@
|
||||||
"integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==",
|
"integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"axios": {
|
||||||
|
"version": "0.19.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/axios/-/axios-0.19.0.tgz",
|
||||||
|
"integrity": "sha512-1uvKqKQta3KBxIz14F2v06AEHZ/dIoeKfbTRkK1E5oqjDnuEerLmYTgJB5AiQZHJcljpg1TuRzdjDR06qNk0DQ==",
|
||||||
|
"requires": {
|
||||||
|
"follow-redirects": "1.5.10",
|
||||||
|
"is-buffer": "^2.0.2"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"debug": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
|
||||||
|
"requires": {
|
||||||
|
"ms": "2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"follow-redirects": {
|
||||||
|
"version": "1.5.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz",
|
||||||
|
"integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==",
|
||||||
|
"requires": {
|
||||||
|
"debug": "=3.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"is-buffer": {
|
||||||
|
"version": "2.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz",
|
||||||
|
"integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A=="
|
||||||
|
},
|
||||||
|
"ms": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||||
|
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"babel-code-frame": {
|
"babel-code-frame": {
|
||||||
"version": "6.26.0",
|
"version": "6.26.0",
|
||||||
"resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz",
|
"resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz",
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "api-directory",
|
"name": "client",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"private": true,
|
"private": false,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"serve": "vue-cli-service serve",
|
"serve": "vue-cli-service serve",
|
||||||
"build": "vue-cli-service build",
|
"build": "vue-cli-service build",
|
||||||
|
@ -10,6 +10,7 @@
|
||||||
"test:unit": "vue-cli-service test:unit"
|
"test:unit": "vue-cli-service test:unit"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"axios": "^0.19.0",
|
||||||
"core-js": "^2.6.5",
|
"core-js": "^2.6.5",
|
||||||
"register-service-worker": "^1.6.2",
|
"register-service-worker": "^1.6.2",
|
||||||
"vue": "^2.6.10",
|
"vue": "^2.6.10",
|
||||||
|
@ -29,6 +30,7 @@
|
||||||
"node-sass": "^4.9.0",
|
"node-sass": "^4.9.0",
|
||||||
"sass-loader": "^7.1.0",
|
"sass-loader": "^7.1.0",
|
||||||
"ts-jest": "^23.0.0",
|
"ts-jest": "^23.0.0",
|
||||||
|
"tslint": "^5.20.0",
|
||||||
"typescript": "^3.4.3",
|
"typescript": "^3.4.3",
|
||||||
"vue-template-compiler": "^2.6.10"
|
"vue-template-compiler": "^2.6.10"
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<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">
|
||||||
<title>api-directory</title>
|
<title>HETIC vs EEMI</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<noscript>
|
<noscript>
|
||||||
|
|
|
@ -1,16 +1,12 @@
|
||||||
<template>
|
<template>
|
||||||
<div id="app">
|
<div id="app">
|
||||||
<div id="nav">
|
<router-view />
|
||||||
<router-link to="/">Home</router-link> |
|
|
||||||
<router-link to="/about">About</router-link>
|
|
||||||
</div>
|
|
||||||
<router-view/>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
#app {
|
#app {
|
||||||
font-family: 'Avenir', Helvetica, Arial, sans-serif;
|
font-family: "Avenir", Helvetica, Arial, sans-serif;
|
||||||
-webkit-font-smoothing: antialiased;
|
-webkit-font-smoothing: antialiased;
|
||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
|
@ -1,63 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="hello">
|
|
||||||
<h1>{{ msg }}</h1>
|
|
||||||
<p>
|
|
||||||
For a guide and recipes on how to configure / customize this project,<br>
|
|
||||||
check out the
|
|
||||||
<a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
|
|
||||||
</p>
|
|
||||||
<h3>Installed CLI Plugins</h3>
|
|
||||||
<ul>
|
|
||||||
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a></li>
|
|
||||||
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-typescript" target="_blank" rel="noopener">typescript</a></li>
|
|
||||||
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-pwa" target="_blank" rel="noopener">pwa</a></li>
|
|
||||||
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-unit-jest" target="_blank" rel="noopener">unit-jest</a></li>
|
|
||||||
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-e2e-cypress" target="_blank" rel="noopener">e2e-cypress</a></li>
|
|
||||||
</ul>
|
|
||||||
<h3>Essential Links</h3>
|
|
||||||
<ul>
|
|
||||||
<li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li>
|
|
||||||
<li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li>
|
|
||||||
<li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li>
|
|
||||||
<li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li>
|
|
||||||
<li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li>
|
|
||||||
</ul>
|
|
||||||
<h3>Ecosystem</h3>
|
|
||||||
<ul>
|
|
||||||
<li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li>
|
|
||||||
<li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li>
|
|
||||||
<li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li>
|
|
||||||
<li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li>
|
|
||||||
<li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import Vue from 'vue';
|
|
||||||
|
|
||||||
export default Vue.extend({
|
|
||||||
name: 'HelloWorld',
|
|
||||||
props: {
|
|
||||||
msg: String,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
|
||||||
<style scoped lang="scss">
|
|
||||||
h3 {
|
|
||||||
margin: 40px 0 0;
|
|
||||||
}
|
|
||||||
ul {
|
|
||||||
list-style-type: none;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
li {
|
|
||||||
display: inline-block;
|
|
||||||
margin: 0 10px;
|
|
||||||
}
|
|
||||||
a {
|
|
||||||
color: #42b983;
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
<template>
|
||||||
|
<div class="score_screen">
|
||||||
|
<h1>Score: {{ score }}/{{ count }}</h1>
|
||||||
|
<h3>Bon c'est pas tip top tout ça</h3>
|
||||||
|
<button>Rejouer</button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import Vue from 'vue';
|
||||||
|
|
||||||
|
export default Vue.extend({
|
||||||
|
name: 'ScoreScreen',
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
messages: [{ min: 2, msg: 'Bon c\'est pas tip top tout ça' }],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
score: Number,
|
||||||
|
count: Number,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
h3 {
|
||||||
|
margin: 40px 0 0;
|
||||||
|
}
|
||||||
|
ul {
|
||||||
|
list-style-type: none;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
li {
|
||||||
|
display: inline-block;
|
||||||
|
margin: 0 10px;
|
||||||
|
}
|
||||||
|
a {
|
||||||
|
color: #42b983;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,9 @@
|
||||||
|
export enum EAnswer {
|
||||||
|
HETIC = 1,
|
||||||
|
EEMI = 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
export default interface IQuestion {
|
||||||
|
text: string;
|
||||||
|
answer: EAnswer;
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
export default interface ISchool {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
}
|
|
@ -9,17 +9,9 @@ export default new Router({
|
||||||
base: process.env.BASE_URL,
|
base: process.env.BASE_URL,
|
||||||
routes: [
|
routes: [
|
||||||
{
|
{
|
||||||
path: '/',
|
path: '*',
|
||||||
name: 'home',
|
name: 'home',
|
||||||
component: Home,
|
component: Home,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
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'),
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
import Vue from 'vue';
|
|
||||||
import Vuex from 'vuex';
|
|
||||||
|
|
||||||
Vue.use(Vuex);
|
|
||||||
|
|
||||||
export default new Vuex.Store({
|
|
||||||
state: {
|
|
||||||
|
|
||||||
},
|
|
||||||
mutations: {
|
|
||||||
|
|
||||||
},
|
|
||||||
actions: {
|
|
||||||
|
|
||||||
},
|
|
||||||
});
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
import Vue from 'vue';
|
||||||
|
import Vuex from 'vuex';
|
||||||
|
|
||||||
|
// Modules
|
||||||
|
import questions from './modules/questions';
|
||||||
|
|
||||||
|
Vue.use(Vuex);
|
||||||
|
|
||||||
|
const debug = process.env.NODE_ENV !== 'production';
|
||||||
|
|
||||||
|
export default new Vuex.Store({
|
||||||
|
modules: {
|
||||||
|
questions,
|
||||||
|
},
|
||||||
|
strict: debug,
|
||||||
|
plugins: [],
|
||||||
|
});
|
|
@ -0,0 +1,60 @@
|
||||||
|
import axios from 'axios';
|
||||||
|
import IQuestion from '@/models/question';
|
||||||
|
import { shuffleArray } from '@/utils';
|
||||||
|
import { Module } from 'vuex';
|
||||||
|
|
||||||
|
const questions: Module<
|
||||||
|
{ index: number; score: number; questions: IQuestion[] },
|
||||||
|
any
|
||||||
|
> = {
|
||||||
|
namespaced: false,
|
||||||
|
state: {
|
||||||
|
index: 0,
|
||||||
|
score: 0,
|
||||||
|
questions: [],
|
||||||
|
},
|
||||||
|
getters: {
|
||||||
|
index(state) {
|
||||||
|
return state.index;
|
||||||
|
},
|
||||||
|
score(state) {
|
||||||
|
return state.score;
|
||||||
|
},
|
||||||
|
questions(state): IQuestion[] {
|
||||||
|
return state.questions;
|
||||||
|
},
|
||||||
|
currentQuestion(state): IQuestion | null {
|
||||||
|
return state.questions.length ? state.questions[state.index] : null;
|
||||||
|
},
|
||||||
|
checkAnswer(state) {
|
||||||
|
return ({ answer }: { answer: number }): boolean =>
|
||||||
|
state.questions[state.index].answer === answer;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
mutations: {
|
||||||
|
async fetchQuestions(state): Promise<IQuestion[]> {
|
||||||
|
try {
|
||||||
|
const res = await axios.get('http://localhost:3000/questions');
|
||||||
|
return (state.questions = shuffleArray(res.data.questions));
|
||||||
|
} catch (e) {
|
||||||
|
throw new Error(e);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
increaseIndex(state: { index: number }): number {
|
||||||
|
return state.index++;
|
||||||
|
},
|
||||||
|
increaseScore(state: { score: number }): number {
|
||||||
|
return state.score++;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
actions: {
|
||||||
|
increaseIndex(context): void {
|
||||||
|
context.commit('increaseIndex');
|
||||||
|
},
|
||||||
|
increaseScore(context): void {
|
||||||
|
context.commit('increaseScore');
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default questions;
|
|
@ -0,0 +1,12 @@
|
||||||
|
const shuffleArray = (arr: unknown[]): any[] => {
|
||||||
|
for (let i = arr.length - 1; i >= 0; i--) {
|
||||||
|
const j = Math.floor(Math.random() * (i + 1));
|
||||||
|
const k = arr[i];
|
||||||
|
arr[i] = arr[j];
|
||||||
|
arr[j] = k;
|
||||||
|
}
|
||||||
|
|
||||||
|
return arr;
|
||||||
|
};
|
||||||
|
|
||||||
|
export { shuffleArray };
|
|
@ -1,5 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="about">
|
|
||||||
<h1>This is an about page</h1>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
|
@ -1,18 +1,71 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="home">
|
<div class="home">
|
||||||
<img alt="Vue logo" src="../assets/logo.png">
|
<div v-show="!finished">
|
||||||
<HelloWorld msg="Welcome to Your Vue.js + TypeScript App"/>
|
<h1>HETIC vs EEMI</h1>
|
||||||
|
|
||||||
|
<h2>{{ getQuestion.text }}</h2>
|
||||||
|
<p>Plus Éemien ou Héticien ? ({{ index + 1 }}/{{ getQuestionCount }})</p>
|
||||||
|
|
||||||
|
<span v-for="(choice) in choices" :key="choice.id">
|
||||||
|
<button @click="answer(choice.id)">{{ choice.name }}</button>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ScoreScreen v-show="finished" :score="score" :count="getQuestionCount" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue';
|
import Vue from "vue";
|
||||||
import HelloWorld from '@/components/HelloWorld.vue'; // @ is an alias to /src
|
import IQuestion from "../models/question";
|
||||||
|
import { mapState, mapGetters, mapMutations } from "vuex";
|
||||||
|
import ScoreScreen from "../components/ScoreScreen.vue";
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
name: 'home',
|
name: "home",
|
||||||
components: {
|
data() {
|
||||||
HelloWorld,
|
return {
|
||||||
|
choices: [{ id: 1, name: "HETIC" }, { id: 2, name: "EEMI" }],
|
||||||
|
finished: false
|
||||||
|
};
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
...mapGetters([
|
||||||
|
"questions",
|
||||||
|
"index",
|
||||||
|
"score",
|
||||||
|
"currentQuestion",
|
||||||
|
"checkAnswer"
|
||||||
|
]),
|
||||||
|
...mapMutations(["fetchQuestions", "increaseIndex", "increaseScore"]),
|
||||||
|
getQuestion(): IQuestion | {} {
|
||||||
|
return this.$store.getters.currentQuestion || {};
|
||||||
|
},
|
||||||
|
getQuestionCount(): number {
|
||||||
|
return this.$store.getters.questions.length;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
answer(answer: number): void {
|
||||||
|
const index: number = this.$store.getters.index;
|
||||||
|
const questions: IQuestion[] = this.$store.getters.questions;
|
||||||
|
|
||||||
|
if (this.$store.getters.checkAnswer({ answer })) {
|
||||||
|
this.$store.dispatch("increaseScore");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (questions[index + 1]) {
|
||||||
|
this.$store.dispatch("increaseIndex");
|
||||||
|
} else {
|
||||||
|
this.finished = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
ScoreScreen
|
||||||
|
},
|
||||||
|
async created() {
|
||||||
|
await this.fetchQuestions;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
import { shuffleArray } from '@/utils';
|
||||||
|
|
||||||
|
describe('Utils - /src/utils/index.ts', () => {
|
||||||
|
describe('#shuffleArr', () => {
|
||||||
|
it('should not change array', () => {
|
||||||
|
const arr = [1];
|
||||||
|
|
||||||
|
expect(shuffleArray(arr)).toStrictEqual(arr);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have correct length', () => {
|
||||||
|
const arr = 'the quick brown fox jumps over the lazy dog'.split(' ');
|
||||||
|
|
||||||
|
expect(shuffleArray(arr).length).toEqual(9);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return an array', () => {
|
||||||
|
const arr = 'the quick brown fox jumps over the lazy dog'.split(' ');
|
||||||
|
|
||||||
|
expect(Array.isArray(shuffleArray(arr))).toEqual(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,54 @@
|
||||||
|
version: '3'
|
||||||
|
|
||||||
|
services:
|
||||||
|
client:
|
||||||
|
container_name: hve_client
|
||||||
|
restart: on-failure
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: ./Dockerfile
|
||||||
|
volumes:
|
||||||
|
- ./client/nginx.conf:/etc/nginx/conf.d/default.conf:ro
|
||||||
|
environment:
|
||||||
|
- NODE_ENV=production
|
||||||
|
networks:
|
||||||
|
- default
|
||||||
|
- web
|
||||||
|
command: ['nginx', '-g', 'daemon off;']
|
||||||
|
# labels:
|
||||||
|
# - 'traefik.docker.network=web'
|
||||||
|
# - 'traefik.enable=true'
|
||||||
|
# - 'traefik.domain=hve.crvx.fr'
|
||||||
|
# - 'traefik.basic.frontend.rule=Host:hve.crvx.fr'
|
||||||
|
# - 'traefik.basic.port=80'
|
||||||
|
# - 'traefik.basic.protocol=http'
|
||||||
|
# - 'traefik.frontend.headers.SSLRedirect=true'
|
||||||
|
# - 'traefik.frontend.headers.STSSeconds=315360000'
|
||||||
|
# - 'traefik.frontend.headers.browserXSSFilter=true'
|
||||||
|
# - 'traefik.frontend.headers.contentTypeNosniff=true'
|
||||||
|
# - 'traefik.frontend.headers.forceSTSHeader=true'
|
||||||
|
# - "traefik.frontend.headers.contentSecurityPolicy=default-src 'self';frame-ancestors 'self';style-src 'self';script-src 'self';img-src 'self';font-src 'self'"
|
||||||
|
# - 'traefik.frontend.headers.referrerPolicy=no-referrer'
|
||||||
|
# - 'traefik.frontend.headers.frameDeny=true'
|
||||||
|
|
||||||
|
api:
|
||||||
|
container_name: hve_api
|
||||||
|
restart: on-failure
|
||||||
|
image: node:8
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: ./server/Dockerfile
|
||||||
|
env_file:
|
||||||
|
- .env
|
||||||
|
environment:
|
||||||
|
- NODE_ENV=production
|
||||||
|
ports:
|
||||||
|
- '3000:3000'
|
||||||
|
networks:
|
||||||
|
- default
|
||||||
|
- postgres
|
||||||
|
command: ['node', '/api/server/index.js']
|
||||||
|
|
||||||
|
networks:
|
||||||
|
web:
|
||||||
|
external: true
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"packages": [
|
||||||
|
"./client",
|
||||||
|
"./server"
|
||||||
|
],
|
||||||
|
"version": "0.0.0"
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
{
|
||||||
|
"name": "HETICvsEEMI",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "Plus Eemien ou Héticien ? Le jeu qui ne fait pas rire les élèves.",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"bootstrap": "lerna bootstrap",
|
||||||
|
"server:install": "cd server && npm i",
|
||||||
|
"client:install": "cd client && npm i",
|
||||||
|
"client:build": "cd client && npm build",
|
||||||
|
"client:lint": "cd client && npm run lint",
|
||||||
|
"client:test": "cd client && npm test",
|
||||||
|
"test": "npm run client:test"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/sundowndev/HETICvsEEMI.git"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/sundowndev/HETICvsEEMI/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/sundowndev/HETICvsEEMI#readme",
|
||||||
|
"devDependencies": {
|
||||||
|
"lerna": "^3.16.4"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
FROM node:8
|
||||||
|
|
||||||
|
WORKDIR /api
|
||||||
|
|
||||||
|
COPY ./package-lock.json .
|
||||||
|
COPY ./package.json .
|
||||||
|
COPY ./server ./server
|
||||||
|
|
||||||
|
# Build
|
||||||
|
RUN npm install --prefix /api
|
||||||
|
|
||||||
|
EXPOSE 3000
|
|
@ -1,8 +1,20 @@
|
||||||
{
|
{
|
||||||
"questions": [
|
"questions": [
|
||||||
{
|
{
|
||||||
"q": "Vous travaillez sur votre projet de visualisation de données durant la pause. Vous voudriez pouvoir y passer plus de temps, mais votre cours de team-building va commencer.",
|
"text": "Vous travaillez sur votre projet de visualisation de données durant la pause. Vous voudriez pouvoir y passer plus de temps, mais votre cours de team-building va commencer.",
|
||||||
"a": 1
|
"answer": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "Le BDE de l'école organise une soirée de ouf. Ça se passe mercredi soir.",
|
||||||
|
"answer": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "Vous sortez d'un week-end d'intégration aux Bahamas, après 6 heures de vol. Nico vous propose un petit \"after-WEI\" dans un bar proche de l'école.",
|
||||||
|
"answer": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "Vous êtes en retard sur vos cours, vous vous demandez comment vous allez passer le prochain partiel. Soudain, votre intervenant vous propose de venir dîner chez lui pour en discuter.",
|
||||||
|
"answer": 1
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
{
|
{
|
||||||
"schools": [{ "id": 1, "name": "Hetic" }, { "id": 2, "name": "EEMI" }]
|
"schools": [{ "id": 1, "name": "HÉTIC" }, { "id": 2, "name": "EEMI" }]
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "server",
|
"name": "server",
|
||||||
"private": true,
|
"private": false,
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
|
|
Loading…
Reference in New Issue