Merge branch 'master' into feat-discord-suppress-notifications
This commit is contained in:
commit
cc698fbacd
3
.github/workflows/beta-release.yml
vendored
3
.github/workflows/beta-release.yml
vendored
@ -50,7 +50,8 @@ jobs:
|
||||
git push origin --delete "release-${VERSION}" || true
|
||||
# Delete local branch if it exists
|
||||
git branch -D "release-${VERSION}" || true
|
||||
# Create new branch from master
|
||||
# For testing purpose
|
||||
# git checkout beta-workflow
|
||||
git checkout -b "release-${VERSION}"
|
||||
|
||||
- name: Install dependencies
|
||||
|
||||
60
.github/workflows/mark-as-draft-on-requesting-changes.yml
vendored
Normal file
60
.github/workflows/mark-as-draft-on-requesting-changes.yml
vendored
Normal file
@ -0,0 +1,60 @@
|
||||
name: Mark PR as draft when changes are requested
|
||||
|
||||
on:
|
||||
pull_request_review:
|
||||
types: [submitted]
|
||||
|
||||
pull_request:
|
||||
types: [labeled]
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
mark-draft:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
pull-requests: write
|
||||
contents: read
|
||||
if: |
|
||||
(
|
||||
github.event_name == 'pull_request_review' &&
|
||||
github.event.review.state == 'changes_requested'
|
||||
) || (
|
||||
github.event_name == 'pull_request' &&
|
||||
github.event.label.name == 'pr:please address review comments'
|
||||
)
|
||||
steps:
|
||||
- name: Add label on requested changes
|
||||
if: github.event_name == 'pull_request_review'
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
PR_NUMBER: ${{ github.event.pull_request.number }}
|
||||
REPO: ${{ github.repository }}
|
||||
run: |
|
||||
gh issue edit "$PR_NUMBER" \
|
||||
--repo "$REPO" \
|
||||
--add-label "pr:please address review comments"
|
||||
|
||||
- name: Mark PR as draft
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
PR_URL: ${{ github.event.pull_request.html_url }}
|
||||
run: gh pr ready "$PR_URL" --undo || true
|
||||
ready-for-review:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name == 'pull_request' && github.event.action == 'ready_for_review'
|
||||
|
||||
steps:
|
||||
- name: Update labels for review
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
PR_NUMBER: ${{ github.event.pull_request.number }}
|
||||
REPO: ${{ github.repository }}
|
||||
run: |
|
||||
gh issue edit "$PR_NUMBER" \
|
||||
--repo "$REPO" \
|
||||
--remove-label "pr:please address review comments" || true
|
||||
|
||||
gh issue edit "$PR_NUMBER" \
|
||||
--repo "$REPO" \
|
||||
--add-label "pr:needs review"
|
||||
@ -36,6 +36,9 @@ export default defineConfig({
|
||||
srcDir: "src",
|
||||
filename: "serviceWorker.ts",
|
||||
strategies: "injectManifest",
|
||||
injectManifest: {
|
||||
maximumFileSizeToCacheInBytes: 3 * 1024 * 1024, // 3 MiB
|
||||
},
|
||||
}),
|
||||
],
|
||||
css: {
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
import { createRequire } from "module";
|
||||
const require = createRequire(import.meta.url);
|
||||
|
||||
const pkg = require("../../package.json");
|
||||
const fs = require("fs");
|
||||
const childProcess = require("child_process");
|
||||
@ -58,8 +61,13 @@ function commit(version) {
|
||||
throw new Error("commit error");
|
||||
}
|
||||
|
||||
// Note: Push is handled by gh pr create in the release script
|
||||
// No need to push here as we're on a release branch, not master
|
||||
// Get the current branch name
|
||||
res = childProcess.spawnSync("git", ["rev-parse", "--abbrev-ref", "HEAD"]);
|
||||
let branchName = res.stdout.toString().trim();
|
||||
console.log("Current branch:", branchName);
|
||||
|
||||
// Git push the branch
|
||||
childProcess.spawnSync("git", ["push", "origin", branchName, "--force"], { stdio: "inherit" });
|
||||
}
|
||||
|
||||
/**
|
||||
@ -4,7 +4,7 @@
|
||||
|
||||
import * as childProcess from "child_process";
|
||||
|
||||
const ignoreList = ["louislam", "CommanderStorm", "UptimeKumaBot", "weblate", "Copilot"];
|
||||
const ignoreList = ["louislam", "CommanderStorm", "UptimeKumaBot", "weblate", "Copilot", "@autofix-ci[bot]"];
|
||||
|
||||
const mergeList = ["Translations Update from Weblate", "Update dependencies"];
|
||||
|
||||
|
||||
@ -48,7 +48,7 @@ checkDocker();
|
||||
await checkTagExists(repoNames, version);
|
||||
|
||||
// node extra/beta/update-version.js
|
||||
execSync("node ./extra/beta/update-version.js");
|
||||
await import("../beta/update-version.mjs");
|
||||
|
||||
// Create Pull Request (gh pr create will handle pushing the branch)
|
||||
await createReleasePR(version, previousVersion, dryRun, branchName, githubRunId);
|
||||
|
||||
264
package-lock.json
generated
264
package-lock.json
generated
@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "uptime-kuma",
|
||||
"version": "2.1.0-beta.1",
|
||||
"version": "2.1.0-beta.2",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "uptime-kuma",
|
||||
"version": "2.1.0-beta.1",
|
||||
"version": "2.1.0-beta.2",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@grpc/grpc-js": "~1.8.22",
|
||||
@ -97,7 +97,7 @@
|
||||
"@fortawesome/fontawesome-svg-core": "~1.2.36",
|
||||
"@fortawesome/free-regular-svg-icons": "~5.15.4",
|
||||
"@fortawesome/free-solid-svg-icons": "~5.15.4",
|
||||
"@fortawesome/vue-fontawesome": "~3.0.0-5",
|
||||
"@fortawesome/vue-fontawesome": "~3.1.3",
|
||||
"@playwright/test": "~1.39.0",
|
||||
"@popperjs/core": "~2.10.2",
|
||||
"@testcontainers/hivemq": "^10.13.1",
|
||||
@ -151,11 +151,11 @@
|
||||
"vite": "~5.4.15",
|
||||
"vite-plugin-compression": "^0.5.1",
|
||||
"vite-plugin-pwa": "^1.1.0",
|
||||
"vue": "~3.4.2",
|
||||
"vue": "~3.5.26",
|
||||
"vue-chartjs": "~5.2.0",
|
||||
"vue-confirm-dialog": "~1.0.2",
|
||||
"vue-contenteditable": "~3.0.4",
|
||||
"vue-i18n": "~9.14.3",
|
||||
"vue-i18n": "~11.2.8",
|
||||
"vue-image-crop-upload": "~3.0.3",
|
||||
"vue-multiselect": "~3.0.0-alpha.2",
|
||||
"vue-prism-editor": "~2.0.0-alpha.2",
|
||||
@ -3491,13 +3491,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@fortawesome/vue-fontawesome": {
|
||||
"version": "3.0.8",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/vue-fontawesome/-/vue-fontawesome-3.0.8.tgz",
|
||||
"integrity": "sha512-yyHHAj4G8pQIDfaIsMvQpwKMboIZtcHTUvPqXjOHyldh1O1vZfH4W03VDPv5RvI9P6DLTzJQlmVgj9wCf7c2Fw==",
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/vue-fontawesome/-/vue-fontawesome-3.1.3.tgz",
|
||||
"integrity": "sha512-OHHUTLPEzdwP8kcYIzhioUdUOjZ4zzmi+midwa4bqscza4OJCOvTKJEHkXNz8PgZ23kWci1HkKVX0bm8f9t9gQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"@fortawesome/fontawesome-svg-core": "~1 || ~6",
|
||||
"@fortawesome/fontawesome-svg-core": "~1 || ~6 || ~7",
|
||||
"vue": ">= 3.0.0 < 4"
|
||||
}
|
||||
},
|
||||
@ -3605,14 +3605,14 @@
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/@intlify/core-base": {
|
||||
"version": "9.14.5",
|
||||
"resolved": "https://registry.npmjs.org/@intlify/core-base/-/core-base-9.14.5.tgz",
|
||||
"integrity": "sha512-5ah5FqZG4pOoHjkvs8mjtv+gPKYU0zCISaYNjBNNqYiaITxW8ZtVih3GS/oTOqN8d9/mDLyrjD46GBApNxmlsA==",
|
||||
"version": "11.2.8",
|
||||
"resolved": "https://registry.npmjs.org/@intlify/core-base/-/core-base-11.2.8.tgz",
|
||||
"integrity": "sha512-nBq6Y1tVkjIUsLsdOjDSJj4AsjvD0UG3zsg9Fyc+OivwlA/oMHSKooUy9tpKj0HqZ+NWFifweHavdljlBLTwdA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@intlify/message-compiler": "9.14.5",
|
||||
"@intlify/shared": "9.14.5"
|
||||
"@intlify/message-compiler": "11.2.8",
|
||||
"@intlify/shared": "11.2.8"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 16"
|
||||
@ -3622,13 +3622,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@intlify/message-compiler": {
|
||||
"version": "9.14.5",
|
||||
"resolved": "https://registry.npmjs.org/@intlify/message-compiler/-/message-compiler-9.14.5.tgz",
|
||||
"integrity": "sha512-IHzgEu61/YIpQV5Pc3aRWScDcnFKWvQA9kigcINcCBXN8mbW+vk9SK+lDxA6STzKQsVJxUPg9ACC52pKKo3SVQ==",
|
||||
"version": "11.2.8",
|
||||
"resolved": "https://registry.npmjs.org/@intlify/message-compiler/-/message-compiler-11.2.8.tgz",
|
||||
"integrity": "sha512-A5n33doOjmHsBtCN421386cG1tWp5rpOjOYPNsnpjIJbQ4POF0QY2ezhZR9kr0boKwaHjbOifvyQvHj2UTrDFQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@intlify/shared": "9.14.5",
|
||||
"@intlify/shared": "11.2.8",
|
||||
"source-map-js": "^1.0.2"
|
||||
},
|
||||
"engines": {
|
||||
@ -3639,9 +3639,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@intlify/shared": {
|
||||
"version": "9.14.5",
|
||||
"resolved": "https://registry.npmjs.org/@intlify/shared/-/shared-9.14.5.tgz",
|
||||
"integrity": "sha512-9gB+E53BYuAEMhbCAxVgG38EZrk59sxBtv3jSizNL2hEWlgjBjAw1AwpLHtNaeda12pe6W20OGEa0TwuMSRbyQ==",
|
||||
"version": "11.2.8",
|
||||
"resolved": "https://registry.npmjs.org/@intlify/shared/-/shared-11.2.8.tgz",
|
||||
"integrity": "sha512-l6e4NZyUgv8VyXXH4DbuucFOBmxLF56C/mqh2tvApbzl2Hrhi1aTDcuv5TKdxzfHYmpO3UB0Cz04fgDT9vszfw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
@ -6473,51 +6473,128 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@vue/reactivity": {
|
||||
"version": "3.4.38",
|
||||
"resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.4.38.tgz",
|
||||
"integrity": "sha512-4vl4wMMVniLsSYYeldAKzbk72+D3hUnkw9z8lDeJacTxAkXeDAP1uE9xr2+aKIN0ipOL8EG2GPouVTH6yF7Gnw==",
|
||||
"version": "3.5.26",
|
||||
"resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.26.tgz",
|
||||
"integrity": "sha512-9EnYB1/DIiUYYnzlnUBgwU32NNvLp/nhxLXeWRhHUEeWNTn1ECxX8aGO7RTXeX6PPcxe3LLuNBFoJbV4QZ+CFQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@vue/shared": "3.4.38"
|
||||
"@vue/shared": "3.5.26"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/reactivity/node_modules/@vue/shared": {
|
||||
"version": "3.5.26",
|
||||
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.26.tgz",
|
||||
"integrity": "sha512-7Z6/y3uFI5PRoKeorTOSXKcDj0MSasfNNltcslbFrPpcw6aXRUALq4IfJlaTRspiWIUOEZbrpM+iQGmCOiWe4A==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@vue/runtime-core": {
|
||||
"version": "3.4.38",
|
||||
"resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.4.38.tgz",
|
||||
"integrity": "sha512-21z3wA99EABtuf+O3IhdxP0iHgkBs1vuoCAsCKLVJPEjpVqvblwBnTj42vzHRlWDCyxu9ptDm7sI2ZMcWrQqlA==",
|
||||
"version": "3.5.26",
|
||||
"resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.26.tgz",
|
||||
"integrity": "sha512-xJWM9KH1kd201w5DvMDOwDHYhrdPTrAatn56oB/LRG4plEQeZRQLw0Bpwih9KYoqmzaxF0OKSn6swzYi84e1/Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@vue/reactivity": "3.4.38",
|
||||
"@vue/shared": "3.4.38"
|
||||
"@vue/reactivity": "3.5.26",
|
||||
"@vue/shared": "3.5.26"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/runtime-core/node_modules/@vue/shared": {
|
||||
"version": "3.5.26",
|
||||
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.26.tgz",
|
||||
"integrity": "sha512-7Z6/y3uFI5PRoKeorTOSXKcDj0MSasfNNltcslbFrPpcw6aXRUALq4IfJlaTRspiWIUOEZbrpM+iQGmCOiWe4A==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@vue/runtime-dom": {
|
||||
"version": "3.4.38",
|
||||
"resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.4.38.tgz",
|
||||
"integrity": "sha512-afZzmUreU7vKwKsV17H1NDThEEmdYI+GCAK/KY1U957Ig2NATPVjCROv61R19fjZNzMmiU03n79OMnXyJVN0UA==",
|
||||
"version": "3.5.26",
|
||||
"resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.26.tgz",
|
||||
"integrity": "sha512-XLLd/+4sPC2ZkN/6+V4O4gjJu6kSDbHAChvsyWgm1oGbdSO3efvGYnm25yCjtFm/K7rrSDvSfPDgN1pHgS4VNQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@vue/reactivity": "3.4.38",
|
||||
"@vue/runtime-core": "3.4.38",
|
||||
"@vue/shared": "3.4.38",
|
||||
"csstype": "^3.1.3"
|
||||
"@vue/reactivity": "3.5.26",
|
||||
"@vue/runtime-core": "3.5.26",
|
||||
"@vue/shared": "3.5.26",
|
||||
"csstype": "^3.2.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/runtime-dom/node_modules/@vue/shared": {
|
||||
"version": "3.5.26",
|
||||
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.26.tgz",
|
||||
"integrity": "sha512-7Z6/y3uFI5PRoKeorTOSXKcDj0MSasfNNltcslbFrPpcw6aXRUALq4IfJlaTRspiWIUOEZbrpM+iQGmCOiWe4A==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@vue/server-renderer": {
|
||||
"version": "3.4.38",
|
||||
"resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.4.38.tgz",
|
||||
"integrity": "sha512-NggOTr82FbPEkkUvBm4fTGcwUY8UuTsnWC/L2YZBmvaQ4C4Jl/Ao4HHTB+l7WnFCt5M/dN3l0XLuyjzswGYVCA==",
|
||||
"version": "3.5.26",
|
||||
"resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.26.tgz",
|
||||
"integrity": "sha512-TYKLXmrwWKSodyVuO1WAubucd+1XlLg4set0YoV+Hu8Lo79mp/YMwWV5mC5FgtsDxX3qo1ONrxFaTP1OQgy1uA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@vue/compiler-ssr": "3.4.38",
|
||||
"@vue/shared": "3.4.38"
|
||||
"@vue/compiler-ssr": "3.5.26",
|
||||
"@vue/shared": "3.5.26"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"vue": "3.4.38"
|
||||
"vue": "3.5.26"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/server-renderer/node_modules/@vue/compiler-core": {
|
||||
"version": "3.5.26",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.26.tgz",
|
||||
"integrity": "sha512-vXyI5GMfuoBCnv5ucIT7jhHKl55Y477yxP6fc4eUswjP8FG3FFVFd41eNDArR+Uk3QKn2Z85NavjaxLxOC19/w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/parser": "^7.28.5",
|
||||
"@vue/shared": "3.5.26",
|
||||
"entities": "^7.0.0",
|
||||
"estree-walker": "^2.0.2",
|
||||
"source-map-js": "^1.2.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/server-renderer/node_modules/@vue/compiler-dom": {
|
||||
"version": "3.5.26",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.26.tgz",
|
||||
"integrity": "sha512-y1Tcd3eXs834QjswshSilCBnKGeQjQXB6PqFn/1nxcQw4pmG42G8lwz+FZPAZAby6gZeHSt/8LMPfZ4Rb+Bd/A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@vue/compiler-core": "3.5.26",
|
||||
"@vue/shared": "3.5.26"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/server-renderer/node_modules/@vue/compiler-ssr": {
|
||||
"version": "3.5.26",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.26.tgz",
|
||||
"integrity": "sha512-lZT9/Y0nSIRUPVvapFJEVDbEXruZh2IYHMk2zTtEgJSlP5gVOqeWXH54xDKAaFS4rTnDeDBQUYDtxKyoW9FwDw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@vue/compiler-dom": "3.5.26",
|
||||
"@vue/shared": "3.5.26"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/server-renderer/node_modules/@vue/shared": {
|
||||
"version": "3.5.26",
|
||||
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.26.tgz",
|
||||
"integrity": "sha512-7Z6/y3uFI5PRoKeorTOSXKcDj0MSasfNNltcslbFrPpcw6aXRUALq4IfJlaTRspiWIUOEZbrpM+iQGmCOiWe4A==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@vue/server-renderer/node_modules/entities": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/entities/-/entities-7.0.0.tgz",
|
||||
"integrity": "sha512-FDWG5cmEYf2Z00IkYRhbFrwIwvdFKH07uV8dvNy0omp/Qb1xcyCWp2UDtcwJF4QZZvk0sLudP6/hAu42TaqVhQ==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"engines": {
|
||||
"node": ">=0.12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/fb55/entities?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/shared": {
|
||||
@ -18943,17 +19020,17 @@
|
||||
}
|
||||
},
|
||||
"node_modules/vue": {
|
||||
"version": "3.4.38",
|
||||
"resolved": "https://registry.npmjs.org/vue/-/vue-3.4.38.tgz",
|
||||
"integrity": "sha512-f0ZgN+mZ5KFgVv9wz0f4OgVKukoXtS3nwET4c2vLBGQR50aI8G0cqbFtLlX9Yiyg3LFGBitruPHt2PxwTduJEw==",
|
||||
"version": "3.5.26",
|
||||
"resolved": "https://registry.npmjs.org/vue/-/vue-3.5.26.tgz",
|
||||
"integrity": "sha512-SJ/NTccVyAoNUJmkM9KUqPcYlY+u8OVL1X5EW9RIs3ch5H2uERxyyIUI4MRxVCSOiEcupX9xNGde1tL9ZKpimA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@vue/compiler-dom": "3.4.38",
|
||||
"@vue/compiler-sfc": "3.4.38",
|
||||
"@vue/runtime-dom": "3.4.38",
|
||||
"@vue/server-renderer": "3.4.38",
|
||||
"@vue/shared": "3.4.38"
|
||||
"@vue/compiler-dom": "3.5.26",
|
||||
"@vue/compiler-sfc": "3.5.26",
|
||||
"@vue/runtime-dom": "3.5.26",
|
||||
"@vue/server-renderer": "3.5.26",
|
||||
"@vue/shared": "3.5.26"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"typescript": "*"
|
||||
@ -19048,15 +19125,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/vue-i18n": {
|
||||
"version": "9.14.5",
|
||||
"resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-9.14.5.tgz",
|
||||
"integrity": "sha512-0jQ9Em3ymWngyiIkj0+c/k7WgaPO+TNzjKSNq9BvBQaKJECqn9cd9fL4tkDhB5G1QBskGl9YxxbDAhgbFtpe2g==",
|
||||
"deprecated": "v9 and v10 no longer supported. please migrate to v11. about maintenance status, see https://vue-i18n.intlify.dev/guide/maintenance.html",
|
||||
"version": "11.2.8",
|
||||
"resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-11.2.8.tgz",
|
||||
"integrity": "sha512-vJ123v/PXCZntd6Qj5Jumy7UBmIuE92VrtdX+AXr+1WzdBHojiBxnAxdfctUFL+/JIN+VQH4BhsfTtiGsvVObg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@intlify/core-base": "9.14.5",
|
||||
"@intlify/shared": "9.14.5",
|
||||
"@intlify/core-base": "11.2.8",
|
||||
"@intlify/shared": "11.2.8",
|
||||
"@vue/devtools-api": "^6.5.0"
|
||||
},
|
||||
"engines": {
|
||||
@ -19150,6 +19226,80 @@
|
||||
"vue": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/vue/node_modules/@vue/compiler-core": {
|
||||
"version": "3.5.26",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.26.tgz",
|
||||
"integrity": "sha512-vXyI5GMfuoBCnv5ucIT7jhHKl55Y477yxP6fc4eUswjP8FG3FFVFd41eNDArR+Uk3QKn2Z85NavjaxLxOC19/w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/parser": "^7.28.5",
|
||||
"@vue/shared": "3.5.26",
|
||||
"entities": "^7.0.0",
|
||||
"estree-walker": "^2.0.2",
|
||||
"source-map-js": "^1.2.1"
|
||||
}
|
||||
},
|
||||
"node_modules/vue/node_modules/@vue/compiler-dom": {
|
||||
"version": "3.5.26",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.26.tgz",
|
||||
"integrity": "sha512-y1Tcd3eXs834QjswshSilCBnKGeQjQXB6PqFn/1nxcQw4pmG42G8lwz+FZPAZAby6gZeHSt/8LMPfZ4Rb+Bd/A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@vue/compiler-core": "3.5.26",
|
||||
"@vue/shared": "3.5.26"
|
||||
}
|
||||
},
|
||||
"node_modules/vue/node_modules/@vue/compiler-sfc": {
|
||||
"version": "3.5.26",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.26.tgz",
|
||||
"integrity": "sha512-egp69qDTSEZcf4bGOSsprUr4xI73wfrY5oRs6GSgXFTiHrWj4Y3X5Ydtip9QMqiCMCPVwLglB9GBxXtTadJ3mA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/parser": "^7.28.5",
|
||||
"@vue/compiler-core": "3.5.26",
|
||||
"@vue/compiler-dom": "3.5.26",
|
||||
"@vue/compiler-ssr": "3.5.26",
|
||||
"@vue/shared": "3.5.26",
|
||||
"estree-walker": "^2.0.2",
|
||||
"magic-string": "^0.30.21",
|
||||
"postcss": "^8.5.6",
|
||||
"source-map-js": "^1.2.1"
|
||||
}
|
||||
},
|
||||
"node_modules/vue/node_modules/@vue/compiler-ssr": {
|
||||
"version": "3.5.26",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.26.tgz",
|
||||
"integrity": "sha512-lZT9/Y0nSIRUPVvapFJEVDbEXruZh2IYHMk2zTtEgJSlP5gVOqeWXH54xDKAaFS4rTnDeDBQUYDtxKyoW9FwDw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@vue/compiler-dom": "3.5.26",
|
||||
"@vue/shared": "3.5.26"
|
||||
}
|
||||
},
|
||||
"node_modules/vue/node_modules/@vue/shared": {
|
||||
"version": "3.5.26",
|
||||
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.26.tgz",
|
||||
"integrity": "sha512-7Z6/y3uFI5PRoKeorTOSXKcDj0MSasfNNltcslbFrPpcw6aXRUALq4IfJlaTRspiWIUOEZbrpM+iQGmCOiWe4A==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/vue/node_modules/entities": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/entities/-/entities-7.0.0.tgz",
|
||||
"integrity": "sha512-FDWG5cmEYf2Z00IkYRhbFrwIwvdFKH07uV8dvNy0omp/Qb1xcyCWp2UDtcwJF4QZZvk0sLudP6/hAu42TaqVhQ==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"engines": {
|
||||
"node": ">=0.12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/fb55/entities?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/vuedraggable": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/vuedraggable/-/vuedraggable-4.1.0.tgz",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "uptime-kuma",
|
||||
"version": "2.1.0-beta.1",
|
||||
"version": "2.1.0-beta.2",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@ -159,7 +159,7 @@
|
||||
"@fortawesome/fontawesome-svg-core": "~1.2.36",
|
||||
"@fortawesome/free-regular-svg-icons": "~5.15.4",
|
||||
"@fortawesome/free-solid-svg-icons": "~5.15.4",
|
||||
"@fortawesome/vue-fontawesome": "~3.0.0-5",
|
||||
"@fortawesome/vue-fontawesome": "~3.1.3",
|
||||
"@playwright/test": "~1.39.0",
|
||||
"@popperjs/core": "~2.10.2",
|
||||
"@testcontainers/hivemq": "^10.13.1",
|
||||
@ -213,11 +213,11 @@
|
||||
"vite": "~5.4.15",
|
||||
"vite-plugin-compression": "^0.5.1",
|
||||
"vite-plugin-pwa": "^1.1.0",
|
||||
"vue": "~3.4.2",
|
||||
"vue": "~3.5.26",
|
||||
"vue-chartjs": "~5.2.0",
|
||||
"vue-confirm-dialog": "~1.0.2",
|
||||
"vue-contenteditable": "~3.0.4",
|
||||
"vue-i18n": "~9.14.3",
|
||||
"vue-i18n": "~11.2.8",
|
||||
"vue-image-crop-upload": "~3.0.3",
|
||||
"vue-multiselect": "~3.0.0-alpha.2",
|
||||
"vue-prism-editor": "~2.0.0-alpha.2",
|
||||
|
||||
@ -176,14 +176,6 @@ class DomainExpiry extends BeanModel {
|
||||
|
||||
const rdap = await getRdapServer(tld.publicSuffix);
|
||||
if (!rdap) {
|
||||
// Only warn when the monitor actually has domain expiry notifications enabled.
|
||||
// The edit monitor page calls this method frequently while the user is typing.
|
||||
if (Boolean(monitor.domainExpiryNotification)) {
|
||||
log.warn(
|
||||
"domain_expiry",
|
||||
`Domain expiry unsupported for '.${tld.publicSuffix}' because its RDAP endpoint is not listed in the IANA database.`
|
||||
);
|
||||
}
|
||||
throw new TranslatableError("domain_expiry_unsupported_unsupported_tld_no_rdap_endpoint", {
|
||||
publicSuffix: tld.publicSuffix,
|
||||
});
|
||||
|
||||
@ -1059,7 +1059,15 @@ class Monitor extends BeanModel {
|
||||
log.debug("monitor", `Failed getting expiration date for domain ${supportInfo.domain}`);
|
||||
}
|
||||
} catch (error) {
|
||||
// purposely not logged due to noise. Is accessible via checkMointor
|
||||
if (
|
||||
error.message === "domain_expiry_unsupported_unsupported_tld_no_rdap_endpoint" &&
|
||||
Boolean(this.domainExpiryNotification)
|
||||
) {
|
||||
log.warn(
|
||||
"domain_expiry",
|
||||
`Domain expiry unsupported for '.${error.meta.publicSuffix}' because its RDAP endpoint is not listed in the IANA database.`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div>
|
||||
<h4>{{ $t("Certificate Info") }}</h4>
|
||||
{{ $t("Certificate Chain") }}:
|
||||
{{ $t("Certificate Chain:") }}
|
||||
<div v-if="valid" class="rounded d-inline-flex ms-2 text-white tag-valid">
|
||||
{{ $t("Valid") }}
|
||||
</div>
|
||||
|
||||
@ -40,14 +40,13 @@
|
||||
required
|
||||
/>
|
||||
|
||||
<div class="form-text">
|
||||
{{ $t("Examples") }}:
|
||||
<i18n-t tag="div" keypath="Examples:" class="form-text">
|
||||
<ul>
|
||||
<li>/var/run/docker.sock</li>
|
||||
<li>http://localhost:2375</li>
|
||||
<li>https://localhost:2376 (TLS)</li>
|
||||
<li><code>/var/run/docker.sock</code></li>
|
||||
<li><code>http://localhost:2375</code></li>
|
||||
<li><code>https://localhost:2376 (TLS)</code></li>
|
||||
</ul>
|
||||
</div>
|
||||
</i18n-t>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@ -83,7 +83,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<span class="selected-count ms-2">
|
||||
{{ $tc("selectedMonitorCountMsg", selectedMonitorCount) }}
|
||||
{{ $t("selectedMonitorCountMsg", selectedMonitorCount) }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@ -360,7 +360,7 @@ export default {
|
||||
|
||||
this.bulkActionInProgress = true;
|
||||
activeMonitors.forEach((id) => this.$root.getSocket().emit("pauseMonitor", id, () => {}));
|
||||
this.$root.toastSuccess(this.$tc("pausedMonitorsMsg", activeMonitors.length));
|
||||
this.$root.toastSuccess(this.$t("pausedMonitorsMsg", activeMonitors.length));
|
||||
this.bulkActionInProgress = false;
|
||||
this.cancelSelectMode();
|
||||
},
|
||||
@ -384,7 +384,7 @@ export default {
|
||||
|
||||
this.bulkActionInProgress = true;
|
||||
inactiveMonitors.forEach((id) => this.$root.getSocket().emit("resumeMonitor", id, () => {}));
|
||||
this.$root.toastSuccess(this.$tc("resumedMonitorsMsg", inactiveMonitors.length));
|
||||
this.$root.toastSuccess(this.$t("resumedMonitorsMsg", inactiveMonitors.length));
|
||||
this.bulkActionInProgress = false;
|
||||
this.cancelSelectMode();
|
||||
},
|
||||
@ -424,10 +424,10 @@ export default {
|
||||
this.bulkActionInProgress = false;
|
||||
|
||||
if (successCount > 0) {
|
||||
this.$root.toastSuccess(this.$tc("deletedMonitorsMsg", successCount));
|
||||
this.$root.toastSuccess(this.$t("deletedMonitorsMsg", successCount));
|
||||
}
|
||||
if (errorCount > 0) {
|
||||
this.$root.toastError(this.$tc("bulkDeleteErrorMsg", errorCount));
|
||||
this.$root.toastError(this.$t("bulkDeleteErrorMsg", errorCount));
|
||||
}
|
||||
|
||||
this.cancelSelectMode();
|
||||
|
||||
@ -231,15 +231,11 @@ export default {
|
||||
*/
|
||||
formattedCertExpiryMessage(monitor) {
|
||||
if (monitor?.element?.validCert && monitor?.element?.certExpiryDaysRemaining) {
|
||||
return (
|
||||
monitor.element.certExpiryDaysRemaining +
|
||||
" " +
|
||||
this.$tc("day", monitor.element.certExpiryDaysRemaining)
|
||||
);
|
||||
return this.$t("days", monitor.element.certExpiryDaysRemaining);
|
||||
} else if (monitor?.element?.validCert === false) {
|
||||
return this.$t("noOrBadCertificate");
|
||||
} else {
|
||||
return this.$t("Unknown") + " " + this.$tc("day", 2);
|
||||
return this.$t("unknownDays");
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@ -31,12 +31,9 @@
|
||||
required
|
||||
/>
|
||||
|
||||
<div class="form-text mt-3">
|
||||
{{ $t("Examples") }}:
|
||||
<ul>
|
||||
<li>ws://chrome.browserless.io/playwright?token=YOUR-API-TOKEN</li>
|
||||
</ul>
|
||||
</div>
|
||||
<i18n-t tag="div" keypath="Example:" class="form-text mt-3">
|
||||
<code>ws://chrome.browserless.io/playwright?token=YOUR-API-TOKEN</code>
|
||||
</i18n-t>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@ -68,7 +68,7 @@
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="tag-monitors" class="form-label">
|
||||
{{ $tc("Monitor", selectedMonitors.length) }}
|
||||
{{ $t("Monitors", selectedMonitors.length) }}
|
||||
</label>
|
||||
<div class="tag-monitors-list">
|
||||
<router-link
|
||||
|
||||
@ -85,12 +85,12 @@ export default {
|
||||
|
||||
title() {
|
||||
if (this.type === "1y") {
|
||||
return `1 ${this.$tc("year", 1)}`;
|
||||
return this.$t("years", 1);
|
||||
}
|
||||
if (this.type === "720") {
|
||||
return `30 ${this.$tc("day", 30)}`;
|
||||
return this.$t("days", 30);
|
||||
}
|
||||
return `24 ${this.$tc("hour", 24)}`;
|
||||
return this.$t("hours", 24);
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@ -2,8 +2,8 @@
|
||||
<div class="mb-3">
|
||||
<label for="octopush-version" class="form-label">{{ $t("Octopush API Version") }}</label>
|
||||
<select id="octopush-version" v-model="$parent.notification.octopushVersion" class="form-select">
|
||||
<option value="2">{{ "octopush" }} ({{ $t("endpoint") }}: api.octopush.com)</option>
|
||||
<option value="1">{{ $t("Legacy Octopush-DM") }} ({{ $t("endpoint") }}: www.octopush-dm.com)</option>
|
||||
<option value="2">{{ $t("octopushEndpoint", { url: "api.octopush.com" }) }}</option>
|
||||
<option value="1">{{ $t("legacyOctopushEndpoint", { url: "www.octopush-dm.com" }) }}</option>
|
||||
</select>
|
||||
<div class="form-text">
|
||||
{{ $t("octopushLegacyHint") }}
|
||||
|
||||
@ -27,7 +27,7 @@
|
||||
<div class="status">
|
||||
{{ $t("apiKey-" + item.status) }}
|
||||
</div>
|
||||
<div class="date">{{ $t("Created") }}: {{ item.createdDate }}</div>
|
||||
<div class="date">{{ $t("createdAt", { date: item.createdDate }) }}</div>
|
||||
<div class="date">
|
||||
{{ $t("Expires") }}:
|
||||
{{ item.expires || $t("Never") }}
|
||||
|
||||
@ -3,8 +3,8 @@
|
||||
<div class="logo d-flex flex-column justify-content-center align-items-center">
|
||||
<object class="my-4" width="200" height="200" data="/icon.svg" />
|
||||
<div class="fs-4 fw-bold">Uptime Kuma</div>
|
||||
<div>{{ $t("Version") }}: {{ $root.info.version }}</div>
|
||||
<div class="frontend-version">{{ $t("Frontend Version") }}: {{ $root.frontendVersion }}</div>
|
||||
<div>{{ $t("versionIs", { version: $root.info.version }) }}</div>
|
||||
<div class="frontend-version">{{ $t("frontendVersionIs", { version: $root.frontendVersion }) }}</div>
|
||||
|
||||
<div v-if="!$root.isFrontendBackendVersionMatched" class="alert alert-warning mt-4" role="alert">
|
||||
⚠️ {{ $t("Frontend Version do not match backend version!") }}
|
||||
|
||||
@ -64,7 +64,7 @@
|
||||
:key="day"
|
||||
class="d-flex align-items-center justify-content-between cert-exp-day-row py-2"
|
||||
>
|
||||
<span>{{ day }} {{ $tc("day", day) }}</span>
|
||||
<span>{{ $t("days", day) }}</span>
|
||||
<button
|
||||
type="button"
|
||||
class="btn-rm-expiry btn btn-outline-danger ms-2 py-1"
|
||||
@ -79,7 +79,7 @@
|
||||
<ActionInput
|
||||
v-model="tlsExpiryNotifInput"
|
||||
:type="'number'"
|
||||
:placeholder="$t('day')"
|
||||
:placeholder="$t('days', 1)"
|
||||
:icon="'plus'"
|
||||
:action="() => addTlsExpiryNotifDay(tlsExpiryNotifInput)"
|
||||
:action-aria-label="$t('Add a new expiry notification day')"
|
||||
@ -102,7 +102,7 @@
|
||||
:key="day"
|
||||
class="d-flex align-items-center justify-content-between cert-exp-day-row py-2"
|
||||
>
|
||||
<span>{{ day }} {{ $tc("day", day) }}</span>
|
||||
<span>{{ $t("days", day) }}</span>
|
||||
<button
|
||||
type="button"
|
||||
class="btn-rm-expiry btn btn-outline-danger ms-2 py-1"
|
||||
@ -117,7 +117,7 @@
|
||||
<ActionInput
|
||||
v-model="domainExpiryNotifInput"
|
||||
:type="'number'"
|
||||
:placeholder="$t('day')"
|
||||
:placeholder="$t('days', 1)"
|
||||
:icon="'plus'"
|
||||
:action="() => addDomainExpiryNotifDay(domainExpiryNotifInput)"
|
||||
:action-aria-label="$t('Add a new expiry notification day')"
|
||||
|
||||
@ -4,15 +4,13 @@
|
||||
<!-- Change Password -->
|
||||
<template v-if="!settings.disableAuth">
|
||||
<p>
|
||||
{{ $t("Current User") }}:
|
||||
<strong>{{ $root.username }}</strong>
|
||||
<button
|
||||
v-if="!settings.disableAuth"
|
||||
id="logout-btn"
|
||||
class="btn btn-danger ms-4 me-2 mb-2"
|
||||
@click="$root.logout"
|
||||
>
|
||||
{{ $t("Logout") }}
|
||||
{{ $t("logoutCurrentUser", { username: $root.username }) }}
|
||||
</button>
|
||||
</p>
|
||||
|
||||
|
||||
@ -19,7 +19,7 @@
|
||||
<Tag :item="tag" />
|
||||
</div>
|
||||
<div class="col-5 px-1 d-none d-sm-block">
|
||||
<div>{{ monitorsByTag(tag.id).length }} {{ $tc("Monitor", monitorsByTag(tag.id).length) }}</div>
|
||||
<div>{{ $t("Monitors", monitorsByTag(tag.id).length) }}</div>
|
||||
</div>
|
||||
<div class="col-2 pe-2 pe-lg-3 d-flex justify-content-end">
|
||||
<button
|
||||
|
||||
@ -20,7 +20,7 @@
|
||||
"General": "General",
|
||||
"Game": "Game",
|
||||
"Primary Base URL": "Primary Base URL",
|
||||
"Version": "Version",
|
||||
"versionIs": "Version: {version}",
|
||||
"Check Update On GitHub": "Check Update On GitHub",
|
||||
"List": "List",
|
||||
"Home": "Home",
|
||||
@ -33,6 +33,7 @@
|
||||
"statusMaintenance": "Maintenance",
|
||||
"Maintenance": "Maintenance",
|
||||
"Unknown": "Unknown",
|
||||
"unknownDays": "Unknown days",
|
||||
"Cannot connect to the socket server": "Cannot connect to the socket server",
|
||||
"Reconnecting...": "Reconnecting...",
|
||||
"General Monitor Type": "General Monitor Type",
|
||||
@ -52,12 +53,14 @@
|
||||
"Current": "Current",
|
||||
"Uptime": "Uptime",
|
||||
"Cert Exp.": "Cert Exp.",
|
||||
"Monitor": "Monitor | Monitors",
|
||||
"Monitors": "{n} Monitor | {n} Monitors",
|
||||
"now": "now",
|
||||
"time ago": "{0} ago",
|
||||
"day": "day | days",
|
||||
"hour": "hour | hours",
|
||||
"year": "year | years",
|
||||
"days": "{n} day | {n} days",
|
||||
"hours": "{n} hour | {n} hours",
|
||||
"minutes": "{n} minute | {n} minutes",
|
||||
"minuteShort": "{n} min | {n} min",
|
||||
"years": "{n} year | {n} years",
|
||||
"Response": "Response",
|
||||
"Ping": "Ping",
|
||||
"Monitor Type": "Monitor Type",
|
||||
@ -143,6 +146,7 @@
|
||||
"where you intend to implement third-party authentication": "where you intend to implement third-party authentication",
|
||||
"Please use this option carefully!": "Please use this option carefully!",
|
||||
"Logout": "Log out",
|
||||
"logoutCurrentUser": "Log out {username}",
|
||||
"Leave": "Leave",
|
||||
"I understand, please disable": "I understand, please disable",
|
||||
"Confirm": "Confirm",
|
||||
@ -278,7 +282,6 @@
|
||||
"records": "records",
|
||||
"One record": "One record",
|
||||
"steamApiKeyDescriptionAt": "For monitoring a Steam Game Server you need a Steam Web-API key. You can register your API key at {url}",
|
||||
"Current User": "Current User",
|
||||
"topic": "Topic",
|
||||
"topicExplanation": "MQTT topic to monitor",
|
||||
"mqttWebSocketPath": "MQTT WebSocket Path",
|
||||
@ -318,8 +321,9 @@
|
||||
"dark": "dark",
|
||||
"Post": "Post",
|
||||
"Please input title and content": "Please input title and content",
|
||||
"Created": "Created",
|
||||
"Last Updated": "Last Updated",
|
||||
"createdAt": "Created: {date}",
|
||||
"lastUpdatedAt": "Last Updated: {date}",
|
||||
"lastUpdatedAtFromNow": "Last Updated: {date} ({fromNow})",
|
||||
"Switch to Light Theme": "Switch to Light Theme",
|
||||
"Switch to Dark Theme": "Switch to Dark Theme",
|
||||
"Show Tags": "Show Tags",
|
||||
@ -354,7 +358,7 @@
|
||||
"proxyDescription": "Proxies must be assigned to a monitor to function.",
|
||||
"enableProxyDescription": "This proxy will not effect on monitor requests until it is activated. You can control temporarily disable the proxy from all monitors by activation status.",
|
||||
"setAsDefaultProxyDescription": "This proxy will be enabled by default for new monitors. You can still disable the proxy separately for each monitor.",
|
||||
"Certificate Chain": "Certificate Chain",
|
||||
"Certificate Chain:": "Certificate Chain:",
|
||||
"Valid": "Valid",
|
||||
"Invalid": "Invalid",
|
||||
"User": "User",
|
||||
@ -401,7 +405,7 @@
|
||||
"Add a new expiry notification day": "Add a new expiry notification day",
|
||||
"Remove the expiry notification": "Remove the expiry notification day",
|
||||
"Proxy": "Proxy",
|
||||
"Date Created": "Date Created",
|
||||
"dateCreatedAtFromNow": "Date Created: {date} ({fromNow})",
|
||||
"Footer Text": "Footer Text",
|
||||
"RSS Title": "RSS Title",
|
||||
"Leave blank to use status page title": "Leave blank to use status page title",
|
||||
@ -475,13 +479,13 @@
|
||||
"disableCloudflaredNoAuthMsg": "You are in No Auth mode, a password is not required.",
|
||||
"trustProxyDescription": "Trust 'X-Forwarded-*' headers. If you want to get the correct client IP and your Uptime Kuma is behind a proxy such as Nginx or Apache, you should enable this.",
|
||||
"wayToGetLineNotifyToken": "You can get an access token from {0}",
|
||||
"Examples": "Examples",
|
||||
"Examples:": "Examples: {0}",
|
||||
"supportBaleChatID": "Support Direct Chat / Group / Channel's Chat ID",
|
||||
"wayToGetBaleChatID": "You can get your chat ID by sending a message to the bot and going to this URL to view the chat_id:",
|
||||
"wayToGetBaleToken": "You can get a token from {0}.",
|
||||
"Home Assistant URL": "Home Assistant URL",
|
||||
"Long-Lived Access Token": "Long-Lived Access Token",
|
||||
"Long-Lived Access Token can be created by clicking on your profile name (bottom left) and scrolling to the bottom then click Create Token. ": "Long-Lived Access Token can be created by clicking on your profile name (bottom left) and scrolling to the bottom then click Create Token. ",
|
||||
"Long-Lived Access Token can be created by clicking on your profile name (bottom left) and scrolling to the bottom then click Create Token. ": "Long-Lived Access Token can be created by clicking on your profile name (bottom left) and scrolling to the bottom then click Create Token.",
|
||||
"Notification Service": "Notification Service",
|
||||
"default: notify all devices": "default: notify all devices",
|
||||
"A list of Notification Services can be found in Home Assistant under \"Developer Tools > Services\" search for \"notification\" to find your device/phone name.": "A list of Notification Services can be found in Home Assistant under \"Developer Tools > Services\" search for \"notification\" to find your device/phone name.",
|
||||
@ -490,7 +494,7 @@
|
||||
"Event type:": "Event type:",
|
||||
"Event data:": "Event data:",
|
||||
"Then choose an action, for example switch the scene to where an RGB light is red.": "Then choose an action, for example switch the scene to where an RGB light is red.",
|
||||
"Frontend Version": "Frontend Version",
|
||||
"frontendVersionIs": "Frontend Version: {version}",
|
||||
"Frontend Version do not match backend version!": "Frontend Version do not match backend version!",
|
||||
"backupOutdatedWarning": "Deprecated: Since a lot of features were added and this backup feature is a bit unmaintained, it cannot generate or restore a complete backup.",
|
||||
"backupRecommend": "Please backup the volume or the data folder (./data/) directly instead.",
|
||||
@ -501,7 +505,7 @@
|
||||
"startDateTime": "Start Date/Time",
|
||||
"endDateTime": "End Date/Time",
|
||||
"cronExpression": "Cron Expression",
|
||||
"cronSchedule": "Schedule: ",
|
||||
"cronScheduleDescription": "Schedule: {description}",
|
||||
"Duration (Minutes)": "Duration (Minutes)",
|
||||
"invalidCronExpression": "Invalid Cron Expression: {0}",
|
||||
"recurringInterval": "Interval",
|
||||
@ -668,6 +672,8 @@
|
||||
"recurringIntervalMessage": "Run once every day | Run once every {0} days",
|
||||
"affectedMonitorsDescription": "Select monitors that are affected by current maintenance",
|
||||
"affectedStatusPages": "Show this maintenance message on selected status pages",
|
||||
"Sets end time based on start time": "Sets end time based on start time",
|
||||
"Please set start time first": "Please set start time first",
|
||||
"noMonitorsSelectedWarning": "You are creating a maintenance without any affected monitors. Are you sure you want to continue?",
|
||||
"noMonitorsOrStatusPagesSelectedError": "Cannot create maintenance without affected monitors or status pages",
|
||||
"passwordNotMatchMsg": "The repeat password does not match.",
|
||||
@ -678,7 +684,6 @@
|
||||
"backupDescription": "You can backup all monitors and notifications into a JSON file.",
|
||||
"backupDescription2": "Note: history and event data is not included.",
|
||||
"backupDescription3": "Sensitive data such as notification tokens are included in the export file; please store export securely.",
|
||||
"endpoint": "endpoint",
|
||||
"octopushAPIKey": "\"API key\" from HTTP API credentials in control panel",
|
||||
"octopushLogin": "\"Login\" from HTTP API credentials in control panel",
|
||||
"promosmsLogin": "API Login Name",
|
||||
@ -730,7 +735,7 @@
|
||||
"apiCredentials": "API credentials",
|
||||
"octopushLegacyHint": "Do you use the legacy version of Octopush (2011-2020) or the new version?",
|
||||
"Check octopush prices": "Check octopush prices {0}.",
|
||||
"octopushPhoneNumber": "Phone number (intl format, eg : +33612345678) ",
|
||||
"octopushPhoneNumber": "Phone number (intl format, eg : +33612345678)",
|
||||
"octopushSMSSender": "SMS Sender Name : 3-11 alphanumeric characters and space (a-zA-Z0-9)",
|
||||
"LunaSea Device ID": "LunaSea Device ID",
|
||||
"Apprise URL": "Apprise URL",
|
||||
@ -880,7 +885,8 @@
|
||||
"From Name/Number": "From Name/Number",
|
||||
"Leave blank to use a shared sender number.": "Leave blank to use a shared sender number.",
|
||||
"Octopush API Version": "Octopush API Version",
|
||||
"Legacy Octopush-DM": "Legacy Octopush-DM",
|
||||
"octopushEndpoint": "octopush (endpoint: {url})",
|
||||
"legacyOctopushEndpoint": "Legacy Octopush-DM (endpoint: {url})",
|
||||
"ntfy Topic": "ntfy Topic",
|
||||
"Server URL should not contain the nfty topic": "Server URL should not contain the nfty topic",
|
||||
"onebotHttpAddress": "OneBot HTTP Address",
|
||||
|
||||
@ -194,7 +194,7 @@
|
||||
class="col-12 col-sm col row d-flex align-items-center d-sm-block"
|
||||
>
|
||||
<h4 class="col-4 col-sm-12">{{ pingTitle(true) }}</h4>
|
||||
<p class="col-4 col-sm-12 mb-0 mb-sm-2">({{ 24 }} {{ $tc("hour", 24) }})</p>
|
||||
<p class="col-4 col-sm-12 mb-0 mb-sm-2">({{ $t("hours", 24) }})</p>
|
||||
<span class="col-4 col-sm-12 num">
|
||||
<CountUp :value="avgPing" />
|
||||
</span>
|
||||
@ -203,7 +203,7 @@
|
||||
<!-- Uptime (24-hour) -->
|
||||
<div class="col-12 col-sm col row d-flex align-items-center d-sm-block">
|
||||
<h4 class="col-4 col-sm-12">{{ $t("Uptime") }}</h4>
|
||||
<p class="col-4 col-sm-12 mb-0 mb-sm-2">({{ 24 }} {{ $tc("hour", 24) }})</p>
|
||||
<p class="col-4 col-sm-12 mb-0 mb-sm-2">({{ $t("hours", 24) }})</p>
|
||||
<span class="col-4 col-sm-12 num">
|
||||
<Uptime :monitor="monitor" type="24" />
|
||||
</span>
|
||||
@ -212,7 +212,7 @@
|
||||
<!-- Uptime (30-day) -->
|
||||
<div class="col-12 col-sm col row d-flex align-items-center d-sm-block">
|
||||
<h4 class="col-4 col-sm-12">{{ $t("Uptime") }}</h4>
|
||||
<p class="col-4 col-sm-12 mb-0 mb-sm-2">({{ 30 }} {{ $tc("day", 30) }})</p>
|
||||
<p class="col-4 col-sm-12 mb-0 mb-sm-2">({{ $t("days", 30) }})</p>
|
||||
<span class="col-4 col-sm-12 num">
|
||||
<Uptime :monitor="monitor" type="720" />
|
||||
</span>
|
||||
@ -221,7 +221,7 @@
|
||||
<!-- Uptime (1-year) -->
|
||||
<div class="col-12 col-sm col row d-flex align-items-center d-sm-block">
|
||||
<h4 class="col-4 col-sm-12">{{ $t("Uptime") }}</h4>
|
||||
<p class="col-4 col-sm-12 mb-0 mb-sm-2">({{ 1 }} {{ $tc("year", 1) }})</p>
|
||||
<p class="col-4 col-sm-12 mb-0 mb-sm-2">({{ $t("years", 1) }})</p>
|
||||
<span class="col-4 col-sm-12 num">
|
||||
<Uptime :monitor="monitor" type="1y" />
|
||||
</span>
|
||||
@ -236,7 +236,7 @@
|
||||
</p>
|
||||
<span class="col-4 col-sm-12 num">
|
||||
<a href="#" @click.prevent="toggleCertInfoBox = !toggleCertInfoBox">
|
||||
{{ tlsInfo.certInfo.daysRemaining }} {{ $tc("day", tlsInfo.certInfo.daysRemaining) }}
|
||||
{{ $t("days", tlsInfo.certInfo.daysRemaining) }}
|
||||
</a>
|
||||
<font-awesome-icon
|
||||
v-if="tlsInfo.hostnameMatchMonitorUrl === false"
|
||||
@ -254,7 +254,7 @@
|
||||
)
|
||||
</p>
|
||||
<span class="col-4 col-sm-12 num">
|
||||
{{ domainInfo.daysRemaining }} {{ $tc("day", domainInfo.daysRemaining) }}
|
||||
{{ $t("days", domainInfo.daysRemaining) }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@ -374,7 +374,7 @@
|
||||
type="checkbox"
|
||||
/>
|
||||
<label class="form-check-label" for="delete-children-checkbox">
|
||||
{{ $t("deleteChildrenMonitors", childrenCount, { count: childrenCount }) }}
|
||||
{{ $t("deleteChildrenMonitors", childrenCount) }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -123,16 +123,13 @@
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- Single Maintenance Window -->
|
||||
<template v-if="maintenance.strategy === 'single'"></template>
|
||||
|
||||
<template v-if="maintenance.strategy === 'cron'">
|
||||
<!-- Cron -->
|
||||
<div class="my-3">
|
||||
<label for="cron" class="form-label">
|
||||
{{ $t("cronExpression") }}
|
||||
</label>
|
||||
<p>{{ $t("cronSchedule") }}{{ cronDescription }}</p>
|
||||
<p>{{ $t("cronScheduleDescription", { description: cronDescription }) }}</p>
|
||||
<input
|
||||
id="cron"
|
||||
v-model="maintenance.cron"
|
||||
@ -167,7 +164,7 @@
|
||||
|
||||
<template v-if="maintenance.intervalDay >= 1">
|
||||
({{
|
||||
$tc("recurringIntervalMessage", maintenance.intervalDay, [
|
||||
$t("recurringIntervalMessage", maintenance.intervalDay, [
|
||||
maintenance.intervalDay,
|
||||
])
|
||||
}})
|
||||
@ -331,6 +328,102 @@
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template v-if="maintenance.strategy === 'single'">
|
||||
<div class="my-3">
|
||||
<div class="d-flex gap-2 flex-wrap">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm"
|
||||
:class="
|
||||
currentDurationMinutes === 15 ? 'btn-primary' : 'btn-outline-primary'
|
||||
"
|
||||
:disabled="currentDurationMinutes === 15"
|
||||
@click="setQuickDuration(15)"
|
||||
>
|
||||
{{ $t("minuteShort", 15) }}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm"
|
||||
:class="
|
||||
currentDurationMinutes === 30 ? 'btn-primary' : 'btn-outline-primary'
|
||||
"
|
||||
:disabled="currentDurationMinutes === 30"
|
||||
@click="setQuickDuration(30)"
|
||||
>
|
||||
{{ $t("minuteShort", 30) }}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm"
|
||||
:class="
|
||||
currentDurationMinutes === 60 ? 'btn-primary' : 'btn-outline-primary'
|
||||
"
|
||||
:disabled="currentDurationMinutes === 60"
|
||||
@click="setQuickDuration(60)"
|
||||
>
|
||||
{{ $t("hours", 1) }}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm"
|
||||
:class="
|
||||
currentDurationMinutes === 120 ? 'btn-primary' : 'btn-outline-primary'
|
||||
"
|
||||
:disabled="currentDurationMinutes === 120"
|
||||
@click="setQuickDuration(120)"
|
||||
>
|
||||
{{ $t("hours", 2) }}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm"
|
||||
:class="
|
||||
currentDurationMinutes === 240 ? 'btn-primary' : 'btn-outline-primary'
|
||||
"
|
||||
:disabled="currentDurationMinutes === 240"
|
||||
@click="setQuickDuration(240)"
|
||||
>
|
||||
{{ $t("hours", 4) }}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm"
|
||||
:class="
|
||||
currentDurationMinutes === 480 ? 'btn-primary' : 'btn-outline-primary'
|
||||
"
|
||||
:disabled="currentDurationMinutes === 480"
|
||||
@click="setQuickDuration(480)"
|
||||
>
|
||||
{{ $t("hours", 8) }}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm"
|
||||
:class="
|
||||
currentDurationMinutes === 720 ? 'btn-primary' : 'btn-outline-primary'
|
||||
"
|
||||
:disabled="currentDurationMinutes === 720"
|
||||
@click="setQuickDuration(720)"
|
||||
>
|
||||
{{ $t("hours", 12) }}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm"
|
||||
:class="
|
||||
currentDurationMinutes === 1440 ? 'btn-primary' : 'btn-outline-primary'
|
||||
"
|
||||
:disabled="currentDurationMinutes === 1440"
|
||||
@click="setQuickDuration(1440)"
|
||||
>
|
||||
{{ $t("hours", 24) }}
|
||||
</button>
|
||||
</div>
|
||||
<div class="form-text">{{ $t("Sets end time based on start time") }}</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -511,6 +604,22 @@ export default {
|
||||
hasStatusPages() {
|
||||
return this.showOnAllPages || this.selectedStatusPages.length > 0;
|
||||
},
|
||||
|
||||
/**
|
||||
* Calculate the current duration in minutes between start and end dates
|
||||
* @returns {number|null} Duration in minutes, or null if dates are invalid
|
||||
*/
|
||||
currentDurationMinutes() {
|
||||
if (!this.maintenance.dateRange?.[0] || !this.maintenance.dateRange?.[1]) {
|
||||
return null;
|
||||
}
|
||||
const start = new Date(this.maintenance.dateRange[0]);
|
||||
const end = new Date(this.maintenance.dateRange[1]);
|
||||
if (isNaN(start.getTime()) || isNaN(end.getTime())) {
|
||||
return null;
|
||||
}
|
||||
return Math.round((end.getTime() - start.getTime()) / 60000);
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
"$route.fullPath"() {
|
||||
@ -570,6 +679,19 @@ export default {
|
||||
this.selectedStatusPages = [];
|
||||
|
||||
if (this.isAdd) {
|
||||
// Get current date/time in local timezone
|
||||
const now = new Date();
|
||||
const oneHourLater = new Date(now.getTime() + 60 * 60000);
|
||||
|
||||
const formatDateTime = (date) => {
|
||||
const year = date.getFullYear();
|
||||
const month = String(date.getMonth() + 1).padStart(2, "0");
|
||||
const day = String(date.getDate()).padStart(2, "0");
|
||||
const hours = String(date.getHours()).padStart(2, "0");
|
||||
const minutes = String(date.getMinutes()).padStart(2, "0");
|
||||
return `${year}-${month}-${day}T${hours}:${minutes}`;
|
||||
};
|
||||
|
||||
this.maintenance = {
|
||||
title: "",
|
||||
description: "",
|
||||
@ -578,7 +700,7 @@ export default {
|
||||
cron: "30 3 * * *",
|
||||
durationMinutes: 60,
|
||||
intervalDay: 1,
|
||||
dateRange: [],
|
||||
dateRange: [formatDateTime(now), formatDateTime(oneHourLater)],
|
||||
timeRange: [
|
||||
{
|
||||
hours: 2,
|
||||
@ -591,7 +713,7 @@ export default {
|
||||
],
|
||||
weekdays: [],
|
||||
daysOfMonth: [],
|
||||
timezoneOption: null,
|
||||
timezoneOption: "SAME_AS_SERVER",
|
||||
};
|
||||
} else if (this.isEdit || this.isClone) {
|
||||
this.$root.getSocket().emit("getMaintenance", this.$route.params.id, (res) => {
|
||||
@ -655,6 +777,30 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Set quick duration for single maintenance
|
||||
* Calculates end time based on start time + duration in minutes
|
||||
* @param {number} minutes Duration in minutes
|
||||
* @returns {void}
|
||||
*/
|
||||
setQuickDuration(minutes) {
|
||||
if (!this.maintenance.dateRange[0]) {
|
||||
this.$root.toastError(this.$t("Please set start time first"));
|
||||
return;
|
||||
}
|
||||
|
||||
const startDate = new Date(this.maintenance.dateRange[0]);
|
||||
const endDate = new Date(startDate.getTime() + minutes * 60000);
|
||||
|
||||
const year = endDate.getFullYear();
|
||||
const month = String(endDate.getMonth() + 1).padStart(2, "0");
|
||||
const day = String(endDate.getDate()).padStart(2, "0");
|
||||
const hours = String(endDate.getHours()).padStart(2, "0");
|
||||
const mins = String(endDate.getMinutes()).padStart(2, "0");
|
||||
|
||||
this.maintenance.dateRange[1] = `${year}-${month}-${day}T${hours}:${mins}`;
|
||||
},
|
||||
|
||||
/**
|
||||
* Handle form submission - show confirmation if no monitors selected
|
||||
* @returns {void}
|
||||
|
||||
@ -342,14 +342,20 @@
|
||||
|
||||
<!-- Incident Date -->
|
||||
<div class="date mt-3">
|
||||
{{ $t("Date Created") }}: {{ $root.datetime(incident.createdDate) }} ({{
|
||||
dateFromNow(incident.createdDate)
|
||||
}})
|
||||
{{
|
||||
$t("dateCreatedAtFromNow", {
|
||||
date: $root.datetime(incident.createdDate),
|
||||
fromNow: dateFromNow(incident.createdDate),
|
||||
})
|
||||
}}
|
||||
<br />
|
||||
<span v-if="incident.lastUpdatedDate">
|
||||
{{ $t("Last Updated") }}: {{ $root.datetime(incident.lastUpdatedDate) }} ({{
|
||||
dateFromNow(incident.lastUpdatedDate)
|
||||
}})
|
||||
{{
|
||||
$t("lastUpdatedAtFromNow", {
|
||||
date: $root.datetime(incident.lastUpdatedDate),
|
||||
fromNow: dateFromNow(incident.lastUpdatedDate),
|
||||
})
|
||||
}}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@ -572,9 +578,9 @@
|
||||
</p>
|
||||
|
||||
<div class="refresh-info mb-2">
|
||||
<div>{{ $t("Last Updated") }}: {{ lastUpdateTimeDisplay }}</div>
|
||||
<div>{{ $t("lastUpdatedAt", { date: lastUpdateTimeDisplay }) }}</div>
|
||||
<div data-testid="update-countdown-text">
|
||||
{{ $tc("statusPageRefreshIn", [updateCountdownText]) }}
|
||||
{{ $t("statusPageRefreshIn", [updateCountdownText]) }}
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user