diff --git a/.env b/.env index e44fb32..d9ac634 100644 --- a/.env +++ b/.env @@ -47,4 +47,3 @@ TRAEFIK_PUBLIC_TAG=traefik-public DOCKER_IMAGE_BACKEND=backend DOCKER_IMAGE_CELERYWORKER=celery DOCKER_IMAGE_FRONTEND=frontend -DOCKER_IMAGE_NEW_FRONTEND=new-frontend diff --git a/docker-compose.override.yml b/docker-compose.override.yml index 91abca8..5a6de73 100644 --- a/docker-compose.override.yml +++ b/docker-compose.override.yml @@ -72,15 +72,6 @@ services: args: INSTALL_DEV: ${INSTALL_DEV-true} - frontend: - build: - context: ./frontend - args: - FRONTEND_ENV: dev - labels: - # - traefik.http.routers.${STACK_NAME?Variable not set}-frontend-http.rule=PathPrefix(`/`) - - traefik.http.routers.${STACK_NAME?Variable not set}-frontend-http.rule=Host(`old-frontend.localhost.tiangolo.com`) - networks: traefik-public: # For local dev, don't expect an external Traefik network diff --git a/docker-compose.yml b/docker-compose.yml index bbbe66c..6dc8c8d 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,7 +2,7 @@ version: "3.3" services: proxy: - image: traefik:v2.2 + image: traefik:v2.3 networks: - ${TRAEFIK_PUBLIC_NETWORK?Variable not set} - default @@ -167,24 +167,12 @@ services: frontend: image: '${DOCKER_IMAGE_FRONTEND?Variable not set}:${TAG-latest}' build: - context: ./frontend - args: - FRONTEND_ENV: ${FRONTEND_ENV-production} - labels: - - traefik.enable=true - - traefik.constraint-label-stack=${TRAEFIK_TAG?Variable not set} - - traefik.http.routers.${STACK_NAME?Variable not set}-frontend-http.rule=PathPrefix(`/`) - - traefik.http.services.${STACK_NAME?Variable not set}-frontend.loadbalancer.server.port=80 - -# new-frontend: -# image: '${DOCKER_IMAGE_NEW_FRONTEND?Variable not set}:${TAG-latest}' -# build: -# context: ./new-frontend - # labels: - # - traefik.enable=true - # - traefik.constraint-label-stack=${TRAEFIK_TAG?Variable not set} - # - traefik.http.routers.${STACK_NAME?Variable not set}-new-frontend-http.rule=PathPrefix(`/`) - # - traefik.http.services.${STACK_NAME?Variable not set}-new-frontend.loadbalancer.server.port=80 + context: ./new-frontend + labels: + - traefik.enable=true + - traefik.constraint-label-stack=${TRAEFIK_TAG?Variable not set} + - traefik.http.routers.${STACK_NAME?Variable not set}-frontend-http.rule=PathPrefix(`/`) + - traefik.http.services.${STACK_NAME?Variable not set}-frontend.loadbalancer.server.port=80 volumes: app-db-data: diff --git a/frontend/.dockerignore b/frontend/.dockerignore deleted file mode 100755 index 3c3629e..0000000 --- a/frontend/.dockerignore +++ /dev/null @@ -1 +0,0 @@ -node_modules diff --git a/frontend/.env b/frontend/.env deleted file mode 100644 index 5f27856..0000000 --- a/frontend/.env +++ /dev/null @@ -1,9 +0,0 @@ -VUE_APP_DOMAIN_DEV=localhost -# VUE_APP_DOMAIN_DEV=local.dockertoolbox.tiangolo.com -# VUE_APP_DOMAIN_DEV=localhost.tiangolo.com -VUE_APP_DOMAIN_STAG= -VUE_APP_DOMAIN_PROD= -VUE_APP_NAME= -VUE_APP_ENV=development -# VUE_APP_ENV=staging -# VUE_APP_ENV=production diff --git a/frontend/.gitignore b/frontend/.gitignore deleted file mode 100644 index 185e663..0000000 --- a/frontend/.gitignore +++ /dev/null @@ -1,21 +0,0 @@ -.DS_Store -node_modules -/dist - -# local env files -.env.local -.env.*.local - -# Log files -npm-debug.log* -yarn-debug.log* -yarn-error.log* - -# Editor directories and files -.idea -.vscode -*.suo -*.ntvs* -*.njsproj -*.sln -*.sw* diff --git a/frontend/.nvmrc b/frontend/.nvmrc deleted file mode 100644 index b460d6f..0000000 --- a/frontend/.nvmrc +++ /dev/null @@ -1 +0,0 @@ -18.12.1 diff --git a/frontend/Dockerfile b/frontend/Dockerfile deleted file mode 100644 index 5980c12..0000000 --- a/frontend/Dockerfile +++ /dev/null @@ -1,30 +0,0 @@ -# Stage 0, "build-stage", based on Node.js, to build and compile the frontend -FROM node:18.12.1 as build-stage - -WORKDIR /app - -COPY package*.json /app/ - -RUN npm install - -COPY ./ /app/ - -ARG FRONTEND_ENV=production - -ENV VUE_APP_ENV=${FRONTEND_ENV} - -ENV NODE_OPTIONS="--openssl-legacy-provider" - -# Comment out the next line to disable tests -RUN npm run test:unit - -RUN npm run build - - -# Stage 1, based on Nginx, to have only the compiled app, ready for production with Nginx -FROM nginx:1.15 - -COPY --from=build-stage /app/dist/ /usr/share/nginx/html - -COPY ./nginx.conf /etc/nginx/conf.d/default.conf -COPY ./nginx-backend-not-found.conf /etc/nginx/extra-conf.d/backend-not-found.conf diff --git a/frontend/README.md b/frontend/README.md deleted file mode 100644 index e7c2b09..0000000 --- a/frontend/README.md +++ /dev/null @@ -1,46 +0,0 @@ -# frontend - -## Node Requirements -You can use either [fnm](https://github.com/Schniz/fnm) or [nvm](https://github.com/nvm-sh/nvm) to manage your Node.js versions. - -### Using nvm -If you prefer nvm, run the following command to install the recommended Node.js version: -``` -nvm install -``` - -### Using fnm -If you prefer fnm, run the following command to install the recommended Node.js version: -``` -fnm install -``` - -## Project setup -``` -npm install -``` - -### Compiles and hot-reloads for development -``` -npm run serve -``` - -### Compiles and minifies for production -``` -npm run build -``` - -### Run your tests -``` -npm run test -``` - -### Lints and fixes files -``` -npm run lint -``` - -### Run your unit tests -``` -npm run test:unit -``` diff --git a/frontend/babel.config.js b/frontend/babel.config.js deleted file mode 100644 index 07b43d2..0000000 --- a/frontend/babel.config.js +++ /dev/null @@ -1,10 +0,0 @@ -module.exports = { - "presets": [ - [ - "@vue/cli-plugin-babel/preset", - { - "useBuiltIns": "entry" - } - ] - ] -} diff --git a/frontend/nginx-backend-not-found.conf b/frontend/nginx-backend-not-found.conf deleted file mode 100644 index f6fea66..0000000 --- a/frontend/nginx-backend-not-found.conf +++ /dev/null @@ -1,9 +0,0 @@ -location /api { - return 404; -} -location /docs { - return 404; -} -location /redoc { - return 404; -} diff --git a/frontend/nginx.conf b/frontend/nginx.conf deleted file mode 100644 index fd4472f..0000000 --- a/frontend/nginx.conf +++ /dev/null @@ -1,11 +0,0 @@ -server { - listen 80; - - location / { - root /usr/share/nginx/html; - index index.html index.htm; - try_files $uri $uri/ /index.html =404; - } - - include /etc/nginx/extra-conf.d/*.conf; -} diff --git a/frontend/package.json b/frontend/package.json deleted file mode 100644 index a83c616..0000000 --- a/frontend/package.json +++ /dev/null @@ -1,74 +0,0 @@ -{ - "name": "frontend", - "version": "0.1.0", - "private": true, - "scripts": { - "serve": "vue-cli-service serve", - "build": "vue-cli-service build", - "test:unit": "vue-cli-service test:unit", - "lint": "vue-cli-service lint" - }, - "dependencies": { - "@babel/polyfill": "^7.2.5", - "axios": "^0.18.0", - "core-js": "^3.4.3", - "register-service-worker": "^1.0.0", - "typesafe-vuex": "^3.1.1", - "vee-validate": "^2.1.7", - "vue": "^2.5.22", - "vue-class-component": "^6.0.0", - "vue-property-decorator": "^7.3.0", - "vue-router": "^3.0.2", - "vuetify": "^1.4.4", - "vuex": "^3.1.0" - }, - "devDependencies": { - "@types/jest": "^23.3.13", - "@vue/cli-plugin-babel": "^4.1.1", - "@vue/cli-plugin-pwa": "^4.1.1", - "@vue/cli-plugin-typescript": "^4.1.1", - "@vue/cli-plugin-unit-jest": "^4.1.1", - "@vue/cli-service": "^4.1.1", - "@vue/test-utils": "^1.0.0-beta.28", - "babel-core": "7.0.0-bridge.0", - "ts-jest": "^23.10.5", - "typescript": "^3.2.4", - "vue-cli-plugin-vuetify": "^2.0.2", - "vue-template-compiler": "^2.5.22" - }, - "postcss": { - "plugins": { - "autoprefixer": {} - } - }, - "browserslist": [ - "> 1%", - "last 2 versions", - "not ie <= 10" - ], - "jest": { - "moduleFileExtensions": [ - "js", - "jsx", - "json", - "vue", - "ts", - "tsx" - ], - "transform": { - "^.+\\.vue$": "vue-jest", - ".+\\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$": "jest-transform-stub", - "^.+\\.tsx?$": "ts-jest" - }, - "moduleNameMapper": { - "^@/(.*)$": "/src/$1" - }, - "snapshotSerializers": [ - "jest-serializer-vue" - ], - "testMatch": [ - "**/tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)" - ], - "testURL": "http://localhost/" - } -} diff --git a/frontend/public/favicon.ico b/frontend/public/favicon.ico deleted file mode 100644 index c7b9a43..0000000 Binary files a/frontend/public/favicon.ico and /dev/null differ diff --git a/frontend/public/img/icons/android-chrome-192x192.png b/frontend/public/img/icons/android-chrome-192x192.png deleted file mode 100644 index b02aa64..0000000 Binary files a/frontend/public/img/icons/android-chrome-192x192.png and /dev/null differ diff --git a/frontend/public/img/icons/android-chrome-512x512.png b/frontend/public/img/icons/android-chrome-512x512.png deleted file mode 100644 index 06088b0..0000000 Binary files a/frontend/public/img/icons/android-chrome-512x512.png and /dev/null differ diff --git a/frontend/public/img/icons/apple-touch-icon-120x120.png b/frontend/public/img/icons/apple-touch-icon-120x120.png deleted file mode 100644 index 1427cf6..0000000 Binary files a/frontend/public/img/icons/apple-touch-icon-120x120.png and /dev/null differ diff --git a/frontend/public/img/icons/apple-touch-icon-152x152.png b/frontend/public/img/icons/apple-touch-icon-152x152.png deleted file mode 100644 index f24d454..0000000 Binary files a/frontend/public/img/icons/apple-touch-icon-152x152.png and /dev/null differ diff --git a/frontend/public/img/icons/apple-touch-icon-180x180.png b/frontend/public/img/icons/apple-touch-icon-180x180.png deleted file mode 100644 index 404e192..0000000 Binary files a/frontend/public/img/icons/apple-touch-icon-180x180.png and /dev/null differ diff --git a/frontend/public/img/icons/apple-touch-icon-60x60.png b/frontend/public/img/icons/apple-touch-icon-60x60.png deleted file mode 100644 index cf10a56..0000000 Binary files a/frontend/public/img/icons/apple-touch-icon-60x60.png and /dev/null differ diff --git a/frontend/public/img/icons/apple-touch-icon-76x76.png b/frontend/public/img/icons/apple-touch-icon-76x76.png deleted file mode 100644 index c500769..0000000 Binary files a/frontend/public/img/icons/apple-touch-icon-76x76.png and /dev/null differ diff --git a/frontend/public/img/icons/apple-touch-icon.png b/frontend/public/img/icons/apple-touch-icon.png deleted file mode 100644 index 03c0c5d..0000000 Binary files a/frontend/public/img/icons/apple-touch-icon.png and /dev/null differ diff --git a/frontend/public/img/icons/favicon-16x16.png b/frontend/public/img/icons/favicon-16x16.png deleted file mode 100644 index 42af009..0000000 Binary files a/frontend/public/img/icons/favicon-16x16.png and /dev/null differ diff --git a/frontend/public/img/icons/favicon-32x32.png b/frontend/public/img/icons/favicon-32x32.png deleted file mode 100644 index 46ca04d..0000000 Binary files a/frontend/public/img/icons/favicon-32x32.png and /dev/null differ diff --git a/frontend/public/img/icons/msapplication-icon-144x144.png b/frontend/public/img/icons/msapplication-icon-144x144.png deleted file mode 100644 index 7808237..0000000 Binary files a/frontend/public/img/icons/msapplication-icon-144x144.png and /dev/null differ diff --git a/frontend/public/img/icons/mstile-150x150.png b/frontend/public/img/icons/mstile-150x150.png deleted file mode 100644 index 3b37a43..0000000 Binary files a/frontend/public/img/icons/mstile-150x150.png and /dev/null differ diff --git a/frontend/public/img/icons/safari-pinned-tab.svg b/frontend/public/img/icons/safari-pinned-tab.svg deleted file mode 100644 index 732afd8..0000000 --- a/frontend/public/img/icons/safari-pinned-tab.svg +++ /dev/null @@ -1,149 +0,0 @@ - - - - -Created by potrace 1.11, written by Peter Selinger 2001-2013 - - - - - diff --git a/frontend/public/index.html b/frontend/public/index.html deleted file mode 100644 index cad5aa7..0000000 --- a/frontend/public/index.html +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - <%= VUE_APP_NAME %> - - - - - - - -
- - - diff --git a/frontend/public/manifest.json b/frontend/public/manifest.json deleted file mode 100644 index 8ce10b9..0000000 --- a/frontend/public/manifest.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "name": "frontend", - "short_name": "frontend", - "icons": [ - { - "src": "/img/icons/android-chrome-192x192.png", - "sizes": "192x192", - "type": "image/png" - }, - { - "src": "/img/icons/android-chrome-512x512.png", - "sizes": "512x512", - "type": "image/png" - } - ], - "start_url": "/", - "display": "standalone", - "background_color": "#000000", - "theme_color": "#4DBA87" -} diff --git a/frontend/public/robots.txt b/frontend/public/robots.txt deleted file mode 100644 index eb05362..0000000 --- a/frontend/public/robots.txt +++ /dev/null @@ -1,2 +0,0 @@ -User-agent: * -Disallow: diff --git a/frontend/src/App.vue b/frontend/src/App.vue deleted file mode 100644 index 795a97c..0000000 --- a/frontend/src/App.vue +++ /dev/null @@ -1,43 +0,0 @@ - - - diff --git a/frontend/src/api.ts b/frontend/src/api.ts deleted file mode 100644 index c24712b..0000000 --- a/frontend/src/api.ts +++ /dev/null @@ -1,45 +0,0 @@ -import axios from 'axios'; -import { apiUrl } from '@/env'; -import { IUserProfile, IUserProfileUpdate, IUserProfileCreate } from './interfaces'; - -function authHeaders(token: string) { - return { - headers: { - Authorization: `Bearer ${token}`, - }, - }; -} - -export const api = { - async logInGetToken(username: string, password: string) { - const params = new URLSearchParams(); - params.append('username', username); - params.append('password', password); - - return axios.post(`${apiUrl}/api/v1/login/access-token`, params); - }, - async getMe(token: string) { - return axios.get(`${apiUrl}/api/v1/users/me`, authHeaders(token)); - }, - async updateMe(token: string, data: IUserProfileUpdate) { - return axios.put(`${apiUrl}/api/v1/users/me`, data, authHeaders(token)); - }, - async getUsers(token: string) { - return axios.get(`${apiUrl}/api/v1/users/`, authHeaders(token)); - }, - async updateUser(token: string, userId: number, data: IUserProfileUpdate) { - return axios.put(`${apiUrl}/api/v1/users/${userId}`, data, authHeaders(token)); - }, - async createUser(token: string, data: IUserProfileCreate) { - return axios.post(`${apiUrl}/api/v1/users/`, data, authHeaders(token)); - }, - async passwordRecovery(email: string) { - return axios.post(`${apiUrl}/api/v1/password-recovery/${email}`); - }, - async resetPassword(password: string, token: string) { - return axios.post(`${apiUrl}/api/v1/reset-password/`, { - new_password: password, - token, - }); - }, -}; diff --git a/frontend/src/assets/logo.png b/frontend/src/assets/logo.png deleted file mode 100644 index f3d2503..0000000 Binary files a/frontend/src/assets/logo.png and /dev/null differ diff --git a/frontend/src/component-hooks.ts b/frontend/src/component-hooks.ts deleted file mode 100644 index cefdc53..0000000 --- a/frontend/src/component-hooks.ts +++ /dev/null @@ -1,8 +0,0 @@ -import Component from 'vue-class-component'; - -// Register the router hooks with their names -Component.registerHooks([ - 'beforeRouteEnter', - 'beforeRouteLeave', - 'beforeRouteUpdate', // for vue-router 2.2+ -]); diff --git a/frontend/src/components/NotificationsManager.vue b/frontend/src/components/NotificationsManager.vue deleted file mode 100644 index 6fcffdb..0000000 --- a/frontend/src/components/NotificationsManager.vue +++ /dev/null @@ -1,77 +0,0 @@ - - diff --git a/frontend/src/components/RouterComponent.vue b/frontend/src/components/RouterComponent.vue deleted file mode 100644 index ed986a6..0000000 --- a/frontend/src/components/RouterComponent.vue +++ /dev/null @@ -1,11 +0,0 @@ - - - diff --git a/frontend/src/components/UploadButton.vue b/frontend/src/components/UploadButton.vue deleted file mode 100644 index 8902e94..0000000 --- a/frontend/src/components/UploadButton.vue +++ /dev/null @@ -1,34 +0,0 @@ - - - - - diff --git a/frontend/src/env.ts b/frontend/src/env.ts deleted file mode 100644 index b3387e6..0000000 --- a/frontend/src/env.ts +++ /dev/null @@ -1,14 +0,0 @@ -const env = process.env.VUE_APP_ENV; - -let envApiUrl = ''; - -if (env === 'production') { - envApiUrl = `https://${process.env.VUE_APP_DOMAIN_PROD}`; -} else if (env === 'staging') { - envApiUrl = `https://${process.env.VUE_APP_DOMAIN_STAG}`; -} else { - envApiUrl = `http://${process.env.VUE_APP_DOMAIN_DEV}`; -} - -export const apiUrl = envApiUrl; -export const appName = process.env.VUE_APP_NAME; diff --git a/frontend/src/interfaces/index.ts b/frontend/src/interfaces/index.ts deleted file mode 100644 index a1b9340..0000000 --- a/frontend/src/interfaces/index.ts +++ /dev/null @@ -1,23 +0,0 @@ -export interface IUserProfile { - email: string; - is_active: boolean; - is_superuser: boolean; - full_name: string; - id: number; -} - -export interface IUserProfileUpdate { - email?: string; - full_name?: string; - password?: string; - is_active?: boolean; - is_superuser?: boolean; -} - -export interface IUserProfileCreate { - email: string; - full_name?: string; - password?: string; - is_active?: boolean; - is_superuser?: boolean; -} diff --git a/frontend/src/main.ts b/frontend/src/main.ts deleted file mode 100644 index a844b1e..0000000 --- a/frontend/src/main.ts +++ /dev/null @@ -1,19 +0,0 @@ -import '@babel/polyfill'; -// Import Component hooks before component definitions -import './component-hooks'; -import Vue from 'vue'; -import './plugins/vuetify'; -import './plugins/vee-validate'; -import App from './App.vue'; -import router from './router'; -import store from '@/store'; -import './registerServiceWorker'; -import 'vuetify/dist/vuetify.min.css'; - -Vue.config.productionTip = false; - -new Vue({ - router, - store, - render: (h) => h(App), -}).$mount('#app'); diff --git a/frontend/src/plugins/vee-validate.ts b/frontend/src/plugins/vee-validate.ts deleted file mode 100644 index 9c4238f..0000000 --- a/frontend/src/plugins/vee-validate.ts +++ /dev/null @@ -1,4 +0,0 @@ -import Vue from 'vue'; -import VeeValidate from 'vee-validate'; - -Vue.use(VeeValidate); diff --git a/frontend/src/plugins/vuetify.ts b/frontend/src/plugins/vuetify.ts deleted file mode 100644 index 8fdfce3..0000000 --- a/frontend/src/plugins/vuetify.ts +++ /dev/null @@ -1,6 +0,0 @@ -import Vue from 'vue'; -import Vuetify from 'vuetify'; - -Vue.use(Vuetify, { - iconfont: 'md', -}); diff --git a/frontend/src/registerServiceWorker.ts b/frontend/src/registerServiceWorker.ts deleted file mode 100644 index d3db583..0000000 --- a/frontend/src/registerServiceWorker.ts +++ /dev/null @@ -1,26 +0,0 @@ -/* tslint:disable:no-console */ - -import { register } from 'register-service-worker'; - -if (process.env.NODE_ENV === 'production') { - register(`${process.env.BASE_URL}service-worker.js`, { - ready() { - console.log( - 'App is being served from cache by a service worker.\n' + - 'For more details, visit https://goo.gl/AFskqB', - ); - }, - cached() { - console.log('Content has been cached for offline use.'); - }, - updated() { - console.log('New content is available; please refresh.'); - }, - offline() { - console.log('No internet connection found. App is running in offline mode.'); - }, - error(error) { - console.error('Error during service worker registration:', error); - }, - }); -} diff --git a/frontend/src/router.ts b/frontend/src/router.ts deleted file mode 100644 index b649c17..0000000 --- a/frontend/src/router.ts +++ /dev/null @@ -1,97 +0,0 @@ -import Vue from 'vue'; -import Router from 'vue-router'; - -import RouterComponent from './components/RouterComponent.vue'; - -Vue.use(Router); - -export default new Router({ - mode: 'history', - base: process.env.BASE_URL, - routes: [ - { - path: '/', - component: () => import(/* webpackChunkName: "start" */ './views/main/Start.vue'), - children: [ - { - path: 'login', - // 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: "login" */ './views/Login.vue'), - }, - { - path: 'recover-password', - component: () => import(/* webpackChunkName: "recover-password" */ './views/PasswordRecovery.vue'), - }, - { - path: 'reset-password', - component: () => import(/* webpackChunkName: "reset-password" */ './views/ResetPassword.vue'), - }, - { - path: 'main', - component: () => import(/* webpackChunkName: "main" */ './views/main/Main.vue'), - children: [ - { - path: 'dashboard', - component: () => import(/* webpackChunkName: "main-dashboard" */ './views/main/Dashboard.vue'), - }, - { - path: 'profile', - component: RouterComponent, - redirect: 'profile/view', - children: [ - { - path: 'view', - component: () => import( - /* webpackChunkName: "main-profile" */ './views/main/profile/UserProfile.vue'), - }, - { - path: 'edit', - component: () => import( - /* webpackChunkName: "main-profile-edit" */ './views/main/profile/UserProfileEdit.vue'), - }, - { - path: 'password', - component: () => import( - /* webpackChunkName: "main-profile-password" */ './views/main/profile/UserProfileEditPassword.vue'), - }, - ], - }, - { - path: 'admin', - component: () => import(/* webpackChunkName: "main-admin" */ './views/main/admin/Admin.vue'), - redirect: 'admin/users/all', - children: [ - { - path: 'users', - redirect: 'users/all', - }, - { - path: 'users/all', - component: () => import( - /* webpackChunkName: "main-admin-users" */ './views/main/admin/AdminUsers.vue'), - }, - { - path: 'users/edit/:id', - name: 'main-admin-users-edit', - component: () => import( - /* webpackChunkName: "main-admin-users-edit" */ './views/main/admin/EditUser.vue'), - }, - { - path: 'users/create', - name: 'main-admin-users-create', - component: () => import( - /* webpackChunkName: "main-admin-users-create" */ './views/main/admin/CreateUser.vue'), - }, - ], - }, - ], - }, - ], - }, - { - path: '/*', redirect: '/', - }, - ], -}); diff --git a/frontend/src/shims-tsx.d.ts b/frontend/src/shims-tsx.d.ts deleted file mode 100644 index 3b88b58..0000000 --- a/frontend/src/shims-tsx.d.ts +++ /dev/null @@ -1,13 +0,0 @@ -import Vue, { VNode } from 'vue'; - -declare global { - namespace JSX { - // tslint:disable no-empty-interface - interface Element extends VNode {} - // tslint:disable no-empty-interface - interface ElementClass extends Vue {} - interface IntrinsicElements { - [elem: string]: any; - } - } -} diff --git a/frontend/src/shims-vue.d.ts b/frontend/src/shims-vue.d.ts deleted file mode 100644 index 8f6f410..0000000 --- a/frontend/src/shims-vue.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -declare module '*.vue' { - import Vue from 'vue'; - export default Vue; -} diff --git a/frontend/src/store/admin/actions.ts b/frontend/src/store/admin/actions.ts deleted file mode 100644 index 125a08e..0000000 --- a/frontend/src/store/admin/actions.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { api } from '@/api'; -import { ActionContext } from 'vuex'; -import { IUserProfileCreate, IUserProfileUpdate } from '@/interfaces'; -import { State } from '../state'; -import { AdminState } from './state'; -import { getStoreAccessors } from 'typesafe-vuex'; -import { commitSetUsers, commitSetUser } from './mutations'; -import { dispatchCheckApiError } from '../main/actions'; -import { commitAddNotification, commitRemoveNotification } from '../main/mutations'; - -type MainContext = ActionContext; - -export const actions = { - async actionGetUsers(context: MainContext) { - try { - const response = await api.getUsers(context.rootState.main.token); - if (response) { - commitSetUsers(context, response.data); - } - } catch (error) { - await dispatchCheckApiError(context, error); - } - }, - async actionUpdateUser(context: MainContext, payload: { id: number, user: IUserProfileUpdate }) { - try { - const loadingNotification = { content: 'saving', showProgress: true }; - commitAddNotification(context, loadingNotification); - const response = (await Promise.all([ - api.updateUser(context.rootState.main.token, payload.id, payload.user), - await new Promise((resolve, reject) => setTimeout(() => resolve(), 500)), - ]))[0]; - commitSetUser(context, response.data); - commitRemoveNotification(context, loadingNotification); - commitAddNotification(context, { content: 'User successfully updated', color: 'success' }); - } catch (error) { - await dispatchCheckApiError(context, error); - } - }, - async actionCreateUser(context: MainContext, payload: IUserProfileCreate) { - try { - const loadingNotification = { content: 'saving', showProgress: true }; - commitAddNotification(context, loadingNotification); - const response = (await Promise.all([ - api.createUser(context.rootState.main.token, payload), - await new Promise((resolve, reject) => setTimeout(() => resolve(), 500)), - ]))[0]; - commitSetUser(context, response.data); - commitRemoveNotification(context, loadingNotification); - commitAddNotification(context, { content: 'User successfully created', color: 'success' }); - } catch (error) { - await dispatchCheckApiError(context, error); - } - }, -}; - -const { dispatch } = getStoreAccessors(''); - -export const dispatchCreateUser = dispatch(actions.actionCreateUser); -export const dispatchGetUsers = dispatch(actions.actionGetUsers); -export const dispatchUpdateUser = dispatch(actions.actionUpdateUser); diff --git a/frontend/src/store/admin/getters.ts b/frontend/src/store/admin/getters.ts deleted file mode 100644 index c5832ef..0000000 --- a/frontend/src/store/admin/getters.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { AdminState } from './state'; -import { getStoreAccessors } from 'typesafe-vuex'; -import { State } from '../state'; - -export const getters = { - adminUsers: (state: AdminState) => state.users, - adminOneUser: (state: AdminState) => (userId: number) => { - const filteredUsers = state.users.filter((user) => user.id === userId); - if (filteredUsers.length > 0) { - return { ...filteredUsers[0] }; - } - }, -}; - -const { read } = getStoreAccessors(''); - -export const readAdminOneUser = read(getters.adminOneUser); -export const readAdminUsers = read(getters.adminUsers); diff --git a/frontend/src/store/admin/index.ts b/frontend/src/store/admin/index.ts deleted file mode 100644 index dcaf6ab..0000000 --- a/frontend/src/store/admin/index.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { mutations } from './mutations'; -import { getters } from './getters'; -import { actions } from './actions'; -import { AdminState } from './state'; - -const defaultState: AdminState = { - users: [], -}; - -export const adminModule = { - state: defaultState, - mutations, - actions, - getters, -}; diff --git a/frontend/src/store/admin/mutations.ts b/frontend/src/store/admin/mutations.ts deleted file mode 100644 index dea471d..0000000 --- a/frontend/src/store/admin/mutations.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { IUserProfile } from '@/interfaces'; -import { AdminState } from './state'; -import { getStoreAccessors } from 'typesafe-vuex'; -import { State } from '../state'; - -export const mutations = { - setUsers(state: AdminState, payload: IUserProfile[]) { - state.users = payload; - }, - setUser(state: AdminState, payload: IUserProfile) { - const users = state.users.filter((user: IUserProfile) => user.id !== payload.id); - users.push(payload); - state.users = users; - }, -}; - -const { commit } = getStoreAccessors(''); - -export const commitSetUser = commit(mutations.setUser); -export const commitSetUsers = commit(mutations.setUsers); diff --git a/frontend/src/store/admin/state.ts b/frontend/src/store/admin/state.ts deleted file mode 100644 index 8dfefe2..0000000 --- a/frontend/src/store/admin/state.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { IUserProfile } from '@/interfaces'; - -export interface AdminState { - users: IUserProfile[]; -} diff --git a/frontend/src/store/index.ts b/frontend/src/store/index.ts deleted file mode 100644 index 1089971..0000000 --- a/frontend/src/store/index.ts +++ /dev/null @@ -1,19 +0,0 @@ -import Vue from 'vue'; -import Vuex, { StoreOptions } from 'vuex'; - -import { mainModule } from './main'; -import { State } from './state'; -import { adminModule } from './admin'; - -Vue.use(Vuex); - -const storeOptions: StoreOptions = { - modules: { - main: mainModule, - admin: adminModule, - }, -}; - -export const store = new Vuex.Store(storeOptions); - -export default store; diff --git a/frontend/src/store/main/actions.ts b/frontend/src/store/main/actions.ts deleted file mode 100644 index d02c06d..0000000 --- a/frontend/src/store/main/actions.ts +++ /dev/null @@ -1,173 +0,0 @@ -import { api } from '@/api'; -import router from '@/router'; -import { getLocalToken, removeLocalToken, saveLocalToken } from '@/utils'; -import { AxiosError } from 'axios'; -import { getStoreAccessors } from 'typesafe-vuex'; -import { ActionContext } from 'vuex'; -import { State } from '../state'; -import { - commitAddNotification, - commitRemoveNotification, - commitSetLoggedIn, - commitSetLogInError, - commitSetToken, - commitSetUserProfile, -} from './mutations'; -import { AppNotification, MainState } from './state'; - -type MainContext = ActionContext; - -export const actions = { - async actionLogIn(context: MainContext, payload: { username: string; password: string }) { - try { - const response = await api.logInGetToken(payload.username, payload.password); - const token = response.data.access_token; - if (token) { - saveLocalToken(token); - commitSetToken(context, token); - commitSetLoggedIn(context, true); - commitSetLogInError(context, false); - await dispatchGetUserProfile(context); - await dispatchRouteLoggedIn(context); - commitAddNotification(context, { content: 'Logged in', color: 'success' }); - } else { - await dispatchLogOut(context); - } - } catch (err) { - commitSetLogInError(context, true); - await dispatchLogOut(context); - } - }, - async actionGetUserProfile(context: MainContext) { - try { - const response = await api.getMe(context.state.token); - if (response.data) { - commitSetUserProfile(context, response.data); - } - } catch (error) { - await dispatchCheckApiError(context, error); - } - }, - async actionUpdateUserProfile(context: MainContext, payload) { - try { - const loadingNotification = { content: 'saving', showProgress: true }; - commitAddNotification(context, loadingNotification); - const response = (await Promise.all([ - api.updateMe(context.state.token, payload), - await new Promise((resolve, reject) => setTimeout(() => resolve(), 500)), - ]))[0]; - commitSetUserProfile(context, response.data); - commitRemoveNotification(context, loadingNotification); - commitAddNotification(context, { content: 'Profile successfully updated', color: 'success' }); - } catch (error) { - await dispatchCheckApiError(context, error); - } - }, - async actionCheckLoggedIn(context: MainContext) { - if (!context.state.isLoggedIn) { - let token = context.state.token; - if (!token) { - const localToken = getLocalToken(); - if (localToken) { - commitSetToken(context, localToken); - token = localToken; - } - } - if (token) { - try { - const response = await api.getMe(token); - commitSetLoggedIn(context, true); - commitSetUserProfile(context, response.data); - } catch (error) { - await dispatchRemoveLogIn(context); - } - } else { - await dispatchRemoveLogIn(context); - } - } - }, - async actionRemoveLogIn(context: MainContext) { - removeLocalToken(); - commitSetToken(context, ''); - commitSetLoggedIn(context, false); - }, - async actionLogOut(context: MainContext) { - await dispatchRemoveLogIn(context); - await dispatchRouteLogOut(context); - }, - async actionUserLogOut(context: MainContext) { - await dispatchLogOut(context); - commitAddNotification(context, { content: 'Logged out', color: 'success' }); - }, - actionRouteLogOut(context: MainContext) { - if (router.currentRoute.path !== '/login') { - router.push('/login'); - } - }, - async actionCheckApiError(context: MainContext, payload: AxiosError) { - if (payload.response!.status === 401) { - await dispatchLogOut(context); - } - }, - actionRouteLoggedIn(context: MainContext) { - if (router.currentRoute.path === '/login' || router.currentRoute.path === '/') { - router.push('/main'); - } - }, - async removeNotification(context: MainContext, payload: { notification: AppNotification, timeout: number }) { - return new Promise((resolve, reject) => { - setTimeout(() => { - commitRemoveNotification(context, payload.notification); - resolve(true); - }, payload.timeout); - }); - }, - async passwordRecovery(context: MainContext, payload: { username: string }) { - const loadingNotification = { content: 'Sending password recovery email', showProgress: true }; - try { - commitAddNotification(context, loadingNotification); - const response = (await Promise.all([ - api.passwordRecovery(payload.username), - await new Promise((resolve, reject) => setTimeout(() => resolve(), 500)), - ]))[0]; - commitRemoveNotification(context, loadingNotification); - commitAddNotification(context, { content: 'Password recovery email sent', color: 'success' }); - await dispatchLogOut(context); - } catch (error) { - commitRemoveNotification(context, loadingNotification); - commitAddNotification(context, { color: 'error', content: 'Incorrect username' }); - } - }, - async resetPassword(context: MainContext, payload: { password: string, token: string }) { - const loadingNotification = { content: 'Resetting password', showProgress: true }; - try { - commitAddNotification(context, loadingNotification); - const response = (await Promise.all([ - api.resetPassword(payload.password, payload.token), - await new Promise((resolve, reject) => setTimeout(() => resolve(), 500)), - ]))[0]; - commitRemoveNotification(context, loadingNotification); - commitAddNotification(context, { content: 'Password successfully reset', color: 'success' }); - await dispatchLogOut(context); - } catch (error) { - commitRemoveNotification(context, loadingNotification); - commitAddNotification(context, { color: 'error', content: 'Error resetting password' }); - } - }, -}; - -const { dispatch } = getStoreAccessors(''); - -export const dispatchCheckApiError = dispatch(actions.actionCheckApiError); -export const dispatchCheckLoggedIn = dispatch(actions.actionCheckLoggedIn); -export const dispatchGetUserProfile = dispatch(actions.actionGetUserProfile); -export const dispatchLogIn = dispatch(actions.actionLogIn); -export const dispatchLogOut = dispatch(actions.actionLogOut); -export const dispatchUserLogOut = dispatch(actions.actionUserLogOut); -export const dispatchRemoveLogIn = dispatch(actions.actionRemoveLogIn); -export const dispatchRouteLoggedIn = dispatch(actions.actionRouteLoggedIn); -export const dispatchRouteLogOut = dispatch(actions.actionRouteLogOut); -export const dispatchUpdateUserProfile = dispatch(actions.actionUpdateUserProfile); -export const dispatchRemoveNotification = dispatch(actions.removeNotification); -export const dispatchPasswordRecovery = dispatch(actions.passwordRecovery); -export const dispatchResetPassword = dispatch(actions.resetPassword); diff --git a/frontend/src/store/main/getters.ts b/frontend/src/store/main/getters.ts deleted file mode 100644 index 58f8397..0000000 --- a/frontend/src/store/main/getters.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { MainState } from './state'; -import { getStoreAccessors } from 'typesafe-vuex'; -import { State } from '../state'; - -export const getters = { - hasAdminAccess: (state: MainState) => { - return ( - state.userProfile && - state.userProfile.is_superuser && state.userProfile.is_active); - }, - loginError: (state: MainState) => state.logInError, - dashboardShowDrawer: (state: MainState) => state.dashboardShowDrawer, - dashboardMiniDrawer: (state: MainState) => state.dashboardMiniDrawer, - userProfile: (state: MainState) => state.userProfile, - token: (state: MainState) => state.token, - isLoggedIn: (state: MainState) => state.isLoggedIn, - firstNotification: (state: MainState) => state.notifications.length > 0 && state.notifications[0], -}; - -const {read} = getStoreAccessors(''); - -export const readDashboardMiniDrawer = read(getters.dashboardMiniDrawer); -export const readDashboardShowDrawer = read(getters.dashboardShowDrawer); -export const readHasAdminAccess = read(getters.hasAdminAccess); -export const readIsLoggedIn = read(getters.isLoggedIn); -export const readLoginError = read(getters.loginError); -export const readToken = read(getters.token); -export const readUserProfile = read(getters.userProfile); -export const readFirstNotification = read(getters.firstNotification); diff --git a/frontend/src/store/main/index.ts b/frontend/src/store/main/index.ts deleted file mode 100644 index 56ba1a0..0000000 --- a/frontend/src/store/main/index.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { mutations } from './mutations'; -import { getters } from './getters'; -import { actions } from './actions'; -import { MainState } from './state'; - -const defaultState: MainState = { - isLoggedIn: null, - token: '', - logInError: false, - userProfile: null, - dashboardMiniDrawer: false, - dashboardShowDrawer: true, - notifications: [], -}; - -export const mainModule = { - state: defaultState, - mutations, - actions, - getters, -}; diff --git a/frontend/src/store/main/mutations.ts b/frontend/src/store/main/mutations.ts deleted file mode 100644 index 3e9c8ba..0000000 --- a/frontend/src/store/main/mutations.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { IUserProfile } from '@/interfaces'; -import { MainState, AppNotification } from './state'; -import { getStoreAccessors } from 'typesafe-vuex'; -import { State } from '../state'; - - -export const mutations = { - setToken(state: MainState, payload: string) { - state.token = payload; - }, - setLoggedIn(state: MainState, payload: boolean) { - state.isLoggedIn = payload; - }, - setLogInError(state: MainState, payload: boolean) { - state.logInError = payload; - }, - setUserProfile(state: MainState, payload: IUserProfile) { - state.userProfile = payload; - }, - setDashboardMiniDrawer(state: MainState, payload: boolean) { - state.dashboardMiniDrawer = payload; - }, - setDashboardShowDrawer(state: MainState, payload: boolean) { - state.dashboardShowDrawer = payload; - }, - addNotification(state: MainState, payload: AppNotification) { - state.notifications.push(payload); - }, - removeNotification(state: MainState, payload: AppNotification) { - state.notifications = state.notifications.filter((notification) => notification !== payload); - }, -}; - -const {commit} = getStoreAccessors(''); - -export const commitSetDashboardMiniDrawer = commit(mutations.setDashboardMiniDrawer); -export const commitSetDashboardShowDrawer = commit(mutations.setDashboardShowDrawer); -export const commitSetLoggedIn = commit(mutations.setLoggedIn); -export const commitSetLogInError = commit(mutations.setLogInError); -export const commitSetToken = commit(mutations.setToken); -export const commitSetUserProfile = commit(mutations.setUserProfile); -export const commitAddNotification = commit(mutations.addNotification); -export const commitRemoveNotification = commit(mutations.removeNotification); diff --git a/frontend/src/store/main/state.ts b/frontend/src/store/main/state.ts deleted file mode 100644 index be24b63..0000000 --- a/frontend/src/store/main/state.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { IUserProfile } from '@/interfaces'; - -export interface AppNotification { - content: string; - color?: string; - showProgress?: boolean; -} - -export interface MainState { - token: string; - isLoggedIn: boolean | null; - logInError: boolean; - userProfile: IUserProfile | null; - dashboardMiniDrawer: boolean; - dashboardShowDrawer: boolean; - notifications: AppNotification[]; -} diff --git a/frontend/src/store/state.ts b/frontend/src/store/state.ts deleted file mode 100644 index ecec111..0000000 --- a/frontend/src/store/state.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { MainState } from './main/state'; - -export interface State { - main: MainState; -} diff --git a/frontend/src/utils.ts b/frontend/src/utils.ts deleted file mode 100644 index ade11b6..0000000 --- a/frontend/src/utils.ts +++ /dev/null @@ -1,5 +0,0 @@ -export const getLocalToken = () => localStorage.getItem('token'); - -export const saveLocalToken = (token: string) => localStorage.setItem('token', token); - -export const removeLocalToken = () => localStorage.removeItem('token'); diff --git a/frontend/src/views/Login.vue b/frontend/src/views/Login.vue deleted file mode 100644 index 28bcb59..0000000 --- a/frontend/src/views/Login.vue +++ /dev/null @@ -1,58 +0,0 @@ - - - - - diff --git a/frontend/src/views/PasswordRecovery.vue b/frontend/src/views/PasswordRecovery.vue deleted file mode 100644 index bc1a7ad..0000000 --- a/frontend/src/views/PasswordRecovery.vue +++ /dev/null @@ -1,52 +0,0 @@ - - - - - diff --git a/frontend/src/views/ResetPassword.vue b/frontend/src/views/ResetPassword.vue deleted file mode 100644 index 3e680eb..0000000 --- a/frontend/src/views/ResetPassword.vue +++ /dev/null @@ -1,84 +0,0 @@ - - - diff --git a/frontend/src/views/main/Dashboard.vue b/frontend/src/views/main/Dashboard.vue deleted file mode 100644 index 421879b..0000000 --- a/frontend/src/views/main/Dashboard.vue +++ /dev/null @@ -1,37 +0,0 @@ - - - diff --git a/frontend/src/views/main/Main.vue b/frontend/src/views/main/Main.vue deleted file mode 100644 index 846d93b..0000000 --- a/frontend/src/views/main/Main.vue +++ /dev/null @@ -1,182 +0,0 @@ - - - diff --git a/frontend/src/views/main/Start.vue b/frontend/src/views/main/Start.vue deleted file mode 100644 index 71eeaaf..0000000 --- a/frontend/src/views/main/Start.vue +++ /dev/null @@ -1,38 +0,0 @@ - - - diff --git a/frontend/src/views/main/admin/Admin.vue b/frontend/src/views/main/admin/Admin.vue deleted file mode 100644 index 1282176..0000000 --- a/frontend/src/views/main/admin/Admin.vue +++ /dev/null @@ -1,28 +0,0 @@ - - - diff --git a/frontend/src/views/main/admin/AdminUsers.vue b/frontend/src/views/main/admin/AdminUsers.vue deleted file mode 100644 index 9b35d9a..0000000 --- a/frontend/src/views/main/admin/AdminUsers.vue +++ /dev/null @@ -1,83 +0,0 @@ - - - diff --git a/frontend/src/views/main/admin/CreateUser.vue b/frontend/src/views/main/admin/CreateUser.vue deleted file mode 100644 index 892283e..0000000 --- a/frontend/src/views/main/admin/CreateUser.vue +++ /dev/null @@ -1,97 +0,0 @@ - - - diff --git a/frontend/src/views/main/admin/EditUser.vue b/frontend/src/views/main/admin/EditUser.vue deleted file mode 100644 index 7421233..0000000 --- a/frontend/src/views/main/admin/EditUser.vue +++ /dev/null @@ -1,163 +0,0 @@ - - - diff --git a/frontend/src/views/main/profile/UserProfile.vue b/frontend/src/views/main/profile/UserProfile.vue deleted file mode 100644 index 25960bd..0000000 --- a/frontend/src/views/main/profile/UserProfile.vue +++ /dev/null @@ -1,46 +0,0 @@ - - - diff --git a/frontend/src/views/main/profile/UserProfileEdit.vue b/frontend/src/views/main/profile/UserProfileEdit.vue deleted file mode 100644 index dfbea8d..0000000 --- a/frontend/src/views/main/profile/UserProfileEdit.vue +++ /dev/null @@ -1,97 +0,0 @@ - - - diff --git a/frontend/src/views/main/profile/UserProfileEditPassword.vue b/frontend/src/views/main/profile/UserProfileEditPassword.vue deleted file mode 100644 index be69392..0000000 --- a/frontend/src/views/main/profile/UserProfileEditPassword.vue +++ /dev/null @@ -1,86 +0,0 @@ - - - diff --git a/frontend/tests/unit/upload-button.spec.ts b/frontend/tests/unit/upload-button.spec.ts deleted file mode 100644 index b40eed7..0000000 --- a/frontend/tests/unit/upload-button.spec.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { shallowMount } from '@vue/test-utils'; -import UploadButton from '@/components/UploadButton.vue'; -import '@/plugins/vuetify'; - -describe('UploadButton.vue', () => { - it('renders props.title when passed', () => { - const title = 'upload a file'; - const wrapper = shallowMount(UploadButton, { - slots: { - default: title, - }, - }); - expect(wrapper.text()).toMatch(title); - }); -}); diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json deleted file mode 100644 index 88cfbc3..0000000 --- a/frontend/tsconfig.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "compilerOptions": { - "noImplicitAny": false, - "target": "esnext", - "module": "esnext", - "strict": true, - "jsx": "preserve", - "importHelpers": true, - "moduleResolution": "node", - "experimentalDecorators": true, - "esModuleInterop": true, - "allowSyntheticDefaultImports": true, - "sourceMap": true, - "baseUrl": ".", - "types": [ - "webpack-env", - "jest" - ], - "paths": { - "@/*": [ - "src/*" - ] - }, - "lib": [ - "esnext", - "dom", - "dom.iterable", - "scripthost" - ] - }, - "include": [ - "src/**/*.ts", - "src/**/*.tsx", - "src/**/*.vue", - "tests/**/*.ts", - "tests/**/*.tsx" - ], - "exclude": [ - "node_modules" - ] -} diff --git a/frontend/tslint.json b/frontend/tslint.json deleted file mode 100644 index 2b37e40..0000000 --- a/frontend/tslint.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "defaultSeverity": "warning", - "extends": [ - "tslint:recommended" - ], - "linterOptions": { - "exclude": [ - "node_modules/**" - ] - }, - "rules": { - "quotemark": [true, "single"], - "indent": [true, "spaces", 2], - "interface-name": false, - "ordered-imports": false, - "object-literal-sort-keys": false, - "no-consecutive-blank-lines": false - } -} diff --git a/frontend/vue.config.js b/frontend/vue.config.js deleted file mode 100644 index 1407134..0000000 --- a/frontend/vue.config.js +++ /dev/null @@ -1,35 +0,0 @@ -module.exports = { - // Fix Vuex-typescript in prod: https://github.com/istrib/vuex-typescript/issues/13#issuecomment-409869231 - configureWebpack: (config) => { - if (process.env.NODE_ENV === 'production') { - config.optimization.minimizer[0].options.terserOptions = Object.assign( - {}, - config.optimization.minimizer[0].options.terserOptions, - { - ecma: 5, - compress: { - keep_fnames: true, - }, - warnings: false, - mangle: { - keep_fnames: true, - }, - }, - ); - } - }, - chainWebpack: config => { - config.module - .rule('vue') - .use('vue-loader') - .loader('vue-loader') - .tap(options => Object.assign(options, { - transformAssetUrls: { - 'v-img': ['src', 'lazy-src'], - 'v-card': 'src', - 'v-card-media': 'src', - 'v-responsive': 'src', - } - })); - }, -}