зеркало из https://github.com/mozilla/code-review.git
Build frontend with webpack 5 (#1211)
* Clean slate * Dev server * API calls & HTML template * Prod build too * Base of eslint * running eslint * Generated fixes * Last lint fixes * Remove useless comments * Bump node image on CI * Remove public path option for CI build * Remove deprecated packages * Update README
This commit is contained in:
Родитель
60ea694b00
Коммит
96430dfb0b
|
@ -217,7 +217,7 @@ tasks:
|
|||
deadline: {$fromNow: '1 hour'}
|
||||
payload:
|
||||
maxRunTime: 3600
|
||||
image: node:11-alpine
|
||||
image: node:16-alpine
|
||||
env:
|
||||
BACKEND_URL: "${backend_url}"
|
||||
command:
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
module.exports = {
|
||||
root: true,
|
||||
extends: [
|
||||
'standard',
|
||||
'plugin:vue/base'
|
||||
],
|
||||
globals: {
|
||||
process: true,
|
||||
BACKEND_URL: true,
|
||||
},
|
||||
|
||||
parser: 'vue-eslint-parser',
|
||||
parserOptions: {
|
||||
ecmaFeatures: {
|
||||
generators: true,
|
||||
impliedStrict: true,
|
||||
objectLiteralDuplicateProperties: false
|
||||
},
|
||||
ecmaVersion: 2017,
|
||||
parser: '@babel/eslint-parser',
|
||||
sourceType: 'module'
|
||||
},
|
||||
plugins: [
|
||||
'babel',
|
||||
'vue'
|
||||
],
|
||||
rules: {
|
||||
'babel/new-cap': [
|
||||
'error',
|
||||
{
|
||||
newIsCap: true
|
||||
}
|
||||
],
|
||||
'babel/object-curly-spacing': [
|
||||
'error',
|
||||
'always'
|
||||
],
|
||||
'new-cap': 'off',
|
||||
'object-curly-spacing': 'off'
|
||||
},
|
||||
settings: {},
|
||||
};
|
|
@ -1,49 +0,0 @@
|
|||
fs = require('fs');
|
||||
|
||||
const envs = {
|
||||
CONFIG: process.env.CONFIG || 'staging',
|
||||
BACKEND_URL: process.env.BACKEND_URL || 'http://localhost:8000',
|
||||
};
|
||||
const PORT = process.env.PORT || 8010;
|
||||
// HTTPS can be disabled by setting HTTPS_DISABLED environment variable to
|
||||
// true. Otherwise it will enforced either using automatically generated
|
||||
// certificates or pre-generated ones.
|
||||
const HTTPS = process.env.HTTPS_DISABLED ? false :
|
||||
(process.env.SSL_CERT && process.env.SSL_KEY && process.env.SSL_CACERT) ?
|
||||
{
|
||||
cert: fs.readFileSync(process.env.SSL_CERT),
|
||||
key: fs.readFileSync(process.env.SSL_KEY),
|
||||
ca: fs.readFileSync(process.env.SSL_CACERT)
|
||||
}
|
||||
: true;
|
||||
|
||||
// Set environment variables to their default values if not defined
|
||||
Object.keys(envs).forEach(env => !(env in process.env) && (process.env[env] = envs[env]));
|
||||
|
||||
module.exports = {
|
||||
use: [
|
||||
'@neutrinojs/standardjs',
|
||||
[
|
||||
'@neutrinojs/vue',
|
||||
{
|
||||
html: {
|
||||
title: 'Mozilla Code Review Bot'
|
||||
},
|
||||
devServer: {
|
||||
port: PORT,
|
||||
https: HTTPS,
|
||||
disableHostCheck: true,
|
||||
historyApiFallback: {
|
||||
rewrites: [
|
||||
{ from: '__heartbeat__', to: 'views/ok.html' },
|
||||
{ from: '__lbheartbeat__', to: 'views/ok.html' },
|
||||
{ from: '__version__', to: 'views/version.json' },
|
||||
],
|
||||
},
|
||||
}
|
||||
}
|
||||
],
|
||||
'@neutrinojs/mocha',
|
||||
['@neutrinojs/env', Object.keys(envs)],
|
||||
]
|
||||
};
|
|
@ -3,11 +3,23 @@ Code Review Frontend
|
|||
|
||||
This is a simple Vue.JS administration frontend, the production instance is publicly available at https://code-review.moz.tools/
|
||||
|
||||
You'll need Node 16+ to be able to build it.
|
||||
|
||||
Developer setup
|
||||
---------------
|
||||
|
||||
```
|
||||
npm install
|
||||
npm run build # to build once
|
||||
npm run start # to start a dev server
|
||||
npm run build # to build once in production mode
|
||||
npm run build:dev # to build once in development mode
|
||||
npm run start # to start a dev server on port 8010
|
||||
```
|
||||
|
||||
|
||||
Linting
|
||||
-------
|
||||
|
||||
eslint is available through:
|
||||
|
||||
- `npm run lint` to list potential errors,
|
||||
- `npm run lint:fix` to automatically fix these errors.
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
{
|
||||
"plugins": [
|
||||
"@babel/plugin-syntax-dynamic-import"
|
||||
],
|
||||
"presets": [
|
||||
[
|
||||
"@babel/preset-env",
|
||||
{
|
||||
"debug": false,
|
||||
"exclude": [
|
||||
"transform-regenerator",
|
||||
"transform-async-to-generator"
|
||||
],
|
||||
"modules": false,
|
||||
"targets": {
|
||||
"browsers": [
|
||||
"last 2 Chrome versions",
|
||||
"last 2 Firefox versions",
|
||||
"last 2 Edge versions",
|
||||
"last 2 Opera versions",
|
||||
"last 2 Safari versions",
|
||||
"last 2 iOS versions"
|
||||
]
|
||||
},
|
||||
"useBuiltIns": false
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -9,6 +9,7 @@
|
|||
"axios": "^0.27.2",
|
||||
"bulma": "^0.9.4",
|
||||
"chartist": "^0.11.4",
|
||||
"lodash": "^4.17.21",
|
||||
"vue": "^2.7.1",
|
||||
"vue-chartist": "^2.3.1",
|
||||
"vue-router": "^3.5.4",
|
||||
|
@ -16,16 +17,34 @@
|
|||
"vuex": "^3.6.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@neutrinojs/mocha": "^8.3.0",
|
||||
"@neutrinojs/standardjs": "^8.3.0",
|
||||
"@neutrinojs/vue": "^8.3.0",
|
||||
"neutrino": "^8.3.0"
|
||||
"@babel/eslint-parser": "^7.18.2",
|
||||
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
|
||||
"@babel/preset-env": "^7.18.6",
|
||||
"babel-loader": "^8.2.5",
|
||||
"clean-webpack-plugin": "^4.0.0",
|
||||
"eslint": "^8.19.0",
|
||||
"eslint-config-standard": "^17.0.0",
|
||||
"eslint-plugin-babel": "^5.3.1",
|
||||
"eslint-plugin-import": "^2.26.0",
|
||||
"eslint-plugin-n": "^15.2.4",
|
||||
"eslint-plugin-promise": "^6.0.0",
|
||||
"eslint-plugin-vue": "^9.1.1",
|
||||
"html-webpack-plugin": "^5.5.0",
|
||||
"mini-css-extract-plugin": "^2.6.1",
|
||||
"process": "^0.11.10",
|
||||
"style-loader": "^3.3.1",
|
||||
"vue-loader": "^15.9.8",
|
||||
"webpack": "^5.73.0",
|
||||
"webpack-cli": "^4.10.0",
|
||||
"webpack-dev-server": "^4.9.3",
|
||||
"webpack-merge": "^5.8.0"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "neutrino build",
|
||||
"start": "neutrino start",
|
||||
"lint": "neutrino lint",
|
||||
"test": "neutrino test"
|
||||
"build": "webpack --mode=production",
|
||||
"build:dev": "webpack --mode=development",
|
||||
"start": "webpack serve --mode=development",
|
||||
"lint": "eslint *.js src/**/*.js src/**/*.vue",
|
||||
"lint:fix": "eslint --fix *.js src/**/*.js src/**/*.vue"
|
||||
},
|
||||
"keywords": [],
|
||||
"license": "MPLv2"
|
||||
|
|
|
@ -3,7 +3,7 @@ export default {
|
|||
name: 'App',
|
||||
computed: {
|
||||
backend_url () {
|
||||
return this.$store.state.backend_url
|
||||
return BACKEND_URL
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,8 +25,8 @@ import mixins from './mixins.js'
|
|||
|
||||
export default {
|
||||
props: {
|
||||
'name': String,
|
||||
'choices': Array
|
||||
name: String,
|
||||
choices: Array
|
||||
},
|
||||
mixins: [
|
||||
mixins.query
|
||||
|
@ -48,7 +48,7 @@ export default {
|
|||
computed: {
|
||||
current () {
|
||||
let current = null
|
||||
let choice = this.choice || this.$route.query[this.name]
|
||||
const choice = this.choice || this.$route.query[this.name]
|
||||
if (choice && this.choices) {
|
||||
current = this.choices.find(c => c === choice || c.value === choice)
|
||||
if (!current) {
|
||||
|
|
|
@ -72,14 +72,14 @@ export default {
|
|||
return this.$store.state.diffs.results
|
||||
},
|
||||
repositories () {
|
||||
let repos = this.$store.state.repositories || []
|
||||
const repos = this.$store.state.repositories || []
|
||||
return repos.map(r => r.slug)
|
||||
}
|
||||
},
|
||||
filters: {
|
||||
treeherder_url (diff) {
|
||||
let rev = diff.mercurial_hash
|
||||
let tryRepo = diff.revision.repository === 'nss' ? 'nss-try' : 'try'
|
||||
const rev = diff.mercurial_hash
|
||||
const tryRepo = diff.revision.repository === 'nss' ? 'nss-try' : 'try'
|
||||
return `https://treeherder.mozilla.org/#/jobs?repo=${tryRepo}&revision=${rev}`
|
||||
},
|
||||
short_repo (url) {
|
||||
|
|
|
@ -32,13 +32,13 @@ export default {
|
|||
},
|
||||
mounted () {
|
||||
// Update filters from query string
|
||||
let newForRevision = parseInt(this.$route.query.issue)
|
||||
const newForRevision = parseInt(this.$route.query.issue)
|
||||
this.filters.publishable = isNaN(newForRevision) ? null : this.choices.publishable[newForRevision]
|
||||
this.filters.path = this.$route.query.path || null
|
||||
this.filters.analyzer = this.$route.query.analyzer || null
|
||||
|
||||
// Load diff
|
||||
var diff = this.$store.dispatch('load_diff', this.$route.params.diffId)
|
||||
const diff = this.$store.dispatch('load_diff', this.$route.params.diffId)
|
||||
diff.then(
|
||||
(response) => {
|
||||
this.$set(this, 'state', 'loaded')
|
||||
|
@ -54,12 +54,12 @@ export default {
|
|||
},
|
||||
paths () {
|
||||
// List sorted unique paths as choices
|
||||
let uniquePaths = new Set(this.all_issues.map(i => i.path))
|
||||
const uniquePaths = new Set(this.all_issues.map(i => i.path))
|
||||
return [...uniquePaths].sort()
|
||||
},
|
||||
analyzers () {
|
||||
// List sorted unique analyzers as choices
|
||||
let uniqueAnalyzers = new Set(this.all_issues.map(i => i.analyzer))
|
||||
const uniqueAnalyzers = new Set(this.all_issues.map(i => i.analyzer))
|
||||
return [...uniqueAnalyzers].sort()
|
||||
},
|
||||
nb_publishable () {
|
||||
|
|
|
@ -16,10 +16,10 @@ export default {
|
|||
},
|
||||
paths () {
|
||||
// Load all issues
|
||||
let paths = new Set()
|
||||
for (let diff of this.revision.diffs) {
|
||||
let issues = this.$store.state.issues[diff.id] || []
|
||||
for (let issue of issues) {
|
||||
const paths = new Set()
|
||||
for (const diff of this.revision.diffs) {
|
||||
const issues = this.$store.state.issues[diff.id] || []
|
||||
for (const issue of issues) {
|
||||
paths.add(issue.path)
|
||||
}
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ export default {
|
|||
},
|
||||
methods: {
|
||||
path_issues (diffId, path) {
|
||||
let issues = this.$store.state.issues[diffId] || []
|
||||
const issues = this.$store.state.issues[diffId] || []
|
||||
return issues.filter(issue => issue.path === path)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ export default {
|
|||
|
||||
return {
|
||||
// Data filters
|
||||
since: since,
|
||||
since,
|
||||
analyzer: null,
|
||||
repository: null,
|
||||
check: null,
|
||||
|
@ -45,7 +45,7 @@ export default {
|
|||
},
|
||||
methods: {
|
||||
load (reset) {
|
||||
let payload = {}
|
||||
const payload = {}
|
||||
if (reset === true || this.since === '') {
|
||||
this.$set(this, 'since', null)
|
||||
} else {
|
||||
|
|
|
@ -15,7 +15,7 @@ export default {
|
|||
}
|
||||
},
|
||||
components: {
|
||||
Choice: Choice
|
||||
Choice
|
||||
},
|
||||
data: function () {
|
||||
return {
|
||||
|
@ -69,7 +69,7 @@ export default {
|
|||
// Filter by revision
|
||||
if (this.filters.revision !== null) {
|
||||
tasks = _.filter(tasks, t => {
|
||||
let payload = t.data.title + t.data.bugzilla_id + t.data.phid + t.data.diff_phid + t.data.id + t.data.diff_id
|
||||
const payload = t.data.title + t.data.bugzilla_id + t.data.phid + t.data.diff_phid + t.data.id + t.data.diff_id
|
||||
return payload.toLowerCase().indexOf(this.filters.revision.toLowerCase()) !== -1
|
||||
})
|
||||
}
|
||||
|
@ -83,7 +83,7 @@ export default {
|
|||
return this.$store.state.tasks ? this.$store.state.tasks.length : 0
|
||||
},
|
||||
states () {
|
||||
let currentTasks = this.$store.state.tasks
|
||||
const currentTasks = this.$store.state.tasks
|
||||
const states = currentTasks.reduce((states, task) => {
|
||||
if (states[task.data.state] === undefined) {
|
||||
states[task.data.state] = 0
|
||||
|
@ -94,12 +94,12 @@ export default {
|
|||
|
||||
// Order states by their nb, and calc percents
|
||||
return Object.keys(states).map(state => {
|
||||
let nb = states[state]
|
||||
const nb = states[state]
|
||||
return {
|
||||
'key': state,
|
||||
'name': state.startsWith('error.') ? 'error: ' + state.substring(6) : state,
|
||||
'nb': nb,
|
||||
'percent': currentTasks && currentTasks.length > 0 ? Math.round(nb * 100 / currentTasks.length) : 0
|
||||
key: state,
|
||||
name: state.startsWith('error.') ? 'error: ' + state.substring(6) : state,
|
||||
nb,
|
||||
percent: currentTasks && currentTasks.length > 0 ? Math.round(nb * 100 / currentTasks.length) : 0
|
||||
}
|
||||
}).sort((x, y) => { return y.nb - x.nb })
|
||||
},
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="<%= htmlWebpackPlugin.options.lang %>">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title><%= htmlWebpackPlugin.options.title %></title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
</html>
|
|
@ -3,14 +3,14 @@ export default {
|
|||
methods: {
|
||||
update_query (name, value) {
|
||||
console.log('update query', name, value)
|
||||
var query = Object.assign({}, this.$route.query)
|
||||
const query = Object.assign({}, this.$route.query)
|
||||
if (value !== null && value !== '') {
|
||||
query[name] = value
|
||||
} else if (name in query) {
|
||||
delete query[name]
|
||||
}
|
||||
if (this.$router) {
|
||||
this.$router.push({ 'query': query })
|
||||
this.$router.push({ query })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -32,8 +32,8 @@ export default {
|
|||
filters: {
|
||||
// Display time since elapsed in a human format
|
||||
since (datetime) {
|
||||
var dspStep = (t, name) => {
|
||||
let x = Math.round(t)
|
||||
const dspStep = (t, name) => {
|
||||
const x = Math.round(t)
|
||||
if (x === 0) {
|
||||
return ''
|
||||
}
|
||||
|
@ -41,15 +41,15 @@ export default {
|
|||
}
|
||||
|
||||
let diff = (new Date() - new Date(datetime)) / 1000
|
||||
let steps = [
|
||||
const steps = [
|
||||
[60, 'second'],
|
||||
[60, 'minute'],
|
||||
[24, 'hour'],
|
||||
[30, 'day'],
|
||||
[12, 'month']
|
||||
]
|
||||
var prev = ''
|
||||
for (let [t, name] of steps) {
|
||||
let prev = ''
|
||||
for (const [t, name] of steps) {
|
||||
if (diff > t) {
|
||||
prev = dspStep(diff % t, name)
|
||||
diff = diff / t
|
||||
|
|
|
@ -7,7 +7,7 @@ const TASKCLUSTER_DIFF_INDEX = 'https://index.taskcluster.net/v1/task/project.re
|
|||
|
||||
export default new Vuex.Store({
|
||||
state: {
|
||||
backend_url: process.env.BACKEND_URL,
|
||||
backend_url: BACKEND_URL,
|
||||
tasks: [],
|
||||
diffs: {},
|
||||
stats: null,
|
||||
|
@ -33,7 +33,7 @@ export default new Vuex.Store({
|
|||
},
|
||||
|
||||
use_tasks (state, tasks) {
|
||||
state.tasks = state.tasks.concat(tasks['tasks'])
|
||||
state.tasks = state.tasks.concat(tasks.tasks)
|
||||
},
|
||||
|
||||
use_diffs (state, diffs) {
|
||||
|
@ -47,7 +47,7 @@ export default new Vuex.Store({
|
|||
},
|
||||
|
||||
use_revision (state, payload) {
|
||||
state.revision = Object.assign(payload.revision, { 'diffs': payload.diffs })
|
||||
state.revision = Object.assign(payload.revision, { diffs: payload.diffs })
|
||||
},
|
||||
|
||||
// Store a new diff to display
|
||||
|
@ -60,8 +60,8 @@ export default new Vuex.Store({
|
|||
|
||||
// Add issues to a diff
|
||||
add_issues (state, payload) {
|
||||
let update = {}
|
||||
let issues = state.issues[payload.diffId] || []
|
||||
const update = {}
|
||||
const issues = state.issues[payload.diffId] || []
|
||||
update[payload.diffId] = issues.concat(payload.issues)
|
||||
state.issues = Object.assign({}, state.issues, update)
|
||||
},
|
||||
|
@ -86,24 +86,24 @@ export default new Vuex.Store({
|
|||
// Load Phabricator diffs from our backend
|
||||
// Load a single page at once, providing pagination state
|
||||
load_diffs (state, payload) {
|
||||
let url = payload.url || this.state.backend_url + '/v1/diff/'
|
||||
const url = payload.url || BACKEND_URL + '/v1/diff/'
|
||||
|
||||
let params = payload.query || {}
|
||||
return axios.get(url, { params: params }).then(resp => {
|
||||
const params = payload.query || {}
|
||||
return axios.get(url, { params }).then(resp => {
|
||||
state.commit('use_diffs', resp.data)
|
||||
})
|
||||
},
|
||||
|
||||
// Load a specific diff and its issues
|
||||
load_diff (state, diffId) {
|
||||
let url = this.state.backend_url + '/v1/diff/' + diffId
|
||||
const url = BACKEND_URL + '/v1/diff/' + diffId
|
||||
state.commit('use_diff', null)
|
||||
return axios.get(url).then(resp => {
|
||||
state.commit('use_diff', resp.data)
|
||||
|
||||
// Load all issues in that diff
|
||||
state.dispatch('load_issues', {
|
||||
diffId: diffId,
|
||||
diffId,
|
||||
url: resp.data.issues_url
|
||||
})
|
||||
}).catch(err => {
|
||||
|
@ -133,9 +133,9 @@ export default new Vuex.Store({
|
|||
if (payload.url === undefined) {
|
||||
state.commit('reset_stats')
|
||||
}
|
||||
const url = payload.url || this.state.backend_url + '/v1/check/stats/'
|
||||
const url = payload.url || BACKEND_URL + '/v1/check/stats/'
|
||||
|
||||
let params = {}
|
||||
const params = {}
|
||||
if (payload.since !== undefined) {
|
||||
params.since = payload.since
|
||||
}
|
||||
|
@ -157,8 +157,8 @@ export default new Vuex.Store({
|
|||
|
||||
// Store new issues for that check
|
||||
load_check_issues (state, payload) {
|
||||
const url = payload.url || this.state.backend_url + `/v1/check/${payload.repository}/${payload.analyzer}/${payload.check}/`
|
||||
let params = {}
|
||||
const url = payload.url || BACKEND_URL + `/v1/check/${payload.repository}/${payload.analyzer}/${payload.check}/`
|
||||
const params = {}
|
||||
if (payload.publishable !== undefined) {
|
||||
params.publishable = payload.publishable
|
||||
}
|
||||
|
@ -171,7 +171,7 @@ export default new Vuex.Store({
|
|||
},
|
||||
|
||||
load_repositories (state, payload) {
|
||||
let url = this.state.backend_url + '/v1/repository/'
|
||||
const url = BACKEND_URL + '/v1/repository/'
|
||||
|
||||
return axios.get(url).then(resp => {
|
||||
// Assume we only have one page here
|
||||
|
@ -182,15 +182,15 @@ export default new Vuex.Store({
|
|||
// Retrieve diff data stored in Taskcluster index
|
||||
// Do not persist that data in our store
|
||||
load_taskcluster_diff (state, payload) {
|
||||
let url = TASKCLUSTER_DIFF_INDEX + payload.id
|
||||
const url = TASKCLUSTER_DIFF_INDEX + payload.id
|
||||
return axios.get(url)
|
||||
},
|
||||
|
||||
// Load a specific revision and its diffs
|
||||
load_revision (state, payload) {
|
||||
return Promise.all([
|
||||
axios.get(this.state.backend_url + '/v1/revision/' + payload.id),
|
||||
axios.get(this.state.backend_url + '/v1/revision/' + payload.id + '/diffs/')
|
||||
axios.get(BACKEND_URL + '/v1/revision/' + payload.id),
|
||||
axios.get(BACKEND_URL + '/v1/revision/' + payload.id + '/diffs/')
|
||||
]).then(([respRevision, respDiffs]) => {
|
||||
// Store revision & diffs data
|
||||
state.commit('use_revision', {
|
||||
|
@ -199,7 +199,7 @@ export default new Vuex.Store({
|
|||
})
|
||||
|
||||
// Start loading issues for each diff
|
||||
for (let diff of respDiffs.data.results) {
|
||||
for (const diff of respDiffs.data.results) {
|
||||
state.dispatch('load_issues', {
|
||||
diffId: diff.id,
|
||||
url: diff.issues_url
|
||||
|
@ -210,7 +210,7 @@ export default new Vuex.Store({
|
|||
|
||||
// Load Phabricator indexed tasks summary from Taskcluster
|
||||
load_index (state, payload) {
|
||||
let channel = payload.channel || 'production'
|
||||
const channel = payload.channel || 'production'
|
||||
let url = `https://firefox-ci-tc.services.mozilla.com/api/index/v1/tasks/project.relman.${channel}.code-review.phabricator.diff?limit=200`
|
||||
if (payload && payload.continuationToken) {
|
||||
url += '&continuationToken=' + payload.continuationToken
|
||||
|
@ -218,7 +218,7 @@ export default new Vuex.Store({
|
|||
return axios.get(url).then(resp => {
|
||||
state.commit('use_tasks', {
|
||||
tasks: resp.data.tasks,
|
||||
url: url
|
||||
url
|
||||
})
|
||||
|
||||
// Continue loading available tasks
|
||||
|
@ -232,8 +232,8 @@ export default new Vuex.Store({
|
|||
},
|
||||
|
||||
load_history (state, payload) {
|
||||
let url = this.state.backend_url + '/v1/check/history/'
|
||||
let params = payload || {}
|
||||
const url = BACKEND_URL + '/v1/check/history/'
|
||||
const params = payload || {}
|
||||
|
||||
// Reset
|
||||
state.commit('use_history', [])
|
||||
|
|
|
@ -0,0 +1,131 @@
|
|||
const path = require('path')
|
||||
const HtmlWebpackPlugin = require('html-webpack-plugin')
|
||||
const { merge } = require('webpack-merge')
|
||||
const webpack = require('webpack')
|
||||
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
|
||||
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
|
||||
|
||||
const { VueLoaderPlugin } = require('vue-loader')
|
||||
|
||||
const common = {
|
||||
context: path.resolve(__dirname),
|
||||
entry: ['./src/index.js'],
|
||||
|
||||
resolve: {
|
||||
extensions: ['.js', '.vue']
|
||||
},
|
||||
|
||||
output: {
|
||||
path: path.resolve(__dirname, 'build'),
|
||||
filename: '[name].bundle.js'
|
||||
},
|
||||
|
||||
plugins: [
|
||||
|
||||
new VueLoaderPlugin(),
|
||||
|
||||
new HtmlWebpackPlugin({
|
||||
title: 'Mozilla Code Review Bot',
|
||||
filename: 'index.html',
|
||||
template: './src/index.html'
|
||||
}),
|
||||
|
||||
new webpack.ProvidePlugin({
|
||||
process: 'process/browser'
|
||||
}),
|
||||
|
||||
// Define backend url as constant
|
||||
// using an environment variable with fallback for devs
|
||||
new webpack.DefinePlugin({
|
||||
BACKEND_URL: JSON.stringify(process.env.BACKEND_URL || 'http://localhost:8000')
|
||||
}),
|
||||
|
||||
new MiniCssExtractPlugin({
|
||||
filename: '[name].[contenthash:8].css'
|
||||
})
|
||||
],
|
||||
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.vue$/,
|
||||
loader: 'vue-loader'
|
||||
},
|
||||
{
|
||||
test: /\.js$/,
|
||||
exclude: /node_modules/,
|
||||
use: ['babel-loader']
|
||||
},
|
||||
{
|
||||
test: /\.(scss|css)$/,
|
||||
use: [
|
||||
MiniCssExtractPlugin.loader,
|
||||
{
|
||||
loader: 'css-loader',
|
||||
options: {
|
||||
importLoaders: 0
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
// Images: Copy image files to build folder
|
||||
{ test: /\.(?:ico|gif|png|jpg|jpeg)$/i, type: 'asset/resource' },
|
||||
|
||||
// Fonts and SVGs: Inline files
|
||||
{ test: /\.(woff(2)?|eot|ttf|otf|svg|)$/, type: 'asset/inline' }
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
const development = {
|
||||
mode: 'development',
|
||||
|
||||
devtool: 'eval-cheap-module-source-map',
|
||||
|
||||
devServer: {
|
||||
port: 8010,
|
||||
hot: true,
|
||||
historyApiFallback: true,
|
||||
open: true
|
||||
}
|
||||
}
|
||||
|
||||
const production = {
|
||||
mode: 'production',
|
||||
|
||||
devtool: 'source-map',
|
||||
|
||||
optimization: {
|
||||
minimize: true,
|
||||
splitChunks: {
|
||||
chunks: 'all',
|
||||
maxInitialRequests: 5,
|
||||
name: false
|
||||
},
|
||||
runtimeChunk: 'single'
|
||||
},
|
||||
|
||||
performance: {
|
||||
hints: 'error',
|
||||
maxAssetSize: 1782579.2,
|
||||
maxEntrypointSize: 2621440
|
||||
},
|
||||
|
||||
plugins: [
|
||||
new CleanWebpackPlugin({
|
||||
verbose: false
|
||||
})
|
||||
]
|
||||
}
|
||||
|
||||
module.exports = (env, args) => {
|
||||
switch (args.mode) {
|
||||
case 'development':
|
||||
return merge(common, development)
|
||||
case 'production':
|
||||
return merge(common, production)
|
||||
default:
|
||||
throw new Error('No matching configuration was found!')
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче