@@ -4,10 +4,16 @@ require('@rushstack/eslint-patch/modern-module-resolution')
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
root: true,
|
root: true,
|
||||||
'extends': [
|
'extends': [
|
||||||
'plugin:vue/vue3-essential',
|
'plugin:vue/vue3-recommended',
|
||||||
'eslint:recommended',
|
|
||||||
'@vue/eslint-config-prettier'
|
'@vue/eslint-config-prettier'
|
||||||
],
|
],
|
||||||
|
'rules': {
|
||||||
|
'vue/max-attributes-per-line': 'off',
|
||||||
|
'vue/html-closing-bracket-newline': 'off',
|
||||||
|
'vue/multi-word-component-names': 'off',
|
||||||
|
'vue/html-self-closing': 'off',
|
||||||
|
'vue/singleline-html-element-content-newline': 'off'
|
||||||
|
},
|
||||||
parserOptions: {
|
parserOptions: {
|
||||||
ecmaVersion: 'latest'
|
ecmaVersion: 'latest'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1 +1,9 @@
|
|||||||
{}
|
{
|
||||||
|
"trailingComma": "none",
|
||||||
|
"tabWidth": 2,
|
||||||
|
"semi": false,
|
||||||
|
"singleQuote": true,
|
||||||
|
"arrowParens": "avoid",
|
||||||
|
"printWidth": 100,
|
||||||
|
"bracketSameLine": true
|
||||||
|
}
|
||||||
19
README.md
19
README.md
@@ -28,25 +28,6 @@ npm run dev
|
|||||||
npm run build
|
npm run build
|
||||||
```
|
```
|
||||||
|
|
||||||
### Run End-to-End Tests with [Playwright](https://playwright.dev)
|
|
||||||
|
|
||||||
```sh
|
|
||||||
# Install browsers for the first run
|
|
||||||
npx playwright install
|
|
||||||
|
|
||||||
# When testing on CI, must build the project first
|
|
||||||
npm run build
|
|
||||||
|
|
||||||
# Runs the end-to-end tests
|
|
||||||
npm run test:e2e
|
|
||||||
# Runs the tests only on Chromium
|
|
||||||
npm run test:e2e -- --project=chromium
|
|
||||||
# Runs the tests of a specific file
|
|
||||||
npm run test:e2e -- tests/example.spec.ts
|
|
||||||
# Runs the tests in debug mode
|
|
||||||
npm run test:e2e -- --debug
|
|
||||||
```
|
|
||||||
|
|
||||||
### Lint with [ESLint](https://eslint.org/)
|
### Lint with [ESLint](https://eslint.org/)
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
const { test, expect } = require('@playwright/test');
|
|
||||||
|
|
||||||
// See here how to get started:
|
|
||||||
// https://playwright.dev/docs/intro
|
|
||||||
test('visits the app root url', async ({ page }) => {
|
|
||||||
await page.goto('/');
|
|
||||||
await expect(page.locator('div.greetings > h1')).toHaveText('You did it!');
|
|
||||||
})
|
|
||||||
7595
package-lock.json
generated
Normal file
7595
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
23
package.json
23
package.json
@@ -6,21 +6,34 @@
|
|||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
"preview": "vite preview",
|
"preview": "vite preview",
|
||||||
"test:e2e": "playwright test",
|
|
||||||
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs --fix --ignore-path .gitignore"
|
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs --fix --ignore-path .gitignore"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@fortawesome/fontawesome-svg-core": "^6.2.1",
|
||||||
|
"@fortawesome/free-brands-svg-icons": "^6.2.1",
|
||||||
|
"@fortawesome/free-regular-svg-icons": "^6.2.1",
|
||||||
|
"@fortawesome/free-solid-svg-icons": "^6.2.1",
|
||||||
|
"@fortawesome/vue-fontawesome": "^3.0.2",
|
||||||
|
"@vuelidate/core": "^2.0.0",
|
||||||
|
"@vuelidate/validators": "^2.0.0",
|
||||||
|
"axios": "^1.2.2",
|
||||||
"vue": "^3.2.45",
|
"vue": "^3.2.45",
|
||||||
"vue-router": "^4.1.6"
|
"vue-i18n": "^9.2.2",
|
||||||
|
"vue-router": "^4.1.6",
|
||||||
|
"vuex": "^4.0.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@playwright/test": "^1.28.1",
|
|
||||||
"@rushstack/eslint-patch": "^1.1.4",
|
"@rushstack/eslint-patch": "^1.1.4",
|
||||||
"@vitejs/plugin-vue": "^3.2.0",
|
"@vitejs/plugin-vue": "^4.0.0",
|
||||||
|
"@vitejs/plugin-vue-jsx": "^3.0.0",
|
||||||
"@vue/eslint-config-prettier": "^7.0.0",
|
"@vue/eslint-config-prettier": "^7.0.0",
|
||||||
|
"autoprefixer": "^10.4.13",
|
||||||
"eslint": "^8.22.0",
|
"eslint": "^8.22.0",
|
||||||
"eslint-plugin-vue": "^9.3.0",
|
"eslint-plugin-vue": "^9.3.0",
|
||||||
|
"jest": "^29.3.1",
|
||||||
|
"postcss": "^8.4.20",
|
||||||
"prettier": "^2.7.1",
|
"prettier": "^2.7.1",
|
||||||
"vite": "^3.2.4"
|
"tailwindcss": "^3.2.4",
|
||||||
|
"vite": "^4.0.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,112 +0,0 @@
|
|||||||
// @ts-check
|
|
||||||
const { devices } = require('@playwright/test')
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read environment variables from file.
|
|
||||||
* https://github.com/motdotla/dotenv
|
|
||||||
*/
|
|
||||||
// require('dotenv').config();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see https://playwright.dev/docs/test-configuration
|
|
||||||
* @type {import('@playwright/test').PlaywrightTestConfig}
|
|
||||||
*/
|
|
||||||
const config = {
|
|
||||||
testDir: './e2e',
|
|
||||||
/* Maximum time one test can run for. */
|
|
||||||
timeout: 30 * 1000,
|
|
||||||
expect: {
|
|
||||||
/**
|
|
||||||
* Maximum time expect() should wait for the condition to be met.
|
|
||||||
* For example in `await expect(locator).toHaveText();`
|
|
||||||
*/
|
|
||||||
timeout: 5000
|
|
||||||
},
|
|
||||||
/* Fail the build on CI if you accidentally left test.only in the source code. */
|
|
||||||
forbidOnly: !!process.env.CI,
|
|
||||||
/* Retry on CI only */
|
|
||||||
retries: process.env.CI ? 2 : 0,
|
|
||||||
/* Opt out of parallel tests on CI. */
|
|
||||||
workers: process.env.CI ? 1 : undefined,
|
|
||||||
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
|
|
||||||
reporter: 'html',
|
|
||||||
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
|
|
||||||
use: {
|
|
||||||
/* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */
|
|
||||||
actionTimeout: 0,
|
|
||||||
/* Base URL to use in actions like `await page.goto('/')`. */
|
|
||||||
baseURL: 'http://localhost:5173',
|
|
||||||
|
|
||||||
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
|
|
||||||
trace: 'on-first-retry',
|
|
||||||
|
|
||||||
/* Only on CI systems run the tests headless */
|
|
||||||
headless: !!process.env.CI
|
|
||||||
},
|
|
||||||
|
|
||||||
/* Configure projects for major browsers */
|
|
||||||
projects: [
|
|
||||||
{
|
|
||||||
name: 'chromium',
|
|
||||||
use: {
|
|
||||||
...devices['Desktop Chrome']
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'firefox',
|
|
||||||
use: {
|
|
||||||
...devices['Desktop Firefox']
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'webkit',
|
|
||||||
use: {
|
|
||||||
...devices['Desktop Safari']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Test against mobile viewports. */
|
|
||||||
// {
|
|
||||||
// name: 'Mobile Chrome',
|
|
||||||
// use: {
|
|
||||||
// ...devices['Pixel 5'],
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// name: 'Mobile Safari',
|
|
||||||
// use: {
|
|
||||||
// ...devices['iPhone 12'],
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
|
|
||||||
/* Test against branded browsers. */
|
|
||||||
// {
|
|
||||||
// name: 'Microsoft Edge',
|
|
||||||
// use: {
|
|
||||||
// channel: 'msedge',
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// name: 'Google Chrome',
|
|
||||||
// use: {
|
|
||||||
// channel: 'chrome',
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
],
|
|
||||||
|
|
||||||
/* Folder for test artifacts such as screenshots, videos, traces, etc. */
|
|
||||||
// outputDir: 'test-results/',
|
|
||||||
|
|
||||||
/* Run your local dev server before starting the tests */
|
|
||||||
webServer: {
|
|
||||||
/**
|
|
||||||
* Use the dev server by default for faster feedback loop.
|
|
||||||
* Use the preview server on CI for more realistic testing.
|
|
||||||
*/
|
|
||||||
command: process.env.CI ? 'vite preview --port 5173' : 'vite dev',
|
|
||||||
port: 5173,
|
|
||||||
reuseExistingServer: !process.env.CI
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = config
|
|
||||||
6
postcss.config.js
Normal file
6
postcss.config.js
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
module.exports = {
|
||||||
|
plugins: {
|
||||||
|
tailwindcss: {},
|
||||||
|
autoprefixer: {}
|
||||||
|
}
|
||||||
|
}
|
||||||
7
src/api/HttpClient.js
Normal file
7
src/api/HttpClient.js
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import axios from 'axios'
|
||||||
|
|
||||||
|
export default axios.create({
|
||||||
|
baseURL: 'https://localhost:8080/',
|
||||||
|
timeout: 1000,
|
||||||
|
headers: { 'X-Custom-Header': 'foobar' }
|
||||||
|
})
|
||||||
@@ -1,4 +1,7 @@
|
|||||||
@import './base.css';
|
@import './base.css';
|
||||||
|
@tailwind base;
|
||||||
|
@tailwind components;
|
||||||
|
@tailwind utilities;
|
||||||
|
|
||||||
#app {
|
#app {
|
||||||
max-width: 1280px;
|
max-width: 1280px;
|
||||||
|
|||||||
6
src/components/PageNotFound.vue
Normal file
6
src/components/PageNotFound.vue
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<h1>Page not Found!</h1>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script></script>
|
||||||
17
src/i18n.js
Normal file
17
src/i18n.js
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import { createI18n as _createI18n } from 'vue-i18n'
|
||||||
|
import en from './locales/en.json'
|
||||||
|
import de from './locales/de.json'
|
||||||
|
export const SUPPORT_LOCALES = ['en', 'de']
|
||||||
|
|
||||||
|
export function createI18n() {
|
||||||
|
return _createI18n({
|
||||||
|
legacy: false,
|
||||||
|
globalInjection: true,
|
||||||
|
locale: 'de',
|
||||||
|
fallbackLocale: 'en',
|
||||||
|
messages: {
|
||||||
|
en,
|
||||||
|
de
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
6
src/locales/de.json
Normal file
6
src/locales/de.json
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"hello": "Hallo i18n in SFC!",
|
||||||
|
"welcome": "Willkommen!",
|
||||||
|
"yes-button": "Ja",
|
||||||
|
"no-button": "Nein!"
|
||||||
|
}
|
||||||
6
src/locales/en.json
Normal file
6
src/locales/en.json
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"hello": "Hello i18n in SFC!",
|
||||||
|
"welcome": "Welcome!",
|
||||||
|
"yes-button": "Yes",
|
||||||
|
"no-button": "No!"
|
||||||
|
}
|
||||||
14
src/main.js
14
src/main.js
@@ -1,11 +1,23 @@
|
|||||||
import { createApp } from 'vue'
|
import { createApp } from 'vue'
|
||||||
import App from './App.vue'
|
import App from './App.vue'
|
||||||
import router from './router'
|
import router from './router'
|
||||||
|
import { createI18n } from './i18n'
|
||||||
|
import store from './store'
|
||||||
|
import { library } from '@fortawesome/fontawesome-svg-core'
|
||||||
|
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
|
||||||
|
import { faUserSecret } from '@fortawesome/free-solid-svg-icons'
|
||||||
|
|
||||||
|
/* add icons to the library */
|
||||||
|
library.add(faUserSecret)
|
||||||
|
|
||||||
import './assets/main.css'
|
import './assets/main.css'
|
||||||
|
|
||||||
|
const i18n = createI18n()
|
||||||
|
|
||||||
const app = createApp(App)
|
const app = createApp(App)
|
||||||
|
|
||||||
app.use(router)
|
app.use(router)
|
||||||
|
app.use(i18n)
|
||||||
|
app.use(store)
|
||||||
|
app.component('FontAwesomeIcon', FontAwesomeIcon)
|
||||||
app.mount('#app')
|
app.mount('#app')
|
||||||
|
|||||||
@@ -12,10 +12,13 @@ const router = createRouter({
|
|||||||
{
|
{
|
||||||
path: '/about',
|
path: '/about',
|
||||||
name: 'about',
|
name: 'about',
|
||||||
// route level code-splitting
|
// this page is lazy-loaded when the route is visited.
|
||||||
// this generates a separate chunk (About.[hash].js) for this route
|
|
||||||
// which is lazy-loaded when the route is visited.
|
|
||||||
component: () => import('../views/AboutView.vue')
|
component: () => import('../views/AboutView.vue')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/:pathMatch(.*)*',
|
||||||
|
name: 'notfound',
|
||||||
|
component: () => import('../components/PageNotFound.vue')
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
|||||||
10
src/store/index.js
Normal file
10
src/store/index.js
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import { createStore } from 'vuex'
|
||||||
|
import moduleA from './moduleA.module'
|
||||||
|
import moduleB from './moduleB.module'
|
||||||
|
|
||||||
|
export default createStore({
|
||||||
|
modules: {
|
||||||
|
a: moduleA,
|
||||||
|
b: moduleB
|
||||||
|
}
|
||||||
|
})
|
||||||
6
src/store/moduleA.module.js
Normal file
6
src/store/moduleA.module.js
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
export default {
|
||||||
|
state: () => ({}),
|
||||||
|
mutations: {},
|
||||||
|
actions: {},
|
||||||
|
getters: {}
|
||||||
|
}
|
||||||
6
src/store/moduleB.module.js
Normal file
6
src/store/moduleB.module.js
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
export default {
|
||||||
|
state: () => ({}),
|
||||||
|
mutations: {},
|
||||||
|
actions: {},
|
||||||
|
getters: {}
|
||||||
|
}
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="about">
|
<div class="about">
|
||||||
<h1>This is an about page</h1>
|
<h1>This is an about page</h1>
|
||||||
|
<font-awesome-icon icon="fa-solid fa-user-secret" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
@media (min-width: 1024px) {
|
@media (min-width: 1024px) {
|
||||||
.about {
|
.about {
|
||||||
|
|||||||
11
tailwind.config.js
Normal file
11
tailwind.config.js
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
/** @type {import('tailwindcss').Config} */
|
||||||
|
module.exports = {
|
||||||
|
content: ['./public/**/*.html', './src/**/*.{js,jsx,ts,tsx,vue}'],
|
||||||
|
theme: {
|
||||||
|
extend: {}
|
||||||
|
},
|
||||||
|
variants: {
|
||||||
|
extend: {}
|
||||||
|
},
|
||||||
|
plugins: []
|
||||||
|
}
|
||||||
@@ -2,10 +2,11 @@ import { fileURLToPath, URL } from 'node:url'
|
|||||||
|
|
||||||
import { defineConfig } from 'vite'
|
import { defineConfig } from 'vite'
|
||||||
import vue from '@vitejs/plugin-vue'
|
import vue from '@vitejs/plugin-vue'
|
||||||
|
import vueJsx from '@vitejs/plugin-vue-jsx'
|
||||||
|
|
||||||
// https://vitejs.dev/config/
|
// https://vitejs.dev/config/
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [vue()],
|
plugins: [vue(), vueJsx()],
|
||||||
resolve: {
|
resolve: {
|
||||||
alias: {
|
alias: {
|
||||||
'@': fileURLToPath(new URL('./src', import.meta.url))
|
'@': fileURLToPath(new URL('./src', import.meta.url))
|
||||||
|
|||||||
Reference in New Issue
Block a user