Commit 398fdd07 authored by Jean Rabreau's avatar Jean Rabreau
Browse files

Merge branch 'release/0.2.0'

parents 169e7f95 39a42412
Pipeline #46005 passed with stages
in 6 minutes and 20 seconds
NODE_ENV=production
VUE_APP_NAME=pount
VUE_APP_LOGO=https://gitlab.com/uploads/-/system/project/avatar/18299282/pount-front-neunoeuil.png
VUE_APP_AXIOS_BASE_URL=http://localhost:8000/api/
NODE_ENV=production
VUE_APP_NAME=pount
VUE_APP_LOGO=https://gitlab.com/uploads/-/system/project/avatar/18299282/pount-front-neunoeuil.png
VUE_APP_AXIOS_BASE_URL=https://pount-api-pprd.app.unistra.fr/api/
VUE_APP_SENTRY_TAG=preprod
NODE_ENV=production
VUE_APP_NAME=pount
VUE_APP_LOGO=https://gitlab.com/uploads/-/system/project/avatar/18299282/pount-front-neunoeuil.png
VUE_APP_AXIOS_BASE_URL=https://pount-api-test.app.unistra.fr/api/
NODE_ENV=test
VUE_APP_NAME=pount
VUE_APP_LOGO=https://gitlab.com/uploads/-/system/project/avatar/18299282/pount-front-neunoeuil.png
VUE_APP_AXIOS_BASE_URL=http://localhost:8000/api/
......@@ -24,3 +24,7 @@ yarn-error.log*
*.njsproj
*.sln
*.sw?
# coverage
.nyc_output
coverage
@vue-unistra:registry=https://git.unistra.fr/api/v4/packages/npm/
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
]
],
plugins: [ "istanbul" ]
}
#!/bin/bash
set -e
PROJECT="pount-front"
if [ ! $# -ge 2 ]; then
echo "👉 Usage: $0 branch/tag goal IRL: $0 feature/introduce_bug prod"
exit 1
fi
# Be aware that if you change next line see line 15 & 103 !
TEMP=$(mktemp -d)
REPOSITORY=$(pwd)
DISTANT_REPO="git@git.unistra.fr/community/pount-front" #$(git config --get remote.origin.url)
WORKING_DIR="$TEMP/git-clone"
DEST_PATH="/var/www/static/pount-app"
# Shall we install ningx config files ?
SETUP_NGINX=false
# Shall we use sentry ?
# if so sentry-cli is required !!!!
USE_SENTRY=false
TEST_HOSTS=("root@django-test2.di.unistra.fr")
TEST_NGINX_CONF="pount-test.app.unistra.fr"
PREPROD_HOSTS=("root@rp-dip-pprd-public.di.unistra.fr")
PREPROD_NGINX_CONF="pount-pprd.app.unistra.fr"
PROD_HOSTS=("root@rp-dip-public-m.di.unistra.fr" "root@rp-dip-public-s.di.unistra.fr")
PROD_NGINX_CONF="pount.unistra.fr"
# Json info file template
TEMPLATE='{"info":{"app_host":"%s","repo_url":"%s","local_user":"%s","tag":"%s","commit_id":"%s"}}'
ENVIRONMENT="$2"
case "$ENVIRONMENT" in
test)
TARGET=${TEST_HOSTS[@]}
HOST="$TEST_NGINX_CONF"
TARGET_NGINX_CONF="$HOST.conf"
SOURCE_ENV_FILE=".env.deploy_test"
;;
preprod)
TARGET=${PREPROD_HOSTS[@]}
HOST="$PREPROD_NGINX_CONF"
TARGET_NGINX_CONF="$HOST.conf"
SOURCE_ENV_FILE=".env.deploy_preprod"
USE_SENTRY=true
;;
prod)
TARGET=${PROD_HOSTS[@}}
HOST="$PROD_NGINX_CONF"
TARGET_NGINX_CONF="$HOST.conf"
SOURCE_ENV_FILE=".env.deploy_prod"
USE_SENTRY=true
;;
esac
echo "ENV : $2"
echo "Branch/Tag : $1"
echo "Target : $TARGET"
# Shall we install nginx config ?
if [ "$SETUP_NGINX" == true ]; then
for i in "${TARGET[@]}"; do
if ! `ssh -q "$i" test -L "/etc/nginx/sites-enabled/$TARGET_NGINX_CONF"`; then
echo "🏗 Setup nginx vhost for $i"
scp -r "nginx/$TARGET_NGINX_CONF" "$i:/etc/nginx/sites-available/"
# TODO: using systemctl instead of service ?
ssh -q "$i" ln -s "/etc/nginx/sites-available/$TARGET_NGINX_CONF /etc/nginx/sites-enabled/$TARGET_NGINX_CONF && service nginx reload"
fi
done
fi
cd "$TEMP"
echo "🍻 Cloning repository"
git clone "$REPOSITORY" "$WORKING_DIR"
cd "$WORKING_DIR"
echo
echo "🔀 Switching to target build"
git checkout $1
# Get last commit id
PROJECT_VERSION=$(git describe --always)
# Create info file for app
echo $(printf "$TEMPLATE" "$HOST" "$DISTANT_REPO" "$(whoami)" "$1" "$PROJECT_VERSION") > "${PROJECT}_info.json"
echo "🏗 Installing npm dependencies"
npm ci
echo "📦 Packaging stuff"
# shellcheck source=/dev/null
. "${SOURCE_ENV_FILE}"
npm run build:$ENVIRONMENT
echo "🚀 Deploying files"
for i in "${TARGET[@]}"; do
echo "Scp files to $i"
ssh -q "$i" mkdir -p $DEST_PATH
echo "destination $DEST_PATH"
scp -r "dist/css" "dist/js" "$i:$DEST_PATH"
scp "dist/index.html" "${PROJECT}_info.json" "$i:$DEST_PATH"
done
# SENTRY
# Sentry needs gitlab repository to be origin
if [ "$USE_SENTRY" == true ]; then
echo "🚧 Manipulating git distant repositories"
git remote remove origin
git remote add origin "$DISTANT_REPO"
PROJECT_VERSION=$(git describe --always)
# Create a release
echo "📌 Telling about $PROJECT_VERSION to Sentry"
sentry-cli releases new -p "$PROJECT" "$PROJECT_VERSION"
# Associate commits with the release
echo "🤖 Associating commits to version"
sentry-cli releases set-commits --auto "$PROJECT_VERSION"
# Declare deployment
echo "🔖 Telling Sentry that we are deploying $PROJECT_VERSION in $ENVIRONMENT"
sentry-cli releases deploys "$PROJECT_VERSION" new -e "$ENVIRONMENT"
fi
# Clean working dir
cd .. && rm -rf "$WORKING_DIR"
echo "🎉 $PROJECT $PROJECT_VERSION successfully deployed"
server {
listen 80;
server_name pount-pprd.app.unistra.fr pount-pprd;
rewrite ^ https://$server_name$request_uri? permanent;
}
server {
listen 443 ssl;
ssl_certificate /etc/ssl/certs/mega_wildcard.pem;
ssl_certificate_key /etc/ssl/private/mega_wildcard.key;
server_name pount-pprd.app.unistra.fr pount-pprd;
charset utf-8;
root /var/www/static/pount-app;
# redirect 404 page to index.html
error_page 404 /index.html;
# Always serve index.html for any request
location / {
try_files $uri $uri/ @rewrites;
}
location @rewrites {
rewrite ^(.+)$ /index.html last;
}
error_log /var/log/nginx/pount-pprd.app.unistra.fr-error.log;
access_log /var/log/nginx/pount-pprd.app.unistra.fr-access.log;
}
server {
listen 80;
server_name pount-test.app.unistra.fr pount-test;
rewrite ^ https://$server_name$request_uri? permanent;
}
server {
listen 443 ssl;
ssl_certificate /etc/ssl/certs/mega_wildcard.pem;
ssl_certificate_key /etc/ssl/private/mega_wildcard.key;
server_name pount-test.app.unistra.fr pount-test;
charset utf-8;
root /var/www/static/pount-app;
# redirect 404 page to index.html
error_page 404 /index.html;
# Always serve index.html for any request
location / {
try_files $uri $uri/ @rewrites;
}
location @rewrites {
rewrite ^(.+)$ /index.html last;
}
error_log /var/log/nginx/pount-test.app.unistra.fr-error.log;
access_log /var/log/nginx/pount-test.app.unistra.fr-access.log;
}
server {
listen 80;
server_name pount.unistra.fr pount;
rewrite ^ https://$server_name$request_uri? permanent;
}
server {
listen 443 ssl;
ssl_certificate /etc/ssl/certs/mega_wildcard.pem;
ssl_certificate_key /etc/ssl/private/mega_wildcard.key;
server_name pount.unistra.fr pount;
charset utf-8;
root /var/www/static/pount-app;
# redirect 404 page to index.html
error_page 404 /index.html;
# Always serve index.html for any request
location / {
try_files $uri $uri/ @rewrites;
}
location @rewrites {
rewrite ^(.+)$ /index.html last;
}
error_log /var/log/nginx/pount.unistra.fr-error.log;
access_log /var/log/nginx/pount.unistra.fr-access.log;
}
module.exports = {
checkCoverage: false,
perFile: true,
skipFull: false,
// sourceMap: false,
// instrument: false,
all: true,
include: [
'src/**/*.vue',
'src/*.vue',
'src/assets/*.js',
'src/store/**/*.js'
],
exclude: [
'src/*.js',
'router/index.js',
'src/plugins/*',
],
reporter: ['lcov', 'text', 'text-summary', 'html'],
extension: ['.js', '.vue'],
}
This diff is collapsed.
......@@ -18,7 +18,7 @@
"https://medium.com/sapioit/why-having-3-numbers-in-the-version-name-is-bad-92fc1f6bc73c",
"https://gist.github.com/jashkenas/cbd2b088e20279ae2c8e"
],
"version": "0.1.0",
"version": "0.2.0",
"@comment private": [
"This whole project is just documentation.",
"Don't publish it in npm as is."
......@@ -27,11 +27,20 @@
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"build:test": "vue-cli-service build --mode deploy_test",
"build:preprod": "vue-cli-service build --mode deploy_preprod",
"build:prod": "vue-cli-service build --mode deploy_prod",
"test:unit": "vue-cli-service test:unit",
"test:coverage": "nyc vue-cli-service test:unit",
"test:e2e": "vue-cli-service test:e2e --env firefox,chrome --headless",
"lint": "vue-cli-service lint"
"lint": "vue-cli-service lint",
"ci": "npm run test:unit && npm run lint"
},
"@comment dependencies": {
"axios": [
"To be able to communicate with servers by calling their APIs.",
"vue-axios doesn't seem to bring much excepted syntactic sugar."
],
"core-js": [
"To use next-gen ECMAScript standards on older browsers.",
"Added by `vue create`, while choosing 'Babel' option."
......@@ -64,10 +73,6 @@
"A Viewtify/Tiptap extension providing a rich TextArea.",
"Used in particular in forms description fields."
],
"axios": [
"To be able to communicate with servers by calling their APIs.",
"vue-axios doesn't seem to bring much excepted syntactic sugar."
],
"vuejs-logger": [
"To get configurable logging.",
"I'm not fond of using a vue-specific logging library, but ...",
......@@ -83,16 +88,20 @@
]
},
"dependencies": {
"axios": "^0.19.2",
"core-js": "^3.6.5",
"firebase": "^7.20.0",
"@sentry/browser": "^5.29.2",
"@sentry/integrations": "^5.29.2",
"@vue-unistra/unistra-formbuilder": "^2.0.7-test",
"axios": "^0.21.1",
"core-js": "^3.8.2",
"jdenticon": "^3.1.0",
"lodash": "^4.17.20",
"tiptap-vuetify": "^2.24.0",
"vue": "^2.6.12",
"vue-i18n": "^8.21.1",
"vue-router": "^3.4.3",
"vuejs-logger": "^1.5.4",
"vuetify": "^2.3.10",
"vuex": "^3.5.1"
"vue-i18n": "^8.22.2",
"vue-router": "^3.4.9",
"vuejs-logger": "^1.5.5",
"vuetify": "^2.4.0",
"vuex": "^3.6.0"
},
"@comment devDependencies": {
"@vue/cli-plugin-babel": [
......@@ -108,6 +117,12 @@
"- `@vue/cli-plugin-eslint`: to use `npm run lint` command",
"- `babel-eslint`: for stuff not yet supported by vanilla eslint"
],
"@vue/cli-plugin-unit-mocha": [
"To use `npm run test:unit` command using mochapack+chai."
],
"@vue/cli-plugin-e2e-nightwatch": [
"To use `npm run test:e2e` command using nightwatch."
],
"@vue/test-utils": [
"To be able to use Vue.js unit testing library.",
"See documentation: https://vue-test-utils.vuejs.org/"
......@@ -116,11 +131,17 @@
"To provide more assertions to Vue.js unit tests as long as extensions.",
"See documentation: https://www.chaijs.com/"
],
"@vue/cli-plugin-unit-mocha": [
"To use `npm run test:unit` command using mochapack+chai."
"sinon": [
"Standalone test spies, stubs and mocks for JavaScript.",
"https://sinonjs.org/"
],
"@vue/cli-plugin-e2e-nightwatch": [
"To use `npm run test:e2e` command using nightwatch."
"nyc": [
"JavaScript test coverage made simple",
"https://istanbul.js.org/"
],
"babel-plugin-istanbul": [
"nyc integration with babel",
"https://github.com/istanbuljs/babel-plugin-istanbul"
],
"chromedriver": [
"Driver for webkit-based browsers used by nightwatch in end-to-end tests.",
......@@ -170,23 +191,28 @@
]
},
"devDependencies": {
"@vue/cli-plugin-babel": "^4.5.6",
"@vue/cli-plugin-e2e-nightwatch": "^4.5.6",
"@vue/cli-plugin-eslint": "^4.5.6",
"@vue/cli-plugin-unit-mocha": "^4.5.6",
"@vue/cli-plugin-vuex": "~4.3.0",
"@vue/cli-service": "^4.5.6",
"@vue/test-utils": "^1.1.0",
"@vue/cli-plugin-babel": "^4.5.9",
"@vue/cli-plugin-e2e-nightwatch": "^4.5.9",
"@vue/cli-plugin-eslint": "^4.5.9",
"@vue/cli-plugin-unit-mocha": "^4.5.9",
"@vue/cli-plugin-vuex": "^4.5.9",
"@vue/cli-service": "^4.5.9",
"@vue/test-utils": "^1.1.2",
"babel-eslint": "^10.0.3",
"babel-plugin-istanbul": "^6.0.0",
"chai": "^4.1.2",
"chromedriver": "^81.0.0",
"eslint": "^6.7.2",
"eslint-plugin-vue": "^6.1.2",
"geckodriver": "^1.20.0",
"null-loader": "^4.0.0",
"sass": "^1.26.10",
"geckodriver": "^1.21.1",
"jwt-simple": "^0.5.6",
"moxios": "^0.4.0",
"null-loader": "^4.0.1",
"nyc": "^15.1.0",
"sass": "^1.32.0",
"sass-loader": "^8.0.0",
"vue-cli-plugin-vuetify": "^2.0.7",
"sinon": "^9.2.2",
"vue-cli-plugin-vuetify": "^2.0.9",
"vue-template-compiler": "^2.6.12",
"vuetify-loader": "^1.6.0"
}
......
<template>
<v-app id='app'>
<v-navigation-drawer app v-model='drawer'>
<v-navigation-drawer app v-model='drawer'>
<template v-slot:prepend>
<v-list dense>
<v-list-item
v-for='item in navItems'
:key="item.text"
link
:to="{name: item.routeName}"
exact
>
<v-list-item-icon>
<v-icon>{{ item.icon }}</v-icon>
</v-list-item-icon>
<v-list-item-title>{{ $t(item.text) }}</v-list-item-title>
</v-list-item>
</v-list>
<v-list dense>
<template v-for='item in items'>
<v-divider/>
</template>
<v-list-group v-if='item.children'
:key='item.text' v-model='item.model'
:prepend-icon='item.model ? item.icon : item["icon-alt"]' append-icon=''
>
<template v-slot:activator>
<v-list-item-content><v-list-item-title>{{ gettext(item.text) }}</v-list-item-title></v-list-item-content>
</template>
<v-list-item v-for='(child, i) in item.children'
:key='i' link
@click='onClick(child)'
>
<v-list-item-action v-if='child.icon'><v-icon>{{ child.icon }}</v-icon></v-list-item-action>
<v-list-item-content><v-list-item-title>{{ gettext(child.text) }}</v-list-item-title></v-list-item-content>
</v-list-item>
</v-list-group>
<v-list-item v-else :key='item.text' link :to='item.to'>
<v-list-item-action><v-icon>{{ item.icon }}</v-icon></v-list-item-action>
<v-list-item-content><v-list-item-title>{{ gettext(item.text) }}</v-list-item-title></v-list-item-content>
<v-list-item-action v-if='item.switch'><v-switch primary v-model='isDark' /></v-list-item-action>
</v-list-item>
<template v-slot:append>
<v-divider/>
<v-list dense>
<v-list-item @click.stop="onThemeClick()">
<v-list-item-icon>
<v-icon>{{ themeItem.icon }}</v-icon>
</v-list-item-icon>
<v-list-item-title>{{ themeItem.text }}</v-list-item-title>
<v-list-item-action>
<v-switch primary v-model='isDark' disabled />
</v-list-item-action>
</v-list-item>
<v-list-group
:value="false"
:prepend-icon="languageMenu.icon"
>
<template v-slot:activator>
<v-list-item-title>{{ languageMenu.text }}</v-list-item-title>
</template>
<v-list-item v-for='(child, i) in languageMenu.children'
:key='i' link
@click='onLanguageClick(child.locale)'
>
<v-list-item-icon>
<v-icon>{{ child.icon }}</v-icon>
</v-list-item-icon>
<v-list-item-title>{{ child.text }}</v-list-item-title>
</v-list-item>
</v-list-group>
</v-list>
</template>
</v-list>
</v-navigation-drawer>
</v-navigation-drawer>
<v-app-bar app>
<v-app-bar-nav-icon @click.stop="drawer = !drawer" />
<v-app-bar app>
<v-app-bar-nav-icon @click.stop='drawer = !drawer' />
<v-img :src="logo" class='mx-2' max-height='48' max-width='48' contain/>
<v-toolbar-title id='app__name'>{{ appName }}</v-toolbar-title>
<v-spacer></v-spacer>
<v-img :src='logo' class='mx-2' max-height='48' max-width='48' contain/>
<v-toolbar-title id='appname'>{{ appname }}</v-toolbar-title>
<v-spacer></v-spacer>
<ProfileMenu v-if='isUserSignedIn' />
<SignInButton v-else />
</v-app-bar>
<notifications v-if="isLogged"/>
<ProfileMenu v-if="isLogged" />
<v-main>
<router-view/>
</v-main>
<v-btn v-else
outlined
color='primary'
@click="onSignIn"
>
<v-icon left>mdi-account</v-icon>
{{ $t('signIn.title') }}
</v-btn>
</v-app-bar>
<v-main>
<v-container fluid class="pa-5" >
<router-view/>
</v-container>
</v-main>
<v-footer app>
<span class='white--text'>Environment: "{{ environment }}"</span>
</v-footer>
<v-footer app>
<span class='white--text'>Environment: "{{ environment }}"</span>
</v-footer>
<notify/>
</v-app>
</template>
<script>
import { config } from './plugins/vuetify'
import i18n from '@/plugins/vue-i18n'
import SignInButton from '@/components/auth/SignInButton'
import ProfileMenu from '@/components/auth/ProfileMenu'
import Notify from '@/components/common/NotifySnack'
import {settingsStorage} from '@/assets/storage'
import {LOCALES_MAP} from '@/plugins/vue-i18n'
import authority from '@/assets/authAxios'
import Notifications from "@/components/menu/notifications/Menu";
export default {
name: 'App',
components: { SignInButton, ProfileMenu },
components: {
Notifications,
Notify,
ProfileMenu: () => import(/* webpackChunkName: "auth" */ './components/menu/ProfileMenu')
},
data: () => ({
drawer: null,
environment: process.env.NODE_ENV,
appName: process.env.VUE_APP_NAME,
logo: process.env.VUE_APP_LOGO,
}),
computed: {
isUserSignedIn() { return this.$store.getters['user/isSignedIn']; },
dark() { return this.isDark ? "on" : "off"; },
locale() { return i18n.locale; },
isDark() { return this.$vuetify.theme.dark },
isLogged() { return this.$store.getters['contrib/isLogged'] },
locales() {
const locales = [];
Object.keys(i18n.messages).forEach(locale => {
const payload = { text: `language.${locale}`, locale, };
this.setLocaleIcon(payload);
locales.push(payload);
});
return locales;
return Object.entries(LOCALES_MAP).map(([locale, text]) => {
const check = this.$i18n.locale === locale ? 'check' : ''
return { locale, text, icon: `mdi-${check}`}
})
},
languagesMenu() { return this.items.find(i => i.text === 'menu.language'); }
},
created() {
this.languagesMenu.children = this.locales;
this.isDark = this.$store.getters['settings/dark'] === 'true';
},
methods: {
gettext: function(key) {
let params = {};
if (key === 'menu.dark') params['mode'] = this.$t(this.dark);
if (key === 'menu.language') params['current'] = this.$t(`language.${i18n.locale}`);
return this.$t(key, params);