Skip to content
Snippets Groups Projects
Commit 265b3be4 authored by Erwan Rouchet's avatar Erwan Rouchet Committed by Bastien Abadie
Browse files

Upgrade Webpack

parent e80034b8
No related branches found
No related tags found
No related merge requests found
{
"presets": [
["env", { "modules": false }],
"stage-3"
]
}
module.exports = {
"extends": [
"standard",
"plugin:vue/essential"
]
};
---
extends:
- standard
- eslint:recommended
- plugin:vue/strongly-recommended
- plugin:import/errors
- plugin:import/warnings
plugins:
- vue
- mocha
env:
browser: true
mocha: true
rules:
vue/eqeqeq: warning
vue/this-in-template: 2
vue/singleline-html-element-content-newline: 0
vue/v-on-style:
- 2
- longform
vue/max-attributes-per-line:
- 1
- singleline: 3
vue/html-self-closing:
- 1
- html:
normal: never
void: always
mocha/max-top-level-suites: 1
mocha/no-exclusive-tests: 2
mocha/no-global-tests: 1
mocha/no-nested-tests: 1
mocha/no-pending-tests: 1
mocha/no-skipped-tests: 1
mocha/no-identical-title: 2
mocha/handle-done-callback: 2
mocha/no-return-and-callback: 2
mocha/no-setup-in-describe: 2
mocha/no-sibling-hooks: 2
mocha/no-top-level-hooks: 1
parserOptions:
parser: babel-eslint
settings:
import/resolver: webpack
......@@ -3,14 +3,29 @@ stages:
- test
- build
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
- node_modules/
before_script:
- npm install --no-progress
frontend-test:
stage: test
before_script:
- npm install --no-progress
script:
- npm run test
frontend-lint:
stage: test
script:
- npm run lint
frontend-audit:
stage: test
script:
- npm audit --parseable
frontend-build:
stage: build
artifacts:
......@@ -18,9 +33,8 @@ frontend-build:
- dist
expire_in: 2 weeks
before_script:
- npm install --no-progress
script:
- npm audit --parseable
- npm run production
variables:
API_BASE_URL: /api/v1
Makefile 0 → 100644
ROOT_DIR:=$(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
TAG=arkindex-frontend
TAG_REMOTE=registry.gitlab.com/arkindex/frontend
VERSION=$(shell git rev-parse --short HEAD)
BRANCH=master
.PHONY: all
all: clean build
clean:
rm -rf dist
build:
docker build --no-cache $(ROOT_DIR)/docker -t $(TAG):$(VERSION) -t $(TAG):latest --build-arg BRANCH=$(BRANCH)
publish-version: require-docker-auth
$(MAKE) build TAG=$(TAG_REMOTE)
docker push $(TAG_REMOTE):$(VERSION)
latest: VERSION=latest
latest: publish-version
release:
$(eval version:=$(shell cat VERSION))
$(MAKE) publish-version VERSION=$(version)
arkindex-dev: CONFIG=arkindex-dev
arkindex-dev: latest
arkindex-prod: CONFIG=arkindex-prod
arkindex-prod: release
ark-vpn: CONFIG=ark-vpn
ark-vpn: latest
require-docker-auth:
@grep registry.gitlab.com ~/.docker/config.json > /dev/null || (echo "Docker Login on registry.gitlab.com"; docker login registry.gitlab.com)
# Arkindex Frontend
## Dev Setup
1. Install Node.js 9 or later and NPM
2. Clone the repository
3. `npm install`
## Common operations
* `npm run build`: Build for development, no Docker image
* `npm start`: Start a local development server on `localhost:8080`
* `npm run production`: Build for production, no Docker image
* `npm run lint`: Perform ESLint checks
* `npm run test`: Run unit tests
* `npm run start-test`: Run unit tests, then watch for edits and re-run with each change
* `make build`: Build to a local Docker image using latest GitLab CI artifact
* `make latest`: Build Docker image, tag as latest and push to GitLab
* `make release`: Build Docker image for a version number and push to GitLab
* `make clean`: Clean build stuff
* `make all`: Clean and build
## Linting rules
See the `.eslintrc.yml` file for the exact ESLint settings. The linting rules are based on the following sets:
* [StandardJS](https://standardjs.com/)
* [ESLint Recommended](https://eslint.org/docs/rules/)
* [Vue.js Essential + Strongly Recommended](https://eslint.vuejs.org/rules/)
* [`eslint-plugin-import`](https://www.npmjs.com/package/eslint-plugin-import)
Some rules have been customized:
* Using `==` and `!=` in templates will show warnings — use `===` and `!==` instead ([vue/eqeqeq](https://eslint.vuejs.org/rules/eqeqeq.html));
* Using `this` in a template causes errors — use `text` instead of `this.text` ([vue/this-in-template](https://eslint.vuejs.org/rules/this-in-template.html));
* Single-line HTML elements are allowed to hold content (`<h1>hello</h1>` is allowed);
* To bind JavaScript expressions to attributes, use `:property=""`, not `v-bind:property=""`, but to bind JavaScript expressions to events, use `v-on:event=""`, not `@event=""` ([vue/v-bind-style](https://eslint.vuejs.org/rules/v-bind-style.html), [vue/v-on-style](https://eslint.vuejs.org/rules/v-on-style.html))
* Single-line HTML elements can have up to three attributes ; you have to switch to multiline elements with one attribute per line above that ([vue/max-attributes-per-line](https://eslint.vuejs.org/rules/max-attributes-per-line.html))
* Void elements (HTML elements which do not hold content, like `br`) should be self-closing &mdash; `<br />` instead of `<br>` ([vue/html-self-closing](https://eslint.vuejs.org/rules/html-self-closing.html))
* HTML elements that can hold content like `p` should never be self-closing &mdash; `<p></p>` instead of `<p />` ([vue/html-self-closing](https://eslint.vuejs.org/rules/html-self-closing.html))
module.exports = {
plugins: [
'lodash',
'@babel/plugin-syntax-dynamic-import'
],
presets: [
[
"@babel/preset-env",
{
modules: false
}
]
]
}
FROM alpine:latest as staging
ARG BRANCH=master
ARG PROJECT_ID=4675768
ARG GITLAB_TOKEN="M98p3wihATgCx4Z5ChvK"
RUN apk --update add wget unzip
RUN mkdir /frontend-build \
&& wget --header "PRIVATE-TOKEN: $GITLAB_TOKEN" https://gitlab.com/api/v4/projects/$PROJECT_ID/jobs/artifacts/$BRANCH/download?job=frontend-build -O /tmp/frontend.zip \
&& unzip /tmp/frontend.zip -d /frontend-build
FROM nginx:alpine
RUN rm /etc/nginx/conf.d/default.conf
COPY front.conf /etc/nginx/conf.d/front.conf
COPY --from=staging /frontend-build/dist /frontend
EXPOSE 80
CMD nginx -g 'daemon off;'
server {
listen 80;
gzip on;
gunzip on;
gzip_disable "msie6";
gzip_types "*";
# Look for .gz files in the directory
gzip_static on;
location / {
root /frontend;
index index.html;
try_files $uri $uri/ /index.html =404;
}
}
......@@ -34,3 +34,8 @@ export const IMPORT_STATE_COLORS = {
export const IMPORT_POLLING_DELAY = 1500
export const TASK_POLLING_DELAY = 1500
export const API_BASE_URL = process.env.API_BASE_URL
export const CSRF_COOKIE_NAME = process.env.CSRF_COOKIE || 'arkindex.csrf'
export const CSRF_COOKIE_HEADER = 'X-CSRFToken'
export const VERSION = process.env.VERSION
......@@ -3,20 +3,25 @@ import '../scss/main.scss'
// Vue js setup
import Vue from 'vue'
import Vuex from 'vuex'
import VueRouter from 'vue-router'
import router from './router'
import store from './store'
import App from '../vue/App'
import {
API_BASE_URL,
CSRF_COOKIE_NAME,
CSRF_COOKIE_HEADER
} from './config'
import { defaults } from 'axios'
defaults.baseURL = window.location.origin + '/api/v1'
defaults.xsrfCookieName = 'arkindex.csrf'
defaults.xsrfHeaderName = 'X-CSRFTOKEN'
if (!API_BASE_URL) throw new Error('Missing API_BASE_URL')
defaults.baseURL = API_BASE_URL
defaults.xsrfCookieName = CSRF_COOKIE_NAME
defaults.xsrfHeaderName = CSRF_COOKIE_HEADER
defaults.withCredentials = true
Vue.use(Vuex)
Vue.use(VueRouter)
// Init generic Vue app
......
......@@ -7,21 +7,24 @@ import VolumeActs from '../vue/Acts/Main'
import ElementDetails from '../vue/Element/Details'
import PageSearch from '../vue/Search/Pages'
import ActSearch from '../vue/Search/Acts'
import CorpusList from '../vue/Corpus/List'
import CorpusEdit from '../vue/Corpus/Edit'
import ImportsList from '../vue/Imports/List'
import ImportStatus from '../vue/Imports/Status/Main'
import ImportFailures from '../vue/Imports/Failures'
import FilesList from '../vue/Imports/Files/List'
import ReposList from '../vue/Imports/Repos/List'
import ReposCreate from '../vue/Imports/Repos/Create'
import MLTools from '../vue/Imports/MLTools'
import OAuthList from '../vue/OAuth/List'
import Login from '../vue/Auth/Login'
import Logout from '../vue/Auth/Logout'
import PasswordReset from '../vue/Auth/PasswordReset'
import PasswordResetConfirm from '../vue/Auth/PasswordResetConfirm'
import NotFound from '../vue/NotFound'
import NotFound from '../vue/Errors/NotFound'
import NoBackend from '../vue/Errors/NoBackend'
// Logged in users-only components are split into another JS chunk to improve performance
const CorpusList = () => import(/* webpackChunkName: "users" */ '../vue/Corpus/List')
const CorpusEdit = () => import(/* webpackChunkName: "users" */ '../vue/Corpus/Edit')
const ImportsList = () => import(/* webpackChunkName: "users" */ '../vue/Imports/List')
const ImportStatus = () => import(/* webpackChunkName: "users" */ '../vue/Imports/Status/Main')
const ImportFailures = () => import(/* webpackChunkName: "users" */ '../vue/Imports/Failures')
const FilesList = () => import(/* webpackChunkName: "users" */ '../vue/Imports/Files/List')
const ReposList = () => import(/* webpackChunkName: "users" */ '../vue/Imports/Repos/List')
const ReposCreate = () => import(/* webpackChunkName: "users" */ '../vue/Imports/Repos/Create')
const MLTools = () => import(/* webpackChunkName: "users" */ '../vue/Imports/MLTools')
const OAuthList = () => import(/* webpackChunkName: "users" */ '../vue/OAuth/List')
const routes = [
{
......@@ -166,8 +169,14 @@ const routes = [
name: 'home',
redirect: { name: 'volumes' }
},
{
path: '/errors/unreachable',
name: 'no-backend',
component: NoBackend
},
{
path: '*',
name: 'not-found',
component: NotFound
}
]
......@@ -178,6 +187,9 @@ const router = new VueRouter({
})
router.beforeEach((to, from, next) => {
// Do not try to fetch stuff from the API when opening an error page
if (['no-backend', 'not-found'].includes(to.name)) next()
let p = Promise.resolve()
// Fetch authentication info if that was not already done
if (!store.getters['auth/hasInfo']) p = store.dispatch('auth/get')
......@@ -188,7 +200,7 @@ router.beforeEach((to, from, next) => {
} else {
next()
}
})
}).catch(() => next({ name: 'no-backend' }))
})
export default router
import Vue from 'vue'
import Vuex from 'vuex'
import Vuex, { Store } from 'vuex'
import axios from 'axios'
import { clone } from 'lodash'
......@@ -122,6 +122,7 @@ export const mutations = {
state.error = null
return
}
// eslint-disable-next-line no-console
console.error('API error', error)
state.error = errorParser(error)
}
......@@ -566,7 +567,7 @@ export const actions = {
}
}
export default new Vuex.Store({
export default new Store({
state,
mutations,
actions,
......
This diff is collapsed.
{
"name": "horae-frontend",
"version": "0.1.0",
"description": "",
"main": "index.js",
"directories": {
"test": "tests"
"name": "arkindex",
"version": "0.9.0",
"description": "Arkindex frontend",
"main": "js/index.js",
"dependencies": {},
"devDependencies": {
"@babel/core": "^7.2.2",
"@babel/plugin-syntax-dynamic-import": "^7.2.0",
"@babel/preset-env": "^7.3.1",
"axios": "^0.18.0",
"axios-mock-adapter": "^1.16.0",
"babel-eslint": "^10.0.1",
"babel-loader": "^8.0.5",
"babel-plugin-lodash": "^3.3.4",
"bulma": "^0.7.2",
"bulmaswatch": "^0.7.2",
"clean-webpack-plugin": "^1.0.1",
"compression-webpack-plugin": "^2.0.0",
"css-loader": "^2.1.0",
"eslint": "^5.13.0",
"eslint-config-standard": "^12.0.0",
"eslint-import-resolver-webpack": "^0.11.0",
"eslint-loader": "^2.1.2",
"eslint-plugin-import": "^2.16.0",
"eslint-plugin-mocha": "^5.2.1",
"eslint-plugin-node": "^8.0.1",
"eslint-plugin-promise": "^4.0.1",
"eslint-plugin-standard": "^4.0.0",
"eslint-plugin-vue": "^5.1.0",
"file-loader": "^3.0.1",
"html-webpack-plugin": "^3.2.0",
"lodash": "^4.17.11",
"lodash-webpack-plugin": "^0.11.5",
"mini-css-extract-plugin": "^0.5.0",
"mocha": "^5.2.0",
"node-sass": "^4.11.0",
"optimize-css-assets-webpack-plugin": "^5.0.1",
"sass-loader": "^7.1.0",
"uglifyjs-webpack-plugin": "^2.1.1",
"vue": "^2.6.2",
"vue-loader": "^15.6.2",
"vue-router": "^3.0.2",
"vue-template-compiler": "^2.6.2",
"vuex": "^3.1.0",
"webpack": "^4.29.0",
"webpack-cleanup-plugin": "^0.5.1",
"webpack-cli": "^3.2.1",
"webpack-dev-server": "^3.1.14",
"webpack-shell-plugin": "^0.5.0"
},
"scripts": {
"build": "webpack --config webpack.config.js --progress --colors",
"start": "webpack --config webpack.config.js --progress --colors --watch",
"test": "webpack --config webpack.config.test.js --progress --colors && mocha build/test-bundle.js",
"production": "webpack --config webpack.config.prod.js --progress --colors"
"production": "NODE_ENV=production webpack",
"build": "NODE_ENV=development webpack",
"start": "webpack-dev-server",
"lint": "eslint --ext .js,.vue js vue test",
"test": "webpack --config webpack-test.config.js",
"start-test": "webpack -w --config webpack-test.config.js"
},
"repository": {
"type": "git",
"url": "git@gitlab.com:arkindex/frontend.git"
},
"author": "Bastien Abadie <bastien@nextcairn.com>",
"author": "Teklia <kermorvant@teklia.com>",
"license": "MIT",
"devDependencies": {
"axios-mock-adapter": "^1.15.0",
"babel-core": "^6.26.0",
"babel-loader": "^7.1.2",
"babel-preset-env": "^1.6.0",
"babel-preset-stage-3": "^6.24.1",
"css-loader": "^0.27.3",
"eslint": "^5.8.0",
"eslint-config-standard": "^12.0.0",
"eslint-loader": "^2.1.1",
"eslint-plugin-import": "^2.14.0",
"eslint-plugin-node": "^8.0.0",
"eslint-plugin-promise": "^4.0.1",
"eslint-plugin-standard": "^4.0.0",
"eslint-plugin-vue": "^4.7.1",
"extract-text-webpack-plugin": "^2.1.0",
"file-loader": "^0.10.1",
"mocha": "^5.2.0",
"node-sass": "^4.9.2",
"resolve-url-loader": "^2.0.2",
"sass-loader": "^6.0.3",
"style-loader": "^0.16.0",
"url-loader": "^1.1.2",
"vue-loader": "^11.3.4",
"vue-template-compiler": "^2.2.6",
"webpack": "^2.3.0",
"webpack-bundle-tracker": "^0.4.2-beta",
"webpack-cleanup-plugin": "^0.5.1"
},
"dependencies": {
"axios": "^0.16.2",
"bulma": "^0.6.1",
"bulmaswatch": "^0.7.1",
"lodash": "^4.17.10",
"vue": "^2.4.2",
"vue-router": "^3.0.1",
"vuex": "^2.2.1"
},
"browserslist": [
"> 1%",
"last 2 versions",
......
......@@ -10,20 +10,6 @@
// Fontello icons
@import "../css/arkindex-embedded.css";
body {
display: flex;
min-height: 100vh;
flex-direction: column;
}
main {
flex: 1;
}
main.container, footer {
margin-top: 1em;
}
#details samp.id {
color: lightgray;
font-size: 50%;
......@@ -33,3 +19,7 @@ td.shrink {
width: 1%;
white-space: nowrap;
}
.panel .panel-heading:last-child {
border-radius: $panel-heading-radius;
}
......@@ -3,13 +3,23 @@
min-height: 0;
}
.navbar-item, .navbar-link {
padding-top: 0;
padding-bottom: 0;
@media screen and (min-width: 1088px) {
.navbar-item, .navbar-link {
padding-top: 0;
padding-bottom: 0;
}
.navbar-dropdown .navbar-item {
padding-top: 0.25rem;
padding-bottom: 0.25rem;
}
}
.navbar-dropdown .navbar-item {
padding-top: 0.25rem;
padding-bottom: 0.25rem;
.navbar-menu {
background-color: $dark;
}
.navbar-dropdown {
background-color: $white;
}
.navbar-brand > .navbar-item,
......
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>ArkIndex</title>
</head>
<body>
<div id="app"></div>
</body>
</html>
import Vue from 'vue'
import Vuex from 'vuex'
describe('store', () => {
require('./store')
})
Vue.use(Vuex)
require('./store')
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment