mirror of
https://github.com/louislam/uptime-kuma.git
synced 2024-12-18 12:14:41 -05:00
Merge branch 'master' into notification_form_i18n
# Conflicts: # src/components/notifications/SMTP.vue # src/languages/en.js
This commit is contained in:
commit
c8706b9aa1
17
.eslintrc.js
17
.eslintrc.js
@ -91,6 +91,23 @@ module.exports = {
|
|||||||
"rules": {
|
"rules": {
|
||||||
"comma-dangle": ["error", "always-multiline"],
|
"comma-dangle": ["error", "always-multiline"],
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// Override for jest puppeteer
|
||||||
|
{
|
||||||
|
"files": [
|
||||||
|
"**/*.spec.js",
|
||||||
|
"**/*.spec.jsx"
|
||||||
|
],
|
||||||
|
env: {
|
||||||
|
jest: true,
|
||||||
|
},
|
||||||
|
globals: {
|
||||||
|
page: true,
|
||||||
|
browser: true,
|
||||||
|
context: true,
|
||||||
|
jestPuppeteer: true,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
34
.github/workflows/auto-test.yml
vendored
Normal file
34
.github/workflows/auto-test.yml
vendored
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
# This workflow will do a clean install of node dependencies, cache/restore them, build the source code and run tests across different versions of node
|
||||||
|
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
|
||||||
|
|
||||||
|
name: Auto Test
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ master ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ master ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
node-version: [14.x, 15.x, 16.x]
|
||||||
|
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Use Node.js ${{ matrix.node-version }}
|
||||||
|
uses: actions/setup-node@v2
|
||||||
|
with:
|
||||||
|
node-version: ${{ matrix.node-version }}
|
||||||
|
cache: 'npm'
|
||||||
|
- run: npm ci
|
||||||
|
- run: npm run build
|
||||||
|
- run: npm test
|
||||||
|
env:
|
||||||
|
HEADLESS_TEST: 1
|
||||||
|
JUST_FOR_TEST: ${{ secrets.JUST_FOR_TEST }}
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -11,3 +11,4 @@ dist-ssr
|
|||||||
|
|
||||||
/private
|
/private
|
||||||
/out
|
/out
|
||||||
|
/tmp
|
||||||
|
100
CONTRIBUTING.md
100
CONTRIBUTING.md
@ -4,11 +4,30 @@ First of all, thank you everyone who made pull requests for Uptime Kuma, I never
|
|||||||
|
|
||||||
The project was created with vite.js (vue3). Then I created a sub-directory called "server" for server part. Both frontend and backend share the same package.json.
|
The project was created with vite.js (vue3). Then I created a sub-directory called "server" for server part. Both frontend and backend share the same package.json.
|
||||||
|
|
||||||
The frontend code build into "dist" directory. The server uses "dist" as root. This is how production is working.
|
The frontend code build into "dist" directory. The server (express.js) exposes the "dist" directory as root of the endpoint. This is how production is working.
|
||||||
|
|
||||||
|
# Key Technical Skills
|
||||||
|
|
||||||
|
- Node.js (You should know what are promise, async/await and arrow function etc.)
|
||||||
|
- Socket.io
|
||||||
|
- SCSS
|
||||||
|
- Vue.js
|
||||||
|
- Bootstrap
|
||||||
|
- SQLite
|
||||||
|
|
||||||
|
# Directories
|
||||||
|
|
||||||
|
- data (App data)
|
||||||
|
- dist (Frontend build)
|
||||||
|
- extra (Extra useful scripts)
|
||||||
|
- public (Frontend resources for dev only)
|
||||||
|
- server (Server source code)
|
||||||
|
- src (Frontend source code)
|
||||||
|
- test (unit test)
|
||||||
|
|
||||||
# Can I create a pull request for Uptime Kuma?
|
# Can I create a pull request for Uptime Kuma?
|
||||||
|
|
||||||
Generally, if the pull request is working fine and it do not affect any existing logic, workflow and perfomance, I will merge to the master branch once it is tested.
|
Generally, if the pull request is working fine and it do not affect any existing logic, workflow and perfomance, I will merge into the master branch once it is tested.
|
||||||
|
|
||||||
If you are not sure, feel free to create an empty pull request draft first.
|
If you are not sure, feel free to create an empty pull request draft first.
|
||||||
|
|
||||||
@ -43,15 +62,14 @@ It changed my current workflow and require further studies.
|
|||||||
|
|
||||||
I personally do not like something need to learn so much and need to config so much before you can finally start the app.
|
I personally do not like something need to learn so much and need to config so much before you can finally start the app.
|
||||||
|
|
||||||
For example, recently, because I am not a python expert, I spent a 2 hours to resolve all problems in order to install and use the Apprise cli. Apprise requires so many hidden requirements, I have to figure out myself how to solve the problems by Google search for my OS. That is painful. I do not want Uptime Kuma to be like this way, so:
|
|
||||||
|
|
||||||
- Easy to install for non-Docker users, no native build dependency is needed (at least for x86_64), no extra config, no extra effort to get it run
|
- Easy to install for non-Docker users, no native build dependency is needed (at least for x86_64), no extra config, no extra effort to get it run
|
||||||
- Single container for Docker users, no very complex docker-composer file. Just map the volume and expose the port, then good to go
|
- Single container for Docker users, no very complex docker-composer file. Just map the volume and expose the port, then good to go
|
||||||
- All settings in frontend.
|
- Settings should be configurable in the frontend. Env var is not encouraged.
|
||||||
- Easy to use
|
- Easy to use
|
||||||
|
|
||||||
# Coding Styles
|
# Coding Styles
|
||||||
|
|
||||||
|
- 4 spaces indentation
|
||||||
- Follow `.editorconfig`
|
- Follow `.editorconfig`
|
||||||
- Follow ESLint
|
- Follow ESLint
|
||||||
|
|
||||||
@ -65,22 +83,16 @@ For example, recently, because I am not a python expert, I spent a 2 hours to re
|
|||||||
|
|
||||||
- Node.js >= 14
|
- Node.js >= 14
|
||||||
- Git
|
- Git
|
||||||
- IDE that supports EditorConfig and ESLint (I am using Intellji Idea)
|
- IDE that supports ESLint and EditorConfig (I am using Intellji Idea)
|
||||||
- A SQLite tool (I am using SQLite Expert Personal)
|
- A SQLite tool (SQLite Expert Personal is suggested)
|
||||||
|
|
||||||
# Install dependencies
|
# Install dependencies
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm install --dev
|
npm ci
|
||||||
```
|
```
|
||||||
|
|
||||||
For npm@7, you need --legacy-peer-deps
|
# How to start the Backend Dev Server
|
||||||
|
|
||||||
```bash
|
|
||||||
npm install --legacy-peer-deps --dev
|
|
||||||
```
|
|
||||||
|
|
||||||
# Backend Dev
|
|
||||||
|
|
||||||
(2021-09-23 Update)
|
(2021-09-23 Update)
|
||||||
|
|
||||||
@ -96,28 +108,24 @@ It is mainly a socket.io app + express.js.
|
|||||||
|
|
||||||
express.js is just used for serving the frontend built files (index.html, .js and .css etc.)
|
express.js is just used for serving the frontend built files (index.html, .js and .css etc.)
|
||||||
|
|
||||||
# Frontend Dev
|
- model/ (Object model, auto mapping to the database table name)
|
||||||
|
- modules/ (Modified 3rd-party modules)
|
||||||
|
- notification-providers/ (indivdual notification logic)
|
||||||
|
- routers/ (Express Routers)
|
||||||
|
- scoket-handler (Socket.io Handlers)
|
||||||
|
- server.js (Server main logic)
|
||||||
|
|
||||||
Start frontend dev server. Hot-reload enabled in this way. It binds to `0.0.0.0:3000` by default.
|
# How to start the Frontend Dev Server
|
||||||
|
|
||||||
```bash
|
1. Set the env var `NODE_ENV` to "development".
|
||||||
npm run dev
|
2. Start the frontend dev server by the following command.
|
||||||
```
|
```bash
|
||||||
|
npm run dev
|
||||||
PS: You can ignore those scss warnings, those warnings are from Bootstrap that I cannot fix.
|
```
|
||||||
|
It binds to `0.0.0.0:3000` by default.
|
||||||
|
|
||||||
You can use Vue.js devtools Chrome extension for debugging.
|
You can use Vue.js devtools Chrome extension for debugging.
|
||||||
|
|
||||||
After the frontend server started. It cannot connect to the websocket server even you have started the server. You need to tell the frontend that is a dev env by running this in DevTool console and refresh:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
localStorage.dev = "dev";
|
|
||||||
```
|
|
||||||
|
|
||||||
So that the frontend will try to connect websocket server in 3001.
|
|
||||||
|
|
||||||
Alternately, you can specific `NODE_ENV` to "development".
|
|
||||||
|
|
||||||
## Build the frontend
|
## Build the frontend
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@ -134,11 +142,33 @@ As you can see, most data in frontend is stored in root level, even though you c
|
|||||||
|
|
||||||
The data and socket logic are in `src/mixins/socket.js`.
|
The data and socket logic are in `src/mixins/socket.js`.
|
||||||
|
|
||||||
|
|
||||||
# Database Migration
|
# Database Migration
|
||||||
|
|
||||||
1. Create `patch{num}.sql` in `./db/`
|
1. Create `patch-{name}.sql` in `./db/`
|
||||||
2. Update `latestVersion` in `./server/database.js`
|
2. Add your patch filename in the `patchList` list in `./server/database.js`
|
||||||
|
|
||||||
# Unit Test
|
# Unit Test
|
||||||
|
|
||||||
Yes, no unit test for now. I know it is very important, but at the same time my spare time is very limited. I want to implement my ideas first. I will go back to this in some points.
|
It is an end-to-end testing. It is using Jest and Puppeteer.
|
||||||
|
|
||||||
|
```
|
||||||
|
npm run build
|
||||||
|
npm test
|
||||||
|
```
|
||||||
|
|
||||||
|
By default, the Chromium window will be shown up during the test. Specifying `HEADLESS_TEST=1` for terminal environments.
|
||||||
|
|
||||||
|
# Update Dependencies
|
||||||
|
|
||||||
|
Install `ncu`
|
||||||
|
https://github.com/raineorshine/npm-check-updates
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ncu -u -t patch
|
||||||
|
npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
Since previously updating vite 2.5.10 to 2.6.0 broke the application completely, from now on, it should update patch release version only.
|
||||||
|
|
||||||
|
Patch release = the third digit
|
||||||
|
@ -19,6 +19,7 @@ if (! newVersion) {
|
|||||||
const exists = tagExists(newVersion);
|
const exists = tagExists(newVersion);
|
||||||
|
|
||||||
if (! exists) {
|
if (! exists) {
|
||||||
|
|
||||||
// Process package.json
|
// Process package.json
|
||||||
pkg.version = newVersion;
|
pkg.version = newVersion;
|
||||||
pkg.scripts.setup = pkg.scripts.setup.replaceAll(oldVersion, newVersion);
|
pkg.scripts.setup = pkg.scripts.setup.replaceAll(oldVersion, newVersion);
|
||||||
@ -29,8 +30,11 @@ if (! exists) {
|
|||||||
|
|
||||||
commit(newVersion);
|
commit(newVersion);
|
||||||
tag(newVersion);
|
tag(newVersion);
|
||||||
|
|
||||||
|
updateWiki(oldVersion, newVersion);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
console.log("version exists")
|
console.log("version exists");
|
||||||
}
|
}
|
||||||
|
|
||||||
function commit(version) {
|
function commit(version) {
|
||||||
@ -38,16 +42,16 @@ function commit(version) {
|
|||||||
|
|
||||||
let res = child_process.spawnSync("git", ["commit", "-m", msg, "-a"]);
|
let res = child_process.spawnSync("git", ["commit", "-m", msg, "-a"]);
|
||||||
let stdout = res.stdout.toString().trim();
|
let stdout = res.stdout.toString().trim();
|
||||||
console.log(stdout)
|
console.log(stdout);
|
||||||
|
|
||||||
if (stdout.includes("no changes added to commit")) {
|
if (stdout.includes("no changes added to commit")) {
|
||||||
throw new Error("commit error")
|
throw new Error("commit error");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function tag(version) {
|
function tag(version) {
|
||||||
let res = child_process.spawnSync("git", ["tag", version]);
|
let res = child_process.spawnSync("git", ["tag", version]);
|
||||||
console.log(res.stdout.toString().trim())
|
console.log(res.stdout.toString().trim());
|
||||||
}
|
}
|
||||||
|
|
||||||
function tagExists(version) {
|
function tagExists(version) {
|
||||||
@ -59,3 +63,38 @@ function tagExists(version) {
|
|||||||
|
|
||||||
return res.stdout.toString().trim() === version;
|
return res.stdout.toString().trim() === version;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function updateWiki(oldVersion, newVersion) {
|
||||||
|
const wikiDir = "./tmp/wiki";
|
||||||
|
const howToUpdateFilename = "./tmp/wiki/🆙-How-to-Update.md";
|
||||||
|
|
||||||
|
safeDelete(wikiDir);
|
||||||
|
|
||||||
|
child_process.spawnSync("git", ["clone", "https://github.com/louislam/uptime-kuma.wiki.git", wikiDir]);
|
||||||
|
let content = fs.readFileSync(howToUpdateFilename).toString();
|
||||||
|
content = content.replaceAll(`git checkout ${oldVersion}`, `git checkout ${newVersion}`);
|
||||||
|
fs.writeFileSync(howToUpdateFilename, content);
|
||||||
|
|
||||||
|
child_process.spawnSync("git", ["add", "-A"], {
|
||||||
|
cwd: wikiDir,
|
||||||
|
});
|
||||||
|
|
||||||
|
child_process.spawnSync("git", ["commit", "-m", `Update to ${newVersion} from ${oldVersion}`], {
|
||||||
|
cwd: wikiDir,
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log("Pushing to Github");
|
||||||
|
child_process.spawnSync("git", ["push"], {
|
||||||
|
cwd: wikiDir,
|
||||||
|
});
|
||||||
|
|
||||||
|
safeDelete(wikiDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
function safeDelete(dir) {
|
||||||
|
if (fs.existsSync(dir)) {
|
||||||
|
fs.rmdirSync(dir, {
|
||||||
|
recursive: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
6
jest-puppeteer.config.js
Normal file
6
jest-puppeteer.config.js
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
module.exports = {
|
||||||
|
"launch": {
|
||||||
|
"headless": process.env.HEADLESS_TEST || false,
|
||||||
|
"userDataDir": "./data/test-chrome-profile",
|
||||||
|
}
|
||||||
|
};
|
7373
package-lock.json
generated
7373
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
27
package.json
27
package.json
@ -20,6 +20,8 @@
|
|||||||
"start-server": "node server/server.js",
|
"start-server": "node server/server.js",
|
||||||
"start-server-dev": "cross-env NODE_ENV=development node server/server.js",
|
"start-server-dev": "cross-env NODE_ENV=development node server/server.js",
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
|
"test": "node test/prepare-test-server.js && node server/server.js --port=3002 --data-dir=./data/test/ --test",
|
||||||
|
"jest": "node test/prepare-jest.js && jest",
|
||||||
"tsc": "tsc",
|
"tsc": "tsc",
|
||||||
"vite-preview-dist": "vite preview --host",
|
"vite-preview-dist": "vite preview --host",
|
||||||
"build-docker": "npm run build-docker-debian && npm run build-docker-alpine",
|
"build-docker": "npm run build-docker-debian && npm run build-docker-alpine",
|
||||||
@ -51,7 +53,7 @@
|
|||||||
"@fortawesome/free-solid-svg-icons": "~5.15.4",
|
"@fortawesome/free-solid-svg-icons": "~5.15.4",
|
||||||
"@fortawesome/vue-fontawesome": "~3.0.0-4",
|
"@fortawesome/vue-fontawesome": "~3.0.0-4",
|
||||||
"@louislam/sqlite3": "~5.0.6",
|
"@louislam/sqlite3": "~5.0.6",
|
||||||
"@popperjs/core": "~2.10.1",
|
"@popperjs/core": "~2.10.2",
|
||||||
"args-parser": "~1.3.0",
|
"args-parser": "~1.3.0",
|
||||||
"axios": "~0.21.4",
|
"axios": "~0.21.4",
|
||||||
"bcryptjs": "~2.4.3",
|
"bcryptjs": "~2.4.3",
|
||||||
@ -70,7 +72,7 @@
|
|||||||
"notp": "~2.0.3",
|
"notp": "~2.0.3",
|
||||||
"password-hash": "~1.2.2",
|
"password-hash": "~1.2.2",
|
||||||
"postcss-rtlcss": "~3.4.1",
|
"postcss-rtlcss": "~3.4.1",
|
||||||
"postcss-scss": "~4.0.0",
|
"postcss-scss": "~4.0.1",
|
||||||
"prom-client": "~13.2.0",
|
"prom-client": "~13.2.0",
|
||||||
"prometheus-api-metrics": "~3.2.0",
|
"prometheus-api-metrics": "~3.2.0",
|
||||||
"qrcode": "~1.4.4",
|
"qrcode": "~1.4.4",
|
||||||
@ -85,7 +87,7 @@
|
|||||||
"vue-chart-3": "~0.5.8",
|
"vue-chart-3": "~0.5.8",
|
||||||
"vue-confirm-dialog": "~1.0.2",
|
"vue-confirm-dialog": "~1.0.2",
|
||||||
"vue-contenteditable": "~3.0.4",
|
"vue-contenteditable": "~3.0.4",
|
||||||
"vue-i18n": "~9.1.7",
|
"vue-i18n": "~9.1.8",
|
||||||
"vue-image-crop-upload": "~3.0.3",
|
"vue-image-crop-upload": "~3.0.3",
|
||||||
"vue-multiselect": "~3.0.0-alpha.2",
|
"vue-multiselect": "~3.0.0-alpha.2",
|
||||||
"vue-qrcode": "~1.0.0",
|
"vue-qrcode": "~1.0.0",
|
||||||
@ -97,17 +99,30 @@
|
|||||||
"@babel/eslint-parser": "~7.15.7",
|
"@babel/eslint-parser": "~7.15.7",
|
||||||
"@types/bootstrap": "~5.1.6",
|
"@types/bootstrap": "~5.1.6",
|
||||||
"@vitejs/plugin-legacy": "~1.5.3",
|
"@vitejs/plugin-legacy": "~1.5.3",
|
||||||
"@vitejs/plugin-vue": "~1.9.1",
|
"@vitejs/plugin-vue": "~1.9.2",
|
||||||
"@vue/compiler-sfc": "~3.2.16",
|
"@vue/compiler-sfc": "~3.2.19",
|
||||||
"core-js": "~3.18.0",
|
"core-js": "~3.18.1",
|
||||||
"cross-env": "~7.0.3",
|
"cross-env": "~7.0.3",
|
||||||
"dns2": "~2.0.1",
|
"dns2": "~2.0.1",
|
||||||
"eslint": "~7.32.0",
|
"eslint": "~7.32.0",
|
||||||
"eslint-plugin-vue": "~7.18.0",
|
"eslint-plugin-vue": "~7.18.0",
|
||||||
|
"jest": "~27.2.4",
|
||||||
|
"jest-puppeteer": "~6.0.0",
|
||||||
|
"puppeteer": "~10.4.0",
|
||||||
"sass": "~1.42.1",
|
"sass": "~1.42.1",
|
||||||
"stylelint": "~13.13.1",
|
"stylelint": "~13.13.1",
|
||||||
"stylelint-config-standard": "~22.0.0",
|
"stylelint-config-standard": "~22.0.0",
|
||||||
"typescript": "~4.4.3",
|
"typescript": "~4.4.3",
|
||||||
"vite": "~2.5.10"
|
"vite": "~2.5.10"
|
||||||
|
},
|
||||||
|
"jest": {
|
||||||
|
"verbose": true,
|
||||||
|
"preset": "jest-puppeteer",
|
||||||
|
"globals": {
|
||||||
|
"__DEV__": true
|
||||||
|
},
|
||||||
|
"testRegex": "./test/*.spec.js",
|
||||||
|
"rootDir": ".",
|
||||||
|
"testTimeout": 30000
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,6 @@ exports.startInterval = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
exports.latestVersion = res.data.version;
|
exports.latestVersion = res.data.version;
|
||||||
console.log("Latest Version: " + exports.latestVersion);
|
|
||||||
} catch (_) { }
|
} catch (_) { }
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -59,7 +59,7 @@ class Prometheus {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
monitor_cert_days_remaining.set(this.monitorLabelValues, tlsInfo.daysRemaining)
|
monitor_cert_days_remaining.set(this.monitorLabelValues, tlsInfo.certInfo.daysRemaining)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e)
|
console.error(e)
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@ console.log("Importing this project modules");
|
|||||||
debug("Importing Monitor");
|
debug("Importing Monitor");
|
||||||
const Monitor = require("./model/monitor");
|
const Monitor = require("./model/monitor");
|
||||||
debug("Importing Settings");
|
debug("Importing Settings");
|
||||||
const { getSettings, setSettings, setting, initJWTSecret, checkLogin } = require("./util-server");
|
const { getSettings, setSettings, setting, initJWTSecret, checkLogin, startUnitTest } = require("./util-server");
|
||||||
|
|
||||||
debug("Importing Notification");
|
debug("Importing Notification");
|
||||||
const { Notification } = require("./notification");
|
const { Notification } = require("./notification");
|
||||||
@ -64,12 +64,11 @@ const port = parseInt(process.env.PORT || args.port || 3001);
|
|||||||
const sslKey = process.env.SSL_KEY || args["ssl-key"] || undefined;
|
const sslKey = process.env.SSL_KEY || args["ssl-key"] || undefined;
|
||||||
const sslCert = process.env.SSL_CERT || args["ssl-cert"] || undefined;
|
const sslCert = process.env.SSL_CERT || args["ssl-cert"] || undefined;
|
||||||
|
|
||||||
// Demo Mode?
|
/**
|
||||||
const demoMode = args["demo"] || false;
|
* Run unit test after the server is ready
|
||||||
|
* @type {boolean}
|
||||||
if (demoMode) {
|
*/
|
||||||
console.log("==== Demo Mode ====");
|
const testMode = !!args["test"] || false;
|
||||||
}
|
|
||||||
|
|
||||||
console.log("Creating express and socket.io instance");
|
console.log("Creating express and socket.io instance");
|
||||||
const app = express();
|
const app = express();
|
||||||
@ -1223,6 +1222,10 @@ exports.entryPage = "dashboard";
|
|||||||
}
|
}
|
||||||
startMonitors();
|
startMonitors();
|
||||||
checkVersion.startInterval();
|
checkVersion.startInterval();
|
||||||
|
|
||||||
|
if (testMode) {
|
||||||
|
startUnitTest();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
@ -5,6 +5,7 @@ const { debug } = require("../src/util");
|
|||||||
const passwordHash = require("./password-hash");
|
const passwordHash = require("./password-hash");
|
||||||
const dayjs = require("dayjs");
|
const dayjs = require("dayjs");
|
||||||
const { Resolver } = require("dns");
|
const { Resolver } = require("dns");
|
||||||
|
const child_process = require("child_process");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Init or reset JWT secret
|
* Init or reset JWT secret
|
||||||
@ -185,38 +186,42 @@ const getDaysRemaining = (validFrom, validTo) => {
|
|||||||
return daysRemaining;
|
return daysRemaining;
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.checkCertificate = function (res) {
|
// Fix certificate Info for display
|
||||||
const {
|
// param: info - the chain obtained from getPeerCertificate()
|
||||||
valid_from,
|
const parseCertificateInfo = function (info) {
|
||||||
valid_to,
|
let link = info;
|
||||||
subjectaltname,
|
|
||||||
issuer,
|
|
||||||
fingerprint,
|
|
||||||
} = res.request.res.socket.getPeerCertificate(false);
|
|
||||||
|
|
||||||
if (!valid_from || !valid_to || !subjectaltname) {
|
while (link) {
|
||||||
throw {
|
if (!link.valid_from || !link.valid_to) {
|
||||||
message: "No TLS certificate in response",
|
break;
|
||||||
};
|
}
|
||||||
|
link.validTo = new Date(link.valid_to);
|
||||||
|
link.validFor = link.subjectaltname?.replace(/DNS:|IP Address:/g, "").split(", ");
|
||||||
|
link.daysRemaining = getDaysRemaining(new Date(), link.validTo);
|
||||||
|
|
||||||
|
// Move up the chain until loop is encountered
|
||||||
|
if (link.issuerCertificate == null) {
|
||||||
|
break;
|
||||||
|
} else if (link.fingerprint == link.issuerCertificate.fingerprint) {
|
||||||
|
link.issuerCertificate = null;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
link = link.issuerCertificate;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return info;
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.checkCertificate = function (res) {
|
||||||
|
const info = res.request.res.socket.getPeerCertificate(true);
|
||||||
const valid = res.request.res.socket.authorized || false;
|
const valid = res.request.res.socket.authorized || false;
|
||||||
|
|
||||||
const validTo = new Date(valid_to);
|
const parsedInfo = parseCertificateInfo(info);
|
||||||
|
|
||||||
const validFor = subjectaltname
|
|
||||||
.replace(/DNS:|IP Address:/g, "")
|
|
||||||
.split(", ");
|
|
||||||
|
|
||||||
const daysRemaining = getDaysRemaining(new Date(), validTo);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
valid,
|
valid: valid,
|
||||||
validFor,
|
certInfo: parsedInfo
|
||||||
validTo,
|
|
||||||
daysRemaining,
|
|
||||||
issuer,
|
|
||||||
fingerprint,
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -288,3 +293,22 @@ exports.checkLogin = (socket) => {
|
|||||||
throw new Error("You are not logged in.");
|
throw new Error("You are not logged in.");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
exports.startUnitTest = async () => {
|
||||||
|
console.log("Starting unit test...");
|
||||||
|
const npm = /^win/.test(process.platform) ? "npm.cmd" : "npm";
|
||||||
|
const child = child_process.spawn(npm, ["run", "jest"]);
|
||||||
|
|
||||||
|
child.stdout.on("data", (data) => {
|
||||||
|
console.log(data.toString());
|
||||||
|
});
|
||||||
|
|
||||||
|
child.stderr.on("data", (data) => {
|
||||||
|
console.log(data.toString());
|
||||||
|
});
|
||||||
|
|
||||||
|
child.on("close", function (code) {
|
||||||
|
console.log("Jest exit code: " + code);
|
||||||
|
process.exit(code);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
@ -321,7 +321,7 @@ h2 {
|
|||||||
.item {
|
.item {
|
||||||
display: block;
|
display: block;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
padding: 13px 15px 10px 15px;
|
padding: 14px 15px;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
transition: all ease-in-out 0.15s;
|
transition: all ease-in-out 0.15s;
|
||||||
|
|
||||||
@ -413,4 +413,4 @@ h2 {
|
|||||||
|
|
||||||
// Localization
|
// Localization
|
||||||
|
|
||||||
@import "localization.scss";
|
@import "localization.scss";
|
||||||
|
52
src/components/CertificateInfo.vue
Normal file
52
src/components/CertificateInfo.vue
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<h4>{{ $t("Certificate Info") }}</h4>
|
||||||
|
{{ $t("Certificate Chain") }}:
|
||||||
|
<div
|
||||||
|
v-if="valid"
|
||||||
|
class="rounded d-inline-flex ms-2 text-white tag-valid"
|
||||||
|
>
|
||||||
|
{{ $t("Valid") }}
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="!valid"
|
||||||
|
class="rounded d-inline-flex ms-2 text-white tag-invalid"
|
||||||
|
>
|
||||||
|
{{ $t("Invalid") }}
|
||||||
|
</div>
|
||||||
|
<certificate-info-row :cert="certInfo" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import CertificateInfoRow from "./CertificateInfoRow.vue";
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
CertificateInfoRow,
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
certInfo: {
|
||||||
|
type: Object,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
valid: {
|
||||||
|
type: Boolean,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@import "../assets/vars.scss";
|
||||||
|
|
||||||
|
.tag-valid {
|
||||||
|
padding: 2px 25px;
|
||||||
|
background-color: $primary;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag-invalid {
|
||||||
|
padding: 2px 25px;
|
||||||
|
background-color: $danger;
|
||||||
|
}
|
||||||
|
</style>
|
122
src/components/CertificateInfoRow.vue
Normal file
122
src/components/CertificateInfoRow.vue
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div class="d-flex flex-row align-items-center p-1 overflow-hidden">
|
||||||
|
<div class="m-3 ps-3">
|
||||||
|
<div class="cert-icon">
|
||||||
|
<font-awesome-icon icon="file" />
|
||||||
|
<font-awesome-icon class="award-icon" icon="award" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="m-3">
|
||||||
|
<table class="text-start">
|
||||||
|
<tbody>
|
||||||
|
<tr class="my-3">
|
||||||
|
<td class="px-3">Subject:</td>
|
||||||
|
<td>{{ formatSubject(cert.subject) }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="my-3">
|
||||||
|
<td class="px-3">Valid To:</td>
|
||||||
|
<td><Datetime :value="cert.validTo" /></td>
|
||||||
|
</tr>
|
||||||
|
<tr class="my-3">
|
||||||
|
<td class="px-3">Days Remaining:</td>
|
||||||
|
<td>{{ cert.daysRemaining }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="my-3">
|
||||||
|
<td class="px-3">Issuer:</td>
|
||||||
|
<td>{{ formatSubject(cert.issuer) }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="my-3">
|
||||||
|
<td class="px-3">Fingerprint:</td>
|
||||||
|
<td>{{ cert.fingerprint }}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex">
|
||||||
|
<font-awesome-icon
|
||||||
|
v-if="cert.issuerCertificate"
|
||||||
|
class="m-2 ps-6 link-icon"
|
||||||
|
icon="link"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<certificate-info-row
|
||||||
|
v-if="cert.issuerCertificate"
|
||||||
|
:cert="cert.issuerCertificate"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Datetime from "../components/Datetime.vue";
|
||||||
|
export default {
|
||||||
|
name: "CertificateInfoRow",
|
||||||
|
components: {
|
||||||
|
Datetime,
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
cert: {
|
||||||
|
type: Object,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
formatSubject(subject) {
|
||||||
|
if (subject.O && subject.CN && subject.C) {
|
||||||
|
return `${subject.CN} - ${subject.O} (${subject.C})`;
|
||||||
|
} else if (subject.O && subject.CN) {
|
||||||
|
return `${subject.CN} - ${subject.O}`;
|
||||||
|
} else if (subject.CN) {
|
||||||
|
return subject.CN;
|
||||||
|
} else {
|
||||||
|
return "no info";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@import "../assets/vars.scss";
|
||||||
|
|
||||||
|
table {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cert-icon {
|
||||||
|
position: relative;
|
||||||
|
font-size: 70px;
|
||||||
|
color: $link-color;
|
||||||
|
opacity: 0.5;
|
||||||
|
|
||||||
|
.dark & {
|
||||||
|
color: $dark-font-color;
|
||||||
|
opacity: 0.3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.award-icon {
|
||||||
|
position: absolute;
|
||||||
|
font-size: 0.5em;
|
||||||
|
bottom: 20%;
|
||||||
|
left: 12%;
|
||||||
|
color: white;
|
||||||
|
|
||||||
|
.dark & {
|
||||||
|
color: $dark-bg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.link-icon {
|
||||||
|
font-size: 20px;
|
||||||
|
margin-left: 50px !important;
|
||||||
|
color: $link-color;
|
||||||
|
opacity: 0.5;
|
||||||
|
|
||||||
|
.dark & {
|
||||||
|
color: $dark-font-color;
|
||||||
|
opacity: 0.3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -38,7 +38,7 @@ export default {
|
|||||||
beatMargin: 4,
|
beatMargin: 4,
|
||||||
move: false,
|
move: false,
|
||||||
maxBeat: -1,
|
maxBeat: -1,
|
||||||
}
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
|
||||||
@ -69,12 +69,12 @@ export default {
|
|||||||
if (start < 0) {
|
if (start < 0) {
|
||||||
// Add empty placeholder
|
// Add empty placeholder
|
||||||
for (let i = start; i < 0; i++) {
|
for (let i = start; i < 0; i++) {
|
||||||
placeholders.push(0)
|
placeholders.push(0);
|
||||||
}
|
}
|
||||||
start = 0;
|
start = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return placeholders.concat(this.beatList.slice(start))
|
return placeholders.concat(this.beatList.slice(start));
|
||||||
},
|
},
|
||||||
|
|
||||||
wrapStyle() {
|
wrapStyle() {
|
||||||
@ -84,7 +84,7 @@ export default {
|
|||||||
return {
|
return {
|
||||||
padding: `${topBottom}px ${leftRight}px`,
|
padding: `${topBottom}px ${leftRight}px`,
|
||||||
width: "100%",
|
width: "100%",
|
||||||
}
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
barStyle() {
|
barStyle() {
|
||||||
@ -94,12 +94,12 @@ export default {
|
|||||||
return {
|
return {
|
||||||
transition: "all ease-in-out 0.25s",
|
transition: "all ease-in-out 0.25s",
|
||||||
transform: `translateX(${width}px)`,
|
transform: `translateX(${width}px)`,
|
||||||
}
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
transform: "translateX(0)",
|
transform: "translateX(0)",
|
||||||
}
|
};
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -109,7 +109,7 @@ export default {
|
|||||||
height: this.beatHeight + "px",
|
height: this.beatHeight + "px",
|
||||||
margin: this.beatMargin + "px",
|
margin: this.beatMargin + "px",
|
||||||
"--hover-scale": this.hoverScale,
|
"--hover-scale": this.hoverScale,
|
||||||
}
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
},
|
},
|
||||||
@ -120,7 +120,7 @@ export default {
|
|||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.move = false;
|
this.move = false;
|
||||||
}, 300)
|
}, 300);
|
||||||
},
|
},
|
||||||
deep: true,
|
deep: true,
|
||||||
},
|
},
|
||||||
@ -162,7 +162,7 @@ export default {
|
|||||||
methods: {
|
methods: {
|
||||||
resize() {
|
resize() {
|
||||||
if (this.$refs.wrap) {
|
if (this.$refs.wrap) {
|
||||||
this.maxBeat = Math.floor(this.$refs.wrap.clientWidth / (this.beatWidth + this.beatMargin * 2))
|
this.maxBeat = Math.floor(this.$refs.wrap.clientWidth / (this.beatWidth + this.beatMargin * 2));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -170,7 +170,7 @@ export default {
|
|||||||
return `${this.$root.datetime(beat.time)} - ${beat.msg}`;
|
return `${this.$root.datetime(beat.time)} - ${beat.msg}`;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@ -183,6 +183,9 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.hp-bar-big {
|
.hp-bar-big {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
|
||||||
.beat {
|
.beat {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
background-color: $primary;
|
background-color: $primary;
|
||||||
|
@ -60,7 +60,6 @@ export default {
|
|||||||
|
|
||||||
this.$root.login(this.username, this.password, this.token, (res) => {
|
this.$root.login(this.username, this.password, this.token, (res) => {
|
||||||
this.processing = false;
|
this.processing = false;
|
||||||
console.log(res);
|
|
||||||
|
|
||||||
if (res.tokenRequired) {
|
if (res.tokenRequired) {
|
||||||
this.tokenRequired = true;
|
this.tokenRequired = true;
|
||||||
|
@ -3,10 +3,10 @@
|
|||||||
<div class="list-header">
|
<div class="list-header">
|
||||||
<div class="placeholder"></div>
|
<div class="placeholder"></div>
|
||||||
<div class="search-wrapper">
|
<div class="search-wrapper">
|
||||||
<a v-if="searchText == ''" class="search-icon">
|
<a v-if="!searchText" class="search-icon">
|
||||||
<font-awesome-icon icon="search" />
|
<font-awesome-icon icon="search" />
|
||||||
</a>
|
</a>
|
||||||
<a v-if="searchText != ''" class="search-icon" @click="clearSearchText">
|
<a v-if="searchText" class="search-icon" @click="clearSearchText">
|
||||||
<font-awesome-icon icon="times" />
|
<font-awesome-icon icon="times" />
|
||||||
</a>
|
</a>
|
||||||
<input v-model="searchText" class="form-control search-input" :placeholder="$t('Search...')" />
|
<input v-model="searchText" class="form-control search-input" :placeholder="$t('Search...')" />
|
||||||
@ -19,21 +19,21 @@
|
|||||||
|
|
||||||
<router-link v-for="(item, index) in sortedMonitorList" :key="index" :to="monitorURL(item.id)" class="item" :class="{ 'disabled': ! item.active }">
|
<router-link v-for="(item, index) in sortedMonitorList" :key="index" :to="monitorURL(item.id)" class="item" :class="{ 'disabled': ! item.active }">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-6 col-md-8 small-padding" :class="{ 'monitorItem': $root.userHeartbeatBar == 'bottom' || $root.userHeartbeatBar == 'none' }">
|
<div class="col-6 col-md-8 small-padding" :class="{ 'monitorItem': $root.userHeartbeatBar === 'bottom' || $root.userHeartbeatBar === 'none' }">
|
||||||
<div class="info">
|
<div class="info">
|
||||||
<Uptime :monitor="item" type="24" :pill="true" />
|
<Uptime :monitor="item" type="24" :pill="true" />
|
||||||
{{ item.name }}
|
<span class="ms-1">{{ item.name }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="tags">
|
<div class="tags">
|
||||||
<Tag v-for="tag in item.tags" :key="tag" :item="tag" :size="'sm'" />
|
<Tag v-for="tag in item.tags" :key="tag" :item="tag" :size="'sm'" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-show="$root.userHeartbeatBar == 'normal'" :key="$root.userHeartbeatBar" class="col-6 col-md-4">
|
<div v-show="$root.userHeartbeatBar === 'normal'" :key="$root.userHeartbeatBar" class="col-6 col-md-4 small-padding">
|
||||||
<HeartbeatBar size="small" :monitor-id="item.id" />
|
<HeartbeatBar size="small" :monitor-id="item.id" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="$root.userHeartbeatBar == 'bottom'" class="row">
|
<div v-if="$root.userHeartbeatBar === 'bottom'" class="row">
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<HeartbeatBar size="small" :monitor-id="item.id" />
|
<HeartbeatBar size="small" :monitor-id="item.id" />
|
||||||
</div>
|
</div>
|
||||||
@ -62,7 +62,7 @@ export default {
|
|||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
searchText: "",
|
searchText: "",
|
||||||
}
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
sortedMonitorList() {
|
sortedMonitorList() {
|
||||||
@ -91,17 +91,17 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return m1.name.localeCompare(m2.name);
|
return m1.name.localeCompare(m2.name);
|
||||||
})
|
});
|
||||||
|
|
||||||
// Simple filter by search text
|
// Simple filter by search text
|
||||||
// finds monitor name, tag name or tag value
|
// finds monitor name, tag name or tag value
|
||||||
if (this.searchText != "") {
|
if (this.searchText) {
|
||||||
const loweredSearchText = this.searchText.toLowerCase();
|
const loweredSearchText = this.searchText.toLowerCase();
|
||||||
result = result.filter(monitor => {
|
result = result.filter(monitor => {
|
||||||
return monitor.name.toLowerCase().includes(loweredSearchText)
|
return monitor.name.toLowerCase().includes(loweredSearchText)
|
||||||
|| monitor.tags.find(tag => tag.name.toLowerCase().includes(loweredSearchText)
|
|| monitor.tags.find(tag => tag.name.toLowerCase().includes(loweredSearchText)
|
||||||
|| tag.value?.toLowerCase().includes(loweredSearchText))
|
|| tag.value?.toLowerCase().includes(loweredSearchText));
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@ -115,7 +115,7 @@ export default {
|
|||||||
this.searchText = "";
|
this.searchText = "";
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
@ -22,33 +22,33 @@ export default {
|
|||||||
return Math.round(this.$root.uptimeList[key] * 10000) / 100 + "%";
|
return Math.round(this.$root.uptimeList[key] * 10000) / 100 + "%";
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.$t("notAvailableShort")
|
return this.$t("notAvailableShort");
|
||||||
},
|
},
|
||||||
|
|
||||||
color() {
|
color() {
|
||||||
if (this.lastHeartBeat.status === 0) {
|
if (this.lastHeartBeat.status === 0) {
|
||||||
return "danger"
|
return "danger";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.lastHeartBeat.status === 1) {
|
if (this.lastHeartBeat.status === 1) {
|
||||||
return "primary"
|
return "primary";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.lastHeartBeat.status === 2) {
|
if (this.lastHeartBeat.status === 2) {
|
||||||
return "warning"
|
return "warning";
|
||||||
}
|
}
|
||||||
|
|
||||||
return "secondary"
|
return "secondary";
|
||||||
},
|
},
|
||||||
|
|
||||||
lastHeartBeat() {
|
lastHeartBeat() {
|
||||||
if (this.monitor.id in this.$root.lastHeartbeatList && this.$root.lastHeartbeatList[this.monitor.id]) {
|
if (this.monitor.id in this.$root.lastHeartbeatList && this.$root.lastHeartbeatList[this.monitor.id]) {
|
||||||
return this.$root.lastHeartbeatList[this.monitor.id]
|
return this.$root.lastHeartbeatList[this.monitor.id];
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
status: -1,
|
status: -1,
|
||||||
}
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
className() {
|
className() {
|
||||||
@ -59,7 +59,7 @@ export default {
|
|||||||
return "";
|
return "";
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
@ -45,17 +45,17 @@
|
|||||||
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="to-email" class="form-label">{{ $t("To Email") }}</label>
|
<label for="to-email" class="form-label">{{ $t("To Email") }}</label>
|
||||||
<input id="to-email" v-model="$parent.notification.smtpTo" type="text" class="form-control" required autocomplete="false" placeholder="example2@kuma.pet, example3@kuma.pet">
|
<input id="to-email" v-model="$parent.notification.smtpTo" type="text" class="form-control" autocomplete="false" placeholder="example2@kuma.pet, example3@kuma.pet" :required="!hasRecipient">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="to-cc" class="form-label">{{ $t("smtpCC") }}</label>
|
<label for="to-cc" class="form-label">{{ $t("smtpCC") }}</label>
|
||||||
<input id="to-cc" v-model="$parent.notification.smtpCC" type="text" class="form-control" autocomplete="false">
|
<input id="to-cc" v-model="$parent.notification.smtpCC" type="text" class="form-control" autocomplete="false" :required="!hasRecipient">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="to-bcc" class="form-label">{{ $t("smtpBCC") }}</label>
|
<label for="to-bcc" class="form-label">{{ $t("smtpBCC") }}</label>
|
||||||
<input id="to-bcc" v-model="$parent.notification.smtpBCC" type="text" class="form-control" autocomplete="false">
|
<input id="to-bcc" v-model="$parent.notification.smtpBCC" type="text" class="form-control" autocomplete="false" :required="!hasRecipient">
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -66,10 +66,19 @@ export default {
|
|||||||
components: {
|
components: {
|
||||||
HiddenInput,
|
HiddenInput,
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
hasRecipient() {
|
||||||
|
if (this.$parent.notification.smtpTo || this.$parent.notification.smtpCC || this.$parent.notification.smtpBCC) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
if (typeof this.$parent.notification.smtpSecure === "undefined") {
|
if (typeof this.$parent.notification.smtpSecure === "undefined") {
|
||||||
this.$parent.notification.smtpSecure = false;
|
this.$parent.notification.smtpSecure = false;
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
|
15
src/i18n.js
15
src/i18n.js
@ -3,21 +3,22 @@ import bgBG from "./languages/bg-BG";
|
|||||||
import daDK from "./languages/da-DK";
|
import daDK from "./languages/da-DK";
|
||||||
import deDE from "./languages/de-DE";
|
import deDE from "./languages/de-DE";
|
||||||
import en from "./languages/en";
|
import en from "./languages/en";
|
||||||
import fa from "./languages/fa";
|
|
||||||
import esEs from "./languages/es-ES";
|
import esEs from "./languages/es-ES";
|
||||||
import ptBR from "./languages/pt-BR";
|
|
||||||
import etEE from "./languages/et-EE";
|
import etEE from "./languages/et-EE";
|
||||||
|
import fa from "./languages/fa";
|
||||||
import frFR from "./languages/fr-FR";
|
import frFR from "./languages/fr-FR";
|
||||||
|
import hu from "./languages/hu";
|
||||||
import itIT from "./languages/it-IT";
|
import itIT from "./languages/it-IT";
|
||||||
import ja from "./languages/ja";
|
import ja from "./languages/ja";
|
||||||
import koKR from "./languages/ko-KR";
|
import koKR from "./languages/ko-KR";
|
||||||
import nlNL from "./languages/nl-NL";
|
import nlNL from "./languages/nl-NL";
|
||||||
import pl from "./languages/pl";
|
import pl from "./languages/pl";
|
||||||
|
import ptBR from "./languages/pt-BR";
|
||||||
import ruRU from "./languages/ru-RU";
|
import ruRU from "./languages/ru-RU";
|
||||||
import sr from "./languages/sr";
|
import sr from "./languages/sr";
|
||||||
import srLatn from "./languages/sr-latn";
|
import srLatn from "./languages/sr-latn";
|
||||||
import trTR from "./languages/tr-TR";
|
|
||||||
import svSE from "./languages/sv-SE";
|
import svSE from "./languages/sv-SE";
|
||||||
|
import trTR from "./languages/tr-TR";
|
||||||
import zhCN from "./languages/zh-CN";
|
import zhCN from "./languages/zh-CN";
|
||||||
import zhHK from "./languages/zh-HK";
|
import zhHK from "./languages/zh-HK";
|
||||||
|
|
||||||
@ -31,6 +32,7 @@ const languageList = {
|
|||||||
"fa": fa,
|
"fa": fa,
|
||||||
"pt-BR": ptBR,
|
"pt-BR": ptBR,
|
||||||
"fr-FR": frFR,
|
"fr-FR": frFR,
|
||||||
|
"hu": hu,
|
||||||
"it-IT": itIT,
|
"it-IT": itIT,
|
||||||
"ja": ja,
|
"ja": ja,
|
||||||
"da-DK": daDK,
|
"da-DK": daDK,
|
||||||
@ -46,12 +48,13 @@ const languageList = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const rtlLangs = ["fa"];
|
const rtlLangs = ["fa"];
|
||||||
|
|
||||||
export const currentLocale = () => localStorage.locale || "en";
|
export const currentLocale = () => localStorage.locale || "en";
|
||||||
|
|
||||||
export const localeDirection = () => {
|
export const localeDirection = () => {
|
||||||
return rtlLangs.includes(currentLocale()) ? "rtl" : "ltr"
|
return rtlLangs.includes(currentLocale()) ? "rtl" : "ltr";
|
||||||
}
|
};
|
||||||
|
|
||||||
export const i18n = createI18n({
|
export const i18n = createI18n({
|
||||||
locale: currentLocale(),
|
locale: currentLocale(),
|
||||||
fallbackLocale: "en",
|
fallbackLocale: "en",
|
||||||
|
@ -30,6 +30,9 @@ import {
|
|||||||
faUpload,
|
faUpload,
|
||||||
faCopy,
|
faCopy,
|
||||||
faCheck,
|
faCheck,
|
||||||
|
faFile,
|
||||||
|
faAward,
|
||||||
|
faLink,
|
||||||
} from "@fortawesome/free-solid-svg-icons";
|
} from "@fortawesome/free-solid-svg-icons";
|
||||||
|
|
||||||
library.add(
|
library.add(
|
||||||
@ -59,6 +62,9 @@ library.add(
|
|||||||
faUpload,
|
faUpload,
|
||||||
faCopy,
|
faCopy,
|
||||||
faCheck,
|
faCheck,
|
||||||
|
faFile,
|
||||||
|
faAward,
|
||||||
|
faLink,
|
||||||
);
|
);
|
||||||
|
|
||||||
export { FontAwesomeIcon };
|
export { FontAwesomeIcon };
|
||||||
|
@ -178,4 +178,22 @@ export default {
|
|||||||
"Add a monitor": "Добави монитор",
|
"Add a monitor": "Добави монитор",
|
||||||
"Edit Status Page": "Редактирай статус страница",
|
"Edit Status Page": "Редактирай статус страница",
|
||||||
"Go to Dashboard": "Към Таблото",
|
"Go to Dashboard": "Към Таблото",
|
||||||
|
telegram: "Telegram",
|
||||||
|
webhook: "Webhook",
|
||||||
|
smtp: "Email (SMTP)",
|
||||||
|
discord: "Discord",
|
||||||
|
teams: "Microsoft Teams",
|
||||||
|
signal: "Signal",
|
||||||
|
gotify: "Gotify",
|
||||||
|
slack: "Slack",
|
||||||
|
"rocket.chat": "Rocket.chat",
|
||||||
|
pushover: "Pushover",
|
||||||
|
pushy: "Pushy",
|
||||||
|
octopush: "Octopush",
|
||||||
|
lunasea: "LunaSea",
|
||||||
|
apprise: "Apprise (Support 50+ Notification services)",
|
||||||
|
pushbullet: "Pushbullet",
|
||||||
|
line: "Line Messenger",
|
||||||
|
mattermost: "Mattermost",
|
||||||
|
"Status Page": "Status Page",
|
||||||
};
|
};
|
||||||
|
@ -170,7 +170,7 @@ export default {
|
|||||||
"Avg. Ping": "Gns. Ping",
|
"Avg. Ping": "Gns. Ping",
|
||||||
"Avg. Response": "Gns. Respons",
|
"Avg. Response": "Gns. Respons",
|
||||||
"Entry Page": "Entry Side",
|
"Entry Page": "Entry Side",
|
||||||
"statusPageNothing": "Intet her, tilføj venligst en Gruppe eller en Overvåger.",
|
statusPageNothing: "Intet her, tilføj venligst en Gruppe eller en Overvåger.",
|
||||||
"No Services": "Ingen Tjenester",
|
"No Services": "Ingen Tjenester",
|
||||||
"All Systems Operational": "Alle Systemer i Drift",
|
"All Systems Operational": "Alle Systemer i Drift",
|
||||||
"Partially Degraded Service": "Delvist Forringet Service",
|
"Partially Degraded Service": "Delvist Forringet Service",
|
||||||
@ -179,4 +179,22 @@ export default {
|
|||||||
"Add a monitor": "Tilføj en Overvåger",
|
"Add a monitor": "Tilføj en Overvåger",
|
||||||
"Edit Status Page": "Rediger Statusside",
|
"Edit Status Page": "Rediger Statusside",
|
||||||
"Go to Dashboard": "Gå til Dashboard",
|
"Go to Dashboard": "Gå til Dashboard",
|
||||||
|
"Status Page": "Status Page",
|
||||||
|
telegram: "Telegram",
|
||||||
|
webhook: "Webhook",
|
||||||
|
smtp: "Email (SMTP)",
|
||||||
|
discord: "Discord",
|
||||||
|
teams: "Microsoft Teams",
|
||||||
|
signal: "Signal",
|
||||||
|
gotify: "Gotify",
|
||||||
|
slack: "Slack",
|
||||||
|
"rocket.chat": "Rocket.chat",
|
||||||
|
pushover: "Pushover",
|
||||||
|
pushy: "Pushy",
|
||||||
|
octopush: "Octopush",
|
||||||
|
lunasea: "LunaSea",
|
||||||
|
apprise: "Apprise (Support 50+ Notification services)",
|
||||||
|
pushbullet: "Pushbullet",
|
||||||
|
line: "Line Messenger",
|
||||||
|
mattermost: "Mattermost",
|
||||||
};
|
};
|
||||||
|
@ -178,4 +178,22 @@ export default {
|
|||||||
"Add a monitor": "Monitor hinzufügen",
|
"Add a monitor": "Monitor hinzufügen",
|
||||||
"Edit Status Page": "Bearbeite Statusseite",
|
"Edit Status Page": "Bearbeite Statusseite",
|
||||||
"Go to Dashboard": "Gehe zum Dashboard",
|
"Go to Dashboard": "Gehe zum Dashboard",
|
||||||
|
"Status Page": "Status Page",
|
||||||
|
telegram: "Telegram",
|
||||||
|
webhook: "Webhook",
|
||||||
|
smtp: "Email (SMTP)",
|
||||||
|
discord: "Discord",
|
||||||
|
teams: "Microsoft Teams",
|
||||||
|
signal: "Signal",
|
||||||
|
gotify: "Gotify",
|
||||||
|
slack: "Slack",
|
||||||
|
"rocket.chat": "Rocket.chat",
|
||||||
|
pushover: "Pushover",
|
||||||
|
pushy: "Pushy",
|
||||||
|
octopush: "Octopush",
|
||||||
|
lunasea: "LunaSea",
|
||||||
|
apprise: "Apprise (Support 50+ Notification services)",
|
||||||
|
pushbullet: "Pushbullet",
|
||||||
|
line: "Line Messenger",
|
||||||
|
mattermost: "Mattermost",
|
||||||
};
|
};
|
||||||
|
@ -178,6 +178,7 @@ export default {
|
|||||||
"Add a monitor": "Add a monitor",
|
"Add a monitor": "Add a monitor",
|
||||||
"Edit Status Page": "Edit Status Page",
|
"Edit Status Page": "Edit Status Page",
|
||||||
"Go to Dashboard": "Go to Dashboard",
|
"Go to Dashboard": "Go to Dashboard",
|
||||||
|
"Status Page": "Status Page",
|
||||||
// Start notification form
|
// Start notification form
|
||||||
defaultNotificationName: "My {notification} Alert ({number})",
|
defaultNotificationName: "My {notification} Alert ({number})",
|
||||||
here: "here",
|
here: "here",
|
||||||
@ -231,45 +232,13 @@ export default {
|
|||||||
aboutKumaURL: "If you leave the Uptime Kuma URL field blank, it will default to the Project Github page.",
|
aboutKumaURL: "If you leave the Uptime Kuma URL field blank, it will default to the Project Github page.",
|
||||||
emojiCheatSheet: "Emoji cheat sheet: {0}",
|
emojiCheatSheet: "Emoji cheat sheet: {0}",
|
||||||
"rocket.chat": "Rocket.chat",
|
"rocket.chat": "Rocket.chat",
|
||||||
"pushover": "Pushover",
|
pushover: "Pushover",
|
||||||
"User Key": "User Key",
|
pushy: "Pushy",
|
||||||
"Device": "Device",
|
octopush: "Octopush",
|
||||||
"Message Title": "Message Title",
|
lunasea: "LunaSea",
|
||||||
"Notification Sound": "Notification Sound",
|
apprise: "Apprise (Support 50+ Notification services)",
|
||||||
"More info on:": "More info on: {0}",
|
pushbullet: "Pushbullet",
|
||||||
pushoverDesc1: "Emergency priority (2) has default 30 second timeout between retries and will expire after 1 hour.",
|
line: "Line Messenger",
|
||||||
pushoverDesc2: "If you want to send notifications to different devices, fill out Device field.",
|
mattermost: "Mattermost",
|
||||||
"pushy": "Pushy",
|
|
||||||
"octopush": "Octopush",
|
|
||||||
"SMS Type": "SMS Type",
|
|
||||||
octopushTypePremium: "Premium (Fast - recommended for alerting)",
|
|
||||||
octopushTypeLowCost: "Low Cost (Slow, sometimes blocked by operator)",
|
|
||||||
"Check octopush prices": "Check octopush prices {0}.",
|
|
||||||
octopushPhoneNumber: "Phone number (intl format, eg : +33612345678) ",
|
|
||||||
octopushSMSSender: "SMS Sender Name : 3-11 alphanumeric characters and space (a-zA-Z0-9)",
|
|
||||||
"lunasea": "LunaSea",
|
|
||||||
"LunaSea Device ID": "LunaSea Device ID",
|
|
||||||
"apprise": "Apprise (Support 50+ Notification services)",
|
|
||||||
"Apprise URL": "Apprise URL",
|
|
||||||
"Example:": "Example: {0}",
|
|
||||||
"Read more:": "Read more: {0}",
|
|
||||||
"Status:": "Status: {0}",
|
|
||||||
"Read more": "Read more",
|
|
||||||
appriseInstalled: "Apprise is installed.",
|
|
||||||
appriseNotInstalled: "Apprise is not installed. {0}",
|
|
||||||
"pushbullet": "Pushbullet",
|
|
||||||
"Access Token": "Access Token",
|
|
||||||
"line": "Line Messenger",
|
|
||||||
"Channel access token": "Channel access token",
|
|
||||||
"Line Developers Console": "Line Developers Console",
|
|
||||||
lineDevConsoleTo: "Line Developers Console - {0}",
|
|
||||||
"Basic Settings": "Basic Settings",
|
|
||||||
"User ID": "User ID",
|
|
||||||
"Messaging API": "Messaging API",
|
|
||||||
wayToGetLineChannelToken: "First access the {0}, create a provider and channel (Messaging API), then you can get the channel access token and user id from the above mentioned menu items.",
|
|
||||||
"mattermost": "Mattermost",
|
|
||||||
"Icon URL": "Icon URL",
|
|
||||||
aboutIconURL: "You can provide a link to a picture in \"Icon URL\" to override the default profile picture. Will not be used if Icon Emoji is set.",
|
|
||||||
aboutMattermostChannelName: "You can override the default channel that webhook posts to by entering the channel name into \"Channel Name\" field. This needs to be enabled in Mattermost webhook settings. Ex: #other-channel",
|
|
||||||
// End notification form
|
// End notification form
|
||||||
};
|
};
|
||||||
|
@ -179,4 +179,22 @@ export default {
|
|||||||
"Add a monitor": "Add a monitor",
|
"Add a monitor": "Add a monitor",
|
||||||
"Edit Status Page": "Edit Status Page",
|
"Edit Status Page": "Edit Status Page",
|
||||||
"Go to Dashboard": "Go to Dashboard",
|
"Go to Dashboard": "Go to Dashboard",
|
||||||
|
"Status Page": "Status Page",
|
||||||
|
telegram: "Telegram",
|
||||||
|
webhook: "Webhook",
|
||||||
|
smtp: "Email (SMTP)",
|
||||||
|
discord: "Discord",
|
||||||
|
teams: "Microsoft Teams",
|
||||||
|
signal: "Signal",
|
||||||
|
gotify: "Gotify",
|
||||||
|
slack: "Slack",
|
||||||
|
"rocket.chat": "Rocket.chat",
|
||||||
|
pushover: "Pushover",
|
||||||
|
pushy: "Pushy",
|
||||||
|
octopush: "Octopush",
|
||||||
|
lunasea: "LunaSea",
|
||||||
|
apprise: "Apprise (Support 50+ Notification services)",
|
||||||
|
pushbullet: "Pushbullet",
|
||||||
|
line: "Line Messenger",
|
||||||
|
mattermost: "Mattermost",
|
||||||
};
|
};
|
||||||
|
@ -1,21 +1,22 @@
|
|||||||
export default {
|
export default {
|
||||||
languageName: "eesti",
|
languageName: "eesti",
|
||||||
checkEverySecond: "Kontrolli {0} sekundilise vahega.",
|
retryCheckEverySecond: "Kontrolli {0} sekundilise vahega.",
|
||||||
retriesDescription: "Mitu korda tuleb kontrollida, mille järel märkida 'maas' ja saata välja teavitus.",
|
retriesDescription: "Mitu korda tuleb kontrollida, mille järel märkida 'maas' ja saata välja teavitus.",
|
||||||
ignoreTLSError: "Eira TLS/SSL viga HTTPS veebisaitidel.",
|
ignoreTLSError: "Eira TLS/SSL viga HTTPS veebisaitidel.",
|
||||||
upsideDownModeDescription: "Käitle teenuse saadavust rikkena, teenuse kättesaamatust töötavaks.",
|
upsideDownModeDescription: "Käitle teenuse saadavust rikkena, teenuse kättesaamatust töötavaks.",
|
||||||
maxRedirectDescription: "Suurim arv ümbersuunamisi, millele järgida. 0 ei luba ühtegi ",
|
maxRedirectDescription: "Suurim arv ümbersuunamisi, millele järgida. 0 ei luba ühtegi ",
|
||||||
acceptedStatusCodesDescription: "Vali välja HTTP koodid, mida arvestada kõlblikuks.",
|
acceptedStatusCodesDescription: "Vali välja HTTP koodid, mida arvestada kõlblikuks.",
|
||||||
passwordNotMatchMsg: "Salasõnad ei kattu.",
|
passwordNotMatchMsg: "Salasõnad ei kattu.",
|
||||||
notificationDescription: "Teavitusmeetodi kasutamiseks seo see seirega.",
|
notificationDescription: "Teavitusteenuse kasutamiseks seo see seirega.",
|
||||||
keywordDescription: "Jälgi võtmesõna HTML või JSON vastustes. (tõstutundlik)",
|
keywordDescription: "Jälgi võtmesõna HTML või JSON vastustes. (tõstutundlik)",
|
||||||
pauseDashboardHome: "Seismas",
|
pauseDashboardHome: "Seisatud",
|
||||||
deleteMonitorMsg: "Kas soovid eemaldada seire?",
|
deleteMonitorMsg: "Kas soovid eemaldada seire?",
|
||||||
deleteNotificationMsg: "Kas soovid eemaldada selle teavitusmeetodi kõikidelt seiretelt?",
|
deleteNotificationMsg: "Kas soovid eemaldada selle teavitusteenuse kõikidelt seiretelt?",
|
||||||
resoverserverDescription: "Cloudflare on vaikimisi pöördserver.",
|
resoverserverDescription: "Cloudflare on vaikimisi pöördserver.",
|
||||||
rrtypeDescription: "Vali kirje tüüp, mida soovid jälgida.",
|
rrtypeDescription: "Vali kirje tüüp, mida soovid jälgida.",
|
||||||
pauseMonitorMsg: "Kas soovid peatada seire?",
|
pauseMonitorMsg: "Kas soovid peatada seire?",
|
||||||
Settings: "Seaded",
|
Settings: "Seaded",
|
||||||
|
"Status Page": "Ülevaade",
|
||||||
Dashboard: "Töölaud",
|
Dashboard: "Töölaud",
|
||||||
"New Update": "Uuem tarkvara versioon on saadaval.",
|
"New Update": "Uuem tarkvara versioon on saadaval.",
|
||||||
Language: "Keel",
|
Language: "Keel",
|
||||||
@ -26,20 +27,21 @@ export default {
|
|||||||
"Check Update On GitHub": "Otsi uuendusi GitHub'ist",
|
"Check Update On GitHub": "Otsi uuendusi GitHub'ist",
|
||||||
List: "Nimekiri",
|
List: "Nimekiri",
|
||||||
Add: "Lisa",
|
Add: "Lisa",
|
||||||
"Add New Monitor": "Seire lisamine",
|
"Add New Monitor": "Lisa seire",
|
||||||
|
"Add a monitor": "Lisa seire",
|
||||||
"Quick Stats": "Ülevaade",
|
"Quick Stats": "Ülevaade",
|
||||||
Up: "Töökorras",
|
Up: "Töökorras",
|
||||||
Down: "Rikkis",
|
Down: "Rikkis",
|
||||||
Pending: "Määramisel",
|
Pending: "Määramisel",
|
||||||
Unknown: "Teadmata",
|
Unknown: "Kahtlast",
|
||||||
Pause: "Seiskamine",
|
Pause: "Seiska",
|
||||||
Name: "Nimi",
|
Name: "Nimi",
|
||||||
Status: "Olek",
|
Status: "Olek",
|
||||||
DateTime: "Kuupäev",
|
DateTime: "Kuupäev",
|
||||||
Message: "Tulemus",
|
Message: "Tulemus",
|
||||||
"No important events": "Märkimisväärsed juhtumid puuduvad.",
|
"No important events": "Märkimisväärsed juhtumid puuduvad.",
|
||||||
Resume: "Taasta",
|
Resume: "Taasta",
|
||||||
Edit: "Muutmine",
|
Edit: "Muuda",
|
||||||
Delete: "Eemalda",
|
Delete: "Eemalda",
|
||||||
Current: "Hetkeseisund",
|
Current: "Hetkeseisund",
|
||||||
Uptime: "Eluiga",
|
Uptime: "Eluiga",
|
||||||
@ -49,7 +51,7 @@ export default {
|
|||||||
"-day": "-päev",
|
"-day": "-päev",
|
||||||
hour: "tund",
|
hour: "tund",
|
||||||
"-hour": "-tund",
|
"-hour": "-tund",
|
||||||
Response: "Vastus",
|
Response: "Reaktsiooniaeg",
|
||||||
Ping: "Ping",
|
Ping: "Ping",
|
||||||
"Monitor Type": "Seire tüüp",
|
"Monitor Type": "Seire tüüp",
|
||||||
Keyword: "Võtmesõna",
|
Keyword: "Võtmesõna",
|
||||||
@ -108,14 +110,14 @@ export default {
|
|||||||
"Repeat Password": "korda salasõna",
|
"Repeat Password": "korda salasõna",
|
||||||
respTime: "Reageerimisaeg (ms)",
|
respTime: "Reageerimisaeg (ms)",
|
||||||
notAvailableShort: "N/A",
|
notAvailableShort: "N/A",
|
||||||
enableDefaultNotificationDescription: "Kõik järgnevalt lisatud seired kasutavad seda teavitusmeetodit. Seiretelt võib teavitusmeetodi ühekaupa eemaldada.",
|
enableDefaultNotificationDescription: "Kõik järgnevalt lisatud seired kasutavad seda teavitusteenuset. Seiretelt võib teavitusteenuse ühekaupa eemaldada.",
|
||||||
clearEventsMsg: "Kas soovid seire kõik sündmused kustutada?",
|
clearEventsMsg: "Kas soovid seire kõik sündmused kustutada?",
|
||||||
clearHeartbeatsMsg: "Kas soovid seire kõik tuksed kustutada?",
|
clearHeartbeatsMsg: "Kas soovid seire kõik tuksed kustutada?",
|
||||||
confirmClearStatisticsMsg: "Kas soovid KÕIK statistika kustutada?",
|
confirmClearStatisticsMsg: "Kas soovid TERVE ajaloo kustutada?",
|
||||||
Export: "Eksport",
|
Export: "Eksport",
|
||||||
Import: "Import",
|
Import: "Import",
|
||||||
"Default enabled": "Kasuta vaikimisi",
|
"Default enabled": "Kasuta vaikimisi",
|
||||||
"Also apply to existing monitors": "Aktiveeri teavitusmeetod olemasolevatel seiretel",
|
"Apply on all existing monitors": "Kõik praegused seired hakkavad kasutama seda teavitusteenust",
|
||||||
Create: "Loo konto",
|
Create: "Loo konto",
|
||||||
"Clear Data": "Eemalda andmed",
|
"Clear Data": "Eemalda andmed",
|
||||||
Events: "Sündmused",
|
Events: "Sündmused",
|
||||||
@ -123,60 +125,75 @@ export default {
|
|||||||
"Auto Get": "Hangi automaatselt",
|
"Auto Get": "Hangi automaatselt",
|
||||||
backupDescription: "Varunda kõik seired ja teavitused JSON faili.",
|
backupDescription: "Varunda kõik seired ja teavitused JSON faili.",
|
||||||
backupDescription2: "PS: Varukoopia EI sisalda seirete ajalugu ja sündmustikku.",
|
backupDescription2: "PS: Varukoopia EI sisalda seirete ajalugu ja sündmustikku.",
|
||||||
backupDescription3: "Varukoopiad sisaldavad teavitusmeetodite pääsuvõtmeid.",
|
backupDescription3: "Varukoopiad sisaldavad teavitusteenusete pääsuvõtmeid.",
|
||||||
alertNoFile: "Palun lisa fail, mida importida.",
|
alertNoFile: "Palun lisa fail, mida importida.",
|
||||||
alertWrongFileType: "Palun lisa JSON-formaadis fail.",
|
alertWrongFileType: "Palun lisa JSON-formaadis fail.",
|
||||||
twoFAVerifyLabel: "Please type in your token to verify that 2FA is working",
|
twoFAVerifyLabel: "2FA kinnitamiseks sisesta pääsukood",
|
||||||
tokenValidSettingsMsg: "Token is valid! You can now save the 2FA settings.",
|
tokenValidSettingsMsg: "Kood õige. Akna võib sulgeda.",
|
||||||
confirmEnableTwoFAMsg: "Are you sure you want to enable 2FA?",
|
confirmEnableTwoFAMsg: "Kas soovid 2FA sisse lülitada?",
|
||||||
confirmDisableTwoFAMsg: "Are you sure you want to disable 2FA?",
|
confirmDisableTwoFAMsg: "Kas soovid 2FA välja lülitada?",
|
||||||
"Apply on all existing monitors": "Apply on all existing monitors",
|
"Verify Token": "Kontrolli",
|
||||||
"Verify Token": "Verify Token",
|
"Setup 2FA": "Kaksikautentimise seadistamine",
|
||||||
"Setup 2FA": "Setup 2FA",
|
"Enable 2FA": "Seadista 2FA",
|
||||||
"Enable 2FA": "Enable 2FA",
|
"Disable 2FA": "Lülita 2FA välja",
|
||||||
"Disable 2FA": "Disable 2FA",
|
"2FA Settings": "2FA seaded",
|
||||||
"2FA Settings": "2FA Settings",
|
"Two Factor Authentication": "Kaksikautentimine",
|
||||||
"Two Factor Authentication": "Two Factor Authentication",
|
Active: "kasutusel",
|
||||||
Active: "Active",
|
Inactive: "seadistamata",
|
||||||
Inactive: "Inactive",
|
Token: "kaksikautentimise kood",
|
||||||
Token: "Token",
|
"Show URI": "Näita URId",
|
||||||
"Show URI": "Show URI",
|
"Clear all statistics": "Tühjenda ajalugu",
|
||||||
"Clear all statistics": "Clear all Statistics",
|
importHandleDescription: "'kombineeri' täiendab varukoopiast ja kirjutab üle samanimelised seireid ja teavitusteenused; 'lisa praegustele' jätab olemasolevad puutumata; 'asenda' kustutab ja asendab kõik seired ja teavitusteenused.",
|
||||||
retryCheckEverySecond: "Retry every {0} seconds.",
|
confirmImportMsg: "Käkerdistest hoidumiseks lae enne taastamist alla uus varukoopia. Kas soovid taastada üles laetud?",
|
||||||
importHandleDescription: "Choose 'Skip existing' if you want to skip every monitor or notification with the same name. 'Overwrite' will delete every existing monitor and notification.",
|
"Heartbeat Retry Interval": "Korduskatsete intervall",
|
||||||
confirmImportMsg: "Are you sure to import the backup? Please make sure you've selected the right import option.",
|
"Import Backup": "Varukoopia importimine",
|
||||||
"Heartbeat Retry Interval": "Heartbeat Retry Interval",
|
"Export Backup": "Varukoopia eksportimine",
|
||||||
"Import Backup": "Import Backup",
|
"Skip existing": "lisa praegustele",
|
||||||
"Export Backup": "Export Backup",
|
Overwrite: "asenda",
|
||||||
"Skip existing": "Skip existing",
|
Options: "Mestimisviis",
|
||||||
Overwrite: "Overwrite",
|
"Keep both": "kombineeri",
|
||||||
Options: "Options",
|
Tags: "Sildid",
|
||||||
"Keep both": "Keep both",
|
"Add New below or Select...": "Leia või lisa all uus…",
|
||||||
Tags: "Tags",
|
"Tag with this name already exist.": "Selle nimega silt on juba olemas.",
|
||||||
"Add New below or Select...": "Add New below or Select...",
|
"Tag with this value already exist.": "Selle väärtusega silt on juba olemas.",
|
||||||
"Tag with this name already exist.": "Tag with this name already exist.",
|
color: "värvus",
|
||||||
"Tag with this value already exist.": "Tag with this value already exist.",
|
"value (optional)": "väärtus (fakultatiivne)",
|
||||||
color: "color",
|
Gray: "hall",
|
||||||
"value (optional)": "value (optional)",
|
Red: "punane",
|
||||||
Gray: "Gray",
|
Orange: "oranž",
|
||||||
Red: "Red",
|
Green: "roheline",
|
||||||
Orange: "Orange",
|
Blue: "sinine",
|
||||||
Green: "Green",
|
Indigo: "indigo",
|
||||||
Blue: "Blue",
|
Purple: "lilla",
|
||||||
Indigo: "Indigo",
|
Pink: "roosa",
|
||||||
Purple: "Purple",
|
"Search...": "Otsi…",
|
||||||
Pink: "Pink",
|
"Avg. Ping": "Keskmine ping",
|
||||||
"Search...": "Search...",
|
"Avg. Response": "Keskmine reaktsiooniaeg",
|
||||||
"Avg. Ping": "Avg. Ping",
|
"Entry Page": "Avaleht",
|
||||||
"Avg. Response": "Avg. Response",
|
statusPageNothing: "Kippu ega kõppu; siia saab lisada seireid või -gruppe.",
|
||||||
"Entry Page": "Entry Page",
|
"No Services": "Teenused puuduvad.",
|
||||||
statusPageNothing: "Nothing here, please add a group or a monitor.",
|
"All Systems Operational": "Kõik töökorras",
|
||||||
"No Services": "No Services",
|
"Partially Degraded Service": "Teenuse töö osaliselt häiritud",
|
||||||
"All Systems Operational": "All Systems Operational",
|
"Degraded Service": "Teenuse töö häiritud",
|
||||||
"Partially Degraded Service": "Partially Degraded Service",
|
"Add Group": "Lisa grupp",
|
||||||
"Degraded Service": "Degraded Service",
|
"Edit Status Page": "Muuda lehte",
|
||||||
"Add Group": "Add Group",
|
"Go to Dashboard": "Töölauale",
|
||||||
"Add a monitor": "Add a monitor",
|
checkEverySecond: "Check every {0} seconds.",
|
||||||
"Edit Status Page": "Edit Status Page",
|
telegram: "Telegram",
|
||||||
"Go to Dashboard": "Go to Dashboard",
|
webhook: "Webhook",
|
||||||
|
smtp: "Email (SMTP)",
|
||||||
|
discord: "Discord",
|
||||||
|
teams: "Microsoft Teams",
|
||||||
|
signal: "Signal",
|
||||||
|
gotify: "Gotify",
|
||||||
|
slack: "Slack",
|
||||||
|
"rocket.chat": "Rocket.chat",
|
||||||
|
pushover: "Pushover",
|
||||||
|
pushy: "Pushy",
|
||||||
|
octopush: "Octopush",
|
||||||
|
lunasea: "LunaSea",
|
||||||
|
apprise: "Apprise (Support 50+ Notification services)",
|
||||||
|
pushbullet: "Pushbullet",
|
||||||
|
line: "Line Messenger",
|
||||||
|
mattermost: "Mattermost",
|
||||||
};
|
};
|
||||||
|
@ -187,4 +187,21 @@ export default {
|
|||||||
Last: "آخرین",
|
Last: "آخرین",
|
||||||
Info: "اطلاعات",
|
Info: "اطلاعات",
|
||||||
"Powered By": "نیرو گرفته از",
|
"Powered By": "نیرو گرفته از",
|
||||||
|
telegram: "Telegram",
|
||||||
|
webhook: "Webhook",
|
||||||
|
smtp: "Email (SMTP)",
|
||||||
|
discord: "Discord",
|
||||||
|
teams: "Microsoft Teams",
|
||||||
|
signal: "Signal",
|
||||||
|
gotify: "Gotify",
|
||||||
|
slack: "Slack",
|
||||||
|
"rocket.chat": "Rocket.chat",
|
||||||
|
pushover: "Pushover",
|
||||||
|
pushy: "Pushy",
|
||||||
|
octopush: "Octopush",
|
||||||
|
lunasea: "LunaSea",
|
||||||
|
apprise: "Apprise (Support 50+ Notification services)",
|
||||||
|
pushbullet: "Pushbullet",
|
||||||
|
line: "Line Messenger",
|
||||||
|
mattermost: "Mattermost",
|
||||||
};
|
};
|
||||||
|
@ -170,7 +170,7 @@ export default {
|
|||||||
"Avg. Ping": "Ping moyen",
|
"Avg. Ping": "Ping moyen",
|
||||||
"Avg. Response": "Réponse moyenne",
|
"Avg. Response": "Réponse moyenne",
|
||||||
"Entry Page": "Page d'accueil",
|
"Entry Page": "Page d'accueil",
|
||||||
"statusPageNothing": "Rien ici, veuillez ajouter un groupe ou une sonde.",
|
statusPageNothing: "Rien ici, veuillez ajouter un groupe ou une sonde.",
|
||||||
"No Services": "Aucun service",
|
"No Services": "Aucun service",
|
||||||
"All Systems Operational": "Tous les systèmes sont opérationnels",
|
"All Systems Operational": "Tous les systèmes sont opérationnels",
|
||||||
"Partially Degraded Service": "Service partiellement dégradé",
|
"Partially Degraded Service": "Service partiellement dégradé",
|
||||||
@ -179,4 +179,22 @@ export default {
|
|||||||
"Add a monitor": "Ajouter une sonde",
|
"Add a monitor": "Ajouter une sonde",
|
||||||
"Edit Status Page": "Modifier la page de statut",
|
"Edit Status Page": "Modifier la page de statut",
|
||||||
"Go to Dashboard": "Accéder au tableau de bord",
|
"Go to Dashboard": "Accéder au tableau de bord",
|
||||||
|
"Status Page": "Status Page",
|
||||||
|
telegram: "Telegram",
|
||||||
|
webhook: "Webhook",
|
||||||
|
smtp: "Email (SMTP)",
|
||||||
|
discord: "Discord",
|
||||||
|
teams: "Microsoft Teams",
|
||||||
|
signal: "Signal",
|
||||||
|
gotify: "Gotify",
|
||||||
|
slack: "Slack",
|
||||||
|
"rocket.chat": "Rocket.chat",
|
||||||
|
pushover: "Pushover",
|
||||||
|
pushy: "Pushy",
|
||||||
|
octopush: "Octopush",
|
||||||
|
lunasea: "LunaSea",
|
||||||
|
apprise: "Apprise (Support 50+ Notification services)",
|
||||||
|
pushbullet: "Pushbullet",
|
||||||
|
line: "Line Messenger",
|
||||||
|
mattermost: "Mattermost",
|
||||||
};
|
};
|
||||||
|
199
src/languages/hu.js
Normal file
199
src/languages/hu.js
Normal file
@ -0,0 +1,199 @@
|
|||||||
|
export default {
|
||||||
|
languageName: "Magyar",
|
||||||
|
checkEverySecond: "Ellenőrzés {0} másodpercenként",
|
||||||
|
retryCheckEverySecond: "Újrapróbál {0} másodpercenként.",
|
||||||
|
retriesDescription: "Maximális próbálkozás mielőtt a szolgáltatás leállt jelőlést kap és értesítés kerül kiküldésre",
|
||||||
|
ignoreTLSError: "TLS/SSL hibák figyelnen kívül hagyása HTTPS weboldalaknál",
|
||||||
|
upsideDownModeDescription: "Az állapot megfordítása. Ha a szolgáltatás elérhető, akkor lesz leállt állapotú.",
|
||||||
|
maxRedirectDescription: "Az átirányítások maximális száma. állítsa 0-ra az átirányítás tiltásához.",
|
||||||
|
acceptedStatusCodesDescription: "Válassza ki az állapot kódokat amelyek sikeres válasznak fognak számítani.",
|
||||||
|
passwordNotMatchMsg: "A megismételt jelszó nem egyezik.",
|
||||||
|
notificationDescription: "Kérem, rendeljen egy értesítést a figyeléshez, hogy működjön.",
|
||||||
|
keywordDescription: "Kulcsszó keresése a html-ben vagy a JSON válaszban. (kis-nagybetű érzékeny)",
|
||||||
|
pauseDashboardHome: "Szünetel",
|
||||||
|
deleteMonitorMsg: "Biztos, hogy törölni akarja ezt a figyelőt?",
|
||||||
|
deleteNotificationMsg: "Biztos, hogy törölni akarja ezt az értesítést az összes figyelőnél?",
|
||||||
|
resoverserverDescription: "A Cloudflare az alapértelmezett szerver, bármikor meg tudja változtatni a resolver server-t.",
|
||||||
|
rrtypeDescription: "Válassza ki az RR-Típust a figyelőhöz",
|
||||||
|
pauseMonitorMsg: "Biztos, hogy szüneteltetni akarja?",
|
||||||
|
enableDefaultNotificationDescription: "Minden új figyelőhöz ez az értesítés engedélyezett lesz alapértelmezetten. Kikapcsolhatja az értesítést külön minden figyelőnél.",
|
||||||
|
clearEventsMsg: "Biztos, hogy törölni akar miden eseményt ennél a figyelnél?",
|
||||||
|
clearHeartbeatsMsg: "Biztos, hogy törölni akar minden heartbeat-et ennél a figyelőnél?",
|
||||||
|
confirmClearStatisticsMsg: "Biztos, hogy törölni akat MINDEN statisztikát?",
|
||||||
|
importHandleDescription: "Válassza a 'Meglévő kihagyását', ha ki szeretné hagyni az azonos nevő figyelőket vagy értesítésket. A 'Felülírás' törölni fog minden meglévő figyelőt és értesítést.",
|
||||||
|
confirmImportMsg: "Biztos, hogy importálja a mentést? Győzödjön meg róla, hogy jól választotta ki az importálás opciót.",
|
||||||
|
twoFAVerifyLabel: "Kérem, adja meg a token-t, hogy a 2FA működését ellenőrizzük",
|
||||||
|
tokenValidSettingsMsg: "A token érvényes! El tudja menteni a 2FA beállításait.",
|
||||||
|
confirmEnableTwoFAMsg: "Biztosan engedélyezi a 2FA-t?",
|
||||||
|
confirmDisableTwoFAMsg: "Biztosan letiltja a 2FA-t?",
|
||||||
|
Settings: "Beállítások",
|
||||||
|
Dashboard: "Irányítópult",
|
||||||
|
"New Update": "Új frissítés",
|
||||||
|
Language: "Nyelv",
|
||||||
|
Appearance: "Megjelenés",
|
||||||
|
Theme: "Téma",
|
||||||
|
General: "Általános",
|
||||||
|
Version: "Verzió",
|
||||||
|
"Check Update On GitHub": "Frissítések keresése a GitHub-on",
|
||||||
|
List: "Lista",
|
||||||
|
Add: "Hozzáadás",
|
||||||
|
"Add New Monitor": "Új figyelő hozzáadása",
|
||||||
|
"Quick Stats": "Gyors statisztikák",
|
||||||
|
Up: "Működik",
|
||||||
|
Down: "Leállt",
|
||||||
|
Pending: "Függőben",
|
||||||
|
Unknown: "Ismeretlen",
|
||||||
|
Pause: "Szünet",
|
||||||
|
Name: "Név",
|
||||||
|
Status: "Állapot",
|
||||||
|
DateTime: "Időpont",
|
||||||
|
Message: "Üzenet",
|
||||||
|
"No important events": "Nincs fontos esemény",
|
||||||
|
Resume: "Folytatás",
|
||||||
|
Edit: "Szerkesztés",
|
||||||
|
Delete: "Törlés",
|
||||||
|
Current: "Aktuális",
|
||||||
|
Uptime: "Uptime",
|
||||||
|
"Cert Exp.": "Tanúsítvány lejár",
|
||||||
|
days: "napok",
|
||||||
|
day: "nap",
|
||||||
|
"-day": "-nap",
|
||||||
|
hour: "óra",
|
||||||
|
"-hour": "-óra",
|
||||||
|
Response: "Válasz",
|
||||||
|
Ping: "Ping",
|
||||||
|
"Monitor Type": "Figyelő típusa",
|
||||||
|
Keyword: "Kulcsszó",
|
||||||
|
"Friendly Name": "Rövid név",
|
||||||
|
URL: "URL",
|
||||||
|
Hostname: "Hostnév",
|
||||||
|
Port: "Port",
|
||||||
|
"Heartbeat Interval": "Heartbeat időköz",
|
||||||
|
Retries: "Újrapróbálkozás",
|
||||||
|
"Heartbeat Retry Interval": "Heartbeat újrapróbálkozások időköze",
|
||||||
|
Advanced: "Haladó",
|
||||||
|
"Upside Down Mode": "Fordított mód",
|
||||||
|
"Max. Redirects": "Max. átirányítás",
|
||||||
|
"Accepted Status Codes": "Elfogadott állapot kódok",
|
||||||
|
Save: "Mentés",
|
||||||
|
Notifications: "Értesítések",
|
||||||
|
"Not available, please setup.": "Nem elérhető, állítsa be.",
|
||||||
|
"Setup Notification": "Értesítés beállítása",
|
||||||
|
Light: "Világos",
|
||||||
|
Dark: "Sötét",
|
||||||
|
Auto: "Auto",
|
||||||
|
"Theme - Heartbeat Bar": "Téma - Heartbeat Bar",
|
||||||
|
Normal: "Normal",
|
||||||
|
Bottom: "Nyomógomb",
|
||||||
|
None: "Nincs",
|
||||||
|
Timezone: "Időzóna",
|
||||||
|
"Search Engine Visibility": "Látható a keresőmotoroknak",
|
||||||
|
"Allow indexing": "Indexelés engedélyezése",
|
||||||
|
"Discourage search engines from indexing site": "Keresőmotorok elriasztása az oldal indexelésétől",
|
||||||
|
"Change Password": "Jelszó változtatása",
|
||||||
|
"Current Password": "Jelenlegi jelszó",
|
||||||
|
"New Password": "Új jelszó",
|
||||||
|
"Repeat New Password": "Ismételje meg az új jelszót",
|
||||||
|
"Update Password": "Jelszó módosítása",
|
||||||
|
"Disable Auth": "Hitelesítés tiltása",
|
||||||
|
"Enable Auth": "Hitelesítés engedélyezése",
|
||||||
|
Logout: "Kijelenetkezés",
|
||||||
|
Leave: "Elhagy",
|
||||||
|
"I understand, please disable": "Megértettem, kérem tilsa le",
|
||||||
|
Confirm: "Megerősítés",
|
||||||
|
Yes: "Igen",
|
||||||
|
No: "Nem",
|
||||||
|
Username: "Felhasználónév",
|
||||||
|
Password: "Jelszó",
|
||||||
|
"Remember me": "Emlékezzen rám",
|
||||||
|
Login: "Bejelentkezés",
|
||||||
|
"No Monitors, please": "Nincs figyelő, kérem",
|
||||||
|
"add one": "adjon hozzá egyet",
|
||||||
|
"Notification Type": "Értesítés típusa",
|
||||||
|
Email: "Email",
|
||||||
|
Test: "Teszt",
|
||||||
|
"Certificate Info": "Tanúsítvány információk",
|
||||||
|
"Resolver Server": "Resolver szerver",
|
||||||
|
"Resource Record Type": "Resource Record típusa",
|
||||||
|
"Last Result": "Utolsó eredmény",
|
||||||
|
"Create your admin account": "Hozza létre az adminisztrátor felhasználót",
|
||||||
|
"Repeat Password": "Jelszó ismétlése",
|
||||||
|
"Import Backup": "Mentés importálása",
|
||||||
|
"Export Backup": "Mentés exportálása",
|
||||||
|
Export: "Exportálás",
|
||||||
|
Import: "Importálás",
|
||||||
|
respTime: "Válaszidő (ms)",
|
||||||
|
notAvailableShort: "N/A",
|
||||||
|
"Default enabled": "Alapértelmezetten engedélyezett",
|
||||||
|
"Apply on all existing monitors": "Alkalmazza az összes figyelőre",
|
||||||
|
Create: "Létrehozás",
|
||||||
|
"Clear Data": "Adatok törlése",
|
||||||
|
Events: "Események",
|
||||||
|
Heartbeats: "Heartbeats",
|
||||||
|
"Auto Get": "Auto Get",
|
||||||
|
backupDescription: "Ki tudja menteni az összes figyelőt és értesítést egy JSON fájlba.",
|
||||||
|
backupDescription2: "Ui.: Történeti és esemény adatokat nem tartalmaz.",
|
||||||
|
backupDescription3: "Érzékeny adatok, pl. szolgáltatás kulcsok is vannak az export fájlban. Figyelmesen őrizze!",
|
||||||
|
alertNoFile: "Válaszzon ki egy fájlt az importáláshoz.",
|
||||||
|
alertWrongFileType: "Válasszon egy JSON fájlt.",
|
||||||
|
"Clear all statistics": "Összes statisztika törlése",
|
||||||
|
"Skip existing": "Meglévő kihagyása",
|
||||||
|
Overwrite: "Felülírás",
|
||||||
|
Options: "Opciók",
|
||||||
|
"Keep both": "Mindegyiket tartsa meg",
|
||||||
|
"Verify Token": "Token ellenőrzése",
|
||||||
|
"Setup 2FA": "2FA beállítása",
|
||||||
|
"Enable 2FA": "2FA engedélyezése",
|
||||||
|
"Disable 2FA": "2FA toltása",
|
||||||
|
"2FA Settings": "2FA beállítások",
|
||||||
|
"Two Factor Authentication": "Two Factor Authentication",
|
||||||
|
Active: "Aktív",
|
||||||
|
Inactive: "Inaktív",
|
||||||
|
Token: "Token",
|
||||||
|
"Show URI": "URI megmutatása",
|
||||||
|
Tags: "Cimkék",
|
||||||
|
"Add New below or Select...": "Adjon hozzá lentre vagy válasszon...",
|
||||||
|
"Tag with this name already exist.": "Ilyen nevű cimke már létezik.",
|
||||||
|
"Tag with this value already exist.": "Ilyen értékű cimke már létezik.",
|
||||||
|
color: "szín",
|
||||||
|
"value (optional)": "érték (opcionális)",
|
||||||
|
Gray: "Szürke",
|
||||||
|
Red: "Piros",
|
||||||
|
Orange: "Narancs",
|
||||||
|
Green: "Zöld",
|
||||||
|
Blue: "Kék",
|
||||||
|
Indigo: "Indigó",
|
||||||
|
Purple: "Lila",
|
||||||
|
Pink: "Rózsaszín",
|
||||||
|
"Search...": "Keres...",
|
||||||
|
"Avg. Ping": "Átl. ping",
|
||||||
|
"Avg. Response": "Átl. válasz",
|
||||||
|
"Entry Page": "Nyitólap",
|
||||||
|
statusPageNothing: "Semmi nincs itt, kérem, adjon hozzá egy figyelőt.",
|
||||||
|
"No Services": "Nincs szolgáltatás",
|
||||||
|
"All Systems Operational": "Minden rendszer működik",
|
||||||
|
"Partially Degraded Service": "Részlegesen leállt szolgáltatás",
|
||||||
|
"Degraded Service": "Leállt szolgáltatás",
|
||||||
|
"Add Group": "Csoport hozzáadása",
|
||||||
|
"Add a monitor": "Figyelő hozzáadása",
|
||||||
|
"Edit Status Page": "Sátusz oldal szerkesztése",
|
||||||
|
"Go to Dashboard": "Menj az irányítópulthoz",
|
||||||
|
telegram: "Telegram",
|
||||||
|
webhook: "Webhook",
|
||||||
|
smtp: "Email (SMTP)",
|
||||||
|
discord: "Discord",
|
||||||
|
teams: "Microsoft Teams",
|
||||||
|
signal: "Signal",
|
||||||
|
gotify: "Gotify",
|
||||||
|
slack: "Slack",
|
||||||
|
"rocket.chat": "Rocket.chat",
|
||||||
|
pushover: "Pushover",
|
||||||
|
pushy: "Pushy",
|
||||||
|
octopush: "Octopush",
|
||||||
|
lunasea: "LunaSea",
|
||||||
|
apprise: "Apprise (Support 50+ Notification services)",
|
||||||
|
pushbullet: "Pushbullet",
|
||||||
|
line: "Line Messenger",
|
||||||
|
mattermost: "Mattermost",
|
||||||
|
"Status Page": "Status Page",
|
||||||
|
};
|
@ -169,7 +169,7 @@ export default {
|
|||||||
"Avg. Ping": "Ping medio",
|
"Avg. Ping": "Ping medio",
|
||||||
"Avg. Response": "Risposta media",
|
"Avg. Response": "Risposta media",
|
||||||
"Entry Page": "Entry Page",
|
"Entry Page": "Entry Page",
|
||||||
"statusPageNothing": "Non c'è nulla qui, aggiungere un gruppo oppure un monitoraggio.",
|
statusPageNothing: "Non c'è nulla qui, aggiungere un gruppo oppure un monitoraggio.",
|
||||||
"No Services": "Nessun Servizio",
|
"No Services": "Nessun Servizio",
|
||||||
"All Systems Operational": "Tutti i sistemi sono operativi",
|
"All Systems Operational": "Tutti i sistemi sono operativi",
|
||||||
"Partially Degraded Service": "Servizio parzialmente degradato",
|
"Partially Degraded Service": "Servizio parzialmente degradato",
|
||||||
@ -178,4 +178,22 @@ export default {
|
|||||||
"Add a monitor": "Aggiungi un monitoraggio",
|
"Add a monitor": "Aggiungi un monitoraggio",
|
||||||
"Edit Status Page": "Modifica pagina di stato",
|
"Edit Status Page": "Modifica pagina di stato",
|
||||||
"Go to Dashboard": "Vai al Cruscotto",
|
"Go to Dashboard": "Vai al Cruscotto",
|
||||||
|
"Status Page": "Status Page",
|
||||||
|
telegram: "Telegram",
|
||||||
|
webhook: "Webhook",
|
||||||
|
smtp: "Email (SMTP)",
|
||||||
|
discord: "Discord",
|
||||||
|
teams: "Microsoft Teams",
|
||||||
|
signal: "Signal",
|
||||||
|
gotify: "Gotify",
|
||||||
|
slack: "Slack",
|
||||||
|
"rocket.chat": "Rocket.chat",
|
||||||
|
pushover: "Pushover",
|
||||||
|
pushy: "Pushy",
|
||||||
|
octopush: "Octopush",
|
||||||
|
lunasea: "LunaSea",
|
||||||
|
apprise: "Apprise (Support 50+ Notification services)",
|
||||||
|
pushbullet: "Pushbullet",
|
||||||
|
line: "Line Messenger",
|
||||||
|
mattermost: "Mattermost",
|
||||||
};
|
};
|
||||||
|
@ -179,4 +179,22 @@ export default {
|
|||||||
"Add a monitor": "Add a monitor",
|
"Add a monitor": "Add a monitor",
|
||||||
"Edit Status Page": "Edit Status Page",
|
"Edit Status Page": "Edit Status Page",
|
||||||
"Go to Dashboard": "Go to Dashboard",
|
"Go to Dashboard": "Go to Dashboard",
|
||||||
|
"Status Page": "Status Page",
|
||||||
|
telegram: "Telegram",
|
||||||
|
webhook: "Webhook",
|
||||||
|
smtp: "Email (SMTP)",
|
||||||
|
discord: "Discord",
|
||||||
|
teams: "Microsoft Teams",
|
||||||
|
signal: "Signal",
|
||||||
|
gotify: "Gotify",
|
||||||
|
slack: "Slack",
|
||||||
|
"rocket.chat": "Rocket.chat",
|
||||||
|
pushover: "Pushover",
|
||||||
|
pushy: "Pushy",
|
||||||
|
octopush: "Octopush",
|
||||||
|
lunasea: "LunaSea",
|
||||||
|
apprise: "Apprise (Support 50+ Notification services)",
|
||||||
|
pushbullet: "Pushbullet",
|
||||||
|
line: "Line Messenger",
|
||||||
|
mattermost: "Mattermost",
|
||||||
};
|
};
|
||||||
|
@ -179,4 +179,22 @@ export default {
|
|||||||
"Add a monitor": "Add a monitor",
|
"Add a monitor": "Add a monitor",
|
||||||
"Edit Status Page": "Edit Status Page",
|
"Edit Status Page": "Edit Status Page",
|
||||||
"Go to Dashboard": "Go to Dashboard",
|
"Go to Dashboard": "Go to Dashboard",
|
||||||
|
"Status Page": "Status Page",
|
||||||
|
telegram: "Telegram",
|
||||||
|
webhook: "Webhook",
|
||||||
|
smtp: "Email (SMTP)",
|
||||||
|
discord: "Discord",
|
||||||
|
teams: "Microsoft Teams",
|
||||||
|
signal: "Signal",
|
||||||
|
gotify: "Gotify",
|
||||||
|
slack: "Slack",
|
||||||
|
"rocket.chat": "Rocket.chat",
|
||||||
|
pushover: "Pushover",
|
||||||
|
pushy: "Pushy",
|
||||||
|
octopush: "Octopush",
|
||||||
|
lunasea: "LunaSea",
|
||||||
|
apprise: "Apprise (Support 50+ Notification services)",
|
||||||
|
pushbullet: "Pushbullet",
|
||||||
|
line: "Line Messenger",
|
||||||
|
mattermost: "Mattermost",
|
||||||
};
|
};
|
||||||
|
@ -179,4 +179,22 @@ export default {
|
|||||||
"Add a monitor": "Add a monitor",
|
"Add a monitor": "Add a monitor",
|
||||||
"Edit Status Page": "Edit Status Page",
|
"Edit Status Page": "Edit Status Page",
|
||||||
"Go to Dashboard": "Go to Dashboard",
|
"Go to Dashboard": "Go to Dashboard",
|
||||||
|
"Status Page": "Status Page",
|
||||||
|
telegram: "Telegram",
|
||||||
|
webhook: "Webhook",
|
||||||
|
smtp: "Email (SMTP)",
|
||||||
|
discord: "Discord",
|
||||||
|
teams: "Microsoft Teams",
|
||||||
|
signal: "Signal",
|
||||||
|
gotify: "Gotify",
|
||||||
|
slack: "Slack",
|
||||||
|
"rocket.chat": "Rocket.chat",
|
||||||
|
pushover: "Pushover",
|
||||||
|
pushy: "Pushy",
|
||||||
|
octopush: "Octopush",
|
||||||
|
lunasea: "LunaSea",
|
||||||
|
apprise: "Apprise (Support 50+ Notification services)",
|
||||||
|
pushbullet: "Pushbullet",
|
||||||
|
line: "Line Messenger",
|
||||||
|
mattermost: "Mattermost",
|
||||||
};
|
};
|
||||||
|
@ -169,14 +169,32 @@ export default {
|
|||||||
"Search...": "Szukaj...",
|
"Search...": "Szukaj...",
|
||||||
"Avg. Ping": "Średni ping",
|
"Avg. Ping": "Średni ping",
|
||||||
"Avg. Response": "Średnia odpowiedź",
|
"Avg. Response": "Średnia odpowiedź",
|
||||||
"Entry Page": "Wejdź na stronę",
|
"Entry Page": "Strona główna",
|
||||||
"statusPageNothing": "Nic tu nie ma, dodaj monitor lub grupę.",
|
statusPageNothing: "Nic tu nie ma, dodaj grupę lub monitor.",
|
||||||
"No Services": "Brak usług",
|
"No Services": "Brak usług",
|
||||||
"All Systems Operational": "Wszystkie systemy działają",
|
"All Systems Operational": "Wszystkie systemy działają",
|
||||||
"Partially Degraded Service": "Częściowy błąd usługi",
|
"Partially Degraded Service": "Częściowy błąd usługi",
|
||||||
"Degraded Service": "Błąd usługi",
|
"Degraded Service": "Błąd usługi",
|
||||||
"Add Group": "Dodaj grupę",
|
"Add Group": "Dodaj grupę",
|
||||||
"Add a monitor": "Dodaj monitoe",
|
"Add a monitor": "Dodaj monitor",
|
||||||
"Edit Status Page": "Edytuj stronę statusu",
|
"Edit Status Page": "Edytuj stronę statusu",
|
||||||
"Go to Dashboard": "Idź do panelu",
|
"Go to Dashboard": "Idź do panelu",
|
||||||
|
"Status Page": "Strona statusu",
|
||||||
|
telegram: "Telegram",
|
||||||
|
webhook: "Webhook",
|
||||||
|
smtp: "Email (SMTP)",
|
||||||
|
discord: "Discord",
|
||||||
|
teams: "Microsoft Teams",
|
||||||
|
signal: "Signal",
|
||||||
|
gotify: "Gotify",
|
||||||
|
slack: "Slack",
|
||||||
|
"rocket.chat": "Rocket.chat",
|
||||||
|
pushover: "Pushover",
|
||||||
|
pushy: "Pushy",
|
||||||
|
octopush: "Octopush",
|
||||||
|
lunasea: "LunaSea",
|
||||||
|
apprise: "Apprise (obsługuje 50+ usług powiadamiania)",
|
||||||
|
pushbullet: "Pushbullet",
|
||||||
|
line: "Line Messenger",
|
||||||
|
mattermost: "Mattermost",
|
||||||
};
|
};
|
||||||
|
@ -179,4 +179,21 @@ export default {
|
|||||||
"Add a monitor": "Adicionar um monitor",
|
"Add a monitor": "Adicionar um monitor",
|
||||||
"Edit Status Page": "Editar Página de Status",
|
"Edit Status Page": "Editar Página de Status",
|
||||||
"Go to Dashboard": "Ir para a dashboard",
|
"Go to Dashboard": "Ir para a dashboard",
|
||||||
|
telegram: "Telegram",
|
||||||
|
webhook: "Webhook",
|
||||||
|
smtp: "Email (SMTP)",
|
||||||
|
discord: "Discord",
|
||||||
|
teams: "Microsoft Teams",
|
||||||
|
signal: "Signal",
|
||||||
|
gotify: "Gotify",
|
||||||
|
slack: "Slack",
|
||||||
|
"rocket.chat": "Rocket.chat",
|
||||||
|
pushover: "Pushover",
|
||||||
|
pushy: "Pushy",
|
||||||
|
octopush: "Octopush",
|
||||||
|
lunasea: "LunaSea",
|
||||||
|
apprise: "Apprise (Support 50+ Notification services)",
|
||||||
|
pushbullet: "Pushbullet",
|
||||||
|
line: "Line Messenger",
|
||||||
|
mattermost: "Mattermost",
|
||||||
};
|
};
|
||||||
|
@ -43,7 +43,7 @@ export default {
|
|||||||
Delete: "Удалить",
|
Delete: "Удалить",
|
||||||
Current: "Текущий",
|
Current: "Текущий",
|
||||||
Uptime: "Аптайм",
|
Uptime: "Аптайм",
|
||||||
"Cert Exp.": "Сертификат просрочен",
|
"Cert Exp.": "Сертификат истекает",
|
||||||
days: "дней",
|
days: "дней",
|
||||||
day: "день",
|
day: "день",
|
||||||
"-day": " дней",
|
"-day": " дней",
|
||||||
@ -180,8 +180,25 @@ export default {
|
|||||||
"Edit Status Page": "Редактировать",
|
"Edit Status Page": "Редактировать",
|
||||||
"Go to Dashboard": "Панель мониторов",
|
"Go to Dashboard": "Панель мониторов",
|
||||||
"Status Page": "Статус сервисов",
|
"Status Page": "Статус сервисов",
|
||||||
"Discard": "Отмена",
|
Discard: "Отмена",
|
||||||
"Create Incident": "Создать инцидент",
|
"Create Incident": "Создать инцидент",
|
||||||
"Switch to Dark Theme": "Тёмная тема",
|
"Switch to Dark Theme": "Тёмная тема",
|
||||||
"Switch to Light Theme": "Светлая тема",
|
"Switch to Light Theme": "Светлая тема",
|
||||||
|
telegram: "Telegram",
|
||||||
|
webhook: "Webhook",
|
||||||
|
smtp: "Email (SMTP)",
|
||||||
|
discord: "Discord",
|
||||||
|
teams: "Microsoft Teams",
|
||||||
|
signal: "Signal",
|
||||||
|
gotify: "Gotify",
|
||||||
|
slack: "Slack",
|
||||||
|
"rocket.chat": "Rocket.chat",
|
||||||
|
pushover: "Pushover",
|
||||||
|
pushy: "Pushy",
|
||||||
|
octopush: "Octopush",
|
||||||
|
lunasea: "LunaSea",
|
||||||
|
apprise: "Apprise (Support 50+ Notification services)",
|
||||||
|
pushbullet: "Pushbullet",
|
||||||
|
line: "Line Messenger",
|
||||||
|
mattermost: "Mattermost",
|
||||||
};
|
};
|
||||||
|
@ -179,4 +179,22 @@ export default {
|
|||||||
"Add a monitor": "Add a monitor",
|
"Add a monitor": "Add a monitor",
|
||||||
"Edit Status Page": "Edit Status Page",
|
"Edit Status Page": "Edit Status Page",
|
||||||
"Go to Dashboard": "Go to Dashboard",
|
"Go to Dashboard": "Go to Dashboard",
|
||||||
|
"Status Page": "Status Page",
|
||||||
|
telegram: "Telegram",
|
||||||
|
webhook: "Webhook",
|
||||||
|
smtp: "Email (SMTP)",
|
||||||
|
discord: "Discord",
|
||||||
|
teams: "Microsoft Teams",
|
||||||
|
signal: "Signal",
|
||||||
|
gotify: "Gotify",
|
||||||
|
slack: "Slack",
|
||||||
|
"rocket.chat": "Rocket.chat",
|
||||||
|
pushover: "Pushover",
|
||||||
|
pushy: "Pushy",
|
||||||
|
octopush: "Octopush",
|
||||||
|
lunasea: "LunaSea",
|
||||||
|
apprise: "Apprise (Support 50+ Notification services)",
|
||||||
|
pushbullet: "Pushbullet",
|
||||||
|
line: "Line Messenger",
|
||||||
|
mattermost: "Mattermost",
|
||||||
};
|
};
|
||||||
|
@ -179,4 +179,22 @@ export default {
|
|||||||
"Add a monitor": "Add a monitor",
|
"Add a monitor": "Add a monitor",
|
||||||
"Edit Status Page": "Edit Status Page",
|
"Edit Status Page": "Edit Status Page",
|
||||||
"Go to Dashboard": "Go to Dashboard",
|
"Go to Dashboard": "Go to Dashboard",
|
||||||
|
"Status Page": "Status Page",
|
||||||
|
telegram: "Telegram",
|
||||||
|
webhook: "Webhook",
|
||||||
|
smtp: "Email (SMTP)",
|
||||||
|
discord: "Discord",
|
||||||
|
teams: "Microsoft Teams",
|
||||||
|
signal: "Signal",
|
||||||
|
gotify: "Gotify",
|
||||||
|
slack: "Slack",
|
||||||
|
"rocket.chat": "Rocket.chat",
|
||||||
|
pushover: "Pushover",
|
||||||
|
pushy: "Pushy",
|
||||||
|
octopush: "Octopush",
|
||||||
|
lunasea: "LunaSea",
|
||||||
|
apprise: "Apprise (Support 50+ Notification services)",
|
||||||
|
pushbullet: "Pushbullet",
|
||||||
|
line: "Line Messenger",
|
||||||
|
mattermost: "Mattermost",
|
||||||
};
|
};
|
||||||
|
@ -179,4 +179,22 @@ export default {
|
|||||||
"Add a monitor": "Add a monitor",
|
"Add a monitor": "Add a monitor",
|
||||||
"Edit Status Page": "Edit Status Page",
|
"Edit Status Page": "Edit Status Page",
|
||||||
"Go to Dashboard": "Go to Dashboard",
|
"Go to Dashboard": "Go to Dashboard",
|
||||||
|
"Status Page": "Status Page",
|
||||||
|
telegram: "Telegram",
|
||||||
|
webhook: "Webhook",
|
||||||
|
smtp: "Email (SMTP)",
|
||||||
|
discord: "Discord",
|
||||||
|
teams: "Microsoft Teams",
|
||||||
|
signal: "Signal",
|
||||||
|
gotify: "Gotify",
|
||||||
|
slack: "Slack",
|
||||||
|
"rocket.chat": "Rocket.chat",
|
||||||
|
pushover: "Pushover",
|
||||||
|
pushy: "Pushy",
|
||||||
|
octopush: "Octopush",
|
||||||
|
lunasea: "LunaSea",
|
||||||
|
apprise: "Apprise (Support 50+ Notification services)",
|
||||||
|
pushbullet: "Pushbullet",
|
||||||
|
line: "Line Messenger",
|
||||||
|
mattermost: "Mattermost",
|
||||||
};
|
};
|
||||||
|
@ -178,4 +178,22 @@ export default {
|
|||||||
"Add a monitor": "Add a monitor",
|
"Add a monitor": "Add a monitor",
|
||||||
"Edit Status Page": "Edit Status Page",
|
"Edit Status Page": "Edit Status Page",
|
||||||
"Go to Dashboard": "Go to Dashboard",
|
"Go to Dashboard": "Go to Dashboard",
|
||||||
|
"Status Page": "Status Page",
|
||||||
|
telegram: "Telegram",
|
||||||
|
webhook: "Webhook",
|
||||||
|
smtp: "Email (SMTP)",
|
||||||
|
discord: "Discord",
|
||||||
|
teams: "Microsoft Teams",
|
||||||
|
signal: "Signal",
|
||||||
|
gotify: "Gotify",
|
||||||
|
slack: "Slack",
|
||||||
|
"rocket.chat": "Rocket.chat",
|
||||||
|
pushover: "Pushover",
|
||||||
|
pushy: "Pushy",
|
||||||
|
octopush: "Octopush",
|
||||||
|
lunasea: "LunaSea",
|
||||||
|
apprise: "Apprise (Support 50+ Notification services)",
|
||||||
|
pushbullet: "Pushbullet",
|
||||||
|
line: "Line Messenger",
|
||||||
|
mattermost: "Mattermost",
|
||||||
};
|
};
|
||||||
|
@ -170,7 +170,7 @@ export default {
|
|||||||
"Avg. Ping": "平均Ping",
|
"Avg. Ping": "平均Ping",
|
||||||
"Avg. Response": "平均响应",
|
"Avg. Response": "平均响应",
|
||||||
"Entry Page": "入口页面",
|
"Entry Page": "入口页面",
|
||||||
"statusPageNothing": "这里什么也没有,请添加一个分组或一个监控项。",
|
statusPageNothing: "这里什么也没有,请添加一个分组或一个监控项。",
|
||||||
"No Services": "无服务",
|
"No Services": "无服务",
|
||||||
"All Systems Operational": "所有服务运行正常",
|
"All Systems Operational": "所有服务运行正常",
|
||||||
"Partially Degraded Service": "部分服务出现故障",
|
"Partially Degraded Service": "部分服务出现故障",
|
||||||
@ -179,4 +179,22 @@ export default {
|
|||||||
"Add a monitor": "添加监控项",
|
"Add a monitor": "添加监控项",
|
||||||
"Edit Status Page": "编辑状态页",
|
"Edit Status Page": "编辑状态页",
|
||||||
"Go to Dashboard": "前往仪表盘",
|
"Go to Dashboard": "前往仪表盘",
|
||||||
|
"Status Page": "Status Page",
|
||||||
|
telegram: "Telegram",
|
||||||
|
webhook: "Webhook",
|
||||||
|
smtp: "Email (SMTP)",
|
||||||
|
discord: "Discord",
|
||||||
|
teams: "Microsoft Teams",
|
||||||
|
signal: "Signal",
|
||||||
|
gotify: "Gotify",
|
||||||
|
slack: "Slack",
|
||||||
|
"rocket.chat": "Rocket.chat",
|
||||||
|
pushover: "Pushover",
|
||||||
|
pushy: "Pushy",
|
||||||
|
octopush: "Octopush",
|
||||||
|
lunasea: "LunaSea",
|
||||||
|
apprise: "Apprise (Support 50+ Notification services)",
|
||||||
|
pushbullet: "Pushbullet",
|
||||||
|
line: "Line Messenger",
|
||||||
|
mattermost: "Mattermost",
|
||||||
};
|
};
|
||||||
|
@ -179,4 +179,22 @@ export default {
|
|||||||
"Add a monitor": "Add a monitor",
|
"Add a monitor": "Add a monitor",
|
||||||
"Edit Status Page": "Edit Status Page",
|
"Edit Status Page": "Edit Status Page",
|
||||||
"Go to Dashboard": "Go to Dashboard",
|
"Go to Dashboard": "Go to Dashboard",
|
||||||
|
"Status Page": "Status Page",
|
||||||
|
telegram: "Telegram",
|
||||||
|
webhook: "Webhook",
|
||||||
|
smtp: "Email (SMTP)",
|
||||||
|
discord: "Discord",
|
||||||
|
teams: "Microsoft Teams",
|
||||||
|
signal: "Signal",
|
||||||
|
gotify: "Gotify",
|
||||||
|
slack: "Slack",
|
||||||
|
"rocket.chat": "Rocket.chat",
|
||||||
|
pushover: "Pushover",
|
||||||
|
pushy: "Pushy",
|
||||||
|
octopush: "Octopush",
|
||||||
|
lunasea: "LunaSea",
|
||||||
|
apprise: "Apprise (Support 50+ Notification services)",
|
||||||
|
pushbullet: "Pushbullet",
|
||||||
|
line: "Line Messenger",
|
||||||
|
mattermost: "Mattermost",
|
||||||
};
|
};
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import "bootstrap";
|
import "bootstrap";
|
||||||
import { createApp, h } from "vue";
|
import { createApp, h } from "vue";
|
||||||
|
import contenteditable from "vue-contenteditable";
|
||||||
import Toast from "vue-toastification";
|
import Toast from "vue-toastification";
|
||||||
import contenteditable from "vue-contenteditable"
|
|
||||||
import "vue-toastification/dist/index.css";
|
import "vue-toastification/dist/index.css";
|
||||||
import App from "./App.vue";
|
import App from "./App.vue";
|
||||||
import "./assets/app.scss";
|
import "./assets/app.scss";
|
||||||
@ -9,10 +9,9 @@ import { i18n } from "./i18n";
|
|||||||
import { FontAwesomeIcon } from "./icon.js";
|
import { FontAwesomeIcon } from "./icon.js";
|
||||||
import datetime from "./mixins/datetime";
|
import datetime from "./mixins/datetime";
|
||||||
import mobile from "./mixins/mobile";
|
import mobile from "./mixins/mobile";
|
||||||
|
import publicMixin from "./mixins/public";
|
||||||
import socket from "./mixins/socket";
|
import socket from "./mixins/socket";
|
||||||
import theme from "./mixins/theme";
|
import theme from "./mixins/theme";
|
||||||
import publicMixin from "./mixins/public";
|
|
||||||
|
|
||||||
import { router } from "./router";
|
import { router } from "./router";
|
||||||
import { appName } from "./util.ts";
|
import { appName } from "./util.ts";
|
||||||
|
|
||||||
@ -27,10 +26,10 @@ const app = createApp({
|
|||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
appName: appName
|
appName: appName
|
||||||
}
|
};
|
||||||
},
|
},
|
||||||
render: () => h(App),
|
render: () => h(App),
|
||||||
})
|
});
|
||||||
|
|
||||||
app.use(router);
|
app.use(router);
|
||||||
app.use(i18n);
|
app.use(i18n);
|
||||||
|
@ -30,7 +30,7 @@ export default {
|
|||||||
importantHeartbeatList: { },
|
importantHeartbeatList: { },
|
||||||
avgPingList: { },
|
avgPingList: { },
|
||||||
uptimeList: { },
|
uptimeList: { },
|
||||||
certInfoList: {},
|
tlsInfoList: {},
|
||||||
notificationList: [],
|
notificationList: [],
|
||||||
connectionErrorMsg: "Cannot connect to the socket server. Reconnecting...",
|
connectionErrorMsg: "Cannot connect to the socket server. Reconnecting...",
|
||||||
};
|
};
|
||||||
@ -154,7 +154,7 @@ export default {
|
|||||||
});
|
});
|
||||||
|
|
||||||
socket.on("certInfo", (monitorID, data) => {
|
socket.on("certInfo", (monitorID, data) => {
|
||||||
this.certInfoList[monitorID] = JSON.parse(data);
|
this.tlsInfoList[monitorID] = JSON.parse(data);
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on("importantHeartbeatList", (monitorID, data, overwrite) => {
|
socket.on("importantHeartbeatList", (monitorID, data, overwrite) => {
|
||||||
@ -179,7 +179,7 @@ export default {
|
|||||||
});
|
});
|
||||||
|
|
||||||
socket.on("connect", () => {
|
socket.on("connect", () => {
|
||||||
console.log("connect");
|
console.log("Connected to the socket server");
|
||||||
this.socket.connectCount++;
|
this.socket.connectCount++;
|
||||||
this.socket.connected = true;
|
this.socket.connected = true;
|
||||||
|
|
||||||
|
@ -73,11 +73,11 @@
|
|||||||
<span class="num"><Uptime :monitor="monitor" type="720" /></span>
|
<span class="num"><Uptime :monitor="monitor" type="720" /></span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="certInfo" class="col">
|
<div v-if="tlsInfo" class="col">
|
||||||
<h4>{{ $t("Cert Exp.") }}</h4>
|
<h4>{{ $t("Cert Exp.") }}</h4>
|
||||||
<p>(<Datetime :value="certInfo.validTo" date-only />)</p>
|
<p>(<Datetime :value="tlsInfo.certInfo.validTo" date-only />)</p>
|
||||||
<span class="num">
|
<span class="num">
|
||||||
<a href="#" @click.prevent="toggleCertInfoBox = !toggleCertInfoBox">{{ certInfo.daysRemaining }} {{ $t("days") }}</a>
|
<a href="#" @click.prevent="toggleCertInfoBox = !toggleCertInfoBox">{{ tlsInfo.certInfo.daysRemaining }} {{ $t("days") }}</a>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -87,41 +87,7 @@
|
|||||||
<div v-if="showCertInfoBox" class="shadow-box big-padding text-center">
|
<div v-if="showCertInfoBox" class="shadow-box big-padding text-center">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<h4>{{ $t("Certificate Info") }}</h4>
|
<certificate-info :certInfo="tlsInfo.certInfo" :valid="tlsInfo.valid" />
|
||||||
<table class="text-start">
|
|
||||||
<tbody>
|
|
||||||
<tr class="my-3">
|
|
||||||
<td class="px-3">
|
|
||||||
Valid:
|
|
||||||
</td>
|
|
||||||
<td>{{ certInfo.valid }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr class="my-3">
|
|
||||||
<td class="px-3">
|
|
||||||
Valid To:
|
|
||||||
</td>
|
|
||||||
<td><Datetime :value="certInfo.validTo" /></td>
|
|
||||||
</tr>
|
|
||||||
<tr class="my-3">
|
|
||||||
<td class="px-3">
|
|
||||||
Days Remaining:
|
|
||||||
</td>
|
|
||||||
<td>{{ certInfo.daysRemaining }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr class="my-3">
|
|
||||||
<td class="px-3">
|
|
||||||
Issuer:
|
|
||||||
</td>
|
|
||||||
<td>{{ certInfo.issuer }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr class="my-3">
|
|
||||||
<td class="px-3">
|
|
||||||
Fingerprint:
|
|
||||||
</td>
|
|
||||||
<td>{{ certInfo.fingerprint }}</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -207,8 +173,8 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { defineAsyncComponent } from "vue";
|
import { defineAsyncComponent } from "vue";
|
||||||
import { useToast } from "vue-toastification"
|
import { useToast } from "vue-toastification";
|
||||||
const toast = useToast()
|
const toast = useToast();
|
||||||
import Confirm from "../components/Confirm.vue";
|
import Confirm from "../components/Confirm.vue";
|
||||||
import HeartbeatBar from "../components/HeartbeatBar.vue";
|
import HeartbeatBar from "../components/HeartbeatBar.vue";
|
||||||
import Status from "../components/Status.vue";
|
import Status from "../components/Status.vue";
|
||||||
@ -218,6 +184,7 @@ import Uptime from "../components/Uptime.vue";
|
|||||||
import Pagination from "v-pagination-3";
|
import Pagination from "v-pagination-3";
|
||||||
const PingChart = defineAsyncComponent(() => import("../components/PingChart.vue"));
|
const PingChart = defineAsyncComponent(() => import("../components/PingChart.vue"));
|
||||||
import Tag from "../components/Tag.vue";
|
import Tag from "../components/Tag.vue";
|
||||||
|
import CertificateInfo from "../components/CertificateInfo.vue";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
@ -230,6 +197,7 @@ export default {
|
|||||||
Pagination,
|
Pagination,
|
||||||
PingChart,
|
PingChart,
|
||||||
Tag,
|
Tag,
|
||||||
|
CertificateInfo,
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@ -239,32 +207,32 @@ export default {
|
|||||||
toggleCertInfoBox: false,
|
toggleCertInfoBox: false,
|
||||||
showPingChartBox: true,
|
showPingChartBox: true,
|
||||||
paginationConfig: {
|
paginationConfig: {
|
||||||
texts:{
|
texts: {
|
||||||
count:`${this.$t("Showing {from} to {to} of {count} records")}|{count} ${this.$t("records")}|${this.$t("One record")}`,
|
count: `${this.$t("Showing {from} to {to} of {count} records")}|{count} ${this.$t("records")}|${this.$t("One record")}`,
|
||||||
first:this.$t("First"),
|
first: this.$t("First"),
|
||||||
last:this.$t("Last"),
|
last: this.$t("Last"),
|
||||||
nextPage:'>',
|
nextPage: ">",
|
||||||
nextChunk:'>>',
|
nextChunk: ">>",
|
||||||
prevPage:'<',
|
prevPage: "<",
|
||||||
prevChunk:'<<'
|
prevChunk: "<<"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
monitor() {
|
monitor() {
|
||||||
let id = this.$route.params.id
|
let id = this.$route.params.id;
|
||||||
return this.$root.monitorList[id];
|
return this.$root.monitorList[id];
|
||||||
},
|
},
|
||||||
|
|
||||||
lastHeartBeat() {
|
lastHeartBeat() {
|
||||||
if (this.monitor.id in this.$root.lastHeartbeatList && this.$root.lastHeartbeatList[this.monitor.id]) {
|
if (this.monitor.id in this.$root.lastHeartbeatList && this.$root.lastHeartbeatList[this.monitor.id]) {
|
||||||
return this.$root.lastHeartbeatList[this.monitor.id]
|
return this.$root.lastHeartbeatList[this.monitor.id];
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
status: -1,
|
status: -1,
|
||||||
}
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
ping() {
|
ping() {
|
||||||
@ -272,7 +240,7 @@ export default {
|
|||||||
return this.lastHeartBeat.ping;
|
return this.lastHeartBeat.ping;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.$t("notAvailableShort")
|
return this.$t("notAvailableShort");
|
||||||
},
|
},
|
||||||
|
|
||||||
avgPing() {
|
avgPing() {
|
||||||
@ -280,14 +248,14 @@ export default {
|
|||||||
return this.$root.avgPingList[this.monitor.id];
|
return this.$root.avgPingList[this.monitor.id];
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.$t("notAvailableShort")
|
return this.$t("notAvailableShort");
|
||||||
},
|
},
|
||||||
|
|
||||||
importantHeartBeatList() {
|
importantHeartBeatList() {
|
||||||
if (this.$root.importantHeartbeatList[this.monitor.id]) {
|
if (this.$root.importantHeartbeatList[this.monitor.id]) {
|
||||||
// eslint-disable-next-line vue/no-side-effects-in-computed-properties
|
// eslint-disable-next-line vue/no-side-effects-in-computed-properties
|
||||||
this.heartBeatList = this.$root.importantHeartbeatList[this.monitor.id];
|
this.heartBeatList = this.$root.importantHeartbeatList[this.monitor.id];
|
||||||
return this.$root.importantHeartbeatList[this.monitor.id]
|
return this.$root.importantHeartbeatList[this.monitor.id];
|
||||||
}
|
}
|
||||||
|
|
||||||
return [];
|
return [];
|
||||||
@ -295,22 +263,22 @@ export default {
|
|||||||
|
|
||||||
status() {
|
status() {
|
||||||
if (this.$root.statusList[this.monitor.id]) {
|
if (this.$root.statusList[this.monitor.id]) {
|
||||||
return this.$root.statusList[this.monitor.id]
|
return this.$root.statusList[this.monitor.id];
|
||||||
}
|
}
|
||||||
|
|
||||||
return { }
|
return { };
|
||||||
},
|
},
|
||||||
|
|
||||||
certInfo() {
|
tlsInfo() {
|
||||||
if (this.$root.certInfoList[this.monitor.id]) {
|
if (this.$root.tlsInfoList[this.monitor.id]) {
|
||||||
return this.$root.certInfoList[this.monitor.id]
|
return this.$root.tlsInfoList[this.monitor.id];
|
||||||
}
|
}
|
||||||
|
|
||||||
return null
|
return null;
|
||||||
},
|
},
|
||||||
|
|
||||||
showCertInfoBox() {
|
showCertInfoBox() {
|
||||||
return this.certInfo != null && this.toggleCertInfoBox;
|
return this.tlsInfo != null && this.toggleCertInfoBox;
|
||||||
},
|
},
|
||||||
|
|
||||||
displayedRecords() {
|
displayedRecords() {
|
||||||
@ -324,8 +292,8 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
testNotification() {
|
testNotification() {
|
||||||
this.$root.getSocket().emit("testNotification", this.monitor.id)
|
this.$root.getSocket().emit("testNotification", this.monitor.id);
|
||||||
toast.success("Test notification is requested.")
|
toast.success("Test notification is requested.");
|
||||||
},
|
},
|
||||||
|
|
||||||
pauseDialog() {
|
pauseDialog() {
|
||||||
@ -334,14 +302,14 @@ export default {
|
|||||||
|
|
||||||
resumeMonitor() {
|
resumeMonitor() {
|
||||||
this.$root.getSocket().emit("resumeMonitor", this.monitor.id, (res) => {
|
this.$root.getSocket().emit("resumeMonitor", this.monitor.id, (res) => {
|
||||||
this.$root.toastRes(res)
|
this.$root.toastRes(res);
|
||||||
})
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
pauseMonitor() {
|
pauseMonitor() {
|
||||||
this.$root.getSocket().emit("pauseMonitor", this.monitor.id, (res) => {
|
this.$root.getSocket().emit("pauseMonitor", this.monitor.id, (res) => {
|
||||||
this.$root.toastRes(res)
|
this.$root.toastRes(res);
|
||||||
})
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
deleteDialog() {
|
deleteDialog() {
|
||||||
@ -360,11 +328,11 @@ export default {
|
|||||||
this.$root.deleteMonitor(this.monitor.id, (res) => {
|
this.$root.deleteMonitor(this.monitor.id, (res) => {
|
||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
toast.success(res.msg);
|
toast.success(res.msg);
|
||||||
this.$router.push("/dashboard")
|
this.$router.push("/dashboard");
|
||||||
} else {
|
} else {
|
||||||
toast.error(res.msg);
|
toast.error(res.msg);
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
clearEvents() {
|
clearEvents() {
|
||||||
@ -372,7 +340,7 @@ export default {
|
|||||||
if (! res.ok) {
|
if (! res.ok) {
|
||||||
toast.error(res.msg);
|
toast.error(res.msg);
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
clearHeartbeats() {
|
clearHeartbeats() {
|
||||||
@ -380,13 +348,13 @@ export default {
|
|||||||
if (! res.ok) {
|
if (! res.ok) {
|
||||||
toast.error(res.msg);
|
toast.error(res.msg);
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
pingTitle(average = false) {
|
pingTitle(average = false) {
|
||||||
let translationPrefix = ""
|
let translationPrefix = "";
|
||||||
if (average) {
|
if (average) {
|
||||||
translationPrefix = "Avg. "
|
translationPrefix = "Avg. ";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.monitor.type === "http") {
|
if (this.monitor.type === "http") {
|
||||||
@ -396,7 +364,7 @@ export default {
|
|||||||
return this.$t(translationPrefix + "Ping");
|
return this.$t(translationPrefix + "Ping");
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
@ -328,6 +328,12 @@
|
|||||||
<p>Моля, използвайте внимателно.</p>
|
<p>Моля, използвайте внимателно.</p>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<template v-else-if="$i18n.locale === 'hu' ">
|
||||||
|
<p>Biztos benne, hogy <strong>kikapcsolja a hitelesítést</strong>?</p>
|
||||||
|
<p>Akkor érdemes, ha <strong>van 3rd-party hitelesítés</strong> az Uptime Kuma-t megelőzően mint a Cloudflare Access.</p>
|
||||||
|
<p>Használja megfontoltan!</p>
|
||||||
|
</template>
|
||||||
|
|
||||||
<!-- English (en) -->
|
<!-- English (en) -->
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<p>Are you sure want to <strong>disable auth</strong>?</p>
|
<p>Are you sure want to <strong>disable auth</strong>?</p>
|
||||||
|
9
test/prepare-jest.js
Normal file
9
test/prepare-jest.js
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
const fs = require("fs");
|
||||||
|
|
||||||
|
const path = "./data/test-chrome-profile";
|
||||||
|
|
||||||
|
if (fs.existsSync(path)) {
|
||||||
|
fs.rmdirSync(path, {
|
||||||
|
recursive: true,
|
||||||
|
});
|
||||||
|
}
|
9
test/prepare-test-server.js
Normal file
9
test/prepare-test-server.js
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
const fs = require("fs");
|
||||||
|
|
||||||
|
const path = "./data/test";
|
||||||
|
|
||||||
|
if (fs.existsSync(path)) {
|
||||||
|
fs.rmdirSync(path, {
|
||||||
|
recursive: true,
|
||||||
|
});
|
||||||
|
}
|
236
test/test.spec.js
Normal file
236
test/test.spec.js
Normal file
@ -0,0 +1,236 @@
|
|||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
const { Page, Browser } = require("puppeteer");
|
||||||
|
const { sleep } = require("../src/util");
|
||||||
|
const axios = require("axios");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set back the correct data type for page object
|
||||||
|
* @type {Page}
|
||||||
|
*/
|
||||||
|
page;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {Browser}
|
||||||
|
*/
|
||||||
|
browser;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
await page.setViewport({
|
||||||
|
width: 1280,
|
||||||
|
height: 720,
|
||||||
|
deviceScaleFactor: 1,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterAll(() => {
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
const baseURL = "http://127.0.0.1:3002";
|
||||||
|
|
||||||
|
describe("Init", () => {
|
||||||
|
const title = "Uptime Kuma";
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
await page.goto(baseURL);
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`should be titled "${title}"`, async () => {
|
||||||
|
await expect(page.title()).resolves.toMatch(title);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Setup Page
|
||||||
|
it("Setup", async () => {
|
||||||
|
// Create an Admin
|
||||||
|
await page.waitForSelector("#floatingInput");
|
||||||
|
await page.waitForSelector("#repeat");
|
||||||
|
await page.click("#floatingInput");
|
||||||
|
await page.type("#floatingInput", "admin");
|
||||||
|
await page.type("#floatingPassword", "admin123");
|
||||||
|
await page.type("#repeat", "admin123");
|
||||||
|
await page.click(".btn-primary[type=submit]");
|
||||||
|
await sleep(3000);
|
||||||
|
|
||||||
|
// Go to /setup again
|
||||||
|
await page.goto(baseURL + "/setup");
|
||||||
|
await sleep(3000);
|
||||||
|
let pathname = await page.evaluate(() => location.pathname);
|
||||||
|
expect(pathname).toEqual("/dashboard");
|
||||||
|
|
||||||
|
// Go to /
|
||||||
|
await page.goto(baseURL);
|
||||||
|
await sleep(3000);
|
||||||
|
pathname = await page.evaluate(() => location.pathname);
|
||||||
|
expect(pathname).toEqual("/dashboard");
|
||||||
|
});
|
||||||
|
|
||||||
|
// Settings Page
|
||||||
|
describe("Settings", () => {
|
||||||
|
beforeAll(async () => {
|
||||||
|
await page.goto(baseURL + "/settings");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Change Language", async () => {
|
||||||
|
await page.waitForSelector("#language");
|
||||||
|
|
||||||
|
await page.select("#language", "zh-HK");
|
||||||
|
let languageTitle = await page.evaluate(() => document.querySelector("[for=language]").innerText);
|
||||||
|
expect(languageTitle).toMatch("語言");
|
||||||
|
|
||||||
|
await page.select("#language", "en");
|
||||||
|
languageTitle = await page.evaluate(() => document.querySelector("[for=language]").innerText);
|
||||||
|
expect(languageTitle).toMatch("Language");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Change Theme", async () => {
|
||||||
|
await sleep(1000);
|
||||||
|
|
||||||
|
// Dark
|
||||||
|
await click(page, ".btn[for=btncheck2]");
|
||||||
|
await page.waitForSelector("div.dark");
|
||||||
|
|
||||||
|
await sleep(1000);
|
||||||
|
|
||||||
|
// Light
|
||||||
|
await click(page, ".btn[for=btncheck1]");
|
||||||
|
await page.waitForSelector("div.light");
|
||||||
|
});
|
||||||
|
|
||||||
|
// TODO: Heartbeat Bar Style
|
||||||
|
|
||||||
|
// TODO: Timezone
|
||||||
|
|
||||||
|
it("Search Engine Visibility", async () => {
|
||||||
|
// Default
|
||||||
|
let res = await axios.get(baseURL + "/robots.txt");
|
||||||
|
expect(res.data).toMatch("Disallow: /");
|
||||||
|
|
||||||
|
// Yes
|
||||||
|
await click(page, "#searchEngineIndexYes");
|
||||||
|
await click(page, "form > div > .btn[type=submit]");
|
||||||
|
await sleep(2000);
|
||||||
|
res = await axios.get(baseURL + "/robots.txt");
|
||||||
|
expect(res.data).not.toMatch("Disallow: /");
|
||||||
|
|
||||||
|
// No
|
||||||
|
await click(page, "#searchEngineIndexNo");
|
||||||
|
await click(page, "form > div > .btn[type=submit]");
|
||||||
|
await sleep(2000);
|
||||||
|
res = await axios.get(baseURL + "/robots.txt");
|
||||||
|
expect(res.data).toMatch("Disallow: /");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Entry Page", async () => {
|
||||||
|
const newPage = await browser.newPage();
|
||||||
|
|
||||||
|
// Default
|
||||||
|
await newPage.goto(baseURL);
|
||||||
|
await sleep(3000);
|
||||||
|
let pathname = await newPage.evaluate(() => location.pathname);
|
||||||
|
expect(pathname).toEqual("/dashboard");
|
||||||
|
|
||||||
|
// Status Page
|
||||||
|
await click(page, "#entryPageNo");
|
||||||
|
await click(page, "form > div > .btn[type=submit]");
|
||||||
|
await sleep(2000);
|
||||||
|
await newPage.goto(baseURL);
|
||||||
|
await sleep(3000);
|
||||||
|
pathname = await newPage.evaluate(() => location.pathname);
|
||||||
|
expect(pathname).toEqual("/status");
|
||||||
|
|
||||||
|
// Back to Dashboard
|
||||||
|
await click(page, "#entryPageYes");
|
||||||
|
await click(page, "form > div > .btn[type=submit]");
|
||||||
|
await sleep(2000);
|
||||||
|
await newPage.goto(baseURL);
|
||||||
|
await sleep(3000);
|
||||||
|
pathname = await newPage.evaluate(() => location.pathname);
|
||||||
|
expect(pathname).toEqual("/dashboard");
|
||||||
|
|
||||||
|
await newPage.close();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Change Password (wrong current password)", async () => {
|
||||||
|
await page.type("#current-password", "wrong_passw$$d");
|
||||||
|
await page.type("#new-password", "new_password123");
|
||||||
|
await page.type("#repeat-new-password", "new_password123");
|
||||||
|
await click(page, "form > div > .btn[type=submit]", 1);
|
||||||
|
await sleep(3000);
|
||||||
|
await click(page, ".btn-danger.btn.me-1");
|
||||||
|
await sleep(2000);
|
||||||
|
await login("admin", "new_password123");
|
||||||
|
await sleep(2000);
|
||||||
|
let elementCount = await page.evaluate(() => document.querySelectorAll("#floatingPassword").length);
|
||||||
|
expect(elementCount).toEqual(1);
|
||||||
|
|
||||||
|
await login("admin", "admin123");
|
||||||
|
await sleep(3000);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Change Password (wrong repeat)", async () => {
|
||||||
|
await page.type("#current-password", "admin123");
|
||||||
|
await page.type("#new-password", "new_password123");
|
||||||
|
await page.type("#repeat-new-password", "new_password1234567898797898");
|
||||||
|
await click(page, "form > div > .btn[type=submit]", 1);
|
||||||
|
await sleep(3000);
|
||||||
|
await click(page, ".btn-danger.btn.me-1");
|
||||||
|
await sleep(2000);
|
||||||
|
await login("admin", "new_password123");
|
||||||
|
await sleep(2000);
|
||||||
|
let elementCount = await page.evaluate(() => document.querySelectorAll("#floatingPassword").length);
|
||||||
|
expect(elementCount).toEqual(1);
|
||||||
|
|
||||||
|
await login("admin", "admin123");
|
||||||
|
await sleep(3000);
|
||||||
|
});
|
||||||
|
|
||||||
|
// TODO: 2FA
|
||||||
|
|
||||||
|
// TODO: Export Backup
|
||||||
|
|
||||||
|
// TODO: Import Backup
|
||||||
|
|
||||||
|
// TODO: Disable Auth
|
||||||
|
|
||||||
|
// TODO: Clear Stats
|
||||||
|
});
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TODO
|
||||||
|
* Create Monitor - All type
|
||||||
|
* Edit Monitor
|
||||||
|
* Delete Monitor
|
||||||
|
*
|
||||||
|
* Create Notification (token problem, maybe hard to test)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
describe("Status Page", () => {
|
||||||
|
const title = "Uptime Kuma";
|
||||||
|
beforeAll(async () => {
|
||||||
|
await page.goto(baseURL + "/status");
|
||||||
|
});
|
||||||
|
it(`should be titled "${title}"`, async () => {
|
||||||
|
await expect(page.title()).resolves.toMatch(title);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
async function login(username, password) {
|
||||||
|
await input(page, "#floatingInput", username);
|
||||||
|
await input(page, "#floatingPassword", password);
|
||||||
|
await page.click(".btn-primary[type=submit]");
|
||||||
|
}
|
||||||
|
|
||||||
|
async function click(page, selector, elementIndex = 0) {
|
||||||
|
return await page.evaluate((s, i) => {
|
||||||
|
return document.querySelectorAll(s)[i].click();
|
||||||
|
}, selector, elementIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function input(page, selector, text) {
|
||||||
|
const element = await page.$(selector);
|
||||||
|
await element.click({ clickCount: 3 });
|
||||||
|
await page.keyboard.press("Backspace");
|
||||||
|
await page.type(selector, text);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user