mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-26 10:21:52 +00:00
chore: update Taiga to 5 (#3136)
* chore: update Taiga to 5 * chore: fix
This commit is contained in:
@@ -98,7 +98,8 @@ this.dialog.openComponent(new PolymorpheusComponent(MyComponent, injector), { la
|
||||
### Errors & Tooltips
|
||||
|
||||
```html
|
||||
<tui-error [error]="[] | tuiFieldError | async" />
|
||||
<tui-error formControlName="controlName" />
|
||||
<tui-error [error]="'Error text'" />
|
||||
<tui-icon [tuiTooltip]="'Hint text'" />
|
||||
```
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
"projects/ui/src/manifest.webmanifest"
|
||||
],
|
||||
"styles": [
|
||||
"node_modules/@taiga-ui/core/styles/taiga-ui-theme.less",
|
||||
"node_modules/@taiga-ui/styles/taiga-ui-theme.less",
|
||||
"projects/shared/styles/taiga.scss",
|
||||
"projects/shared/styles/shared.scss",
|
||||
"projects/ui/src/styles.scss"
|
||||
@@ -158,7 +158,7 @@
|
||||
}
|
||||
],
|
||||
"styles": [
|
||||
"node_modules/@taiga-ui/core/styles/taiga-ui-theme.less",
|
||||
"node_modules/@taiga-ui/styles/taiga-ui-theme.less",
|
||||
"projects/shared/styles/taiga.scss",
|
||||
"projects/shared/styles/shared.scss",
|
||||
"projects/setup-wizard/src/styles.scss"
|
||||
@@ -258,8 +258,8 @@
|
||||
}
|
||||
],
|
||||
"styles": [
|
||||
"node_modules/@taiga-ui/core/styles/taiga-ui-theme.less",
|
||||
"node_modules/@taiga-ui/core/styles/taiga-ui-fonts.less",
|
||||
"node_modules/@taiga-ui/styles/taiga-ui-theme.less",
|
||||
"node_modules/@taiga-ui/styles/taiga-ui-fonts.less",
|
||||
"projects/shared/styles/shared.scss",
|
||||
"projects/start-tunnel/src/styles.scss"
|
||||
],
|
||||
|
||||
489
web/package-lock.json
generated
489
web/package-lock.json
generated
@@ -9,7 +9,6 @@
|
||||
"version": "0.4.0-alpha.20",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@angular/animations": "^21.2.1",
|
||||
"@angular/cdk": "^21.2.1",
|
||||
"@angular/common": "^21.2.1",
|
||||
"@angular/compiler": "^21.2.1",
|
||||
@@ -24,19 +23,19 @@
|
||||
"@noble/hashes": "^1.4.0",
|
||||
"@start9labs/argon2": "^0.3.0",
|
||||
"@start9labs/start-sdk": "file:../sdk/baseDist",
|
||||
"@taiga-ui/addon-charts": "4.73.0",
|
||||
"@taiga-ui/addon-commerce": "4.73.0",
|
||||
"@taiga-ui/addon-mobile": "4.73.0",
|
||||
"@taiga-ui/addon-table": "4.73.0",
|
||||
"@taiga-ui/cdk": "4.73.0",
|
||||
"@taiga-ui/core": "4.73.0",
|
||||
"@taiga-ui/dompurify": "4.1.11",
|
||||
"@taiga-ui/event-plugins": "4.7.0",
|
||||
"@taiga-ui/experimental": "4.73.0",
|
||||
"@taiga-ui/icons": "4.73.0",
|
||||
"@taiga-ui/kit": "4.73.0",
|
||||
"@taiga-ui/layout": "4.73.0",
|
||||
"@taiga-ui/polymorpheus": "4.9.0",
|
||||
"@taiga-ui/addon-charts": "5.0.0-rc.4",
|
||||
"@taiga-ui/addon-commerce": "5.0.0-rc.4",
|
||||
"@taiga-ui/addon-mobile": "5.0.0-rc.4",
|
||||
"@taiga-ui/addon-table": "5.0.0-rc.4",
|
||||
"@taiga-ui/cdk": "5.0.0-rc.4",
|
||||
"@taiga-ui/core": "5.0.0-rc.4",
|
||||
"@taiga-ui/dompurify": "5.0.1",
|
||||
"@taiga-ui/event-plugins": "5.0.0",
|
||||
"@taiga-ui/experimental": "5.0.0-rc.4",
|
||||
"@taiga-ui/icons": "5.0.0-rc.4",
|
||||
"@taiga-ui/kit": "5.0.0-rc.4",
|
||||
"@taiga-ui/layout": "5.0.0-rc.4",
|
||||
"@taiga-ui/polymorpheus": "5.0.0",
|
||||
"ansi-to-html": "^0.7.2",
|
||||
"base64-js": "^1.5.1",
|
||||
"buffer": "^6.0.3",
|
||||
@@ -46,7 +45,7 @@
|
||||
"cron": "^2.2.0",
|
||||
"cronstrue": "^2.21.0",
|
||||
"deep-equality-data-structures": "1.5.1",
|
||||
"dompurify": "^3.1.7",
|
||||
"dompurify": "^3.3.2",
|
||||
"fast-json-patch": "^3.1.1",
|
||||
"fuse.js": "^6.4.6",
|
||||
"jose": "^4.9.0",
|
||||
@@ -71,7 +70,6 @@
|
||||
"@angular/cli": "^21.2.1",
|
||||
"@angular/compiler-cli": "^21.2.1",
|
||||
"@angular/language-service": "^21.2.1",
|
||||
"@types/dompurify": "3.0.5",
|
||||
"@types/estree": "^0.0.51",
|
||||
"@types/js-yaml": "^4.0.5",
|
||||
"@types/marked": "^4.0.3",
|
||||
@@ -448,22 +446,6 @@
|
||||
"hawkeye": "index.mjs"
|
||||
}
|
||||
},
|
||||
"node_modules/@angular/animations": {
|
||||
"version": "21.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@angular/animations/-/animations-21.2.1.tgz",
|
||||
"integrity": "sha512-zT/S29pUTbziCLvZ2itBdNWd5i8tsXexofH7KA4n2yvYmK1EhNpE7TlHRjghmsHgtDt4VnGiMW4zXEyrl05Dwg==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"tslib": "^2.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^20.19.0 || ^22.12.0 || >=24.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@angular/core": "21.2.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@angular/build": {
|
||||
"version": "21.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@angular/build/-/build-21.2.1.tgz",
|
||||
@@ -2200,46 +2182,46 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@maskito/angular": {
|
||||
"version": "3.11.1",
|
||||
"resolved": "https://registry.npmjs.org/@maskito/angular/-/angular-3.11.1.tgz",
|
||||
"integrity": "sha512-+OZzbRJj/9fOGhgPr0xYctSHe/Ngahip3VdNWBslRTpt7g+UTBYcB8vU9J4cHfpdXYeLM3tM0tnKksc3Eis0+Q==",
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@maskito/angular/-/angular-5.1.1.tgz",
|
||||
"integrity": "sha512-NCKvUpIF3KCJDRpDWcI0DAeVQaYgsJmGAycq7h/LVu6h7P0nSd5xanYpoM2/F1MdXvGh/aEAF37KooTsfwUqog==",
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"tslib": "2.8.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@angular/core": ">=16.0.0",
|
||||
"@angular/forms": ">=16.0.0",
|
||||
"@maskito/core": "^3.11.1"
|
||||
"@angular/core": ">=19.0.0",
|
||||
"@angular/forms": ">=19.0.0",
|
||||
"@maskito/core": "^5.1.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@maskito/core": {
|
||||
"version": "3.11.1",
|
||||
"resolved": "https://registry.npmjs.org/@maskito/core/-/core-3.11.1.tgz",
|
||||
"integrity": "sha512-zN5k/BiZXblo8mEFhsGnnXBCqKMkjEGArorOOcpB1/ymZyqF12Dk6IipEsSE6abMnWw4YF2tukzfq73BFZKz8A==",
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@maskito/core/-/core-5.1.1.tgz",
|
||||
"integrity": "sha512-grxipbOGKBs++kgAM/5K/lCghY/AfkSKNcRDSp8Nspf9dngxWiraMiPQVFsS8E0sab1wHEWlMXBdqEa3WyQXPA==",
|
||||
"license": "Apache-2.0",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/@maskito/kit": {
|
||||
"version": "3.11.1",
|
||||
"resolved": "https://registry.npmjs.org/@maskito/kit/-/kit-3.11.1.tgz",
|
||||
"integrity": "sha512-KOBUqxRz383xJWCoe+Emwxv2oAzUrZobIN+Gntmi5Py2S10XbqYnGX/6W7QHN8CUK2Nx11d3HsxbEQaq5Hinjg==",
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@maskito/kit/-/kit-5.1.1.tgz",
|
||||
"integrity": "sha512-YlMPGzyX/zuYaAxWRFTwBYoP3bV1WzMhrW8D+7Tn6nUfCBUTogvnJrVhVyOi6dZzXGX8qP1yRVT6W/IVt79F5g==",
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"peerDependencies": {
|
||||
"@maskito/core": "^3.11.1"
|
||||
"@maskito/core": "^5.1.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@maskito/phone": {
|
||||
"version": "3.11.1",
|
||||
"resolved": "https://registry.npmjs.org/@maskito/phone/-/phone-3.11.1.tgz",
|
||||
"integrity": "sha512-ptNDPIZQs/v598qydBa9cnvoCE8+k2Sv07kKKVx3vG0V40DQnIlEL+LYKrJJbMIiPOB6CH90hB9eaA9KKReZ6w==",
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@maskito/phone/-/phone-5.1.1.tgz",
|
||||
"integrity": "sha512-yBb42/7FZpEjlAvvT5SabWX8jZdMjhGv4g7G6McarVM1RcG6vcV+kZd0xjAdDvOv8s5zGww+pN39Scn0tt+QMg==",
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"peerDependencies": {
|
||||
"@maskito/core": "^3.11.1",
|
||||
"@maskito/kit": "^3.11.1",
|
||||
"@maskito/core": "^5.1.1",
|
||||
"@maskito/kit": "^5.1.1",
|
||||
"libphonenumber-js": ">=1.0.0"
|
||||
}
|
||||
},
|
||||
@@ -2732,52 +2714,53 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@ng-web-apis/common": {
|
||||
"version": "4.14.0",
|
||||
"resolved": "https://registry.npmjs.org/@ng-web-apis/common/-/common-4.14.0.tgz",
|
||||
"integrity": "sha512-eLrpy9e8R+eJKRUWv06jauaDCJ/6/9llmHPTvmWH3yTS9HIn+twk5ZmyfNwFqA/r8g9Kt4Ap48YuaydQy00nuw==",
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@ng-web-apis/common/-/common-5.1.0.tgz",
|
||||
"integrity": "sha512-omhjrojnwgJXIPT4H4sLruqCSGlWeLLuIAUkDB+fIARd1shT0vYmA9qugaNd54XmLOnL7Hu97FYkXnULFyT85w==",
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"tslib": "^2.3.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@angular/common": ">=16.0.0",
|
||||
"@angular/core": ">=16.0.0",
|
||||
"@angular/common": ">=19.0.0",
|
||||
"@angular/core": ">=19.0.0",
|
||||
"@types/dom-speech-recognition": "^0.0.7",
|
||||
"rxjs": ">=7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@ng-web-apis/intersection-observer": {
|
||||
"version": "4.14.0",
|
||||
"resolved": "https://registry.npmjs.org/@ng-web-apis/intersection-observer/-/intersection-observer-4.14.0.tgz",
|
||||
"integrity": "sha512-VDuak0+jDPwPttqQbgIYCD1tM2F7wKSXZWWUjFdNfkV47GspEPzzf12lY1eiltIiCB4cv6asZNs5ijnsxpnb9A==",
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@ng-web-apis/intersection-observer/-/intersection-observer-5.1.0.tgz",
|
||||
"integrity": "sha512-Fonur9MS3bxDyCbGX3gcuEsvIRPA/0PrkpOe2EohVJMdrVjs8eB6SbQR4DSKVv5We1maMSzt3jhd1u5KEMp2xA==",
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"tslib": "^2.3.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@angular/core": ">=16.0.0",
|
||||
"@ng-web-apis/common": ">=4.12.0"
|
||||
"@angular/core": ">=19.0.0",
|
||||
"@ng-web-apis/common": "^5.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@ng-web-apis/mutation-observer": {
|
||||
"version": "4.14.0",
|
||||
"resolved": "https://registry.npmjs.org/@ng-web-apis/mutation-observer/-/mutation-observer-4.14.0.tgz",
|
||||
"integrity": "sha512-AUZDtVWN1rUSZoaB5AWhRYZ8DNSPoPQ2Ld8G8q9ocxfpslDHvjQQjUj5r0zHjAwKe1f9cNuow2nU+n6k3hF6ew==",
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@ng-web-apis/mutation-observer/-/mutation-observer-5.1.0.tgz",
|
||||
"integrity": "sha512-X8DepT55KG/xY/WnQ05pnSxpyzv76CWiDrKanzOeUy9SUckrfpjCWkGvyz9fSzUv27mOC4t/ry6Fnu+em28Tzg==",
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"tslib": "^2.3.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@angular/core": ">=16.0.0",
|
||||
"@ng-web-apis/common": ">=4.12.0"
|
||||
"@angular/core": ">=19.0.0",
|
||||
"@ng-web-apis/common": "^5.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@ng-web-apis/platform": {
|
||||
"version": "4.14.0",
|
||||
"resolved": "https://registry.npmjs.org/@ng-web-apis/platform/-/platform-4.14.0.tgz",
|
||||
"integrity": "sha512-zmsbg0cEumppG6VlxIpM+ghJXBJ6G2mlTm+XmC9HYCnRJxYJjqIVRDZbYUQ4pGQHz4iJxRbp2C3VOndre72+3g==",
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@ng-web-apis/platform/-/platform-5.1.0.tgz",
|
||||
"integrity": "sha512-Jp6BqEDQ0C7/NpQ2TqTvy2ddjcOt1nON9KlCOaIR7L+YY88KToeQLD3dsFRFbxwWB1G1okgpxysMoFunatltYQ==",
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
@@ -2785,31 +2768,31 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@ng-web-apis/resize-observer": {
|
||||
"version": "4.14.0",
|
||||
"resolved": "https://registry.npmjs.org/@ng-web-apis/resize-observer/-/resize-observer-4.14.0.tgz",
|
||||
"integrity": "sha512-W5VXT/y0Vv68Gx/2urgu/JmIQfv0jPtzfvGtyulgGALfBrnei4oVXvJe2aZmLb0/VkxH65qlYOKVEOGqBrwSwQ==",
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@ng-web-apis/resize-observer/-/resize-observer-5.1.0.tgz",
|
||||
"integrity": "sha512-cuEPAaZJ2UDOA283S/Ehz7tdDLuCY6tLmdcYHlXTdnMcXiyrqUsu0dKQ04ZoZ0KXfoSjT95jPUTabot5psVPkw==",
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"tslib": "^2.3.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@angular/core": ">=16.0.0",
|
||||
"@ng-web-apis/common": ">=4.12.0"
|
||||
"@angular/core": ">=19.0.0",
|
||||
"@ng-web-apis/common": "^5.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@ng-web-apis/screen-orientation": {
|
||||
"version": "4.14.0",
|
||||
"resolved": "https://registry.npmjs.org/@ng-web-apis/screen-orientation/-/screen-orientation-4.14.0.tgz",
|
||||
"integrity": "sha512-XlXjxhYT7QKW0WKQE4BIJ2OZ7c1EFRXUQ4eXQ41Jwl8ukG0zkixOTrxGlnfy7ijX5df3sX/+0kKCXwsyj/n5BA==",
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@ng-web-apis/screen-orientation/-/screen-orientation-5.1.0.tgz",
|
||||
"integrity": "sha512-x6W2C45EAcaHk/0QR5hcWg6bByyPD+E/xPlQjR8sQwLN+AE8ag1hrhmIbkQOyEP2K2kvU81M0ndbre0o4dRo9Q==",
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"tslib": "^2.3.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@angular/core": ">=16.0.0",
|
||||
"@ng-web-apis/common": ">=4.12.0",
|
||||
"@angular/core": ">=19.0.0",
|
||||
"@ng-web-apis/common": "^5.1.0",
|
||||
"rxjs": ">=7.0.0"
|
||||
}
|
||||
},
|
||||
@@ -4182,118 +4165,118 @@
|
||||
"link": true
|
||||
},
|
||||
"node_modules/@taiga-ui/addon-charts": {
|
||||
"version": "4.73.0",
|
||||
"resolved": "https://registry.npmjs.org/@taiga-ui/addon-charts/-/addon-charts-4.73.0.tgz",
|
||||
"integrity": "sha512-BZhmupFnngsGICumSvaA7b8jf5lprQ5PD5Nqduq6iQ/pa02qv4VdR7HE2OM07kg4pBm4OX3OtJ0H9V0N/buchQ==",
|
||||
"version": "5.0.0-rc.4",
|
||||
"resolved": "https://registry.npmjs.org/@taiga-ui/addon-charts/-/addon-charts-5.0.0-rc.4.tgz",
|
||||
"integrity": "sha512-goStkREzlt2vgK0gRI2o2BEud8YNqMxXAG3NW1YxyAO/P13OwzuxWxGBW013ykzxfpEVynUlswpUPWHyowNa8g==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"tslib": ">=2.8.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@angular/common": ">=16.0.0",
|
||||
"@angular/core": ">=16.0.0",
|
||||
"@ng-web-apis/common": "^4.14.0",
|
||||
"@taiga-ui/cdk": "^4.73.0",
|
||||
"@taiga-ui/core": "^4.73.0",
|
||||
"@taiga-ui/polymorpheus": "^4.9.0"
|
||||
"@angular/common": ">=19.0.0",
|
||||
"@angular/core": ">=19.0.0",
|
||||
"@ng-web-apis/common": "^5.1.0",
|
||||
"@taiga-ui/cdk": "^5.0.0-rc.4",
|
||||
"@taiga-ui/core": "^5.0.0-rc.4",
|
||||
"@taiga-ui/polymorpheus": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@taiga-ui/addon-commerce": {
|
||||
"version": "4.73.0",
|
||||
"resolved": "https://registry.npmjs.org/@taiga-ui/addon-commerce/-/addon-commerce-4.73.0.tgz",
|
||||
"integrity": "sha512-jLNGPZgAnqhrLp5jJ2LNaDVuQs7SX1pUitDm4xpt26GnO7GuQmjY2E0SmZtEbBf/9ykROAnPzgWJbaIj6e5V0A==",
|
||||
"version": "5.0.0-rc.4",
|
||||
"resolved": "https://registry.npmjs.org/@taiga-ui/addon-commerce/-/addon-commerce-5.0.0-rc.4.tgz",
|
||||
"integrity": "sha512-5Z/QbxC4NQKJ0F7Y7oJG86o1Ek+4XiBeV61F42/syHmD1/3Y2KEll+1GBvlx++xFHJvjfa0+xFUx3omLJjIGzA==",
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"tslib": ">=2.8.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@angular/common": ">=16.0.0",
|
||||
"@angular/core": ">=16.0.0",
|
||||
"@angular/forms": ">=16.0.0",
|
||||
"@maskito/angular": "^3.11.1",
|
||||
"@maskito/core": "^3.11.1",
|
||||
"@maskito/kit": "^3.11.1",
|
||||
"@ng-web-apis/common": "^4.14.0",
|
||||
"@taiga-ui/cdk": "^4.73.0",
|
||||
"@taiga-ui/core": "^4.73.0",
|
||||
"@taiga-ui/i18n": "^4.73.0",
|
||||
"@taiga-ui/kit": "^4.73.0",
|
||||
"@taiga-ui/polymorpheus": "^4.9.0",
|
||||
"@angular/common": ">=19.0.0",
|
||||
"@angular/core": ">=19.0.0",
|
||||
"@angular/forms": ">=19.0.0",
|
||||
"@maskito/angular": "^5.1.1",
|
||||
"@maskito/core": "^5.1.1",
|
||||
"@maskito/kit": "^5.1.1",
|
||||
"@ng-web-apis/common": "^5.1.0",
|
||||
"@taiga-ui/cdk": "^5.0.0-rc.4",
|
||||
"@taiga-ui/core": "^5.0.0-rc.4",
|
||||
"@taiga-ui/i18n": "^5.0.0-rc.4",
|
||||
"@taiga-ui/kit": "^5.0.0-rc.4",
|
||||
"@taiga-ui/polymorpheus": "^5.0.0",
|
||||
"rxjs": ">=7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@taiga-ui/addon-mobile": {
|
||||
"version": "4.73.0",
|
||||
"resolved": "https://registry.npmjs.org/@taiga-ui/addon-mobile/-/addon-mobile-4.73.0.tgz",
|
||||
"integrity": "sha512-5ohDbwkE2ur57eMYmM6Tl7IOvVNxzPiHnZRB5ZcntmDkFp7UBgSOFptelqraL9DP8w5LEmvrshT6ObygRQNe+Q==",
|
||||
"version": "5.0.0-rc.4",
|
||||
"resolved": "https://registry.npmjs.org/@taiga-ui/addon-mobile/-/addon-mobile-5.0.0-rc.4.tgz",
|
||||
"integrity": "sha512-EkPCgOSnj7+SmgcQu4HVsmTNsBYiJ5SpuoktgxtZPmfeK4GXEmO1z6Pizotb3EHmyuyNBN69jeS4IPkdplvzsw==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"tslib": ">=2.8.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@angular/cdk": ">=16.0.0",
|
||||
"@angular/common": ">=16.0.0",
|
||||
"@angular/core": ">=16.0.0",
|
||||
"@ng-web-apis/common": "^4.14.0",
|
||||
"@taiga-ui/cdk": "^4.73.0",
|
||||
"@taiga-ui/core": "^4.73.0",
|
||||
"@taiga-ui/kit": "^4.73.0",
|
||||
"@taiga-ui/layout": "^4.73.0",
|
||||
"@taiga-ui/polymorpheus": "^4.9.0",
|
||||
"@angular/cdk": ">=19.0.0",
|
||||
"@angular/common": ">=19.0.0",
|
||||
"@angular/core": ">=19.0.0",
|
||||
"@ng-web-apis/common": "^5.1.0",
|
||||
"@ng-web-apis/platform": "^5.1.0",
|
||||
"@taiga-ui/cdk": "^5.0.0-rc.4",
|
||||
"@taiga-ui/core": "^5.0.0-rc.4",
|
||||
"@taiga-ui/kit": "^5.0.0-rc.4",
|
||||
"@taiga-ui/layout": "^5.0.0-rc.4",
|
||||
"@taiga-ui/polymorpheus": "^5.0.0",
|
||||
"rxjs": ">=7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@taiga-ui/addon-table": {
|
||||
"version": "4.73.0",
|
||||
"resolved": "https://registry.npmjs.org/@taiga-ui/addon-table/-/addon-table-4.73.0.tgz",
|
||||
"integrity": "sha512-fRxnCopvanInTdrVtNNXclY6T5u3fU87De564sngAcV9Y8Q1O44bZCyyDE/+jsoz3IIDZUD+2OEZjOGHMWLFOA==",
|
||||
"version": "5.0.0-rc.4",
|
||||
"resolved": "https://registry.npmjs.org/@taiga-ui/addon-table/-/addon-table-5.0.0-rc.4.tgz",
|
||||
"integrity": "sha512-j3ICBUoj4XKKvzzIbTQyLdif32+lHSlBozFDQcXhtL1x9C1mWOvidgU9kcsjygs0lEnjoIUTVza59sYMv3UKMQ==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"tslib": ">=2.8.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@angular/common": ">=16.0.0",
|
||||
"@angular/core": ">=16.0.0",
|
||||
"@ng-web-apis/intersection-observer": "^4.14.0",
|
||||
"@taiga-ui/cdk": "^4.73.0",
|
||||
"@taiga-ui/core": "^4.73.0",
|
||||
"@taiga-ui/i18n": "^4.73.0",
|
||||
"@taiga-ui/kit": "^4.73.0",
|
||||
"@taiga-ui/polymorpheus": "^4.9.0",
|
||||
"@angular/common": ">=19.0.0",
|
||||
"@angular/core": ">=19.0.0",
|
||||
"@ng-web-apis/intersection-observer": "^5.1.0",
|
||||
"@taiga-ui/cdk": "^5.0.0-rc.4",
|
||||
"@taiga-ui/core": "^5.0.0-rc.4",
|
||||
"@taiga-ui/i18n": "^5.0.0-rc.4",
|
||||
"@taiga-ui/kit": "^5.0.0-rc.4",
|
||||
"@taiga-ui/polymorpheus": "^5.0.0",
|
||||
"rxjs": ">=7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@taiga-ui/cdk": {
|
||||
"version": "4.73.0",
|
||||
"resolved": "https://registry.npmjs.org/@taiga-ui/cdk/-/cdk-4.73.0.tgz",
|
||||
"integrity": "sha512-bNRr5ORof60KevnMINNhbLbj8U9xgEMNvagzTtrtjVfEvCOJE1/+ufCnWjjkEdT/V0fDnbuhKsu16ngctbOhXQ==",
|
||||
"version": "5.0.0-rc.4",
|
||||
"resolved": "https://registry.npmjs.org/@taiga-ui/cdk/-/cdk-5.0.0-rc.4.tgz",
|
||||
"integrity": "sha512-eZhqZvK8OE+alI5zJ3z0bQdufj77HCtREOC+Wsv5Fjz1mRZz4X19V3hpISfb6arp1m7kBfIscaPcZi0MuTcbUg==",
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"tslib": "2.8.1"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@angular-devkit/core": ">=16.0.0",
|
||||
"@angular-devkit/schematics": ">=16.0.0",
|
||||
"@schematics/angular": ">=16.0.0",
|
||||
"@angular-devkit/core": ">=19.0.0",
|
||||
"@angular-devkit/schematics": ">=19.0.0",
|
||||
"@schematics/angular": ">=19.0.0",
|
||||
"ng-morph": "^4.8.4",
|
||||
"parse5": "^7.3.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@angular/animations": ">=16.0.0",
|
||||
"@angular/cdk": ">=16.0.0",
|
||||
"@angular/common": ">=16.0.0",
|
||||
"@angular/core": ">=16.0.0",
|
||||
"@angular/forms": ">=16.0.0",
|
||||
"@ng-web-apis/common": "^4.14.0",
|
||||
"@ng-web-apis/mutation-observer": "^4.14.0",
|
||||
"@ng-web-apis/platform": "^4.14.0",
|
||||
"@ng-web-apis/resize-observer": "^4.14.0",
|
||||
"@ng-web-apis/screen-orientation": "^4.14.0",
|
||||
"@taiga-ui/event-plugins": "^4.7.0",
|
||||
"@taiga-ui/font-watcher": "~0.3.0",
|
||||
"@taiga-ui/polymorpheus": "^4.9.0",
|
||||
"@angular/cdk": ">=19.0.0",
|
||||
"@angular/common": ">=19.0.0",
|
||||
"@angular/core": ">=19.0.0",
|
||||
"@angular/forms": ">=19.0.0",
|
||||
"@ng-web-apis/common": "^5.1.0",
|
||||
"@ng-web-apis/mutation-observer": "^5.1.0",
|
||||
"@ng-web-apis/platform": "^5.1.0",
|
||||
"@ng-web-apis/resize-observer": "^5.1.0",
|
||||
"@ng-web-apis/screen-orientation": "^5.1.0",
|
||||
"@taiga-ui/event-plugins": "^5.0.0",
|
||||
"@taiga-ui/font-watcher": "~0.5.0",
|
||||
"@taiga-ui/polymorpheus": "^5.0.0",
|
||||
"rxjs": ">=7.0.0"
|
||||
}
|
||||
},
|
||||
@@ -4324,49 +4307,59 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@taiga-ui/core": {
|
||||
"version": "4.73.0",
|
||||
"resolved": "https://registry.npmjs.org/@taiga-ui/core/-/core-4.73.0.tgz",
|
||||
"integrity": "sha512-8EyHWgenkWxdfRP1LtqkE/bV/9a3mK8MtVmFxauEjcbeyafnE6MJ7K2KgD+iU9TZsOdH7nuWiA44Sv14t1wcUA==",
|
||||
"version": "5.0.0-rc.4",
|
||||
"resolved": "https://registry.npmjs.org/@taiga-ui/core/-/core-5.0.0-rc.4.tgz",
|
||||
"integrity": "sha512-mO1W/4Y743pk3dDg539J3rbAJ5CzNDU+EBCAxYV4wOftpFeSJuCFYvATt6p8XGHtTRCDk6dNXQ1+fkR7PqQ9Yg==",
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"tslib": ">=2.8.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@angular/animations": ">=16.0.0",
|
||||
"@angular/common": ">=16.0.0",
|
||||
"@angular/core": ">=16.0.0",
|
||||
"@angular/forms": ">=16.0.0",
|
||||
"@angular/platform-browser": ">=16.0.0",
|
||||
"@angular/router": ">=16.0.0",
|
||||
"@ng-web-apis/common": "^4.14.0",
|
||||
"@ng-web-apis/mutation-observer": "^4.14.0",
|
||||
"@taiga-ui/cdk": "^4.73.0",
|
||||
"@taiga-ui/event-plugins": "^4.7.0",
|
||||
"@taiga-ui/i18n": "^4.73.0",
|
||||
"@taiga-ui/polymorpheus": "^4.9.0",
|
||||
"@angular/common": ">=19.0.0",
|
||||
"@angular/core": ">=19.0.0",
|
||||
"@angular/forms": ">=19.0.0",
|
||||
"@angular/platform-browser": ">=19.0.0",
|
||||
"@angular/router": ">=19.0.0",
|
||||
"@ng-web-apis/common": "^5.1.0",
|
||||
"@ng-web-apis/mutation-observer": "^5.1.0",
|
||||
"@ng-web-apis/platform": "^5.1.0",
|
||||
"@taiga-ui/cdk": "^5.0.0-rc.4",
|
||||
"@taiga-ui/event-plugins": "^5.0.0",
|
||||
"@taiga-ui/i18n": "^5.0.0-rc.4",
|
||||
"@taiga-ui/polymorpheus": "^5.0.0",
|
||||
"@taiga-ui/styles": "^5.0.0-rc.4",
|
||||
"rxjs": ">=7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@taiga-ui/design-tokens": {
|
||||
"version": "0.283.0",
|
||||
"resolved": "https://registry.npmjs.org/@taiga-ui/design-tokens/-/design-tokens-0.283.0.tgz",
|
||||
"integrity": "sha512-fuLJYwY5a499hh4Cw+ABcO5bEdhcVP8l/1t6GQZApV6L1NfFQgmnf16vbtvGe/0TFCALpoydUGnELtZuwnrRiA==",
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"tslib": "^2.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@taiga-ui/dompurify": {
|
||||
"version": "4.1.11",
|
||||
"resolved": "https://registry.npmjs.org/@taiga-ui/dompurify/-/dompurify-4.1.11.tgz",
|
||||
"integrity": "sha512-nwskeI/wFe+spuLQdkhVCn/GJBHJamxZ5deZuyto7C4I3O+pF8GaCNJdKM1YG5TZyGz932Qm8uNtBVZ/fZX8sQ==",
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@taiga-ui/dompurify/-/dompurify-5.0.1.tgz",
|
||||
"integrity": "sha512-5OdVzGRMEiy1g/WZUtbPbBt3f7A1lGDWFOm9a4MZGZrGhONv2++uIKLDBkOQchY8ur09vo+QC/pBSRGCIgeQ+g==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"tslib": "^2.8.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@angular/core": ">=16.0.0",
|
||||
"@angular/platform-browser": ">=16.0.0",
|
||||
"@types/dompurify": "3.0.5",
|
||||
"dompurify": "3.1.7"
|
||||
"@angular/core": ">=19.0.0",
|
||||
"@angular/platform-browser": ">=19.0.0",
|
||||
"dompurify": "^3.2.7"
|
||||
}
|
||||
},
|
||||
"node_modules/@taiga-ui/event-plugins": {
|
||||
"version": "4.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@taiga-ui/event-plugins/-/event-plugins-4.7.0.tgz",
|
||||
"integrity": "sha512-j3HPRPR7XxKxgMeytb+r/CNUoLBMVrfdfL8KJr1XiFO9jyEvoC4chFXDXWlkGyUHJIC6wy5VIXlIlI/kpqOiGg==",
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@taiga-ui/event-plugins/-/event-plugins-5.0.0.tgz",
|
||||
"integrity": "sha512-8AxIUn/lX4kwuDlIFmhElgBNtGDgQVC9/F+3O2A29IcMSt9693KRi8qKwToe9p3UuUsT9nnj5YeE11BtJMG0wA==",
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
@@ -4379,116 +4372,128 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@taiga-ui/experimental": {
|
||||
"version": "4.73.0",
|
||||
"resolved": "https://registry.npmjs.org/@taiga-ui/experimental/-/experimental-4.73.0.tgz",
|
||||
"integrity": "sha512-OFRO4rhWY780gf/iMip7sJJ1BBT2rWG5663Qqu/+6SAF4pyzcgKq5uIAkULQYFBQwqBNyB0zAx3fZAqdQ8m34A==",
|
||||
"version": "5.0.0-rc.4",
|
||||
"resolved": "https://registry.npmjs.org/@taiga-ui/experimental/-/experimental-5.0.0-rc.4.tgz",
|
||||
"integrity": "sha512-/kw2uLivfeaNse8DkBABPNpTu3GiZ2R7JB0exBK0Flv0xZ3zZLRuIOMK2uHQqoc3v1zgQaFukXTz6CWuzUJYDA==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"tslib": ">=2.8.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@angular/common": ">=16.0.0",
|
||||
"@angular/core": ">=16.0.0",
|
||||
"@taiga-ui/addon-commerce": "^4.73.0",
|
||||
"@taiga-ui/cdk": "^4.73.0",
|
||||
"@taiga-ui/core": "^4.73.0",
|
||||
"@taiga-ui/kit": "^4.73.0",
|
||||
"@taiga-ui/layout": "^4.73.0",
|
||||
"@taiga-ui/polymorpheus": "^4.9.0",
|
||||
"@angular/common": ">=19.0.0",
|
||||
"@angular/core": ">=19.0.0",
|
||||
"@taiga-ui/addon-commerce": "^5.0.0-rc.4",
|
||||
"@taiga-ui/cdk": "^5.0.0-rc.4",
|
||||
"@taiga-ui/core": "^5.0.0-rc.4",
|
||||
"@taiga-ui/kit": "^5.0.0-rc.4",
|
||||
"@taiga-ui/layout": "^5.0.0-rc.4",
|
||||
"@taiga-ui/polymorpheus": "^5.0.0",
|
||||
"rxjs": ">=7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@taiga-ui/font-watcher": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@taiga-ui/font-watcher/-/font-watcher-0.3.0.tgz",
|
||||
"integrity": "sha512-ldI8XMvpVQEfxtcCzbLKs02QbqyB+qJKHIV/x19Q5mxs+kqrS3Pzm3j4mt8tPnuWhgi4+PHvAk3QLN9zmwcoJg==",
|
||||
"version": "0.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@taiga-ui/font-watcher/-/font-watcher-0.5.0.tgz",
|
||||
"integrity": "sha512-9QBUh3XT6KOS+pKVy4ggr0CxgiZtbDYlterUNcfXw8cswkIkiUl5VGDQdvmta60iPHqOrOd/Z/7aAUom35vX/g==",
|
||||
"license": "Apache-2.0",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/@taiga-ui/i18n": {
|
||||
"version": "4.73.0",
|
||||
"resolved": "https://registry.npmjs.org/@taiga-ui/i18n/-/i18n-4.73.0.tgz",
|
||||
"integrity": "sha512-nU7pXeH3+mwQdWZCnXILDAZhRcQ4L/Gl+Y/G/yFpvkEfoCljhVsY0HZZgMSAEGfOSeS7R0ZhZX+9be6uHUvn4w==",
|
||||
"version": "5.0.0-rc.4",
|
||||
"resolved": "https://registry.npmjs.org/@taiga-ui/i18n/-/i18n-5.0.0-rc.4.tgz",
|
||||
"integrity": "sha512-3hxhfewlY+5vsLPPl47rtlt47iVqnhDI2uD6waUm0ZqL/0YLhTEowkY2/DHhXoFp4+ZVcyTVRCWGf0G7BnJG+Q==",
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"tslib": ">=2.8.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@angular/core": ">=16.0.0",
|
||||
"@ng-web-apis/common": "^4.14.0",
|
||||
"@angular/core": ">=19.0.0",
|
||||
"@ng-web-apis/common": "^5.1.0",
|
||||
"rxjs": ">=7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@taiga-ui/icons": {
|
||||
"version": "4.73.0",
|
||||
"resolved": "https://registry.npmjs.org/@taiga-ui/icons/-/icons-4.73.0.tgz",
|
||||
"integrity": "sha512-Ae8qTTf18OlAyFgv04aDkQ6T81J0c8NtFtGWMbNnNc2/CtVt2s0e7z6dcAvs0LODNidzXU6jn/OQT4w4PeAe+w==",
|
||||
"version": "5.0.0-rc.4",
|
||||
"resolved": "https://registry.npmjs.org/@taiga-ui/icons/-/icons-5.0.0-rc.4.tgz",
|
||||
"integrity": "sha512-2MZLcSf8x2+5yizWVdW9Ual6++zdzU64MXWeBx8zlNVyeedxTww5AFbVFs16ItaeT4YdZM0uZmRY59TmnCP9Rg==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"tslib": "^2.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@taiga-ui/kit": {
|
||||
"version": "4.73.0",
|
||||
"resolved": "https://registry.npmjs.org/@taiga-ui/kit/-/kit-4.73.0.tgz",
|
||||
"integrity": "sha512-8dypi4hZLi0GEFuraQERLNyKbR56BqQjU7c6p9x7X7iiMt4LpHUVH9+kd+e9irGWMr09SWLx4PFNV+q+T1c8TQ==",
|
||||
"version": "5.0.0-rc.4",
|
||||
"resolved": "https://registry.npmjs.org/@taiga-ui/kit/-/kit-5.0.0-rc.4.tgz",
|
||||
"integrity": "sha512-MzK8tSzEl0dkhWcuKxmem/DSF+NnPvsNWJyGEx7hJO3IH0Ukcu806YfsSUld392U/7PZePAFRWKgMADdkQY29g==",
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"tslib": ">=2.8.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@angular/common": ">=16.0.0",
|
||||
"@angular/core": ">=16.0.0",
|
||||
"@angular/forms": ">=16.0.0",
|
||||
"@angular/router": ">=16.0.0",
|
||||
"@maskito/angular": "^3.11.1",
|
||||
"@maskito/core": "^3.11.1",
|
||||
"@maskito/kit": "^3.11.1",
|
||||
"@maskito/phone": "^3.11.1",
|
||||
"@ng-web-apis/common": "^4.14.0",
|
||||
"@ng-web-apis/intersection-observer": "^4.14.0",
|
||||
"@ng-web-apis/mutation-observer": "^4.14.0",
|
||||
"@ng-web-apis/resize-observer": "^4.14.0",
|
||||
"@taiga-ui/cdk": "^4.73.0",
|
||||
"@taiga-ui/core": "^4.73.0",
|
||||
"@taiga-ui/i18n": "^4.73.0",
|
||||
"@taiga-ui/polymorpheus": "^4.9.0",
|
||||
"@angular/common": ">=19.0.0",
|
||||
"@angular/core": ">=19.0.0",
|
||||
"@angular/forms": ">=19.0.0",
|
||||
"@angular/router": ">=19.0.0",
|
||||
"@maskito/angular": "^5.1.1",
|
||||
"@maskito/core": "^5.1.1",
|
||||
"@maskito/kit": "^5.1.1",
|
||||
"@maskito/phone": "^5.1.1",
|
||||
"@ng-web-apis/common": "^5.1.0",
|
||||
"@ng-web-apis/intersection-observer": "^5.1.0",
|
||||
"@ng-web-apis/mutation-observer": "^5.1.0",
|
||||
"@ng-web-apis/platform": "^5.1.0",
|
||||
"@ng-web-apis/resize-observer": "^5.1.0",
|
||||
"@taiga-ui/cdk": "^5.0.0-rc.4",
|
||||
"@taiga-ui/core": "^5.0.0-rc.4",
|
||||
"@taiga-ui/i18n": "^5.0.0-rc.4",
|
||||
"@taiga-ui/polymorpheus": "^5.0.0",
|
||||
"@taiga-ui/styles": "^5.0.0-rc.4",
|
||||
"rxjs": ">=7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@taiga-ui/layout": {
|
||||
"version": "4.73.0",
|
||||
"resolved": "https://registry.npmjs.org/@taiga-ui/layout/-/layout-4.73.0.tgz",
|
||||
"integrity": "sha512-JX2DRCdGw3ayvW07RtI7MjrceO7m7/0wj2RfkjT2Pa93elWooS85lDVy88tlVfcfm/bV2ZGwbemyecAwNjk/yQ==",
|
||||
"version": "5.0.0-rc.4",
|
||||
"resolved": "https://registry.npmjs.org/@taiga-ui/layout/-/layout-5.0.0-rc.4.tgz",
|
||||
"integrity": "sha512-sKuksa89xxeIHgx3QchpTorySsjz+XMhcYi5ix/Mh/u+vgDxrcLCYGWAx9fcG/3mGTaCIIEMfaEQDs28jb9Ptw==",
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"tslib": ">=2.8.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@angular/common": ">=16.0.0",
|
||||
"@angular/core": ">=16.0.0",
|
||||
"@taiga-ui/cdk": "^4.73.0",
|
||||
"@taiga-ui/core": "^4.73.0",
|
||||
"@taiga-ui/kit": "^4.73.0",
|
||||
"@taiga-ui/polymorpheus": "^4.9.0",
|
||||
"@angular/common": ">=19.0.0",
|
||||
"@angular/core": ">=19.0.0",
|
||||
"@taiga-ui/cdk": "^5.0.0-rc.4",
|
||||
"@taiga-ui/core": "^5.0.0-rc.4",
|
||||
"@taiga-ui/kit": "^5.0.0-rc.4",
|
||||
"@taiga-ui/polymorpheus": "^5.0.0",
|
||||
"rxjs": ">=7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@taiga-ui/polymorpheus": {
|
||||
"version": "4.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@taiga-ui/polymorpheus/-/polymorpheus-4.9.0.tgz",
|
||||
"integrity": "sha512-TbIIwslbEnxunKuL9OyPZdmefrvJEK6HYiADEKQHUMUs4Pk2UbhMckUieURo83yPDamk/Mww+Nu/g60J/4uh2w==",
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@taiga-ui/polymorpheus/-/polymorpheus-5.0.0.tgz",
|
||||
"integrity": "sha512-FRus7OgxYyRuETB17g1/YXYs8PAeF4x8+K4ZDfD3Ede8Vxv/XslAYZvf/Ro0wag6Uiy0kAP4bvSaIGPS1Y8Fyg==",
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"tslib": "^2.8.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@angular/core": ">=16.0.0",
|
||||
"@angular/platform-browser": ">=16.0.0"
|
||||
"@angular/core": ">=19.0.0",
|
||||
"@angular/platform-browser": ">=19.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@taiga-ui/styles": {
|
||||
"version": "5.0.0-rc.4",
|
||||
"resolved": "https://registry.npmjs.org/@taiga-ui/styles/-/styles-5.0.0-rc.4.tgz",
|
||||
"integrity": "sha512-xAiHSlVFIv6Ti5BEE3AIkjt0zUW5jibeWnB+P7I9D7+E3vV0n/XlpX0SBHKK6DMdrVaPgURzNQnjSrwwtmkWxQ==",
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"peerDependencies": {
|
||||
"@taiga-ui/design-tokens": "~0.283.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@ts-morph/common": {
|
||||
@@ -4622,15 +4627,12 @@
|
||||
"tslib": "^2.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/dompurify": {
|
||||
"version": "3.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/dompurify/-/dompurify-3.0.5.tgz",
|
||||
"integrity": "sha512-1Wg0g3BtQF7sSb27fJQAKck1HECM6zV1EB66j8JH9i3LCjYabJa0FSdiSgsD5K/RbrsR0SiraKacLB+T8ZVYAg==",
|
||||
"node_modules/@types/dom-speech-recognition": {
|
||||
"version": "0.0.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/dom-speech-recognition/-/dom-speech-recognition-0.0.7.tgz",
|
||||
"integrity": "sha512-NjiUoJbBlKhyufNsMZLSp+pbPNtPAFnR738RCJvtZy/HVQ2TZjmqpMyaeOSMXgxdfZM60nt8QGbtfmQrJAH2sw==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@types/trusted-types": "*"
|
||||
}
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/@types/estree": {
|
||||
"version": "0.0.51",
|
||||
@@ -4715,7 +4717,8 @@
|
||||
"version": "2.0.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz",
|
||||
"integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==",
|
||||
"license": "MIT"
|
||||
"license": "MIT",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/@types/uuid": {
|
||||
"version": "8.3.4",
|
||||
@@ -6089,11 +6092,17 @@
|
||||
}
|
||||
},
|
||||
"node_modules/dompurify": {
|
||||
"version": "3.1.7",
|
||||
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.1.7.tgz",
|
||||
"integrity": "sha512-VaTstWtsneJY8xzy7DekmYWEOZcmzIe3Qb3zPd4STve1OBTa+e+WmS1ITQec1fZYXI3HCsOZZiSMpG6oxoWMWQ==",
|
||||
"version": "3.3.2",
|
||||
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.3.2.tgz",
|
||||
"integrity": "sha512-6obghkliLdmKa56xdbLOpUZ43pAR6xFy1uOrxBaIDjT+yaRuuybLjGS9eVBoSR/UPU5fq3OXClEHLJNGvbxKpQ==",
|
||||
"license": "(MPL-2.0 OR Apache-2.0)",
|
||||
"peer": true
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@types/trusted-types": "^2.0.7"
|
||||
}
|
||||
},
|
||||
"node_modules/domutils": {
|
||||
"version": "3.2.2",
|
||||
@@ -8025,9 +8034,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/libphonenumber-js": {
|
||||
"version": "1.12.36",
|
||||
"resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.12.36.tgz",
|
||||
"integrity": "sha512-woWhKMAVx1fzzUnMCyOzglgSgf6/AFHLASdOBcchYCyvWSGWt12imw3iu2hdI5d4dGZRsNWAmWiz37sDKUPaRQ==",
|
||||
"version": "1.12.38",
|
||||
"resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.12.38.tgz",
|
||||
"integrity": "sha512-vwzxmasAy9hZigxtqTbFEwp8ZdZ975TiqVDwj5bKx5sR+zi5ucUQy9mbVTkKM9GzqdLdxux/hTw2nmN5J7POMA==",
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
|
||||
@@ -33,7 +33,6 @@
|
||||
"format:check": "prettier --check projects/"
|
||||
},
|
||||
"dependencies": {
|
||||
"@angular/animations": "^21.2.1",
|
||||
"@angular/cdk": "^21.2.1",
|
||||
"@angular/common": "^21.2.1",
|
||||
"@angular/compiler": "^21.2.1",
|
||||
@@ -48,19 +47,19 @@
|
||||
"@noble/hashes": "^1.4.0",
|
||||
"@start9labs/argon2": "^0.3.0",
|
||||
"@start9labs/start-sdk": "file:../sdk/baseDist",
|
||||
"@taiga-ui/addon-charts": "4.73.0",
|
||||
"@taiga-ui/addon-commerce": "4.73.0",
|
||||
"@taiga-ui/addon-mobile": "4.73.0",
|
||||
"@taiga-ui/addon-table": "4.73.0",
|
||||
"@taiga-ui/cdk": "4.73.0",
|
||||
"@taiga-ui/core": "4.73.0",
|
||||
"@taiga-ui/dompurify": "4.1.11",
|
||||
"@taiga-ui/event-plugins": "4.7.0",
|
||||
"@taiga-ui/experimental": "4.73.0",
|
||||
"@taiga-ui/icons": "4.73.0",
|
||||
"@taiga-ui/kit": "4.73.0",
|
||||
"@taiga-ui/layout": "4.73.0",
|
||||
"@taiga-ui/polymorpheus": "4.9.0",
|
||||
"@taiga-ui/addon-charts": "5.0.0-rc.4",
|
||||
"@taiga-ui/addon-commerce": "5.0.0-rc.4",
|
||||
"@taiga-ui/addon-mobile": "5.0.0-rc.4",
|
||||
"@taiga-ui/addon-table": "5.0.0-rc.4",
|
||||
"@taiga-ui/cdk": "5.0.0-rc.4",
|
||||
"@taiga-ui/core": "5.0.0-rc.4",
|
||||
"@taiga-ui/dompurify": "5.0.1",
|
||||
"@taiga-ui/event-plugins": "5.0.0",
|
||||
"@taiga-ui/experimental": "5.0.0-rc.4",
|
||||
"@taiga-ui/icons": "5.0.0-rc.4",
|
||||
"@taiga-ui/kit": "5.0.0-rc.4",
|
||||
"@taiga-ui/layout": "5.0.0-rc.4",
|
||||
"@taiga-ui/polymorpheus": "5.0.0",
|
||||
"ansi-to-html": "^0.7.2",
|
||||
"base64-js": "^1.5.1",
|
||||
"buffer": "^6.0.3",
|
||||
@@ -70,7 +69,7 @@
|
||||
"cron": "^2.2.0",
|
||||
"cronstrue": "^2.21.0",
|
||||
"deep-equality-data-structures": "1.5.1",
|
||||
"dompurify": "^3.1.7",
|
||||
"dompurify": "^3.3.2",
|
||||
"fast-json-patch": "^3.1.1",
|
||||
"fuse.js": "^6.4.6",
|
||||
"jose": "^4.9.0",
|
||||
@@ -95,7 +94,6 @@
|
||||
"@angular/cli": "^21.2.1",
|
||||
"@angular/compiler-cli": "^21.2.1",
|
||||
"@angular/language-service": "^21.2.1",
|
||||
"@types/dompurify": "3.0.5",
|
||||
"@types/estree": "^0.0.51",
|
||||
"@types/js-yaml": "^4.0.5",
|
||||
"@types/marked": "^4.0.3",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@use '@taiga-ui/core/styles/taiga-ui-local' as taiga;
|
||||
@use '@taiga-ui/styles/utils' as taiga;
|
||||
|
||||
:host {
|
||||
margin: 0;
|
||||
|
||||
@@ -15,12 +15,9 @@ import { MarketplacePkgBase } from '../../../types'
|
||||
selector: 'marketplace-dep-item',
|
||||
template: `
|
||||
<div class="outer-container">
|
||||
<tui-avatar
|
||||
appearance="action-grayscale"
|
||||
class="dep-img"
|
||||
size="l"
|
||||
[src]="getImage(dep.key)"
|
||||
/>
|
||||
<span tuiAvatar appearance="action-grayscale" class="dep-img" size="l">
|
||||
<img alt="" [src]="getImage(dep.key)" />
|
||||
</span>
|
||||
<div>
|
||||
<tui-line-clamp [linesLimit]="2" [content]="titleContent" />
|
||||
<ng-template #titleContent>
|
||||
@@ -107,8 +104,10 @@ export class MarketplaceDepItemComponent {
|
||||
dep!: KeyValue<string, T.DependencyMetadata>
|
||||
|
||||
getImage(key: string) {
|
||||
const icon = this.pkg.dependencyMetadata[key]?.icon
|
||||
return icon ? icon : 'assets/img/service-icons/fallback.png'
|
||||
return (
|
||||
this.pkg.dependencyMetadata[key]?.icon ||
|
||||
'assets/img/service-icons/fallback.png'
|
||||
)
|
||||
}
|
||||
|
||||
getTitle(key: string): string {
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
import { ChangeDetectionStrategy, Component, Input } from '@angular/core'
|
||||
import { RouterLink } from '@angular/router'
|
||||
import { i18nPipe, TrustUrlPipe } from '@start9labs/shared'
|
||||
import { TuiTitle } from '@taiga-ui/core'
|
||||
import { TuiTitle, TuiCell } from '@taiga-ui/core'
|
||||
import { TuiAvatar } from '@taiga-ui/kit'
|
||||
import { TuiCell } from '@taiga-ui/layout'
|
||||
import { MarketplacePkg } from '../../types'
|
||||
|
||||
@Component({
|
||||
@@ -21,10 +20,9 @@ import { MarketplacePkg } from '../../types'
|
||||
[queryParams]="{ id: pkg.id, flavor: pkg.flavor }"
|
||||
queryParamsHandling="merge"
|
||||
>
|
||||
<tui-avatar
|
||||
appearance="action-grayscale"
|
||||
[src]="pkg.icon | trustUrl"
|
||||
/>
|
||||
<span tuiAvatar appearance="action-grayscale">
|
||||
<img alt="" [src]="pkg.icon | trustUrl" />
|
||||
</span>
|
||||
<span tuiTitle>
|
||||
{{ pkg.title }}
|
||||
<span tuiSubtitle>{{ pkg.version }}</span>
|
||||
|
||||
@@ -4,7 +4,7 @@ import {
|
||||
inject,
|
||||
Input,
|
||||
} from '@angular/core'
|
||||
import { TUI_IS_MOBILE } from '@taiga-ui/cdk'
|
||||
import { WA_IS_MOBILE } from '@ng-web-apis/platform'
|
||||
import { TuiButton, TuiDialogContext, TuiDialogService } from '@taiga-ui/core'
|
||||
import { TuiCarousel } from '@taiga-ui/kit'
|
||||
import { PolymorpheusContent } from '@taiga-ui/polymorpheus'
|
||||
@@ -130,7 +130,7 @@ export class MarketplacePackageScreenshotComponent {
|
||||
|
||||
index = 0
|
||||
|
||||
isMobile = inject(TUI_IS_MOBILE)
|
||||
isMobile = inject(WA_IS_MOBILE)
|
||||
|
||||
presentModalImg(content: PolymorpheusContent<TuiDialogContext>) {
|
||||
this.dialogs
|
||||
|
||||
@@ -8,7 +8,7 @@ import { StateService } from './services/state.service'
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
template: '<tui-root tuiTheme="dark"><router-outlet /></tui-root>',
|
||||
template: '<tui-root><router-outlet /></tui-root>',
|
||||
imports: [TuiRoot, RouterOutlet],
|
||||
})
|
||||
export class AppComponent implements OnInit {
|
||||
|
||||
@@ -10,7 +10,6 @@ import {
|
||||
provideZoneChangeDetection,
|
||||
signal,
|
||||
} from '@angular/core'
|
||||
import { provideAnimations } from '@angular/platform-browser/animations'
|
||||
import {
|
||||
PreloadAllModules,
|
||||
provideRouter,
|
||||
@@ -29,8 +28,10 @@ import {
|
||||
import {
|
||||
tuiButtonOptionsProvider,
|
||||
tuiTextfieldOptionsProvider,
|
||||
provideTaiga,
|
||||
tuiHintOptionsProvider,
|
||||
tuiDialogOptionsProvider,
|
||||
} from '@taiga-ui/core'
|
||||
import { provideEventPlugins } from '@taiga-ui/event-plugins'
|
||||
|
||||
import { ROUTES } from './app.routes'
|
||||
import { ApiService } from './services/api.service'
|
||||
@@ -47,8 +48,9 @@ const version = require('../../../../package.json').version
|
||||
export const APP_CONFIG: ApplicationConfig = {
|
||||
providers: [
|
||||
provideZoneChangeDetection(),
|
||||
provideAnimations(),
|
||||
provideEventPlugins(),
|
||||
provideTaiga({ mode: 'dark' }),
|
||||
tuiHintOptionsProvider({ appearance: 'primary-grayscale' }),
|
||||
tuiDialogOptionsProvider({ size: 's' }),
|
||||
provideRouter(
|
||||
ROUTES,
|
||||
withDisabledInitialNavigation(),
|
||||
|
||||
@@ -13,14 +13,10 @@ import {
|
||||
TuiDialogContext,
|
||||
TuiError,
|
||||
TuiIcon,
|
||||
TuiTextfield,
|
||||
TuiInput,
|
||||
tuiValidationErrorsProvider,
|
||||
} from '@taiga-ui/core'
|
||||
import {
|
||||
TUI_VALIDATION_ERRORS,
|
||||
TuiButtonLoading,
|
||||
TuiFieldErrorPipe,
|
||||
TuiPassword,
|
||||
} from '@taiga-ui/kit'
|
||||
import { TuiButtonLoading, TuiPassword } from '@taiga-ui/kit'
|
||||
import { injectContext, PolymorpheusComponent } from '@taiga-ui/polymorpheus'
|
||||
import { ApiService } from '../services/api.service'
|
||||
import { StartOSDiskInfoWithId } from '../types'
|
||||
@@ -36,42 +32,36 @@ export interface CifsResult {
|
||||
<tui-textfield>
|
||||
<label tuiLabel>{{ 'Hostname' | i18n }}*</label>
|
||||
<input
|
||||
tuiTextfield
|
||||
tuiInput
|
||||
formControlName="hostname"
|
||||
placeholder="e.g. 'My Computer' OR 'my-computer.local'"
|
||||
/>
|
||||
</tui-textfield>
|
||||
<tui-error
|
||||
formControlName="hostname"
|
||||
[error]="['required'] | tuiFieldError | async"
|
||||
/>
|
||||
<tui-error formControlName="hostname" [order]="['required']" />
|
||||
|
||||
<tui-textfield class="input">
|
||||
<label tuiLabel>{{ 'Path' | i18n }}*</label>
|
||||
<input
|
||||
tuiTextfield
|
||||
tuiInput
|
||||
formControlName="path"
|
||||
placeholder="/Desktop/my-folder"
|
||||
/>
|
||||
</tui-textfield>
|
||||
<tui-error formControlName="path" [error]="[] | tuiFieldError | async" />
|
||||
<tui-error formControlName="path" />
|
||||
|
||||
<tui-textfield class="input">
|
||||
<label tuiLabel>{{ 'Username' | i18n }}*</label>
|
||||
<input
|
||||
tuiTextfield
|
||||
tuiInput
|
||||
formControlName="username"
|
||||
placeholder="Enter username"
|
||||
/>
|
||||
</tui-textfield>
|
||||
<tui-error
|
||||
formControlName="username"
|
||||
[error]="[] | tuiFieldError | async"
|
||||
/>
|
||||
<tui-error formControlName="username" />
|
||||
|
||||
<tui-textfield class="input">
|
||||
<label tuiLabel>{{ 'Password' | i18n }}</label>
|
||||
<input tuiTextfield type="password" formControlName="password" />
|
||||
<input tuiInput type="password" formControlName="password" />
|
||||
<tui-icon tuiPassword />
|
||||
</tui-textfield>
|
||||
|
||||
@@ -107,20 +97,16 @@ export interface CifsResult {
|
||||
ReactiveFormsModule,
|
||||
TuiButton,
|
||||
TuiButtonLoading,
|
||||
TuiTextfield,
|
||||
TuiInput,
|
||||
TuiPassword,
|
||||
TuiError,
|
||||
TuiFieldErrorPipe,
|
||||
TuiIcon,
|
||||
i18nPipe,
|
||||
],
|
||||
providers: [
|
||||
{
|
||||
provide: TUI_VALIDATION_ERRORS,
|
||||
useValue: {
|
||||
required: 'This field is required',
|
||||
},
|
||||
},
|
||||
tuiValidationErrorsProvider({
|
||||
required: 'This field is required',
|
||||
}),
|
||||
],
|
||||
})
|
||||
export class CifsComponent {
|
||||
@@ -183,10 +169,7 @@ export class CifsComponent {
|
||||
this.dialogs
|
||||
.openAlert(
|
||||
'Unable to connect to network folder. Ensure (1) target computer is connected to LAN, (2) target folder is being shared, and (3) hostname, path, and credentials are accurate.',
|
||||
{
|
||||
label: 'Connection Failed',
|
||||
size: 's',
|
||||
},
|
||||
{ label: 'Connection Failed' },
|
||||
)
|
||||
.subscribe()
|
||||
}
|
||||
|
||||
@@ -1,13 +1,19 @@
|
||||
import { Component, inject } from '@angular/core'
|
||||
import { Component } from '@angular/core'
|
||||
import { i18nPipe } from '@start9labs/shared'
|
||||
import { TuiButton } from '@taiga-ui/core'
|
||||
import { TuiButton, TuiTitle } from '@taiga-ui/core'
|
||||
import { TuiDialogContext } from '@taiga-ui/core'
|
||||
import { injectContext } from '@taiga-ui/polymorpheus'
|
||||
import { TuiHeader } from '@taiga-ui/layout'
|
||||
import { injectContext, PolymorpheusComponent } from '@taiga-ui/polymorpheus'
|
||||
|
||||
@Component({
|
||||
imports: [TuiButton, i18nPipe],
|
||||
imports: [TuiButton, TuiHeader, TuiTitle, i18nPipe],
|
||||
template: `
|
||||
<p>{{ 'This drive contains existing StartOS data.' | i18n }}</p>
|
||||
<header tuiHeader>
|
||||
<hgroup tuiTitle>
|
||||
<h2 [id]="context.id">{{ 'StartOS Data Detected' | i18n }}</h2>
|
||||
<p>{{ 'This drive contains existing StartOS data.' | i18n }}</p>
|
||||
</hgroup>
|
||||
</header>
|
||||
<ul>
|
||||
<li>
|
||||
<strong class="g-positive">{{ 'Preserve' | i18n }}</strong>
|
||||
@@ -28,30 +34,19 @@ import { injectContext } from '@taiga-ui/polymorpheus'
|
||||
</button>
|
||||
<button
|
||||
tuiButton
|
||||
class="preserve-btn"
|
||||
appearance=""
|
||||
[style.background]="'var(--tui-status-positive)'"
|
||||
(click)="context.completeWith(true)"
|
||||
>
|
||||
{{ 'Preserve' | i18n }}
|
||||
</button>
|
||||
</footer>
|
||||
`,
|
||||
styles: `
|
||||
p {
|
||||
margin: 0 0 0.75rem;
|
||||
}
|
||||
|
||||
footer {
|
||||
display: flex;
|
||||
margin-top: 2rem;
|
||||
gap: 0.5rem;
|
||||
flex-direction: column-reverse;
|
||||
}
|
||||
|
||||
.preserve-btn {
|
||||
background: var(--tui-status-positive) !important;
|
||||
}
|
||||
`,
|
||||
})
|
||||
export class PreserveOverwriteDialog {
|
||||
protected readonly context = injectContext<TuiDialogContext<boolean>>()
|
||||
}
|
||||
|
||||
export const PRESERVE_OVERWRITE = new PolymorpheusComponent(
|
||||
PreserveOverwriteDialog,
|
||||
)
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { Component, inject } from '@angular/core'
|
||||
import { Component } from '@angular/core'
|
||||
import { FormsModule } from '@angular/forms'
|
||||
import { i18nPipe } from '@start9labs/shared'
|
||||
import { TuiDialogContext, TuiTextfield } from '@taiga-ui/core'
|
||||
import { TuiDialogContext, TuiTitle } from '@taiga-ui/core'
|
||||
import { TuiDataListWrapper, TuiSelect } from '@taiga-ui/kit'
|
||||
import { TuiHeader } from '@taiga-ui/layout'
|
||||
import { injectContext, PolymorpheusComponent } from '@taiga-ui/polymorpheus'
|
||||
import { StartOSDiskInfoWithId } from '../types'
|
||||
|
||||
@@ -11,36 +12,48 @@ interface Data {
|
||||
}
|
||||
|
||||
@Component({
|
||||
imports: [FormsModule, TuiTextfield, TuiSelect, TuiDataListWrapper, i18nPipe],
|
||||
imports: [
|
||||
FormsModule,
|
||||
TuiSelect,
|
||||
TuiDataListWrapper,
|
||||
i18nPipe,
|
||||
TuiHeader,
|
||||
TuiTitle,
|
||||
],
|
||||
template: `
|
||||
<p>{{ 'Multiple backups found. Select which one to restore.' | i18n }}</p>
|
||||
<header tuiHeader>
|
||||
<hgroup tuiTitle>
|
||||
<h2 [id]="context.id">{{ 'Select Network Backup' | i18n }}</h2>
|
||||
<p>
|
||||
{{ 'Multiple backups found. Select which one to restore.' | i18n }}
|
||||
</p>
|
||||
</hgroup>
|
||||
</header>
|
||||
<tui-textfield [stringify]="stringify">
|
||||
<label tuiLabel>{{ 'Backups' | i18n }}</label>
|
||||
<input tuiSelect [(ngModel)]="selectedServer" />
|
||||
<tui-data-list-wrapper
|
||||
new
|
||||
*tuiTextfieldDropdown
|
||||
*tuiDropdown
|
||||
[items]="context.data.servers"
|
||||
[itemContent]="serverContent"
|
||||
/>
|
||||
</tui-textfield>
|
||||
|
||||
<ng-template #serverContent let-server>
|
||||
<div class="server-item">
|
||||
<span>{{ server.id }}</span>
|
||||
<span tuiTitle>
|
||||
{{ server.id }}
|
||||
<!-- @TODO eos-version? -->
|
||||
<small>{{ server['eos-version'] }}</small>
|
||||
</div>
|
||||
@if (server['eos-version']) {
|
||||
<span tuiSubtitle>
|
||||
{{ server['eos-version'] }}
|
||||
</span>
|
||||
}
|
||||
</span>
|
||||
</ng-template>
|
||||
`,
|
||||
styles: `
|
||||
.server-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
small {
|
||||
opacity: 0.7;
|
||||
}
|
||||
div {
|
||||
margin-block-end: 1rem;
|
||||
}
|
||||
`,
|
||||
})
|
||||
|
||||
@@ -1,32 +1,27 @@
|
||||
import { Component } from '@angular/core'
|
||||
import { FormsModule } from '@angular/forms'
|
||||
import { i18nPipe } from '@start9labs/shared'
|
||||
import {
|
||||
TuiButton,
|
||||
TuiDialogContext,
|
||||
TuiIcon,
|
||||
TuiTextfield,
|
||||
} from '@taiga-ui/core'
|
||||
import { TuiButton, TuiDialogContext, TuiIcon, TuiInput } from '@taiga-ui/core'
|
||||
import { TuiPassword } from '@taiga-ui/kit'
|
||||
import { injectContext } from '@taiga-ui/polymorpheus'
|
||||
import { injectContext, PolymorpheusComponent } from '@taiga-ui/polymorpheus'
|
||||
|
||||
@Component({
|
||||
imports: [
|
||||
FormsModule,
|
||||
TuiButton,
|
||||
TuiTextfield,
|
||||
TuiPassword,
|
||||
TuiIcon,
|
||||
i18nPipe,
|
||||
],
|
||||
imports: [FormsModule, TuiButton, TuiInput, TuiPassword, TuiIcon, i18nPipe],
|
||||
template: `
|
||||
<p>
|
||||
{{ 'Enter the password that was used to encrypt this backup.' | i18n }}
|
||||
</p>
|
||||
<header tuiHeader>
|
||||
<hgroup tuiTitle>
|
||||
<h2 [id]="context.id">{{ 'Unlock Backup' | i18n }}</h2>
|
||||
<p>
|
||||
{{
|
||||
'Enter the password that was used to encrypt this backup.' | i18n
|
||||
}}
|
||||
</p>
|
||||
</hgroup>
|
||||
</header>
|
||||
<tui-textfield>
|
||||
<label tuiLabel>{{ 'Password' | i18n }}</label>
|
||||
<input
|
||||
tuiTextfield
|
||||
tuiInput
|
||||
type="password"
|
||||
[(ngModel)]="password"
|
||||
(keyup.enter)="unlock()"
|
||||
@@ -62,3 +57,5 @@ export class UnlockPasswordDialog {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const UNLOCK_PASSWORD = new PolymorpheusComponent(UnlockPasswordDialog)
|
||||
|
||||
@@ -12,24 +12,29 @@ import {
|
||||
ErrorService,
|
||||
i18nKey,
|
||||
i18nPipe,
|
||||
LoadingService,
|
||||
toGuid,
|
||||
} from '@start9labs/shared'
|
||||
import { TUI_IS_MOBILE } from '@taiga-ui/cdk'
|
||||
import { WA_IS_MOBILE } from '@ng-web-apis/platform'
|
||||
import {
|
||||
TuiButton,
|
||||
TuiIcon,
|
||||
TuiLoader,
|
||||
TuiTextfield,
|
||||
TuiInput,
|
||||
TuiNotification,
|
||||
TuiTitle,
|
||||
} from '@taiga-ui/core'
|
||||
import { TuiDataListWrapper, TuiSelect, TuiTooltip } from '@taiga-ui/kit'
|
||||
import {
|
||||
TuiDataListWrapper,
|
||||
TuiNotificationMiddleService,
|
||||
TuiSelect,
|
||||
TuiTooltip,
|
||||
} from '@taiga-ui/kit'
|
||||
import { TuiCardLarge, TuiHeader } from '@taiga-ui/layout'
|
||||
import { PolymorpheusComponent } from '@taiga-ui/polymorpheus'
|
||||
import { filter, Subscription } from 'rxjs'
|
||||
import { ApiService } from '../services/api.service'
|
||||
import { StateService } from '../services/state.service'
|
||||
import { PreserveOverwriteDialog } from '../components/preserve-overwrite.dialog'
|
||||
import { PRESERVE_OVERWRITE } from '../components/preserve-overwrite.dialog'
|
||||
|
||||
@Component({
|
||||
template: `
|
||||
@@ -42,7 +47,7 @@ import { PreserveOverwriteDialog } from '../components/preserve-overwrite.dialog
|
||||
@if (loading) {
|
||||
<tui-loader />
|
||||
} @else if (drives.length === 0) {
|
||||
<p class="no-drives">
|
||||
<p tuiNotification size="m" appearance="warning">
|
||||
{{
|
||||
'No drives found. Please connect a drive and click Refresh.'
|
||||
| i18n
|
||||
@@ -70,8 +75,7 @@ import { PreserveOverwriteDialog } from '../components/preserve-overwrite.dialog
|
||||
}
|
||||
@if (!mobile) {
|
||||
<tui-data-list-wrapper
|
||||
new
|
||||
*tuiTextfieldDropdown
|
||||
*tuiDropdown
|
||||
[items]="drives"
|
||||
[itemContent]="driveContent"
|
||||
/>
|
||||
@@ -100,36 +104,27 @@ import { PreserveOverwriteDialog } from '../components/preserve-overwrite.dialog
|
||||
}
|
||||
@if (!mobile) {
|
||||
<tui-data-list-wrapper
|
||||
new
|
||||
*tuiTextfieldDropdown
|
||||
*tuiDropdown
|
||||
[items]="drives"
|
||||
[itemContent]="driveContent"
|
||||
/>
|
||||
}
|
||||
@if (preserveData === true) {
|
||||
<tui-icon
|
||||
icon="@tui.database"
|
||||
style="color: var(--tui-status-positive); pointer-events: none"
|
||||
/>
|
||||
<tui-icon icon="@tui.database" class="g-positive" />
|
||||
}
|
||||
@if (preserveData === false) {
|
||||
<tui-icon
|
||||
icon="@tui.database-zap"
|
||||
style="color: var(--tui-status-negative); pointer-events: none"
|
||||
/>
|
||||
<tui-icon icon="@tui.database-zap" class="g-negative" />
|
||||
}
|
||||
<tui-icon [tuiTooltip]="dataDriveTooltip" />
|
||||
</tui-textfield>
|
||||
|
||||
<ng-template #driveContent let-drive>
|
||||
<div class="drive-item">
|
||||
<span class="drive-name">
|
||||
{{ driveName(drive) }}
|
||||
</span>
|
||||
<small>
|
||||
<span tuiTitle>
|
||||
{{ driveName(drive) }}
|
||||
<span tuiSubtitle>
|
||||
{{ formatCapacity(drive.capacity) }} · {{ drive.logicalname }}
|
||||
</small>
|
||||
</div>
|
||||
</span>
|
||||
</span>
|
||||
</ng-template>
|
||||
}
|
||||
|
||||
@@ -152,19 +147,8 @@ import { PreserveOverwriteDialog } from '../components/preserve-overwrite.dialog
|
||||
}
|
||||
`,
|
||||
styles: `
|
||||
.no-drives {
|
||||
text-align: center;
|
||||
color: var(--tui-text-secondary);
|
||||
padding: 2rem;
|
||||
}
|
||||
|
||||
.drive-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
small {
|
||||
opacity: 0.7;
|
||||
}
|
||||
tui-icon:not([tuiTooltip]) {
|
||||
pointer-events: none;
|
||||
}
|
||||
`,
|
||||
imports: [
|
||||
@@ -173,7 +157,8 @@ import { PreserveOverwriteDialog } from '../components/preserve-overwrite.dialog
|
||||
TuiButton,
|
||||
TuiIcon,
|
||||
TuiLoader,
|
||||
TuiTextfield,
|
||||
TuiInput,
|
||||
TuiNotification,
|
||||
TuiSelect,
|
||||
TuiDataListWrapper,
|
||||
TuiTooltip,
|
||||
@@ -186,13 +171,13 @@ export default class DrivesPage {
|
||||
private readonly api = inject(ApiService)
|
||||
private readonly router = inject(Router)
|
||||
private readonly dialogs = inject(DialogService)
|
||||
private readonly loader = inject(LoadingService)
|
||||
private readonly loader = inject(TuiNotificationMiddleService)
|
||||
private readonly errorService = inject(ErrorService)
|
||||
private readonly stateService = inject(StateService)
|
||||
private readonly cdr = inject(ChangeDetectorRef)
|
||||
private readonly i18n = inject(i18nPipe)
|
||||
|
||||
protected readonly mobile = inject(TUI_IS_MOBILE)
|
||||
protected readonly mobile = inject(WA_IS_MOBILE)
|
||||
|
||||
@HostListener('document:keydown', ['$event'])
|
||||
onKeydown(event: KeyboardEvent) {
|
||||
@@ -308,38 +293,27 @@ export default class DrivesPage {
|
||||
private showPreserveOverwriteDialog() {
|
||||
let selectionMade = false
|
||||
|
||||
this.dialogs
|
||||
.openComponent<boolean>(
|
||||
new PolymorpheusComponent(PreserveOverwriteDialog),
|
||||
{
|
||||
label: 'StartOS Data Detected',
|
||||
size: 's',
|
||||
dismissible: true,
|
||||
closeable: true,
|
||||
},
|
||||
)
|
||||
.subscribe({
|
||||
next: preserve => {
|
||||
selectionMade = true
|
||||
this.preserveData = preserve
|
||||
this.dialogs.openComponent<boolean>(PRESERVE_OVERWRITE).subscribe({
|
||||
next: preserve => {
|
||||
selectionMade = true
|
||||
this.preserveData = preserve
|
||||
this.cdr.markForCheck()
|
||||
},
|
||||
complete: () => {
|
||||
if (!selectionMade) {
|
||||
// Dialog was dismissed without selection - clear the data drive
|
||||
this.selectedDataDrive = null
|
||||
this.preserveData = null
|
||||
this.cdr.markForCheck()
|
||||
},
|
||||
complete: () => {
|
||||
if (!selectionMade) {
|
||||
// Dialog was dismissed without selection - clear the data drive
|
||||
this.selectedDataDrive = null
|
||||
this.preserveData = null
|
||||
this.cdr.markForCheck()
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
private showOsDriveWarning() {
|
||||
this.dialogs
|
||||
.openConfirm({
|
||||
label: 'Warning',
|
||||
size: 's',
|
||||
data: {
|
||||
content: `<ul>
|
||||
<li class="g-negative">${this.i18n.transform('Data on the OS drive may be overwritten.')}</li>
|
||||
@@ -363,7 +337,6 @@ export default class DrivesPage {
|
||||
this.dialogs
|
||||
.openConfirm({
|
||||
label: 'Warning',
|
||||
size: 's',
|
||||
data: {
|
||||
content: message as i18nKey,
|
||||
yes: 'Continue',
|
||||
@@ -397,10 +370,9 @@ export default class DrivesPage {
|
||||
this.dialogSub = this.dialogs
|
||||
.openAlert('StartOS has been installed successfully.', {
|
||||
label: 'Installation Complete!',
|
||||
size: 's',
|
||||
dismissible: false,
|
||||
closeable: true,
|
||||
data: { button: this.i18n.transform('Continue to Setup') },
|
||||
closable: true,
|
||||
data: this.i18n.transform('Continue to Setup'),
|
||||
})
|
||||
.subscribe({
|
||||
complete: () => {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { Component, inject } from '@angular/core'
|
||||
import { Router } from '@angular/router'
|
||||
import { i18nPipe } from '@start9labs/shared'
|
||||
import { TuiAppearance, TuiTitle } from '@taiga-ui/core'
|
||||
import { TuiTitle, TuiCell } from '@taiga-ui/core'
|
||||
import { TuiAvatar } from '@taiga-ui/kit'
|
||||
import { TuiCardLarge, TuiCell, TuiHeader } from '@taiga-ui/layout'
|
||||
import { TuiCardLarge, TuiHeader } from '@taiga-ui/layout'
|
||||
import { StateService } from '../services/state.service'
|
||||
|
||||
@Component({
|
||||
@@ -14,7 +14,7 @@ import { StateService } from '../services/state.service'
|
||||
</header>
|
||||
|
||||
<button tuiCell="l" (click)="startFresh()">
|
||||
<tui-avatar appearance="positive" src="@tui.plus" />
|
||||
<span tuiAvatar="@tui.plus" appearance="positive"></span>
|
||||
<div tuiTitle>
|
||||
{{ 'Start Fresh' | i18n }}
|
||||
<div tuiSubtitle>{{ 'Set up a brand new server' | i18n }}</div>
|
||||
@@ -22,7 +22,7 @@ import { StateService } from '../services/state.service'
|
||||
</button>
|
||||
|
||||
<button tuiCell="l" (click)="restore()">
|
||||
<tui-avatar appearance="warning" src="@tui.archive-restore" />
|
||||
<span tuiAvatar="@tui.archive-restore" appearance="warning"></span>
|
||||
<div tuiTitle>
|
||||
{{ 'Restore from Backup' | i18n }}
|
||||
<div tuiSubtitle>
|
||||
@@ -32,7 +32,7 @@ import { StateService } from '../services/state.service'
|
||||
</button>
|
||||
|
||||
<button tuiCell="l" (click)="transfer()">
|
||||
<tui-avatar appearance="info" src="@tui.hard-drive-download" />
|
||||
<span tuiAvatar="@tui.hard-drive-download" appearance="info"></span>
|
||||
<div tuiTitle>
|
||||
{{ 'Transfer' | i18n }}
|
||||
<div tuiSubtitle>
|
||||
@@ -42,15 +42,7 @@ import { StateService } from '../services/state.service'
|
||||
</button>
|
||||
</div>
|
||||
`,
|
||||
imports: [
|
||||
TuiAppearance,
|
||||
TuiCardLarge,
|
||||
TuiHeader,
|
||||
TuiCell,
|
||||
TuiTitle,
|
||||
TuiAvatar,
|
||||
i18nPipe,
|
||||
],
|
||||
imports: [TuiCardLarge, TuiHeader, TuiCell, TuiTitle, TuiAvatar, i18nPipe],
|
||||
})
|
||||
export default class HomePage {
|
||||
private readonly router = inject(Router)
|
||||
|
||||
@@ -6,8 +6,8 @@ import {
|
||||
Keyboard,
|
||||
LanguageCode,
|
||||
} from '@start9labs/shared'
|
||||
import { TUI_IS_MOBILE } from '@taiga-ui/cdk'
|
||||
import { TuiButton, TuiTextfield, TuiTitle } from '@taiga-ui/core'
|
||||
import { WA_IS_MOBILE } from '@ng-web-apis/platform'
|
||||
import { TuiButton, TuiTitle } from '@taiga-ui/core'
|
||||
import {
|
||||
TuiButtonLoading,
|
||||
TuiChevron,
|
||||
@@ -36,11 +36,7 @@ import { StateService } from '../services/state.service'
|
||||
<input tuiSelect [(ngModel)]="selected" />
|
||||
}
|
||||
@if (!mobile) {
|
||||
<tui-data-list-wrapper
|
||||
new
|
||||
*tuiTextfieldDropdown
|
||||
[items]="keyboards"
|
||||
/>
|
||||
<tui-data-list-wrapper *tuiDropdown [items]="keyboards" />
|
||||
}
|
||||
</tui-textfield>
|
||||
|
||||
@@ -61,7 +57,6 @@ import { StateService } from '../services/state.service'
|
||||
TuiCardLarge,
|
||||
TuiButton,
|
||||
TuiButtonLoading,
|
||||
TuiTextfield,
|
||||
TuiChevron,
|
||||
TuiSelect,
|
||||
TuiDataListWrapper,
|
||||
@@ -74,7 +69,7 @@ export default class KeyboardPage {
|
||||
private readonly api = inject(ApiService)
|
||||
private readonly stateService = inject(StateService)
|
||||
|
||||
protected readonly mobile = inject(TUI_IS_MOBILE)
|
||||
protected readonly mobile = inject(WA_IS_MOBILE)
|
||||
// All keyboards, with language-specific keyboards at the top
|
||||
readonly keyboards = getAllKeyboardsSorted(
|
||||
this.stateService.language as LanguageCode,
|
||||
|
||||
@@ -2,9 +2,10 @@ import { Component, computed, inject, signal } from '@angular/core'
|
||||
import { Router } from '@angular/router'
|
||||
import { FormsModule } from '@angular/forms'
|
||||
import { i18nPipe, i18nService, Language, LANGUAGES } from '@start9labs/shared'
|
||||
import { TUI_IS_MOBILE } from '@taiga-ui/cdk'
|
||||
import { TuiButton, TuiTextfield, TuiTitle } from '@taiga-ui/core'
|
||||
import { WA_IS_MOBILE } from '@ng-web-apis/platform'
|
||||
import { TuiButton, TuiCell, TuiTitle } from '@taiga-ui/core'
|
||||
import {
|
||||
TuiAvatar,
|
||||
TuiButtonLoading,
|
||||
TuiChevron,
|
||||
TuiDataListWrapper,
|
||||
@@ -18,13 +19,15 @@ import { StateService } from '../services/state.service'
|
||||
template: `
|
||||
<section tuiCardLarge="compact">
|
||||
<header tuiHeader>
|
||||
<h2 tuiTitle>
|
||||
<span class="inline-title">
|
||||
<img src="assets/img/icon.png" alt="Start9" />
|
||||
<hgroup tuiTitle>
|
||||
<h2 tuiCell="m">
|
||||
<span tuiAvatar>
|
||||
<img src="assets/img/icon.png" alt="Start9" />
|
||||
</span>
|
||||
{{ 'Welcome to' | i18n }} StartOS
|
||||
</span>
|
||||
<span tuiSubtitle>{{ 'Select your language' | i18n }}</span>
|
||||
</h2>
|
||||
</h2>
|
||||
<p tuiSubtitle>{{ 'Select your language' | i18n }}</p>
|
||||
</hgroup>
|
||||
</header>
|
||||
<tui-textfield
|
||||
tuiChevron
|
||||
@@ -48,8 +51,7 @@ import { StateService } from '../services/state.service'
|
||||
}
|
||||
@if (!mobile) {
|
||||
<tui-data-list-wrapper
|
||||
*tuiTextfieldDropdown
|
||||
new
|
||||
*tuiDropdown
|
||||
[items]="languages"
|
||||
[itemContent]="itemContent"
|
||||
/>
|
||||
@@ -57,11 +59,10 @@ import { StateService } from '../services/state.service'
|
||||
</tui-textfield>
|
||||
|
||||
<ng-template #itemContent let-item>
|
||||
@let lang = asLanguage(item);
|
||||
<div class="language-item">
|
||||
<span>{{ lang.nativeName }}</span>
|
||||
<small>{{ lang.name | i18n }}</small>
|
||||
</div>
|
||||
<span tuiTitle>
|
||||
{{ asLanguage(item).nativeName }}
|
||||
<span tuiSubtitle>{{ asLanguage(item).name | i18n }}</span>
|
||||
</span>
|
||||
</ng-template>
|
||||
|
||||
<footer>
|
||||
@@ -76,22 +77,13 @@ import { StateService } from '../services/state.service'
|
||||
</footer>
|
||||
</section>
|
||||
`,
|
||||
styles: `
|
||||
.language-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
small {
|
||||
opacity: 0.7;
|
||||
}
|
||||
}
|
||||
`,
|
||||
imports: [
|
||||
FormsModule,
|
||||
TuiCardLarge,
|
||||
TuiButton,
|
||||
TuiButtonLoading,
|
||||
TuiTextfield,
|
||||
TuiAvatar,
|
||||
TuiCell,
|
||||
TuiChevron,
|
||||
TuiSelect,
|
||||
TuiDataListWrapper,
|
||||
@@ -106,7 +98,7 @@ export default class LanguagePage {
|
||||
private readonly stateService = inject(StateService)
|
||||
private readonly i18nService = inject(i18nService)
|
||||
|
||||
protected readonly mobile = inject(TUI_IS_MOBILE)
|
||||
protected readonly mobile = inject(WA_IS_MOBILE)
|
||||
readonly languages = LANGUAGES
|
||||
|
||||
selected =
|
||||
|
||||
@@ -12,10 +12,10 @@ import {
|
||||
getErrorMessage,
|
||||
i18nPipe,
|
||||
InitializingComponent,
|
||||
LoadingService,
|
||||
} from '@start9labs/shared'
|
||||
import { T } from '@start9labs/start-sdk'
|
||||
import { TuiButton } from '@taiga-ui/core'
|
||||
import { TuiNotificationMiddleService } from '@taiga-ui/kit'
|
||||
import {
|
||||
catchError,
|
||||
filter,
|
||||
@@ -64,7 +64,7 @@ import { StateService } from '../services/state.service'
|
||||
})
|
||||
export default class LoadingPage {
|
||||
private readonly api = inject(ApiService)
|
||||
private readonly loader = inject(LoadingService)
|
||||
private readonly loader = inject(TuiNotificationMiddleService)
|
||||
private readonly dialog = inject(DialogService)
|
||||
private readonly router = inject(Router)
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { AsyncPipe } from '@angular/common'
|
||||
import { Component, inject } from '@angular/core'
|
||||
import { Router } from '@angular/router'
|
||||
import {
|
||||
@@ -8,31 +7,28 @@ import {
|
||||
ReactiveFormsModule,
|
||||
Validators,
|
||||
} from '@angular/forms'
|
||||
import {
|
||||
ErrorService,
|
||||
i18nPipe,
|
||||
LoadingService,
|
||||
normalizeHostname,
|
||||
} from '@start9labs/shared'
|
||||
import { ErrorService, i18nPipe, normalizeHostname } from '@start9labs/shared'
|
||||
import { TuiAutoFocus, TuiMapperPipe, TuiValidator } from '@taiga-ui/cdk'
|
||||
import {
|
||||
TuiButton,
|
||||
TuiError,
|
||||
TuiIcon,
|
||||
TuiTextfield,
|
||||
TuiTitle,
|
||||
} from '@taiga-ui/core'
|
||||
import {
|
||||
TuiFieldErrorPipe,
|
||||
TuiPassword,
|
||||
TuiInput,
|
||||
tuiValidationErrorsProvider,
|
||||
} from '@taiga-ui/kit'
|
||||
import { TuiCardLarge, TuiHeader } from '@taiga-ui/layout'
|
||||
} from '@taiga-ui/core'
|
||||
import { TuiNotificationMiddleService, TuiPassword } from '@taiga-ui/kit'
|
||||
import { TuiCardLarge, TuiForm, TuiHeader } from '@taiga-ui/layout'
|
||||
import { StateService } from '../services/state.service'
|
||||
|
||||
@Component({
|
||||
template: `
|
||||
<section tuiCardLarge="compact">
|
||||
<form
|
||||
tuiCardLarge="compact"
|
||||
tuiForm
|
||||
[formGroup]="form"
|
||||
(ngSubmit)="submit()"
|
||||
>
|
||||
<header tuiHeader>
|
||||
<h2 tuiTitle>
|
||||
{{
|
||||
@@ -43,104 +39,80 @@ import { StateService } from '../services/state.service'
|
||||
</h2>
|
||||
</header>
|
||||
|
||||
<form [formGroup]="form" (ngSubmit)="submit()">
|
||||
@if (isFresh) {
|
||||
<tui-textfield>
|
||||
<label tuiLabel>{{ 'Server Name' | i18n }}</label>
|
||||
<input tuiTextfield tuiAutoFocus formControlName="name" />
|
||||
</tui-textfield>
|
||||
<tui-error
|
||||
formControlName="name"
|
||||
[error]="[] | tuiFieldError | async"
|
||||
/>
|
||||
@if (form.controls.name.value?.trim()) {
|
||||
<p class="hostname-preview">{{ derivedHostname }}.local</p>
|
||||
}
|
||||
@if (isFresh) {
|
||||
<tui-textfield>
|
||||
<label tuiLabel>{{ 'Server Name' | i18n }}</label>
|
||||
<input tuiInput tuiAutoFocus formControlName="name" />
|
||||
</tui-textfield>
|
||||
<tui-error formControlName="name" />
|
||||
@if (form.controls.name.value?.trim()) {
|
||||
<tui-error class="g-secondary" error="{{ derivedHostname }}.local" />
|
||||
}
|
||||
}
|
||||
|
||||
<tui-textfield [style.margin-top.rem]="isFresh ? 1 : 0">
|
||||
<label tuiLabel>
|
||||
{{ isFresh ? ('Password' | i18n) : ('New Password' | i18n) }}
|
||||
</label>
|
||||
<input
|
||||
tuiTextfield
|
||||
type="password"
|
||||
[tuiAutoFocus]="!isFresh"
|
||||
maxlength="64"
|
||||
formControlName="password"
|
||||
/>
|
||||
<tui-icon tuiPassword />
|
||||
</tui-textfield>
|
||||
<tui-error
|
||||
<tui-textfield>
|
||||
<label tuiLabel>
|
||||
{{ isFresh ? ('Password' | i18n) : ('New Password' | i18n) }}
|
||||
</label>
|
||||
<input
|
||||
tuiInput
|
||||
type="password"
|
||||
[tuiAutoFocus]="!isFresh"
|
||||
maxlength="64"
|
||||
formControlName="password"
|
||||
[error]="[] | tuiFieldError | async"
|
||||
/>
|
||||
<tui-icon tuiPassword />
|
||||
</tui-textfield>
|
||||
<tui-error formControlName="password" />
|
||||
|
||||
<tui-textfield [style.margin-top.rem]="1">
|
||||
<label tuiLabel>{{ 'Confirm Password' | i18n }}</label>
|
||||
<input
|
||||
tuiTextfield
|
||||
type="password"
|
||||
formControlName="confirm"
|
||||
[tuiValidator]="
|
||||
form.controls.password.value || '' | tuiMapper: validator
|
||||
"
|
||||
/>
|
||||
<tui-icon tuiPassword />
|
||||
</tui-textfield>
|
||||
<tui-error
|
||||
<tui-textfield>
|
||||
<label tuiLabel>{{ 'Confirm Password' | i18n }}</label>
|
||||
<input
|
||||
tuiInput
|
||||
type="password"
|
||||
formControlName="confirm"
|
||||
[error]="[] | tuiFieldError | async"
|
||||
[tuiValidator]="
|
||||
form.controls.password.value || '' | tuiMapper: validator
|
||||
"
|
||||
/>
|
||||
<tui-icon tuiPassword />
|
||||
</tui-textfield>
|
||||
<tui-error formControlName="confirm" />
|
||||
|
||||
<footer>
|
||||
<footer>
|
||||
<button
|
||||
tuiButton
|
||||
size="m"
|
||||
[disabled]="
|
||||
isFresh
|
||||
? form.invalid
|
||||
: form.controls.password.value && form.invalid
|
||||
"
|
||||
>
|
||||
{{ 'Finish' | i18n }}
|
||||
</button>
|
||||
@if (!isFresh) {
|
||||
<button
|
||||
tuiButton
|
||||
[disabled]="
|
||||
isFresh
|
||||
? form.invalid
|
||||
: form.controls.password.value && form.invalid
|
||||
"
|
||||
size="m"
|
||||
appearance="secondary"
|
||||
type="button"
|
||||
(click)="skip()"
|
||||
>
|
||||
{{ 'Finish' | i18n }}
|
||||
{{ 'Skip' | i18n }}
|
||||
</button>
|
||||
@if (!isFresh) {
|
||||
<button
|
||||
tuiButton
|
||||
appearance="secondary"
|
||||
type="button"
|
||||
(click)="skip()"
|
||||
>
|
||||
{{ 'Skip' | i18n }}
|
||||
</button>
|
||||
}
|
||||
</footer>
|
||||
</form>
|
||||
</section>
|
||||
`,
|
||||
styles: `
|
||||
.hostname-preview {
|
||||
color: var(--tui-text-secondary);
|
||||
font: var(--tui-font-text-s);
|
||||
margin-top: 0.25rem;
|
||||
}
|
||||
|
||||
footer {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
margin-top: 1.5rem;
|
||||
}
|
||||
}
|
||||
</footer>
|
||||
</form>
|
||||
`,
|
||||
imports: [
|
||||
AsyncPipe,
|
||||
ReactiveFormsModule,
|
||||
TuiCardLarge,
|
||||
TuiButton,
|
||||
TuiError,
|
||||
TuiAutoFocus,
|
||||
TuiFieldErrorPipe,
|
||||
TuiTextfield,
|
||||
TuiInput,
|
||||
TuiForm,
|
||||
TuiPassword,
|
||||
TuiValidator,
|
||||
TuiIcon,
|
||||
@@ -160,7 +132,7 @@ import { StateService } from '../services/state.service'
|
||||
})
|
||||
export default class PasswordPage {
|
||||
private readonly router = inject(Router)
|
||||
private readonly loader = inject(LoadingService)
|
||||
private readonly loader = inject(TuiNotificationMiddleService)
|
||||
private readonly errorService = inject(ErrorService)
|
||||
private readonly stateService = inject(StateService)
|
||||
private readonly i18n = inject(i18nPipe)
|
||||
|
||||
@@ -6,11 +6,11 @@ import {
|
||||
TuiButton,
|
||||
TuiDataList,
|
||||
TuiDropdown,
|
||||
TuiIcon,
|
||||
TuiLink,
|
||||
TuiLoader,
|
||||
TuiOptGroup,
|
||||
TuiTitle,
|
||||
} from '@taiga-ui/core'
|
||||
import { TuiChevron } from '@taiga-ui/kit'
|
||||
import { TuiCardLarge, TuiHeader } from '@taiga-ui/layout'
|
||||
import { PolymorpheusComponent } from '@taiga-ui/polymorpheus'
|
||||
import { ApiService } from '../services/api.service'
|
||||
@@ -18,22 +18,25 @@ import { StateService } from '../services/state.service'
|
||||
import { StartOSDiskInfoFull, StartOSDiskInfoWithId } from '../types'
|
||||
import { CIFS, CifsResult } from '../components/cifs.component'
|
||||
import { SELECT_NETWORK_BACKUP } from '../components/select-network-backup.dialog'
|
||||
import { UnlockPasswordDialog } from '../components/unlock-password.dialog'
|
||||
import { UNLOCK_PASSWORD } from '../components/unlock-password.dialog'
|
||||
|
||||
@Component({
|
||||
template: `
|
||||
<section tuiCardLarge="compact">
|
||||
<header tuiHeader>
|
||||
<h2 tuiTitle>
|
||||
{{ 'Select Backup' | i18n }}
|
||||
<span tuiSubtitle>
|
||||
<hgroup tuiTitle>
|
||||
<h2>{{ 'Select Backup' | i18n }}</h2>
|
||||
<p tuiSubtitle>
|
||||
{{ 'Select the StartOS backup you want to restore' | i18n }}
|
||||
<a class="refresh" (click)="refresh()">
|
||||
<tui-icon icon="@tui.rotate-cw" />
|
||||
{{ 'Refresh' | i18n }}
|
||||
</a>
|
||||
</span>
|
||||
</h2>
|
||||
<button
|
||||
tuiLink
|
||||
appearance="action"
|
||||
iconEnd="@tui.rotate-cw"
|
||||
[textContent]="'Refresh' | i18n"
|
||||
(click)="refresh()"
|
||||
></button>
|
||||
</p>
|
||||
</hgroup>
|
||||
</header>
|
||||
|
||||
@if (loading) {
|
||||
@@ -41,82 +44,50 @@ import { UnlockPasswordDialog } from '../components/unlock-password.dialog'
|
||||
} @else {
|
||||
<button
|
||||
tuiButton
|
||||
iconEnd="@tui.chevron-down"
|
||||
[tuiDropdown]="dropdown"
|
||||
[tuiDropdownLimitWidth]="'fixed'"
|
||||
tuiChevron
|
||||
tuiDropdown
|
||||
tuiDropdownLimitWidth="fixed"
|
||||
[(tuiDropdownOpen)]="open"
|
||||
style="width: 100%"
|
||||
>
|
||||
{{ 'Select Backup' | i18n }}
|
||||
</button>
|
||||
|
||||
<ng-template #dropdown>
|
||||
<tui-data-list>
|
||||
<tui-opt-group>
|
||||
<button tuiOption new (click)="openCifs()">
|
||||
<tui-icon icon="@tui.folder-plus" />
|
||||
{{ 'Open Network Backup' | i18n }}
|
||||
</button>
|
||||
</tui-opt-group>
|
||||
<tui-data-list *tuiDropdown>
|
||||
<button tuiOption iconStart="@tui.folder-plus" (click)="openCifs()">
|
||||
{{ 'Open Network Backup' | i18n }}
|
||||
</button>
|
||||
<hr />
|
||||
<tui-opt-group [label]="'Physical Backups' | i18n">
|
||||
@for (server of physicalServers; track server.id) {
|
||||
<button tuiOption new (click)="selectPhysicalBackup(server)">
|
||||
<div class="server-item">
|
||||
<span>{{ server.id }}</span>
|
||||
<small>
|
||||
<button tuiOption (click)="selectPhysicalBackup(server)">
|
||||
<span tuiTitle>
|
||||
{{ server.id }}
|
||||
<span tuiSubtitle>
|
||||
{{ server.drive.vendor }} {{ server.drive.model }} ·
|
||||
{{ server.partition.logicalname }}
|
||||
</small>
|
||||
</div>
|
||||
</span>
|
||||
</span>
|
||||
</button>
|
||||
} @empty {
|
||||
<div class="no-items">{{ 'No physical backups' | i18n }}</div>
|
||||
<button tuiOption [disabled]="true">
|
||||
{{ 'No physical backups' | i18n }}
|
||||
</button>
|
||||
}
|
||||
</tui-opt-group>
|
||||
</tui-data-list>
|
||||
</ng-template>
|
||||
</button>
|
||||
}
|
||||
</section>
|
||||
`,
|
||||
styles: `
|
||||
.refresh {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.25rem;
|
||||
cursor: pointer;
|
||||
color: var(--tui-text-action);
|
||||
|
||||
tui-icon {
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
}
|
||||
|
||||
.server-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
small {
|
||||
opacity: 0.7;
|
||||
}
|
||||
}
|
||||
|
||||
.no-items {
|
||||
padding: 0.5rem 0.75rem;
|
||||
color: var(--tui-text-secondary);
|
||||
font-style: italic;
|
||||
}
|
||||
`,
|
||||
imports: [
|
||||
TuiButton,
|
||||
TuiCardLarge,
|
||||
TuiDataList,
|
||||
TuiDropdown,
|
||||
TuiLoader,
|
||||
TuiIcon,
|
||||
TuiOptGroup,
|
||||
TuiTitle,
|
||||
TuiHeader,
|
||||
i18nPipe,
|
||||
TuiLink,
|
||||
TuiChevron,
|
||||
],
|
||||
})
|
||||
export default class RestorePage {
|
||||
@@ -142,10 +113,7 @@ export default class RestorePage {
|
||||
openCifs() {
|
||||
this.open = false
|
||||
this.dialogs
|
||||
.openComponent<CifsResult>(CIFS, {
|
||||
label: 'Connect Network Folder',
|
||||
size: 's',
|
||||
})
|
||||
.openComponent<CifsResult>(CIFS, { label: 'Connect Network Folder' })
|
||||
.subscribe(result => {
|
||||
if (result) {
|
||||
this.handleCifsResult(result)
|
||||
@@ -167,7 +135,7 @@ export default class RestorePage {
|
||||
type: 'cifs',
|
||||
...result.cifs,
|
||||
})
|
||||
} else if (result.servers.length > 1) {
|
||||
} else {
|
||||
this.showSelectNetworkBackupDialog(result.cifs, result.servers)
|
||||
}
|
||||
}
|
||||
@@ -178,8 +146,6 @@ export default class RestorePage {
|
||||
) {
|
||||
this.dialogs
|
||||
.openComponent<StartOSDiskInfoWithId | null>(SELECT_NETWORK_BACKUP, {
|
||||
label: 'Select Network Backup',
|
||||
size: 's',
|
||||
data: { servers },
|
||||
})
|
||||
.subscribe(server => {
|
||||
@@ -194,13 +160,7 @@ export default class RestorePage {
|
||||
target: { type: 'disk'; logicalname: string } | ({ type: 'cifs' } & T.Cifs),
|
||||
) {
|
||||
this.dialogs
|
||||
.openComponent<string | null>(
|
||||
new PolymorpheusComponent(UnlockPasswordDialog),
|
||||
{
|
||||
label: 'Unlock Backup',
|
||||
size: 's',
|
||||
},
|
||||
)
|
||||
.openComponent<string | null>(UNLOCK_PASSWORD)
|
||||
.subscribe(password => {
|
||||
if (password) {
|
||||
this.stateService.recoverySource = {
|
||||
|
||||
@@ -12,9 +12,9 @@ import {
|
||||
ErrorService,
|
||||
i18nPipe,
|
||||
} from '@start9labs/shared'
|
||||
import { TuiIcon, TuiLoader, TuiTitle } from '@taiga-ui/core'
|
||||
import { TuiIcon, TuiLoader, TuiTitle, TuiCell } from '@taiga-ui/core'
|
||||
import { TuiAvatar } from '@taiga-ui/kit'
|
||||
import { TuiCardLarge, TuiCell, TuiHeader } from '@taiga-ui/layout'
|
||||
import { TuiCardLarge, TuiHeader } from '@taiga-ui/layout'
|
||||
import { ApiService } from '../services/api.service'
|
||||
import { StateService } from '../services/state.service'
|
||||
import { DocumentationComponent } from '../components/documentation.component'
|
||||
@@ -50,7 +50,7 @@ import { PolymorpheusComponent } from '@taiga-ui/polymorpheus'
|
||||
<!-- Step: Download Address Info (non-kiosk only) -->
|
||||
@if (!stateService.kiosk) {
|
||||
<button tuiCell="l" [disabled]="downloaded" (click)="download()">
|
||||
<tui-avatar appearance="secondary" src="@tui.download" />
|
||||
<span tuiAvatar="@tui.download" appearance="secondary"></span>
|
||||
<div tuiTitle>
|
||||
{{ 'Download Address Info' | i18n }}
|
||||
<div tuiSubtitle>
|
||||
@@ -74,7 +74,7 @@ import { PolymorpheusComponent } from '@taiga-ui/polymorpheus'
|
||||
[disabled]="(!stateService.kiosk && !downloaded) || usbRemoved"
|
||||
(click)="removeMedia()"
|
||||
>
|
||||
<tui-avatar appearance="secondary" src="@tui.usb" />
|
||||
<span tuiAvatar="@tui.usb" appearance="secondary"></span>
|
||||
<div tuiTitle>
|
||||
{{ 'Remove Installation Media' | i18n }}
|
||||
<div tuiSubtitle>
|
||||
@@ -96,7 +96,7 @@ import { PolymorpheusComponent } from '@taiga-ui/polymorpheus'
|
||||
[disabled]="!usbRemoved || rebooted || rebooting"
|
||||
(click)="reboot()"
|
||||
>
|
||||
<tui-avatar appearance="secondary" src="@tui.rotate-cw" />
|
||||
<span tuiAvatar="@tui.rotate-cw" appearance="secondary"></span>
|
||||
<div tuiTitle>
|
||||
{{ 'Restart Server' | i18n }}
|
||||
<div tuiSubtitle>
|
||||
@@ -125,7 +125,7 @@ import { PolymorpheusComponent } from '@taiga-ui/polymorpheus'
|
||||
[disabled]="!canOpenAddress"
|
||||
(click)="openLocalAddress()"
|
||||
>
|
||||
<tui-avatar appearance="secondary" src="@tui.external-link" />
|
||||
<span tuiAvatar="@tui.external-link" appearance="secondary"></span>
|
||||
<div tuiTitle>
|
||||
{{ 'Open Local Address' | i18n }}
|
||||
<div tuiSubtitle>{{ lanAddress }}</div>
|
||||
@@ -143,7 +143,7 @@ import { PolymorpheusComponent } from '@taiga-ui/polymorpheus'
|
||||
[disabled]="result.needsRestart && !rebooted"
|
||||
(click)="exitKiosk()"
|
||||
>
|
||||
<tui-avatar appearance="secondary" src="@tui.log-in" />
|
||||
<span tuiAvatar="@tui.log-in" appearance="secondary"></span>
|
||||
<div tuiTitle>
|
||||
{{ 'Continue to Login' | i18n }}
|
||||
<div tuiSubtitle>
|
||||
@@ -233,9 +233,8 @@ export default class SuccessPage implements AfterViewInit {
|
||||
removeMedia() {
|
||||
this.dialogs
|
||||
.openComponent<boolean>(new PolymorpheusComponent(RemoveMediaDialog), {
|
||||
size: 's',
|
||||
dismissible: false,
|
||||
closeable: false,
|
||||
closable: false,
|
||||
})
|
||||
.subscribe(() => {
|
||||
this.usbRemoved = true
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Component, inject } from '@angular/core'
|
||||
import { Component, inject, OnInit } from '@angular/core'
|
||||
import { Router } from '@angular/router'
|
||||
import {
|
||||
DialogService,
|
||||
@@ -11,10 +11,11 @@ import {
|
||||
TuiButton,
|
||||
TuiDataList,
|
||||
TuiDropdown,
|
||||
TuiIcon,
|
||||
TuiLink,
|
||||
TuiLoader,
|
||||
TuiTitle,
|
||||
} from '@taiga-ui/core'
|
||||
import { TuiChevron } from '@taiga-ui/kit'
|
||||
import { TuiCardLarge, TuiHeader } from '@taiga-ui/layout'
|
||||
import { filter } from 'rxjs'
|
||||
import { ApiService } from '../services/api.service'
|
||||
@@ -24,18 +25,21 @@ import { StateService } from '../services/state.service'
|
||||
template: `
|
||||
<section tuiCardLarge="compact">
|
||||
<header tuiHeader>
|
||||
<h2 tuiTitle>
|
||||
{{ 'Transfer Data' | i18n }}
|
||||
<span tuiSubtitle>
|
||||
<hgroup tuiTitle>
|
||||
<h2>{{ 'Transfer Data' | i18n }}</h2>
|
||||
<p tuiSubtitle>
|
||||
{{
|
||||
'Select the drive containing your existing StartOS data' | i18n
|
||||
}}
|
||||
<a class="refresh" (click)="refresh()">
|
||||
<tui-icon icon="@tui.rotate-cw" />
|
||||
{{ 'Refresh' | i18n }}
|
||||
</a>
|
||||
</span>
|
||||
</h2>
|
||||
<button
|
||||
tuiLink
|
||||
appearance="action"
|
||||
iconEnd="@tui.rotate-cw"
|
||||
[textContent]="'Refresh' | i18n"
|
||||
(click)="refresh()"
|
||||
></button>
|
||||
</p>
|
||||
</hgroup>
|
||||
</header>
|
||||
|
||||
@if (loading) {
|
||||
@@ -43,75 +47,43 @@ import { StateService } from '../services/state.service'
|
||||
} @else {
|
||||
<button
|
||||
tuiButton
|
||||
iconEnd="@tui.chevron-down"
|
||||
[tuiDropdown]="dropdown"
|
||||
[tuiDropdownLimitWidth]="'fixed'"
|
||||
tuiChevron
|
||||
tuiDropdown
|
||||
tuiDropdownLimitWidth="fixed"
|
||||
[(tuiDropdownOpen)]="open"
|
||||
style="width: 100%"
|
||||
>
|
||||
{{ 'Select Drive' | i18n }}
|
||||
</button>
|
||||
|
||||
<ng-template #dropdown>
|
||||
<tui-data-list>
|
||||
<tui-data-list
|
||||
*tuiDropdown
|
||||
[emptyContent]="'No StartOS data drives found' | i18n"
|
||||
>
|
||||
@for (drive of drives; track drive.logicalname) {
|
||||
<button tuiOption new (click)="select(drive)">
|
||||
<div class="drive-item">
|
||||
<span>{{ drive.vendor }} {{ drive.model }}</span>
|
||||
<small>{{ drive.logicalname }}</small>
|
||||
</div>
|
||||
<button tuiOption (click)="select(drive)">
|
||||
<span tuiTitle>
|
||||
{{ drive.vendor }} {{ drive.model }}
|
||||
<span tuiSubtitle>{{ drive.logicalname }}</span>
|
||||
</span>
|
||||
</button>
|
||||
} @empty {
|
||||
<div class="no-items">
|
||||
{{ 'No StartOS data drives found' | i18n }}
|
||||
</div>
|
||||
}
|
||||
</tui-data-list>
|
||||
</ng-template>
|
||||
</button>
|
||||
}
|
||||
</section>
|
||||
`,
|
||||
styles: `
|
||||
.refresh {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.25rem;
|
||||
cursor: pointer;
|
||||
color: var(--tui-text-action);
|
||||
|
||||
tui-icon {
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
}
|
||||
|
||||
.drive-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
small {
|
||||
opacity: 0.7;
|
||||
}
|
||||
}
|
||||
|
||||
.no-items {
|
||||
padding: 0.5rem 0.75rem;
|
||||
color: var(--tui-text-secondary);
|
||||
font-style: italic;
|
||||
}
|
||||
`,
|
||||
imports: [
|
||||
TuiButton,
|
||||
TuiCardLarge,
|
||||
TuiDataList,
|
||||
TuiDropdown,
|
||||
TuiIcon,
|
||||
TuiLink,
|
||||
TuiChevron,
|
||||
TuiLoader,
|
||||
TuiTitle,
|
||||
TuiHeader,
|
||||
i18nPipe,
|
||||
],
|
||||
})
|
||||
export default class TransferPage {
|
||||
export default class TransferPage implements OnInit {
|
||||
private readonly api = inject(ApiService)
|
||||
private readonly router = inject(Router)
|
||||
private readonly dialogs = inject(DialogService)
|
||||
@@ -137,7 +109,6 @@ export default class TransferPage {
|
||||
this.dialogs
|
||||
.openConfirm({
|
||||
label: 'Warning',
|
||||
size: 's',
|
||||
data: {
|
||||
content:
|
||||
'After transferring data from this drive, do not attempt to boot into it again as a Start9 Server. This may result in services malfunctioning, data corruption, or loss of funds.',
|
||||
|
||||
@@ -12,6 +12,10 @@ tui-root {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
ul {
|
||||
padding-inline-start: 1rem;
|
||||
}
|
||||
|
||||
router-outlet + * {
|
||||
height: 100%;
|
||||
max-width: min(35rem, 100vw);
|
||||
@@ -30,41 +34,11 @@ router-outlet + * {
|
||||
}
|
||||
}
|
||||
|
||||
.inline-title {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
|
||||
:first-child {
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
button:disabled {
|
||||
opacity: var(--tui-disabled-opacity);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
header {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
text-align: center;
|
||||
font: var(--tui-font-heading-4);
|
||||
|
||||
p {
|
||||
font: var(--tui-font-text-m);
|
||||
color: var(--tui-text-secondary);
|
||||
}
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin: 0;
|
||||
font: var(--tui-font-heading-6);
|
||||
}
|
||||
|
||||
.g-positive {
|
||||
color: var(--tui-status-positive);
|
||||
}
|
||||
@@ -77,14 +51,27 @@ h2 {
|
||||
color: var(--tui-status-negative);
|
||||
}
|
||||
|
||||
.g-secondary {
|
||||
color: var(--tui-text-secondary) !important;
|
||||
}
|
||||
|
||||
.g-info {
|
||||
color: var(--tui-status-info);
|
||||
}
|
||||
|
||||
[tuiCardLarge] footer button {
|
||||
width: 100%;
|
||||
[tuiCardLarge] footer {
|
||||
display: flex;
|
||||
|
||||
button {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
||||
[tuiCell]:not(:last-of-type) {
|
||||
[tuiCell]:not([tuiOption]):not(:last-of-type) {
|
||||
box-shadow: 0 calc(0.5rem + 1px) 0 -0.5rem var(--tui-border-normal);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Remove in Taiga v5.0
|
||||
[tuiButton] {
|
||||
min-block-size: var(--t-size);
|
||||
}
|
||||
|
||||
@@ -11,7 +11,12 @@ import { getErrorMessage } from '../services/error.service'
|
||||
@Component({
|
||||
template: `
|
||||
@if (error()) {
|
||||
<tui-notification appearance="negative" safeLinks [innerHTML]="error()" />
|
||||
<div
|
||||
tuiNotification
|
||||
appearance="negative"
|
||||
safeLinks
|
||||
[innerHTML]="error()"
|
||||
></div>
|
||||
}
|
||||
|
||||
@if (content(); as result) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { ChangeDetectionStrategy, Component } from '@angular/core'
|
||||
import { FormsModule } from '@angular/forms'
|
||||
import { TuiAutoFocus } from '@taiga-ui/cdk'
|
||||
import { TuiButton, TuiDialogContext, TuiTextfield } from '@taiga-ui/core'
|
||||
import { TuiButton, TuiDialogContext, TuiInput } from '@taiga-ui/core'
|
||||
import { injectContext, PolymorpheusComponent } from '@taiga-ui/polymorpheus'
|
||||
import { i18nPipe } from '../i18n/i18n.pipe'
|
||||
import { i18nKey } from '../i18n/i18n.providers'
|
||||
@@ -23,7 +23,7 @@ import { i18nKey } from '../i18n/i18n.providers'
|
||||
</label>
|
||||
}
|
||||
<input
|
||||
tuiTextfield
|
||||
tuiInput
|
||||
tuiAutoFocus
|
||||
[ngModelOptions]="{ standalone: true }"
|
||||
[(ngModel)]="value"
|
||||
@@ -81,7 +81,7 @@ import { i18nKey } from '../i18n/i18n.providers'
|
||||
-webkit-text-security: disc;
|
||||
}
|
||||
`,
|
||||
imports: [FormsModule, TuiButton, TuiTextfield, TuiAutoFocus, i18nPipe],
|
||||
imports: [FormsModule, TuiButton, TuiInput, TuiAutoFocus, i18nPipe],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class PromptModal {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { DatePipe } from '@angular/common'
|
||||
import { Component, input } from '@angular/core'
|
||||
import { TuiIcon, TuiTitle } from '@taiga-ui/core'
|
||||
import { TuiCell } from '@taiga-ui/layout'
|
||||
import { TuiIcon, TuiTitle, TuiCell } from '@taiga-ui/core'
|
||||
import { StartOSDiskInfo } from '../types/api'
|
||||
|
||||
@Component({
|
||||
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
InjectionToken,
|
||||
input,
|
||||
} from '@angular/core'
|
||||
import { tuiSetSignal } from '@taiga-ui/cdk'
|
||||
import { TuiHintDirective } from '@taiga-ui/core'
|
||||
import { i18nPipe } from '../i18n/i18n.pipe'
|
||||
|
||||
@@ -33,7 +34,8 @@ export class DocsLinkDirective {
|
||||
})
|
||||
|
||||
constructor() {
|
||||
inject(TuiHintDirective).content.set(
|
||||
tuiSetSignal(
|
||||
inject(TuiHintDirective).content,
|
||||
inject(i18nPipe).transform('Documentation'),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -32,7 +32,6 @@ export * from './services/download-html.service'
|
||||
export * from './services/exver.service'
|
||||
export * from './services/error.service'
|
||||
export * from './services/http.service'
|
||||
export * from './services/loading.service'
|
||||
export * from './services/setup-logs.service'
|
||||
|
||||
export * from './types/api'
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { inject, Injectable } from '@angular/core'
|
||||
import { Clipboard } from '@angular/cdk/clipboard'
|
||||
import { TuiAlertService } from '@taiga-ui/core'
|
||||
import { TuiNotificationService } from '@taiga-ui/core'
|
||||
|
||||
import { i18nPipe } from '../i18n/i18n.pipe'
|
||||
|
||||
@@ -8,7 +8,7 @@ import { i18nPipe } from '../i18n/i18n.pipe'
|
||||
export class CopyService {
|
||||
private readonly clipboard = inject(Clipboard)
|
||||
private readonly i18n = inject(i18nPipe)
|
||||
private readonly alerts = inject(TuiAlertService)
|
||||
private readonly alerts = inject(TuiNotificationService)
|
||||
|
||||
async copy(text: string) {
|
||||
const success = this.clipboard.copy(text)
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { ErrorHandler, inject, Injectable } from '@angular/core'
|
||||
import { TuiAlertService } from '@taiga-ui/core'
|
||||
import { TuiNotificationService } from '@taiga-ui/core'
|
||||
import { HttpError } from '../classes/http-error'
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class ErrorService extends ErrorHandler {
|
||||
private readonly alerts = inject(TuiAlertService)
|
||||
private readonly alerts = inject(TuiNotificationService)
|
||||
|
||||
override handleError(error: HttpError | string, link?: string) {
|
||||
console.error(error)
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
import { ChangeDetectionStrategy, Component, Injectable } from '@angular/core'
|
||||
import { TuiPopoverService } from '@taiga-ui/cdk'
|
||||
import { TUI_DIALOGS, TuiLoader } from '@taiga-ui/core'
|
||||
import { injectContext } from '@taiga-ui/polymorpheus'
|
||||
import { i18nPipe } from '../i18n/i18n.pipe'
|
||||
import { i18nKey } from '../i18n/i18n.providers'
|
||||
|
||||
@Component({
|
||||
template: '<tui-loader [textContent]="content | i18n" />',
|
||||
styles: `
|
||||
:host {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
max-width: 80%;
|
||||
margin: auto;
|
||||
padding: 1.5rem;
|
||||
background: var(--tui-background-elevation-1);
|
||||
border-radius: var(--tui-radius-m);
|
||||
box-shadow: var(--tui-shadow-popup);
|
||||
|
||||
--tui-background-accent-1: var(--tui-status-warning);
|
||||
}
|
||||
|
||||
tui-loader {
|
||||
flex-shrink: 0;
|
||||
min-width: 2rem;
|
||||
}
|
||||
`,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
imports: [TuiLoader, i18nPipe],
|
||||
})
|
||||
class LoadingComponent {
|
||||
readonly content = injectContext<{ content: i18nKey }>().content
|
||||
}
|
||||
|
||||
@Injectable({
|
||||
providedIn: `root`,
|
||||
useFactory: () => new LoadingService(TUI_DIALOGS, LoadingComponent),
|
||||
})
|
||||
export class LoadingService extends TuiPopoverService<unknown> {
|
||||
override open<G = void>(textContent: i18nKey | '' = '') {
|
||||
return super.open<G>(textContent)
|
||||
}
|
||||
}
|
||||
@@ -95,9 +95,6 @@ $wide-modal: 900px;
|
||||
--tw-color-zinc-800: 39 39 42;
|
||||
--tw-color-zinc-900: 24 24 27;
|
||||
--tw-color-zinc-950: 9 9 11;
|
||||
|
||||
--tui-font-text: 'Proxima Nova', system-ui;
|
||||
--tui-font-heading: 'Proxima Nova', system-ui;
|
||||
}
|
||||
|
||||
body {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@use '@taiga-ui/core/styles/taiga-ui-local' as taiga;
|
||||
@use '@taiga-ui/styles/utils' as taiga;
|
||||
|
||||
[tuiTheme='dark'] {
|
||||
--tui-background-base: rgba(23, 23, 23, 1);
|
||||
@@ -135,13 +135,13 @@ tui-dropdown[data-appearance='start-os'][data-appearance='start-os'] {
|
||||
inset 0 0 1rem rgba(0, 0, 0, 0.25),
|
||||
var(--tui-shadow-medium);
|
||||
|
||||
[tuiOption] {
|
||||
justify-content: flex-start;
|
||||
gap: 0.5rem;
|
||||
input {
|
||||
// Checkmark
|
||||
--tui-text-action: var(--tui-text-primary);
|
||||
}
|
||||
}
|
||||
|
||||
// @TODO Alex: Move to Taiga UI
|
||||
// TODO: Remove in Taiga v5.0
|
||||
a[tuiIconButton]:not([href]) {
|
||||
pointer-events: none;
|
||||
opacity: var(--tui-disabled-opacity);
|
||||
@@ -160,7 +160,7 @@ tui-textfield [tuiTooltip] {
|
||||
padding-block: 0.75rem;
|
||||
|
||||
[tuiTitle] {
|
||||
font: var(--tui-font-text-l);
|
||||
font: var(--tui-typography-body-l);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -169,7 +169,16 @@ tui-textfield [tuiTooltip] {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Remove after migrating to v5
|
||||
[tuiOption] {
|
||||
word-break: break-word;
|
||||
:root {
|
||||
--tui-typography-family-text: 'Proxima Nova', system-ui;
|
||||
--tui-typography-family-display: 'Proxima Nova', system-ui;
|
||||
}
|
||||
|
||||
tui-notification-middle {
|
||||
--tui-background-accent-1: var(--tui-status-warning);
|
||||
}
|
||||
|
||||
// TODO: Remove in Taiga v5.0
|
||||
[tuiButton] {
|
||||
min-block-size: var(--t-size);
|
||||
}
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
import { tuiDropdownOptionsProvider } from '@taiga-ui/core'
|
||||
import { provideEventPlugins } from '@taiga-ui/event-plugins'
|
||||
import { provideAnimations } from '@angular/platform-browser/animations'
|
||||
import {
|
||||
tuiDropdownOptionsProvider,
|
||||
tuiDialogOptionsProvider,
|
||||
provideTaiga,
|
||||
} from '@taiga-ui/core'
|
||||
import {
|
||||
ApplicationConfig,
|
||||
provideBrowserGlobalErrorListeners,
|
||||
provideZonelessChangeDetection,
|
||||
} from '@angular/core'
|
||||
import { provideRouter, withRouterConfig } from '@angular/router'
|
||||
import { tuiDialogOptionsProvider } from '@taiga-ui/experimental'
|
||||
import { PatchDB } from 'patch-db-client'
|
||||
import {
|
||||
PATCH_CACHE,
|
||||
@@ -31,11 +32,10 @@ const {
|
||||
|
||||
export const appConfig: ApplicationConfig = {
|
||||
providers: [
|
||||
provideAnimations(),
|
||||
provideBrowserGlobalErrorListeners(),
|
||||
provideZonelessChangeDetection(),
|
||||
provideRouter(routes, withRouterConfig({ onSameUrlNavigation: 'reload' })),
|
||||
provideEventPlugins(),
|
||||
provideTaiga({ mode: 'dark' }),
|
||||
tuiDropdownOptionsProvider({ appearance: 'start-9' }),
|
||||
tuiDialogOptionsProvider({ appearance: 'start-9 taiga' }),
|
||||
{
|
||||
|
||||
@@ -29,7 +29,7 @@ import { SidebarService } from 'src/app/services/sidebar.service'
|
||||
}
|
||||
|
||||
h1 {
|
||||
font: var(--tui-font-heading-6);
|
||||
font: var(--tui-typography-heading-h6);
|
||||
margin-inline-end: auto;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
import { ChangeDetectionStrategy, Component, inject } from '@angular/core'
|
||||
import { Router, RouterLink, RouterLinkActive } from '@angular/router'
|
||||
import { ErrorService, LoadingService } from '@start9labs/shared'
|
||||
import { ErrorService } from '@start9labs/shared'
|
||||
import { TuiButton } from '@taiga-ui/core'
|
||||
import { TuiBadgeNotification } from '@taiga-ui/kit'
|
||||
import {
|
||||
TuiBadgeNotification,
|
||||
TuiNotificationMiddleService,
|
||||
} from '@taiga-ui/kit'
|
||||
import { ApiService } from 'src/app/services/api/api.service'
|
||||
import { AuthService } from 'src/app/services/auth.service'
|
||||
import { SidebarService } from 'src/app/services/sidebar.service'
|
||||
@@ -110,7 +113,7 @@ export class Nav {
|
||||
private readonly router = inject(Router)
|
||||
protected readonly sidebars = inject(SidebarService)
|
||||
protected readonly api = inject(ApiService)
|
||||
private readonly loader = inject(LoadingService)
|
||||
private readonly loader = inject(TuiNotificationMiddleService)
|
||||
private readonly errorService = inject(ErrorService)
|
||||
protected readonly update = inject(UpdateService)
|
||||
|
||||
@@ -133,7 +136,7 @@ export class Nav {
|
||||
] as const
|
||||
|
||||
protected async logout() {
|
||||
const loader = this.loader.open().subscribe()
|
||||
const loader = this.loader.open('').subscribe()
|
||||
try {
|
||||
await this.api.logout()
|
||||
this.service.authenticated.set(false)
|
||||
|
||||
@@ -1,32 +1,26 @@
|
||||
import { AsyncPipe } from '@angular/common'
|
||||
import { ChangeDetectionStrategy, Component, inject } from '@angular/core'
|
||||
import {
|
||||
NonNullableFormBuilder,
|
||||
ReactiveFormsModule,
|
||||
Validators,
|
||||
} from '@angular/forms'
|
||||
import { ErrorService, LoadingService } from '@start9labs/shared'
|
||||
import { ErrorService } from '@start9labs/shared'
|
||||
import { utils } from '@start9labs/start-sdk'
|
||||
import { WA_IS_MOBILE } from '@ng-web-apis/platform'
|
||||
import { TuiResponsiveDialogService } from '@taiga-ui/addon-mobile'
|
||||
import {
|
||||
TUI_IS_MOBILE,
|
||||
TuiAnimated,
|
||||
TuiAutoFocus,
|
||||
tuiMarkControlAsTouchedAndValidate,
|
||||
} from '@taiga-ui/cdk'
|
||||
import {
|
||||
TuiButton,
|
||||
TuiDialogContext,
|
||||
TuiError,
|
||||
TuiTextfield,
|
||||
} from '@taiga-ui/core'
|
||||
import { TuiDialogService } from '@taiga-ui/experimental'
|
||||
import { TuiButton, TuiDialogContext, TuiError, TuiInput } from '@taiga-ui/core'
|
||||
import {
|
||||
TuiChevron,
|
||||
TuiDataListWrapper,
|
||||
TuiElasticContainer,
|
||||
TuiFieldErrorPipe,
|
||||
TuiNotificationMiddleService,
|
||||
TuiSelect,
|
||||
} from '@taiga-ui/kit'
|
||||
import { TuiForm } from '@taiga-ui/layout'
|
||||
import { TuiForm, TuiElasticContainer } from '@taiga-ui/layout'
|
||||
import { injectContext, PolymorpheusComponent } from '@taiga-ui/polymorpheus'
|
||||
import { ApiService } from 'src/app/services/api/api.service'
|
||||
|
||||
@@ -44,9 +38,9 @@ import {
|
||||
<form tuiForm [formGroup]="form">
|
||||
<tui-textfield>
|
||||
<label tuiLabel>Name</label>
|
||||
<input tuiTextfield tuiAutoFocus formControlName="name" />
|
||||
<input tuiInput tuiAutoFocus formControlName="name" />
|
||||
</tui-textfield>
|
||||
<tui-error formControlName="name" [error]="[] | tuiFieldError | async" />
|
||||
<tui-error formControlName="name" />
|
||||
|
||||
@if (!context.data.device) {
|
||||
<tui-textfield tuiChevron [stringify]="stringify">
|
||||
@@ -63,31 +57,24 @@ import {
|
||||
}
|
||||
@if (!mobile) {
|
||||
<tui-data-list-wrapper
|
||||
*tuiTextfieldDropdown
|
||||
new
|
||||
*tuiDropdown
|
||||
[items]="context.data.subnets()"
|
||||
(itemClick)="onSubnet($event)"
|
||||
/>
|
||||
}
|
||||
</tui-textfield>
|
||||
<tui-error
|
||||
formControlName="subnet"
|
||||
[error]="[] | tuiFieldError | async"
|
||||
/>
|
||||
<tui-error formControlName="subnet" />
|
||||
|
||||
<tui-elastic-container>
|
||||
@if (form.controls.subnet.value?.range) {
|
||||
<tui-textfield>
|
||||
<tui-textfield tuiAnimated>
|
||||
<label tuiLabel>LAN IP</label>
|
||||
<input tuiTextfield tuiAutoFocus formControlName="ip" />
|
||||
<input tuiInput tuiAutoFocus formControlName="ip" />
|
||||
</tui-textfield>
|
||||
}
|
||||
</tui-elastic-container>
|
||||
@if (form.controls.subnet.value?.range) {
|
||||
<tui-error
|
||||
formControlName="ip"
|
||||
[error]="[] | tuiFieldError | async"
|
||||
/>
|
||||
<tui-error formControlName="ip" />
|
||||
}
|
||||
}
|
||||
<footer>
|
||||
@@ -97,27 +84,26 @@ import {
|
||||
`,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
imports: [
|
||||
AsyncPipe,
|
||||
ReactiveFormsModule,
|
||||
TuiAutoFocus,
|
||||
TuiButton,
|
||||
TuiDataListWrapper,
|
||||
TuiError,
|
||||
TuiFieldErrorPipe,
|
||||
TuiForm,
|
||||
TuiSelect,
|
||||
TuiTextfield,
|
||||
TuiInput,
|
||||
TuiAnimated,
|
||||
TuiChevron,
|
||||
TuiElasticContainer,
|
||||
],
|
||||
})
|
||||
export class DevicesAdd {
|
||||
private readonly loading = inject(LoadingService)
|
||||
private readonly loading = inject(TuiNotificationMiddleService)
|
||||
private readonly api = inject(ApiService)
|
||||
private readonly errorService = inject(ErrorService)
|
||||
private readonly dialogs = inject(TuiDialogService)
|
||||
private readonly dialogs = inject(TuiResponsiveDialogService)
|
||||
|
||||
protected readonly mobile = inject(TUI_IS_MOBILE)
|
||||
protected readonly mobile = inject(WA_IS_MOBILE)
|
||||
protected readonly context =
|
||||
injectContext<TuiDialogContext<void, DeviceData>>()
|
||||
|
||||
@@ -160,7 +146,7 @@ export class DevicesAdd {
|
||||
return
|
||||
}
|
||||
|
||||
const loader = this.loading.open().subscribe()
|
||||
const loader = this.loading.open('').subscribe()
|
||||
const { ip, name, subnet } = this.form.getRawValue()
|
||||
const data = { ip, name, subnet: subnet?.range || '' }
|
||||
|
||||
|
||||
@@ -1,11 +1,5 @@
|
||||
import { ChangeDetectionStrategy, Component } from '@angular/core'
|
||||
import {
|
||||
TuiButton,
|
||||
TuiDialogContext,
|
||||
TuiIcon,
|
||||
TuiTextfield,
|
||||
TuiTitle,
|
||||
} from '@taiga-ui/core'
|
||||
import { TuiButton, TuiDialogContext, TuiIcon, TuiTitle } from '@taiga-ui/core'
|
||||
import { TuiCopy, TuiSegmented, TuiTextarea } from '@taiga-ui/kit'
|
||||
import { TuiHeader } from '@taiga-ui/layout'
|
||||
import { injectContext, PolymorpheusComponent } from '@taiga-ui/polymorpheus'
|
||||
@@ -60,7 +54,6 @@ import { QrCodeComponent } from 'ng-qrcode'
|
||||
TuiIcon,
|
||||
TuiTitle,
|
||||
TuiSegmented,
|
||||
TuiTextfield,
|
||||
TuiTextarea,
|
||||
TuiCopy,
|
||||
],
|
||||
|
||||
@@ -6,15 +6,10 @@ import {
|
||||
Signal,
|
||||
} from '@angular/core'
|
||||
import { toSignal } from '@angular/core/rxjs-interop'
|
||||
import { ErrorService, LoadingService } from '@start9labs/shared'
|
||||
import {
|
||||
TuiButton,
|
||||
TuiDataList,
|
||||
TuiDropdown,
|
||||
TuiTextfield,
|
||||
} from '@taiga-ui/core'
|
||||
import { TuiDialogService } from '@taiga-ui/experimental'
|
||||
import { TUI_CONFIRM } from '@taiga-ui/kit'
|
||||
import { ErrorService } from '@start9labs/shared'
|
||||
import { TuiResponsiveDialogService } from '@taiga-ui/addon-mobile'
|
||||
import { TuiButton, TuiDataList, TuiDropdown } from '@taiga-ui/core'
|
||||
import { TUI_CONFIRM, TuiNotificationMiddleService } from '@taiga-ui/kit'
|
||||
import { PatchDB } from 'patch-db-client'
|
||||
import { filter, map } from 'rxjs'
|
||||
import { ApiService } from 'src/app/services/api/api.service'
|
||||
@@ -49,16 +44,15 @@ import { MappedDevice, MappedSubnet } from './utils'
|
||||
tuiIconButton
|
||||
size="xs"
|
||||
tuiDropdown
|
||||
tuiDropdownOpen
|
||||
tuiDropdownAuto
|
||||
appearance="flat-grayscale"
|
||||
iconStart="@tui.ellipsis-vertical"
|
||||
>
|
||||
Actions
|
||||
<tui-data-list *tuiTextfieldDropdown size="s">
|
||||
<tui-data-list *tuiDropdown size="s">
|
||||
<button
|
||||
tuiOption
|
||||
iconStart="@tui.pencil"
|
||||
new
|
||||
(click)="onEdit(device)"
|
||||
>
|
||||
Rename
|
||||
@@ -66,7 +60,6 @@ import { MappedDevice, MappedSubnet } from './utils'
|
||||
<button
|
||||
tuiOption
|
||||
iconStart="@tui.settings"
|
||||
new
|
||||
(click)="onConfig(device)"
|
||||
>
|
||||
View Config
|
||||
@@ -74,7 +67,6 @@ import { MappedDevice, MappedSubnet } from './utils'
|
||||
<button
|
||||
tuiOption
|
||||
iconStart="@tui.trash"
|
||||
new
|
||||
(click)="onDelete(device)"
|
||||
>
|
||||
Delete
|
||||
@@ -90,12 +82,12 @@ import { MappedDevice, MappedSubnet } from './utils'
|
||||
</table>
|
||||
`,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
imports: [TuiButton, TuiDropdown, TuiDataList, TuiTextfield],
|
||||
imports: [TuiButton, TuiDropdown, TuiDataList],
|
||||
})
|
||||
export default class Devices {
|
||||
private readonly dialogs = inject(TuiDialogService)
|
||||
private readonly dialogs = inject(TuiResponsiveDialogService)
|
||||
private readonly api = inject(ApiService)
|
||||
private readonly loading = inject(LoadingService)
|
||||
private readonly loading = inject(TuiNotificationMiddleService)
|
||||
private readonly errorService = inject(ErrorService)
|
||||
|
||||
protected readonly subnets: Signal<readonly MappedSubnet[]> = toSignal(
|
||||
@@ -145,7 +137,7 @@ export default class Devices {
|
||||
}
|
||||
|
||||
async onConfig({ subnet, ip }: MappedDevice) {
|
||||
const loader = this.loading.open().subscribe()
|
||||
const loader = this.loading.open('').subscribe()
|
||||
try {
|
||||
const data = await this.api.showDeviceConfig({ subnet: subnet.range, ip })
|
||||
|
||||
@@ -163,7 +155,7 @@ export default class Devices {
|
||||
.open(TUI_CONFIRM, { label: 'Are you sure?' })
|
||||
.pipe(filter(Boolean))
|
||||
.subscribe(async () => {
|
||||
const loader = this.loading.open().subscribe()
|
||||
const loader = this.loading.open('').subscribe()
|
||||
try {
|
||||
await this.api.deleteDevice({ subnet: subnet.range, ip })
|
||||
} catch (e: any) {
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
import { AsyncPipe } from '@angular/common'
|
||||
import { ChangeDetectionStrategy, Component, inject } from '@angular/core'
|
||||
import {
|
||||
NonNullableFormBuilder,
|
||||
ReactiveFormsModule,
|
||||
Validators,
|
||||
} from '@angular/forms'
|
||||
import { ErrorService, LoadingService } from '@start9labs/shared'
|
||||
import { ErrorService } from '@start9labs/shared'
|
||||
import { WA_IS_MOBILE } from '@ng-web-apis/platform'
|
||||
import {
|
||||
TUI_IS_MOBILE,
|
||||
tuiMarkControlAsTouchedAndValidate,
|
||||
TuiValueChanges,
|
||||
} from '@taiga-ui/cdk'
|
||||
@@ -16,18 +15,16 @@ import {
|
||||
TuiDialogContext,
|
||||
TuiError,
|
||||
TuiNumberFormat,
|
||||
TuiTextfield,
|
||||
TuiCheckbox,
|
||||
} from '@taiga-ui/core'
|
||||
import {
|
||||
TuiCheckbox,
|
||||
TuiChevron,
|
||||
TuiDataListWrapper,
|
||||
TuiFieldErrorPipe,
|
||||
TuiInputNumber,
|
||||
TuiNotificationMiddleService,
|
||||
TuiSelect,
|
||||
TuiElasticContainer,
|
||||
} from '@taiga-ui/kit'
|
||||
import { TuiForm } from '@taiga-ui/layout'
|
||||
import { TuiForm, TuiElasticContainer } from '@taiga-ui/layout'
|
||||
import { injectContext, PolymorpheusComponent } from '@taiga-ui/polymorpheus'
|
||||
import { ApiService } from 'src/app/services/api/api.service'
|
||||
|
||||
@@ -49,17 +46,10 @@ import { MappedDevice, PortForwardsData } from './utils'
|
||||
<input tuiSelect formControlName="externalip" />
|
||||
}
|
||||
@if (!mobile) {
|
||||
<tui-data-list-wrapper
|
||||
*tuiTextfieldDropdown
|
||||
new
|
||||
[items]="context.data.ips()"
|
||||
/>
|
||||
<tui-data-list-wrapper *tuiDropdown [items]="context.data.ips()" />
|
||||
}
|
||||
</tui-textfield>
|
||||
<tui-error
|
||||
formControlName="externalip"
|
||||
[error]="[] | tuiFieldError | async"
|
||||
/>
|
||||
<tui-error formControlName="externalip" />
|
||||
<tui-textfield>
|
||||
<label tuiLabel>External Port</label>
|
||||
<input
|
||||
@@ -71,10 +61,7 @@ import { MappedDevice, PortForwardsData } from './utils'
|
||||
(tuiValueChanges)="checkShow80()"
|
||||
/>
|
||||
</tui-textfield>
|
||||
<tui-error
|
||||
formControlName="externalport"
|
||||
[error]="[] | tuiFieldError | async"
|
||||
/>
|
||||
<tui-error formControlName="externalport" />
|
||||
<tui-textfield tuiChevron [stringify]="stringify">
|
||||
<label tuiLabel>Device</label>
|
||||
@if (mobile) {
|
||||
@@ -89,16 +76,12 @@ import { MappedDevice, PortForwardsData } from './utils'
|
||||
}
|
||||
@if (!mobile) {
|
||||
<tui-data-list-wrapper
|
||||
*tuiTextfieldDropdown
|
||||
new
|
||||
*tuiDropdown
|
||||
[items]="context.data.devices()"
|
||||
/>
|
||||
}
|
||||
</tui-textfield>
|
||||
<tui-error
|
||||
formControlName="device"
|
||||
[error]="[] | tuiFieldError | async"
|
||||
/>
|
||||
<tui-error formControlName="device" />
|
||||
<tui-textfield>
|
||||
<label tuiLabel>Internal Port</label>
|
||||
<input
|
||||
@@ -110,10 +93,7 @@ import { MappedDevice, PortForwardsData } from './utils'
|
||||
(tuiValueChanges)="checkShow80()"
|
||||
/>
|
||||
</tui-textfield>
|
||||
<tui-error
|
||||
formControlName="internalport"
|
||||
[error]="[] | tuiFieldError | async"
|
||||
/>
|
||||
<tui-error formControlName="internalport" />
|
||||
<tui-elastic-container>
|
||||
@if (show80) {
|
||||
<label tuiLabel>
|
||||
@@ -132,7 +112,6 @@ import { MappedDevice, PortForwardsData } from './utils'
|
||||
`,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
imports: [
|
||||
AsyncPipe,
|
||||
ReactiveFormsModule,
|
||||
TuiButton,
|
||||
TuiChevron,
|
||||
@@ -140,8 +119,6 @@ import { MappedDevice, PortForwardsData } from './utils'
|
||||
TuiError,
|
||||
TuiInputNumber,
|
||||
TuiNumberFormat,
|
||||
TuiFieldErrorPipe,
|
||||
TuiTextfield,
|
||||
TuiSelect,
|
||||
TuiForm,
|
||||
TuiCheckbox,
|
||||
@@ -151,12 +128,12 @@ import { MappedDevice, PortForwardsData } from './utils'
|
||||
})
|
||||
export class PortForwardsAdd {
|
||||
private readonly api = inject(ApiService)
|
||||
private readonly loading = inject(LoadingService)
|
||||
private readonly loading = inject(TuiNotificationMiddleService)
|
||||
private readonly errorService = inject(ErrorService)
|
||||
|
||||
show80 = false
|
||||
|
||||
protected readonly mobile = inject(TUI_IS_MOBILE)
|
||||
protected readonly mobile = inject(WA_IS_MOBILE)
|
||||
protected readonly context =
|
||||
injectContext<TuiDialogContext<void, PortForwardsData>>()
|
||||
|
||||
@@ -183,7 +160,7 @@ export class PortForwardsAdd {
|
||||
return
|
||||
}
|
||||
|
||||
const loader = this.loading.open().subscribe()
|
||||
const loader = this.loading.open('').subscribe()
|
||||
|
||||
const { externalip, externalport, device, internalport, also80 } =
|
||||
this.form.getRawValue()
|
||||
|
||||
@@ -7,11 +7,11 @@ import {
|
||||
} from '@angular/core'
|
||||
import { toSignal } from '@angular/core/rxjs-interop'
|
||||
import { ReactiveFormsModule } from '@angular/forms'
|
||||
import { ErrorService, LoadingService } from '@start9labs/shared'
|
||||
import { ErrorService } from '@start9labs/shared'
|
||||
import { utils } from '@start9labs/start-sdk'
|
||||
import { TuiResponsiveDialogService } from '@taiga-ui/addon-mobile'
|
||||
import { TuiButton } from '@taiga-ui/core'
|
||||
import { TuiDialogService } from '@taiga-ui/experimental'
|
||||
import { TUI_CONFIRM } from '@taiga-ui/kit'
|
||||
import { TUI_CONFIRM, TuiNotificationMiddleService } from '@taiga-ui/kit'
|
||||
import { PatchDB } from 'patch-db-client'
|
||||
import { filter, map } from 'rxjs'
|
||||
import { PORT_FORWARDS_ADD } from 'src/app/routes/home/routes/port-forwards/add'
|
||||
@@ -65,9 +65,9 @@ import { MappedDevice, MappedForward } from './utils'
|
||||
imports: [ReactiveFormsModule, TuiButton],
|
||||
})
|
||||
export default class PortForwards {
|
||||
private readonly dialogs = inject(TuiDialogService)
|
||||
private readonly dialogs = inject(TuiResponsiveDialogService)
|
||||
private readonly api = inject(ApiService)
|
||||
private readonly loading = inject(LoadingService)
|
||||
private readonly loading = inject(TuiNotificationMiddleService)
|
||||
private readonly patch = inject<PatchDB<TunnelData>>(PatchDB)
|
||||
private readonly errorService = inject(ErrorService)
|
||||
|
||||
@@ -127,7 +127,7 @@ export default class PortForwards {
|
||||
.open(TUI_CONFIRM, { label: 'Are you sure?' })
|
||||
.pipe(filter(Boolean))
|
||||
.subscribe(async () => {
|
||||
const loader = this.loading.open().subscribe()
|
||||
const loader = this.loading.open('').subscribe()
|
||||
const source = `${externalip}:${externalport}`
|
||||
|
||||
try {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { AsyncPipe } from '@angular/common'
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
@@ -15,17 +14,14 @@ import {
|
||||
import { ErrorService } from '@start9labs/shared'
|
||||
import { TuiAutoFocus, TuiValidator } from '@taiga-ui/cdk'
|
||||
import {
|
||||
TuiAlertService,
|
||||
TuiButton,
|
||||
TuiDialogContext,
|
||||
TuiError,
|
||||
TuiTextfield,
|
||||
} from '@taiga-ui/core'
|
||||
import {
|
||||
TuiButtonLoading,
|
||||
TuiFieldErrorPipe,
|
||||
TuiNotificationService,
|
||||
TuiInput,
|
||||
tuiValidationErrorsProvider,
|
||||
} from '@taiga-ui/kit'
|
||||
} from '@taiga-ui/core'
|
||||
import { TuiButtonLoading } from '@taiga-ui/kit'
|
||||
import { TuiForm } from '@taiga-ui/layout'
|
||||
import { injectContext, PolymorpheusComponent } from '@taiga-ui/polymorpheus'
|
||||
import { map } from 'rxjs'
|
||||
@@ -36,24 +32,18 @@ import { ApiService } from 'src/app/services/api/api.service'
|
||||
<form tuiForm [formGroup]="form">
|
||||
<tui-textfield>
|
||||
<label tuiLabel>New password</label>
|
||||
<input tuiTextfield tuiAutoFocus formControlName="password" />
|
||||
<input tuiInput tuiAutoFocus formControlName="password" />
|
||||
</tui-textfield>
|
||||
<tui-error
|
||||
formControlName="password"
|
||||
[error]="[] | tuiFieldError | async"
|
||||
/>
|
||||
<tui-error formControlName="password" />
|
||||
<tui-textfield>
|
||||
<label tuiLabel>Confirm new password</label>
|
||||
<input
|
||||
tuiTextfield
|
||||
tuiInput
|
||||
formControlName="confirm"
|
||||
[tuiValidator]="matchValidator()"
|
||||
/>
|
||||
</tui-textfield>
|
||||
<tui-error
|
||||
formControlName="confirm"
|
||||
[error]="[] | tuiFieldError | async"
|
||||
/>
|
||||
<tui-error formControlName="confirm" />
|
||||
<footer>
|
||||
<button
|
||||
tuiButton
|
||||
@@ -76,22 +66,20 @@ import { ApiService } from 'src/app/services/api/api.service'
|
||||
],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
imports: [
|
||||
AsyncPipe,
|
||||
ReactiveFormsModule,
|
||||
TuiAutoFocus,
|
||||
TuiButton,
|
||||
TuiButtonLoading,
|
||||
TuiError,
|
||||
TuiFieldErrorPipe,
|
||||
TuiForm,
|
||||
TuiTextfield,
|
||||
TuiInput,
|
||||
TuiValidator,
|
||||
],
|
||||
})
|
||||
export class ChangePasswordDialog {
|
||||
private readonly context = injectContext<TuiDialogContext<void>>()
|
||||
private readonly api = inject(ApiService)
|
||||
private readonly alerts = inject(TuiAlertService)
|
||||
private readonly alerts = inject(TuiNotificationService)
|
||||
private readonly errorService = inject(ErrorService)
|
||||
|
||||
protected readonly loading = signal(false)
|
||||
|
||||
@@ -5,25 +5,25 @@ import {
|
||||
signal,
|
||||
} from '@angular/core'
|
||||
import { ErrorService } from '@start9labs/shared'
|
||||
import { TuiAppearance, TuiButton, TuiTitle } from '@taiga-ui/core'
|
||||
import { TuiDialogService } from '@taiga-ui/experimental'
|
||||
import { TuiResponsiveDialogService } from '@taiga-ui/addon-mobile'
|
||||
import { TuiButton, TuiCell, TuiTitle } from '@taiga-ui/core'
|
||||
import { TuiBadge, TuiButtonLoading } from '@taiga-ui/kit'
|
||||
import { TuiCard, TuiCell } from '@taiga-ui/layout'
|
||||
import { TuiCard } from '@taiga-ui/layout'
|
||||
import { UpdateService } from 'src/app/services/update.service'
|
||||
|
||||
import { CHANGE_PASSWORD } from './change-password'
|
||||
|
||||
@Component({
|
||||
template: `
|
||||
<div tuiCardLarge tuiAppearance="neutral">
|
||||
<div tuiCardLarge>
|
||||
<div tuiCell>
|
||||
<span tuiTitle>
|
||||
<strong>
|
||||
Version
|
||||
@if (update.hasUpdate()) {
|
||||
<tui-badge appearance="positive" size="s">
|
||||
<span tuiBadge appearance="positive" size="s">
|
||||
Update Available
|
||||
</tui-badge>
|
||||
</span>
|
||||
}
|
||||
</strong>
|
||||
<span tuiSubtitle>Current: {{ update.installed() ?? '—' }}</span>
|
||||
@@ -52,19 +52,20 @@ import { CHANGE_PASSWORD } from './change-password'
|
||||
</div>
|
||||
</div>
|
||||
`,
|
||||
styles: `
|
||||
[tuiCardLarge] {
|
||||
background: var(--tui-background-neutral-1);
|
||||
|
||||
&:not([data-appearance]) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
`,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
imports: [
|
||||
TuiCard,
|
||||
TuiCell,
|
||||
TuiTitle,
|
||||
TuiButton,
|
||||
TuiButtonLoading,
|
||||
TuiBadge,
|
||||
TuiAppearance,
|
||||
],
|
||||
imports: [TuiCard, TuiCell, TuiTitle, TuiButton, TuiButtonLoading, TuiBadge],
|
||||
})
|
||||
export default class Settings {
|
||||
private readonly dialogs = inject(TuiDialogService)
|
||||
private readonly dialogs = inject(TuiResponsiveDialogService)
|
||||
private readonly errorService = inject(ErrorService)
|
||||
|
||||
protected readonly update = inject(UpdateService)
|
||||
|
||||
@@ -1,19 +1,12 @@
|
||||
import { AsyncPipe } from '@angular/common'
|
||||
import { ChangeDetectionStrategy, Component, inject } from '@angular/core'
|
||||
import {
|
||||
NonNullableFormBuilder,
|
||||
ReactiveFormsModule,
|
||||
Validators,
|
||||
} from '@angular/forms'
|
||||
import { LoadingService } from '@start9labs/shared'
|
||||
import { TuiAutoFocus, tuiMarkControlAsTouchedAndValidate } from '@taiga-ui/cdk'
|
||||
import {
|
||||
TuiButton,
|
||||
TuiDialogContext,
|
||||
TuiError,
|
||||
TuiTextfield,
|
||||
} from '@taiga-ui/core'
|
||||
import { TuiFieldErrorPipe } from '@taiga-ui/kit'
|
||||
import { TuiButton, TuiDialogContext, TuiError, TuiInput } from '@taiga-ui/core'
|
||||
import { TuiNotificationMiddleService } from '@taiga-ui/kit'
|
||||
import { TuiForm } from '@taiga-ui/layout'
|
||||
import { injectContext, PolymorpheusComponent } from '@taiga-ui/polymorpheus'
|
||||
import { ApiService } from 'src/app/services/api/api.service'
|
||||
@@ -23,18 +16,15 @@ import { ApiService } from 'src/app/services/api/api.service'
|
||||
<form tuiForm [formGroup]="form">
|
||||
<tui-textfield>
|
||||
<label tuiLabel>Name</label>
|
||||
<input tuiTextfield tuiAutoFocus formControlName="name" />
|
||||
<input tuiInput tuiAutoFocus formControlName="name" />
|
||||
</tui-textfield>
|
||||
<tui-error formControlName="name" [error]="[] | tuiFieldError | async" />
|
||||
<tui-error formControlName="name" />
|
||||
@if (!context.data.name) {
|
||||
<tui-textfield>
|
||||
<label tuiLabel>IP Range</label>
|
||||
<input tuiTextfield formControlName="subnet" />
|
||||
<input tuiInput formControlName="subnet" />
|
||||
</tui-textfield>
|
||||
<tui-error
|
||||
formControlName="subnet"
|
||||
[error]="[] | tuiFieldError | async"
|
||||
/>
|
||||
<tui-error formControlName="subnet" />
|
||||
}
|
||||
<footer>
|
||||
<button tuiButton (click)="onSave()">Save</button>
|
||||
@@ -43,19 +33,17 @@ import { ApiService } from 'src/app/services/api/api.service'
|
||||
`,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
imports: [
|
||||
AsyncPipe,
|
||||
ReactiveFormsModule,
|
||||
TuiAutoFocus,
|
||||
TuiButton,
|
||||
TuiError,
|
||||
TuiFieldErrorPipe,
|
||||
TuiForm,
|
||||
TuiTextfield,
|
||||
TuiInput,
|
||||
],
|
||||
})
|
||||
export class SubnetsAdd {
|
||||
private readonly api = inject(ApiService)
|
||||
private readonly loading = inject(LoadingService)
|
||||
private readonly loading = inject(TuiNotificationMiddleService)
|
||||
|
||||
protected readonly context = injectContext<TuiDialogContext<void, Data>>()
|
||||
protected readonly form = inject(NonNullableFormBuilder).group({
|
||||
@@ -78,7 +66,7 @@ export class SubnetsAdd {
|
||||
return
|
||||
}
|
||||
|
||||
const loader = this.loading.open().subscribe()
|
||||
const loader = this.loading.open('').subscribe()
|
||||
const value = this.form.getRawValue()
|
||||
|
||||
try {
|
||||
|
||||
@@ -1,15 +1,9 @@
|
||||
import { ChangeDetectionStrategy, Component, inject } from '@angular/core'
|
||||
import { toSignal } from '@angular/core/rxjs-interop'
|
||||
import { LoadingService } from '@start9labs/shared'
|
||||
import { utils } from '@start9labs/start-sdk'
|
||||
import {
|
||||
TuiButton,
|
||||
TuiDataList,
|
||||
TuiDropdown,
|
||||
TuiTextfield,
|
||||
} from '@taiga-ui/core'
|
||||
import { TuiDialogService } from '@taiga-ui/experimental'
|
||||
import { TUI_CONFIRM } from '@taiga-ui/kit'
|
||||
import { TuiResponsiveDialogService } from '@taiga-ui/addon-mobile'
|
||||
import { TuiButton, TuiDataList, TuiDropdown } from '@taiga-ui/core'
|
||||
import { TUI_CONFIRM, TuiNotificationMiddleService } from '@taiga-ui/kit'
|
||||
import { PatchDB } from 'patch-db-client'
|
||||
import { filter, map } from 'rxjs'
|
||||
import { ApiService } from 'src/app/services/api/api.service'
|
||||
@@ -41,16 +35,15 @@ import { SUBNETS_ADD } from './add'
|
||||
tuiIconButton
|
||||
size="xs"
|
||||
tuiDropdown
|
||||
tuiDropdownOpen
|
||||
tuiDropdownAuto
|
||||
appearance="flat-grayscale"
|
||||
iconStart="@tui.ellipsis-vertical"
|
||||
>
|
||||
Actions
|
||||
<tui-data-list *tuiTextfieldDropdown size="s">
|
||||
<tui-data-list *tuiDropdown size="s">
|
||||
<button
|
||||
tuiOption
|
||||
iconStart="@tui.pencil"
|
||||
new
|
||||
(click)="onEdit(subnet)"
|
||||
>
|
||||
Rename
|
||||
@@ -58,7 +51,6 @@ import { SUBNETS_ADD } from './add'
|
||||
<button
|
||||
tuiOption
|
||||
iconStart="@tui.trash"
|
||||
new
|
||||
(click)="onDelete($index)"
|
||||
>
|
||||
Delete
|
||||
@@ -74,12 +66,12 @@ import { SUBNETS_ADD } from './add'
|
||||
</table>
|
||||
`,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
imports: [TuiButton, TuiDropdown, TuiDataList, TuiTextfield],
|
||||
imports: [TuiButton, TuiDropdown, TuiDataList],
|
||||
})
|
||||
export default class Subnets {
|
||||
private readonly dialogs = inject(TuiDialogService)
|
||||
private readonly dialogs = inject(TuiResponsiveDialogService)
|
||||
private readonly api = inject(ApiService)
|
||||
private readonly loading = inject(LoadingService)
|
||||
private readonly loading = inject(TuiNotificationMiddleService)
|
||||
|
||||
protected readonly subnets = toSignal<MappedSubnet[], []>(
|
||||
inject<PatchDB<TunnelData>>(PatchDB)
|
||||
@@ -120,7 +112,7 @@ export default class Subnets {
|
||||
.pipe(filter(Boolean))
|
||||
.subscribe(async () => {
|
||||
const subnet = this.subnets()[index]?.range || ''
|
||||
const loader = this.loading.open().subscribe()
|
||||
const loader = this.loading.open('').subscribe()
|
||||
|
||||
try {
|
||||
await this.api.deleteSubnet({ subnet })
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
} from '@angular/core'
|
||||
import { FormsModule } from '@angular/forms'
|
||||
import { Router } from '@angular/router'
|
||||
import { TuiButton, TuiError, TuiTextfield } from '@taiga-ui/core'
|
||||
import { TuiButton, TuiError, TuiInput } from '@taiga-ui/core'
|
||||
import { TuiButtonLoading } from '@taiga-ui/kit'
|
||||
import { ApiService } from 'src/app/services/api/api.service'
|
||||
import { AuthService } from 'src/app/services/auth.service'
|
||||
@@ -17,7 +17,7 @@ import { AuthService } from 'src/app/services/auth.service'
|
||||
<form (ngSubmit)="login()">
|
||||
<tui-textfield [tuiTextfieldCleaner]="false">
|
||||
<input
|
||||
tuiTextfield
|
||||
tuiInput
|
||||
type="password"
|
||||
placeholder="Enter password"
|
||||
[ngModelOptions]="{ standalone: true }"
|
||||
@@ -59,7 +59,7 @@ import { AuthService } from 'src/app/services/auth.service'
|
||||
}
|
||||
`,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
imports: [TuiButton, TuiTextfield, FormsModule, TuiError, TuiButtonLoading],
|
||||
imports: [TuiButton, TuiInput, FormsModule, TuiError, TuiButtonLoading],
|
||||
})
|
||||
export default class Login {
|
||||
private readonly auth = inject(AuthService)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Component, computed, inject, Injectable, signal } from '@angular/core'
|
||||
import { toObservable } from '@angular/core/rxjs-interop'
|
||||
import { ErrorService } from '@start9labs/shared'
|
||||
import { TuiResponsiveDialogService } from '@taiga-ui/addon-mobile'
|
||||
import { TuiLoader } from '@taiga-ui/core'
|
||||
import { TuiDialogService } from '@taiga-ui/experimental'
|
||||
import { PolymorpheusComponent } from '@taiga-ui/polymorpheus'
|
||||
import {
|
||||
catchError,
|
||||
@@ -31,7 +31,7 @@ class UpdatingDialog {
|
||||
export class UpdateService {
|
||||
private readonly api = inject(ApiService)
|
||||
private readonly auth = inject(AuthService)
|
||||
private readonly dialogs = inject(TuiDialogService)
|
||||
private readonly dialogs = inject(TuiResponsiveDialogService)
|
||||
private readonly errorService = inject(ErrorService)
|
||||
|
||||
readonly result = signal<TunnelUpdateResult | null>(null)
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
<link rel="icon" type="image/svg+xml" href="/assets/icons/favicon.svg" />
|
||||
<link rel="shortcut icon" href="/assets/icons/favicon.ico" />
|
||||
</head>
|
||||
<body tuiTheme="dark">
|
||||
<body>
|
||||
<app-root></app-root>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
--tui-background-accent-1: #428bf9;
|
||||
--tui-background-accent-1-hover: #126df7;
|
||||
--tui-background-accent-1-pressed: #156ed4;
|
||||
--tui-stroke-width: 1.5px;
|
||||
}
|
||||
|
||||
body {
|
||||
@@ -41,9 +42,21 @@ tui-dropdown[data-appearance='start-9'] {
|
||||
backdrop-filter: blur(1rem);
|
||||
}
|
||||
|
||||
tui-dialog[new][data-appearance~='start-9'] {
|
||||
background: var(--tui-background-neutral-1);
|
||||
backdrop-filter: blur(5rem);
|
||||
[tuiTheme='dark'] tui-dialog[data-appearance~='start-9'],
|
||||
[tuiTheme='dark'] tui-sheet-dialog[data-appearance~='start-9'] .t-sheet {
|
||||
background:
|
||||
linear-gradient(45deg, #5240a89c, transparent),
|
||||
linear-gradient(to bottom, #5240a854, transparent),
|
||||
color-mix(in hsl, var(--tui-background-elevation-1) 90%, transparent 10%);
|
||||
background-blend-mode: multiply;
|
||||
|
||||
header {
|
||||
background: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
tui-notification-middle {
|
||||
--tui-background-accent-1: var(--tui-status-warning);
|
||||
}
|
||||
|
||||
.g-table {
|
||||
|
||||
@@ -14,7 +14,7 @@ import { PatchMonitorService } from './services/patch-monitor.service'
|
||||
selector: 'app-root',
|
||||
imports: [TuiRoot, RouterOutlet, ToastContainerComponent],
|
||||
template: `
|
||||
<tui-root tuiTheme="dark">
|
||||
<tui-root>
|
||||
<router-outlet />
|
||||
<toast-container />
|
||||
</tui-root>
|
||||
|
||||
@@ -10,7 +10,6 @@ import {
|
||||
provideZoneChangeDetection,
|
||||
} from '@angular/core'
|
||||
import { UntypedFormBuilder } from '@angular/forms'
|
||||
import { provideAnimations } from '@angular/platform-browser/animations'
|
||||
import {
|
||||
ActivationStart,
|
||||
PreloadAllModules,
|
||||
@@ -40,21 +39,22 @@ import {
|
||||
} from '@start9labs/shared'
|
||||
import { tuiObfuscateOptionsProvider } from '@taiga-ui/cdk'
|
||||
import {
|
||||
TUI_DATE_FORMAT,
|
||||
provideTaiga,
|
||||
TUI_DIALOGS_CLOSE,
|
||||
TUI_MEDIA,
|
||||
tuiAlertOptionsProvider,
|
||||
tuiButtonOptionsProvider,
|
||||
tuiDateFormatProvider,
|
||||
tuiDropdownOptionsProvider,
|
||||
tuiHintOptionsProvider,
|
||||
tuiNotificationOptionsProvider,
|
||||
tuiNumberFormatProvider,
|
||||
} from '@taiga-ui/core'
|
||||
import { provideEventPlugins } from '@taiga-ui/event-plugins'
|
||||
import {
|
||||
TUI_DATE_TIME_VALUE_TRANSFORMER,
|
||||
TUI_DATE_VALUE_TRANSFORMER,
|
||||
tuiInputDateOptionsProvider,
|
||||
tuiInputDateTimeOptionsProvider,
|
||||
} from '@taiga-ui/kit'
|
||||
import { PatchDB } from 'patch-db-client'
|
||||
import { filter, identity, merge, of, pairwise } from 'rxjs'
|
||||
import { filter, identity, merge, pairwise } from 'rxjs'
|
||||
import { FilterUpdatesPipe } from 'src/app/routes/portal/routes/updates/filter-updates.pipe'
|
||||
import { ApiService } from 'src/app/services/api/embassy-api.service'
|
||||
import { LiveApiService } from 'src/app/services/api/embassy-live-api.service'
|
||||
@@ -63,14 +63,16 @@ import { AuthService } from 'src/app/services/auth.service'
|
||||
import { CategoryService } from 'src/app/services/category.service'
|
||||
import { ClientStorageService } from 'src/app/services/client-storage.service'
|
||||
import { ConfigService } from 'src/app/services/config.service'
|
||||
import { DateTransformerService } from 'src/app/services/date-transformer.service'
|
||||
import { DatetimeTransformerService } from 'src/app/services/datetime-transformer.service'
|
||||
import {
|
||||
PATCH_CACHE,
|
||||
PatchDbSource,
|
||||
} from 'src/app/services/patch-db/patch-db-source'
|
||||
import { StateService } from 'src/app/services/state.service'
|
||||
import { StorageService } from 'src/app/services/storage.service'
|
||||
import {
|
||||
DateTransformer,
|
||||
DatetimeTransformer,
|
||||
} from 'src/app/utils/value-transformers'
|
||||
import { environment } from 'src/environments/environment'
|
||||
|
||||
import { ROUTES } from './app.routes'
|
||||
@@ -83,8 +85,7 @@ const {
|
||||
export const APP_CONFIG: ApplicationConfig = {
|
||||
providers: [
|
||||
provideZoneChangeDetection(),
|
||||
provideAnimations(),
|
||||
provideEventPlugins(),
|
||||
provideTaiga({ mode: 'dark' }),
|
||||
provideHttpClient(withInterceptorsFromDi(), withFetch()),
|
||||
provideRouter(
|
||||
ROUTES,
|
||||
@@ -107,24 +108,13 @@ export const APP_CONFIG: ApplicationConfig = {
|
||||
tuiNumberFormatProvider({ decimalSeparator: '.', thousandSeparator: '' }),
|
||||
tuiButtonOptionsProvider({ size: 'm' }),
|
||||
tuiDropdownOptionsProvider({ appearance: 'start-os' }),
|
||||
tuiAlertOptionsProvider({
|
||||
tuiNotificationOptionsProvider({
|
||||
autoClose: appearance => (appearance === 'negative' ? 0 : 3000),
|
||||
}),
|
||||
{
|
||||
provide: TUI_DATE_FORMAT,
|
||||
useValue: of({
|
||||
mode: 'MDY',
|
||||
separator: '/',
|
||||
}),
|
||||
},
|
||||
{
|
||||
provide: TUI_DATE_VALUE_TRANSFORMER,
|
||||
useClass: DateTransformerService,
|
||||
},
|
||||
{
|
||||
provide: TUI_DATE_TIME_VALUE_TRANSFORMER,
|
||||
useClass: DatetimeTransformerService,
|
||||
},
|
||||
tuiDateFormatProvider({ mode: 'mm/dd/yyyy', separator: '/' }),
|
||||
tuiInputDateOptionsProvider({ valueTransformer: DateTransformer }),
|
||||
tuiInputDateTimeOptionsProvider({ valueTransformer: DatetimeTransformer }),
|
||||
tuiHintOptionsProvider({ appearance: 'primary-grayscale' }),
|
||||
{
|
||||
provide: ApiService,
|
||||
useClass: useMocks ? MockApiService : LiveApiService,
|
||||
|
||||
@@ -7,8 +7,7 @@ import {
|
||||
} from '@angular/core'
|
||||
import { toSignal } from '@angular/core/rxjs-interop'
|
||||
import { i18nKey, i18nPipe } from '@start9labs/shared'
|
||||
import { TuiDialogContext, TuiIcon, TuiTitle } from '@taiga-ui/core'
|
||||
import { TuiCell } from '@taiga-ui/layout'
|
||||
import { TuiDialogContext, TuiIcon, TuiTitle, TuiCell } from '@taiga-ui/core'
|
||||
import { injectContext, PolymorpheusComponent } from '@taiga-ui/polymorpheus'
|
||||
import { PatchDB } from 'patch-db-client'
|
||||
import { map } from 'rxjs'
|
||||
|
||||
@@ -2,7 +2,7 @@ import { AsyncPipe } from '@angular/common'
|
||||
import { ChangeDetectionStrategy, Component, inject } from '@angular/core'
|
||||
import { RouterLink } from '@angular/router'
|
||||
import { i18nPipe } from '@start9labs/shared'
|
||||
import { TuiAlert, TuiLink } from '@taiga-ui/core'
|
||||
import { TuiLink, TuiNotification } from '@taiga-ui/core'
|
||||
import { PatchDB } from 'patch-db-client'
|
||||
import { endWith, map, merge, Observable, pairwise, Subject } from 'rxjs'
|
||||
import { DataModel } from 'src/app/services/patch-db/data-model'
|
||||
@@ -11,9 +11,9 @@ import { DataModel } from 'src/app/services/patch-db/data-model'
|
||||
selector: 'notifications-toast',
|
||||
template: `
|
||||
<ng-template
|
||||
[tuiAlert]="!!(visible$ | async)"
|
||||
[tuiAlertOptions]="{ label: 'StartOS' }"
|
||||
(tuiAlertChange)="onDismiss()"
|
||||
[tuiNotification]="!!(visible$ | async)"
|
||||
[tuiNotificationOptions]="{ label: 'StartOS' }"
|
||||
(tuiNotificationChange)="onDismiss()"
|
||||
>
|
||||
{{ 'New notifications' | i18n }}
|
||||
<a tuiLink routerLink="/notifications" [queryParams]="{ toast: true }">
|
||||
@@ -22,7 +22,7 @@ import { DataModel } from 'src/app/services/patch-db/data-model'
|
||||
</ng-template>
|
||||
`,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
imports: [TuiAlert, RouterLink, AsyncPipe, i18nPipe, TuiLink],
|
||||
imports: [TuiNotification, RouterLink, AsyncPipe, i18nPipe, TuiLink],
|
||||
})
|
||||
export class NotificationsToastComponent {
|
||||
private readonly dismiss$ = new Subject<boolean>()
|
||||
|
||||
@@ -2,11 +2,12 @@ import { ChangeDetectionStrategy, Component, inject } from '@angular/core'
|
||||
import { toSignal } from '@angular/core/rxjs-interop'
|
||||
import { SwUpdate } from '@angular/service-worker'
|
||||
import { WA_WINDOW } from '@ng-web-apis/common'
|
||||
import { i18nPipe, LoadingService } from '@start9labs/shared'
|
||||
import { i18nPipe } from '@start9labs/shared'
|
||||
import { Version } from '@start9labs/start-sdk'
|
||||
import { TuiResponsiveDialog } from '@taiga-ui/addon-mobile'
|
||||
import { TuiAutoFocus } from '@taiga-ui/cdk'
|
||||
import { TuiButton } from '@taiga-ui/core'
|
||||
import { TuiNotificationMiddleService } from '@taiga-ui/kit'
|
||||
import { PatchDB } from 'patch-db-client'
|
||||
import { distinctUntilChanged, map, merge, Subject } from 'rxjs'
|
||||
import { ConfigService } from 'src/app/services/config.service'
|
||||
@@ -74,7 +75,7 @@ import { DataModel } from 'src/app/services/patch-db/data-model'
|
||||
export class RefreshAlertComponent {
|
||||
private readonly win = inject(WA_WINDOW)
|
||||
private readonly updates = inject(SwUpdate)
|
||||
private readonly loader = inject(LoadingService)
|
||||
private readonly loader = inject(TuiNotificationMiddleService)
|
||||
private readonly version = Version.parse(inject(ConfigService).version)
|
||||
|
||||
readonly i18n = inject(i18nPipe)
|
||||
|
||||
@@ -2,13 +2,9 @@ import { CommonModule } from '@angular/common'
|
||||
import { Component, Inject } from '@angular/core'
|
||||
import { RouterLink } from '@angular/router'
|
||||
import { WA_WINDOW } from '@ng-web-apis/common'
|
||||
import {
|
||||
DialogService,
|
||||
i18nKey,
|
||||
i18nPipe,
|
||||
LoadingService,
|
||||
} from '@start9labs/shared'
|
||||
import { DialogService, i18nKey, i18nPipe } from '@start9labs/shared'
|
||||
import { TuiButton } from '@taiga-ui/core'
|
||||
import { TuiNotificationMiddleService } from '@taiga-ui/kit'
|
||||
import { filter } from 'rxjs'
|
||||
import { ApiService } from 'src/app/services/api/embassy-api.service'
|
||||
import { ConfigService } from 'src/app/services/config.service'
|
||||
@@ -29,7 +25,7 @@ export default class HomePage {
|
||||
}
|
||||
|
||||
constructor(
|
||||
private readonly loader: LoadingService,
|
||||
private readonly loader: TuiNotificationMiddleService,
|
||||
private readonly api: ApiService,
|
||||
private readonly dialog: DialogService,
|
||||
@Inject(WA_WINDOW) private readonly window: Window,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Component, inject, DOCUMENT } from '@angular/core'
|
||||
import { DocsLinkDirective, i18nPipe, RELATIVE_URL } from '@start9labs/shared'
|
||||
import { TuiButton, TuiIcon, TuiSurface } from '@taiga-ui/core'
|
||||
import { TuiCardLarge } from '@taiga-ui/layout'
|
||||
import { TuiButton, TuiIcon } from '@taiga-ui/core'
|
||||
import { TuiCardLarge, TuiSurface } from '@taiga-ui/layout'
|
||||
import { ApiService } from 'src/app/services/api/embassy-api.service'
|
||||
import { ConfigService } from 'src/app/services/config.service'
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
<label tuiLabel>{{ 'Password' | i18n }}</label>
|
||||
<input
|
||||
tuiAutoFocus
|
||||
tuiTextfield
|
||||
tuiInput
|
||||
type="password"
|
||||
[ngModelOptions]="{ standalone: true }"
|
||||
[(ngModel)]="password"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@use '@taiga-ui/core/styles/taiga-ui-local' as taiga;
|
||||
@use '@taiga-ui/styles/utils' as taiga;
|
||||
|
||||
.card {
|
||||
@include taiga.center-all();
|
||||
|
||||
@@ -3,10 +3,10 @@ import { Component, DestroyRef, DOCUMENT, inject, Inject } from '@angular/core'
|
||||
import { takeUntilDestroyed } from '@angular/core/rxjs-interop'
|
||||
import { FormsModule } from '@angular/forms'
|
||||
import { Router } from '@angular/router'
|
||||
import { i18nKey, i18nPipe, LoadingService } from '@start9labs/shared'
|
||||
import { i18nKey, i18nPipe } from '@start9labs/shared'
|
||||
import { TuiAutoFocus } from '@taiga-ui/cdk'
|
||||
import { TuiButton, TuiError, TuiIcon, TuiTextfield } from '@taiga-ui/core'
|
||||
import { TuiPassword } from '@taiga-ui/kit'
|
||||
import { TuiButton, TuiError, TuiIcon, TuiInput } from '@taiga-ui/core'
|
||||
import { TuiNotificationMiddleService, TuiPassword } from '@taiga-ui/kit'
|
||||
import { TuiCardLarge } from '@taiga-ui/layout'
|
||||
import { CAWizardComponent } from 'src/app/routes/login/ca-wizard/ca-wizard.component'
|
||||
import { ApiService } from 'src/app/services/api/embassy-api.service'
|
||||
@@ -23,7 +23,7 @@ import { ConfigService } from 'src/app/services/config.service'
|
||||
CAWizardComponent,
|
||||
TuiButton,
|
||||
TuiCardLarge,
|
||||
TuiTextfield,
|
||||
TuiInput,
|
||||
TuiIcon,
|
||||
TuiPassword,
|
||||
TuiAutoFocus,
|
||||
@@ -39,7 +39,7 @@ export default class LoginPage {
|
||||
constructor(
|
||||
private readonly router: Router,
|
||||
private readonly authService: AuthService,
|
||||
private readonly loader: LoadingService,
|
||||
private readonly loader: TuiNotificationMiddleService,
|
||||
private readonly api: ApiService,
|
||||
public readonly config: ConfigService,
|
||||
@Inject(DOCUMENT) public readonly document: Document,
|
||||
|
||||
@@ -14,7 +14,7 @@ import {
|
||||
} from '@taiga-ui/cdk'
|
||||
import { TuiButton, TuiDialogContext } from '@taiga-ui/core'
|
||||
import { TuiConfirmService } from '@taiga-ui/kit'
|
||||
import { POLYMORPHEUS_CONTEXT } from '@taiga-ui/polymorpheus'
|
||||
import { injectContext } from '@taiga-ui/polymorpheus'
|
||||
import { Operation } from 'fast-json-patch'
|
||||
import { FormGroupComponent } from 'src/app/routes/portal/components/form/containers/group.component'
|
||||
import { InvalidService } from 'src/app/routes/portal/components/form/containers/control.directive'
|
||||
@@ -76,7 +76,7 @@ export interface FormContext<T> {
|
||||
styles: `
|
||||
.note {
|
||||
color: var(--tui-text-secondary);
|
||||
font: var(--tui-font-text-s);
|
||||
font: var(--tui-typography-body-s);
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
@@ -107,10 +107,9 @@ export class FormComponent<T extends Record<string, any>> implements OnInit {
|
||||
private readonly confirm = inject(TuiConfirmService, { optional: true })
|
||||
private readonly formService = inject(FormService)
|
||||
private readonly invalidService = inject(InvalidService)
|
||||
private readonly context = inject<TuiDialogContext<void, FormContext<T>>>(
|
||||
POLYMORPHEUS_CONTEXT,
|
||||
{ optional: true },
|
||||
)
|
||||
private readonly context = injectContext<
|
||||
TuiDialogContext<void, FormContext<T>>
|
||||
>({ optional: true })
|
||||
|
||||
@Input() spec = this.context?.data.spec || {}
|
||||
@Input() buttons = this.context?.data.buttons || []
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { AsyncPipe } from '@angular/common'
|
||||
import {
|
||||
ChangeDetectorRef,
|
||||
Component,
|
||||
@@ -11,19 +10,14 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop'
|
||||
import {
|
||||
AbstractControl,
|
||||
FormArrayName,
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
} from '@angular/forms'
|
||||
import { DialogService, i18nKey, i18nPipe } from '@start9labs/shared'
|
||||
import { IST } from '@start9labs/start-sdk'
|
||||
import { TuiAnimated } from '@taiga-ui/cdk'
|
||||
import {
|
||||
TuiButton,
|
||||
TuiError,
|
||||
TuiIcon,
|
||||
TuiLink,
|
||||
TuiTextfield,
|
||||
} from '@taiga-ui/core'
|
||||
import { TuiFieldErrorPipe, TuiTooltip } from '@taiga-ui/kit'
|
||||
import { TuiButton, TuiError, TuiIcon, TuiInput, TuiLink } from '@taiga-ui/core'
|
||||
import { TuiTooltip } from '@taiga-ui/kit'
|
||||
import { filter } from 'rxjs'
|
||||
import { FormService } from 'src/app/services/form.service'
|
||||
|
||||
@@ -51,7 +45,13 @@ import { FormObjectComponent } from './object.component'
|
||||
+ {{ 'Add' | i18n }}
|
||||
</button>
|
||||
</div>
|
||||
<tui-error [error]="order | tuiFieldError | async" />
|
||||
<!-- TODO: Remove ngModel in Taiga v5.0 -->
|
||||
<tui-error
|
||||
[ngModel]=""
|
||||
[ngModelOptions]="{ standalone: true }"
|
||||
[formArray]="array.control"
|
||||
[order]="order"
|
||||
/>
|
||||
@for (item of array.control.controls; track item) {
|
||||
<div tuiAnimated class="control">
|
||||
<div>
|
||||
@@ -92,7 +92,7 @@ import { FormObjectComponent } from './object.component'
|
||||
}
|
||||
`,
|
||||
styles: `
|
||||
@use '@taiga-ui/core/styles/taiga-ui-local' as taiga;
|
||||
@use '@taiga-ui/styles/utils' as taiga;
|
||||
|
||||
:host {
|
||||
display: block;
|
||||
@@ -102,7 +102,7 @@ import { FormObjectComponent } from './object.component'
|
||||
.label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font: var(--tui-font-heading-6);
|
||||
font: var(--tui-typography-heading-h6);
|
||||
}
|
||||
|
||||
.add {
|
||||
@@ -173,21 +173,20 @@ import { FormObjectComponent } from './object.component'
|
||||
`,
|
||||
hostDirectives: [ControlDirective],
|
||||
imports: [
|
||||
AsyncPipe,
|
||||
ReactiveFormsModule,
|
||||
TuiIcon,
|
||||
TuiTooltip,
|
||||
TuiLink,
|
||||
TuiError,
|
||||
TuiFieldErrorPipe,
|
||||
TuiButton,
|
||||
TuiTextfield,
|
||||
TuiInput,
|
||||
i18nPipe,
|
||||
HintPipe,
|
||||
MustachePipe,
|
||||
FormControlComponent,
|
||||
forwardRef(() => FormObjectComponent),
|
||||
TuiAnimated,
|
||||
FormsModule,
|
||||
],
|
||||
})
|
||||
export class FormArrayComponent {
|
||||
|
||||
@@ -1,19 +1,15 @@
|
||||
import { AsyncPipe } from '@angular/common'
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
inject,
|
||||
Input,
|
||||
} from '@angular/core'
|
||||
import { ReactiveFormsModule } from '@angular/forms'
|
||||
import { DialogService, i18nPipe } from '@start9labs/shared'
|
||||
import { IST } from '@start9labs/start-sdk'
|
||||
import { tuiAsControl, TuiControl } from '@taiga-ui/cdk'
|
||||
import { TuiError } from '@taiga-ui/core'
|
||||
import {
|
||||
TUI_FORMAT_ERROR,
|
||||
TUI_VALIDATION_ERRORS,
|
||||
TuiFieldErrorPipe,
|
||||
} from '@taiga-ui/kit'
|
||||
import { TUI_VALIDATION_ERRORS, TuiError } from '@taiga-ui/core'
|
||||
import { TUI_FORMAT_ERROR } from '@taiga-ui/kit'
|
||||
import { PolymorpheusOutlet } from '@taiga-ui/polymorpheus'
|
||||
|
||||
import { ControlSpec } from '../controls/control'
|
||||
@@ -35,7 +31,7 @@ export const ERRORS = [
|
||||
selector: 'form-control',
|
||||
template: `
|
||||
<ng-container *polymorpheusOutlet="controls[spec.type]" />
|
||||
<tui-error [error]="order | tuiFieldError | async" />
|
||||
<tui-error [formControl]="$any(control.control)" [order]="order" />
|
||||
`,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
providers: [
|
||||
@@ -53,7 +49,7 @@ export const ERRORS = [
|
||||
},
|
||||
],
|
||||
hostDirectives: [ControlDirective],
|
||||
imports: [AsyncPipe, PolymorpheusOutlet, TuiError, TuiFieldErrorPipe],
|
||||
imports: [PolymorpheusOutlet, TuiError, ReactiveFormsModule],
|
||||
})
|
||||
export class FormControlComponent<
|
||||
T extends ControlSpec,
|
||||
@@ -91,7 +87,7 @@ export class FormControlComponent<
|
||||
.openConfirm({
|
||||
label: 'Warning',
|
||||
data: { content: warning as any, yes: 'Confirm', no: 'Cancel' },
|
||||
closeable: false,
|
||||
closable: false,
|
||||
dismissible: false,
|
||||
})
|
||||
.subscribe(confirm => {
|
||||
|
||||
@@ -3,13 +3,14 @@ import {
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
Input,
|
||||
signal,
|
||||
SkipSelf,
|
||||
ViewEncapsulation,
|
||||
} from '@angular/core'
|
||||
import { ControlContainer, ReactiveFormsModule } from '@angular/forms'
|
||||
import { IST } from '@start9labs/start-sdk'
|
||||
import { TUI_DEFAULT_ERROR_MESSAGE } from '@taiga-ui/core'
|
||||
import { identity, of } from 'rxjs'
|
||||
import { identity } from 'rxjs'
|
||||
|
||||
import { FilterHiddenPipe } from '../pipes/filter-hidden.pipe'
|
||||
import { FormArrayComponent } from './array.component'
|
||||
@@ -92,7 +93,7 @@ import { FormUnionComponent } from './union.component'
|
||||
viewProviders: [
|
||||
{
|
||||
provide: TUI_DEFAULT_ERROR_MESSAGE,
|
||||
useValue: of('Unknown error'),
|
||||
useValue: signal('Unknown error'),
|
||||
},
|
||||
{
|
||||
provide: ControlContainer,
|
||||
|
||||
@@ -9,8 +9,7 @@ import {
|
||||
} from '@angular/core'
|
||||
import { ControlContainer } from '@angular/forms'
|
||||
import { IST } from '@start9labs/start-sdk'
|
||||
import { TuiButton, TuiIcon } from '@taiga-ui/core'
|
||||
import { TuiExpand } from '@taiga-ui/experimental'
|
||||
import { TuiButton, TuiIcon, TuiExpand } from '@taiga-ui/core'
|
||||
import { TuiTooltip } from '@taiga-ui/kit'
|
||||
|
||||
import { ControlDirective } from './control.directive'
|
||||
@@ -43,7 +42,7 @@ import { FormGroupComponent } from './group.component'
|
||||
</tui-expand>
|
||||
`,
|
||||
styles: `
|
||||
@use '@taiga-ui/core/styles/taiga-ui-local' as taiga;
|
||||
@use '@taiga-ui/styles/utils' as taiga;
|
||||
|
||||
:host {
|
||||
display: flex;
|
||||
@@ -57,7 +56,7 @@ import { FormGroupComponent } from './group.component'
|
||||
display: flex;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
font: var(--tui-font-text-l);
|
||||
font: var(--tui-typography-body-l);
|
||||
font-weight: bold;
|
||||
margin: 0 0 -0.75rem;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { TuiElasticContainer } from '@taiga-ui/layout'
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
@@ -13,7 +14,6 @@ import {
|
||||
} from '@angular/forms'
|
||||
import { IST } from '@start9labs/start-sdk'
|
||||
import { TuiValueChanges } from '@taiga-ui/cdk'
|
||||
import { TuiElasticContainer } from '@taiga-ui/kit'
|
||||
import { FormService } from 'src/app/services/form.service'
|
||||
import { FormControlComponent } from './control.component'
|
||||
import { FormGroupComponent } from './group.component'
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { ChangeDetectionStrategy, Component } from '@angular/core'
|
||||
import { FormsModule } from '@angular/forms'
|
||||
import { IST } from '@start9labs/start-sdk'
|
||||
import { TuiIcon, TuiTextfield } from '@taiga-ui/core'
|
||||
import { TuiIcon, TuiInput } from '@taiga-ui/core'
|
||||
import { TuiInputColor, TuiTooltip } from '@taiga-ui/kit'
|
||||
|
||||
import { Control } from './control'
|
||||
@@ -35,7 +35,7 @@ import { HintPipe } from '../pipes/hint.pipe'
|
||||
`,
|
||||
imports: [
|
||||
FormsModule,
|
||||
TuiTextfield,
|
||||
TuiInput,
|
||||
TuiInputColor,
|
||||
TuiIcon,
|
||||
TuiTooltip,
|
||||
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
TuiMapperPipe,
|
||||
TuiTime,
|
||||
} from '@taiga-ui/cdk'
|
||||
import { TuiIcon, TuiTextfield } from '@taiga-ui/core'
|
||||
import { TuiIcon, TuiInput } from '@taiga-ui/core'
|
||||
import {
|
||||
TuiInputDate,
|
||||
TuiInputDateTime,
|
||||
@@ -22,21 +22,23 @@ import { HintPipe } from '../pipes/hint.pipe'
|
||||
@Component({
|
||||
selector: 'form-datetime',
|
||||
template: `
|
||||
<!--
|
||||
TODO: Move @switch down to only affect <input ... /> after fix:
|
||||
https://github.com/taiga-family/taiga-ui/issues/11780
|
||||
-->
|
||||
@switch (spec.inputmode) {
|
||||
@case ('time') {
|
||||
<tui-textfield (tuiActiveZoneChange)="!$event && control.onTouched()">
|
||||
@if (spec.name) {
|
||||
<label tuiLabel>
|
||||
{{ spec.name }}
|
||||
@if (spec.required) {
|
||||
<span>*</span>
|
||||
}
|
||||
</label>
|
||||
<tui-textfield (tuiActiveZoneChange)="!$event && control.onTouched()">
|
||||
@if (spec.name) {
|
||||
<label tuiLabel>
|
||||
{{ spec.name }}
|
||||
@if (spec.required) {
|
||||
<span>*</span>
|
||||
}
|
||||
</label>
|
||||
}
|
||||
@if (spec | hint; as hint) {
|
||||
<tui-icon [tuiTooltip]="hint" />
|
||||
}
|
||||
@if (spec.inputmode !== 'time') {
|
||||
<tui-calendar *tuiDropdown />
|
||||
}
|
||||
@switch (spec.inputmode) {
|
||||
@case ('time') {
|
||||
<input
|
||||
tuiInputTime
|
||||
type="time"
|
||||
@@ -47,21 +49,8 @@ import { HintPipe } from '../pipes/hint.pipe'
|
||||
(ngModelChange)="value = $event?.toString() || null"
|
||||
(blur)="control.onTouched()"
|
||||
/>
|
||||
@if (spec | hint; as hint) {
|
||||
<tui-icon [tuiTooltip]="hint" />
|
||||
}
|
||||
</tui-textfield>
|
||||
}
|
||||
@case ('date') {
|
||||
<tui-textfield (tuiActiveZoneChange)="!$event && control.onTouched()">
|
||||
@if (spec.name) {
|
||||
<label tuiLabel>
|
||||
{{ spec.name }}
|
||||
@if (spec.required) {
|
||||
<span>*</span>
|
||||
}
|
||||
</label>
|
||||
}
|
||||
}
|
||||
@case ('date') {
|
||||
<input
|
||||
tuiInputDate
|
||||
type="date"
|
||||
@@ -73,22 +62,8 @@ import { HintPipe } from '../pipes/hint.pipe'
|
||||
[(ngModel)]="value"
|
||||
(blur)="control.onTouched()"
|
||||
/>
|
||||
@if (spec | hint; as hint) {
|
||||
<tui-icon [tuiTooltip]="hint" />
|
||||
}
|
||||
<tui-calendar *tuiTextfieldDropdown />
|
||||
</tui-textfield>
|
||||
}
|
||||
@case ('datetime-local') {
|
||||
<tui-textfield (tuiActiveZoneChange)="!$event && control.onTouched()">
|
||||
@if (spec.name) {
|
||||
<label tuiLabel>
|
||||
{{ spec.name }}
|
||||
@if (spec.required) {
|
||||
<span>*</span>
|
||||
}
|
||||
</label>
|
||||
}
|
||||
}
|
||||
@case ('datetime-local') {
|
||||
<input
|
||||
tuiInputDateTime
|
||||
type="datetime-local"
|
||||
@@ -100,17 +75,13 @@ import { HintPipe } from '../pipes/hint.pipe'
|
||||
[(ngModel)]="value"
|
||||
(blur)="control.onTouched()"
|
||||
/>
|
||||
@if (spec | hint; as hint) {
|
||||
<tui-icon [tuiTooltip]="hint" />
|
||||
}
|
||||
<tui-calendar *tuiTextfieldDropdown />
|
||||
</tui-textfield>
|
||||
}
|
||||
}
|
||||
}
|
||||
</tui-textfield>
|
||||
`,
|
||||
imports: [
|
||||
FormsModule,
|
||||
TuiTextfield,
|
||||
TuiInput,
|
||||
TuiIcon,
|
||||
TuiTooltip,
|
||||
TuiInputTime,
|
||||
|
||||
@@ -30,7 +30,7 @@ import { Control } from './control'
|
||||
}
|
||||
</div>
|
||||
@if (value) {
|
||||
<tui-chip>
|
||||
<span tuiChip>
|
||||
{{ value.name }}
|
||||
<button
|
||||
tuiIconButton
|
||||
@@ -42,7 +42,7 @@ import { Control } from './control'
|
||||
>
|
||||
{{ 'Delete' | i18n }}
|
||||
</button>
|
||||
</tui-chip>
|
||||
</span>
|
||||
} @else {
|
||||
<small>{{ 'Click or drop file here' | i18n }}</small>
|
||||
}
|
||||
@@ -54,7 +54,7 @@ import { Control } from './control'
|
||||
</label>
|
||||
`,
|
||||
styles: `
|
||||
@use '@taiga-ui/core/styles/taiga-ui-local' as taiga;
|
||||
@use '@taiga-ui/styles/utils' as taiga;
|
||||
|
||||
.template {
|
||||
@include taiga.transition(opacity);
|
||||
@@ -63,7 +63,7 @@ import { Control } from './control'
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 0.5rem;
|
||||
font: var(--tui-font-text-m);
|
||||
font: var(--tui-typography-body-m);
|
||||
font-weight: bold;
|
||||
|
||||
&_hidden {
|
||||
|
||||
@@ -29,12 +29,6 @@ import { Control } from './control'
|
||||
}
|
||||
</tui-textfield>
|
||||
`,
|
||||
styles: `
|
||||
// TODO: Remove after Taiga UI update
|
||||
:host ::ng-deep .t-input {
|
||||
pointer-events: none;
|
||||
}
|
||||
`,
|
||||
imports: [
|
||||
FormsModule,
|
||||
TuiTextfield,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Component } from '@angular/core'
|
||||
import { FormsModule } from '@angular/forms'
|
||||
import { IST } from '@start9labs/start-sdk'
|
||||
import { TuiIcon, TuiNumberFormat, TuiTextfield } from '@taiga-ui/core'
|
||||
import { TuiIcon, TuiNumberFormat, TuiInput } from '@taiga-ui/core'
|
||||
import { TuiInputNumber, TuiTooltip } from '@taiga-ui/kit'
|
||||
|
||||
import { Control } from './control'
|
||||
@@ -39,7 +39,7 @@ import { HintPipe } from '../pipes/hint.pipe'
|
||||
`,
|
||||
imports: [
|
||||
FormsModule,
|
||||
TuiTextfield,
|
||||
TuiInput,
|
||||
TuiInputNumber,
|
||||
TuiNumberFormat,
|
||||
TuiIcon,
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { WA_IS_MOBILE } from '@ng-web-apis/platform'
|
||||
import { Component, inject } from '@angular/core'
|
||||
import { FormsModule } from '@angular/forms'
|
||||
import { Router, RouterLink } from '@angular/router'
|
||||
import { invert } from '@start9labs/shared'
|
||||
import { IST } from '@start9labs/start-sdk'
|
||||
import { TUI_IS_MOBILE } from '@taiga-ui/cdk'
|
||||
import { TuiDataList, TuiIcon, TuiTextfield } from '@taiga-ui/core'
|
||||
import { TuiDataList, TuiIcon, TuiInput } from '@taiga-ui/core'
|
||||
import {
|
||||
TuiChevron,
|
||||
TuiFluidTypography,
|
||||
@@ -50,12 +50,11 @@ import { HintPipe } from '../pipes/hint.pipe'
|
||||
/>
|
||||
}
|
||||
@if (!mobile) {
|
||||
<tui-data-list *tuiTextfieldDropdown>
|
||||
<tui-data-list *tuiDropdown>
|
||||
@for (item of items; track item) {
|
||||
@if (inverted[item]?.startsWith('~')) {
|
||||
<a
|
||||
tuiOption
|
||||
new
|
||||
iconEnd="@tui.arrow-right"
|
||||
tuiFluidTypography
|
||||
[routerLink]="inverted[item]?.slice(1)"
|
||||
@@ -65,7 +64,6 @@ import { HintPipe } from '../pipes/hint.pipe'
|
||||
} @else {
|
||||
<button
|
||||
tuiOption
|
||||
new
|
||||
tuiFluidTypography
|
||||
[style.white-space]="'nowrap'"
|
||||
[value]="item"
|
||||
@@ -85,7 +83,7 @@ import { HintPipe } from '../pipes/hint.pipe'
|
||||
imports: [
|
||||
FormsModule,
|
||||
RouterLink,
|
||||
TuiTextfield,
|
||||
TuiInput,
|
||||
TuiSelect,
|
||||
TuiDataList,
|
||||
TuiFluidTypography,
|
||||
@@ -98,7 +96,7 @@ import { HintPipe } from '../pipes/hint.pipe'
|
||||
export class FormSelectComponent extends Control<IST.ValueSpecSelect, string> {
|
||||
protected readonly router = inject(Router)
|
||||
protected readonly inverted = invert(this.spec.values)
|
||||
protected readonly mobile = inject(TUI_IS_MOBILE)
|
||||
protected readonly mobile = inject(WA_IS_MOBILE)
|
||||
protected readonly items = Object.values(this.spec.values)
|
||||
protected readonly disabledItemHandler = (item: string) =>
|
||||
Array.isArray(this.spec.disabled) &&
|
||||
|
||||
@@ -3,7 +3,7 @@ import { FormsModule } from '@angular/forms'
|
||||
import { i18nPipe } from '@start9labs/shared'
|
||||
import { IST, utils } from '@start9labs/start-sdk'
|
||||
import { tuiInjectElement } from '@taiga-ui/cdk'
|
||||
import { TuiButton, TuiIcon, TuiTextfield } from '@taiga-ui/core'
|
||||
import { TuiButton, TuiIcon, TuiInput } from '@taiga-ui/core'
|
||||
import { TuiTooltip } from '@taiga-ui/kit'
|
||||
|
||||
import { Control } from './control'
|
||||
@@ -22,7 +22,7 @@ import { HintPipe } from '../pipes/hint.pipe'
|
||||
</label>
|
||||
}
|
||||
<input
|
||||
tuiTextfield
|
||||
tuiInput
|
||||
[attr.inputmode]="spec.inputmode"
|
||||
[attr.minLength]="spec.minLength"
|
||||
[attr.maxLength]="spec.maxLength"
|
||||
@@ -86,7 +86,7 @@ import { HintPipe } from '../pipes/hint.pipe'
|
||||
`,
|
||||
imports: [
|
||||
FormsModule,
|
||||
TuiTextfield,
|
||||
TuiInput,
|
||||
TuiButton,
|
||||
TuiIcon,
|
||||
TuiTooltip,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Component } from '@angular/core'
|
||||
import { FormsModule } from '@angular/forms'
|
||||
import { IST } from '@start9labs/start-sdk'
|
||||
import { TuiIcon, TuiTextfield } from '@taiga-ui/core'
|
||||
import { TuiIcon, TuiInput } from '@taiga-ui/core'
|
||||
import { TuiTextarea, TuiTooltip } from '@taiga-ui/kit'
|
||||
|
||||
import { Control } from './control'
|
||||
@@ -37,14 +37,7 @@ import { HintPipe } from '../pipes/hint.pipe'
|
||||
}
|
||||
</tui-textfield>
|
||||
`,
|
||||
imports: [
|
||||
FormsModule,
|
||||
TuiTextfield,
|
||||
TuiTextarea,
|
||||
TuiIcon,
|
||||
TuiTooltip,
|
||||
HintPipe,
|
||||
],
|
||||
imports: [FormsModule, TuiInput, TuiTextarea, TuiIcon, TuiTooltip, HintPipe],
|
||||
})
|
||||
export class FormTextareaComponent extends Control<
|
||||
IST.ValueSpecTextarea,
|
||||
|
||||
@@ -2,9 +2,8 @@ import { ChangeDetectionStrategy, Component, inject } from '@angular/core'
|
||||
import { toSignal } from '@angular/core/rxjs-interop'
|
||||
import { CopyService, i18nPipe } from '@start9labs/shared'
|
||||
import { T } from '@start9labs/start-sdk'
|
||||
import { TuiButton, TuiHint, TuiTitle } from '@taiga-ui/core'
|
||||
import { TuiButton, TuiHint, TuiTitle, TuiCell } from '@taiga-ui/core'
|
||||
import { TuiFade } from '@taiga-ui/kit'
|
||||
import { TuiCell } from '@taiga-ui/layout'
|
||||
import { PolymorpheusComponent } from '@taiga-ui/polymorpheus'
|
||||
import { PatchDB } from 'patch-db-client'
|
||||
import { ConfigService } from 'src/app/services/config.service'
|
||||
|
||||
@@ -22,7 +22,7 @@ import { HeaderStatusComponent } from './status.component'
|
||||
<header-menu class="item item_corner" />
|
||||
`,
|
||||
styles: `
|
||||
@use '@taiga-ui/core/styles/taiga-ui-local' as taiga;
|
||||
@use '@taiga-ui/styles/utils' as taiga;
|
||||
|
||||
@keyframes connecting {
|
||||
25%,
|
||||
@@ -122,7 +122,7 @@ import { HeaderStatusComponent } from './status.component'
|
||||
display: flex;
|
||||
height: 100%;
|
||||
align-items: center;
|
||||
font: var(--tui-font-text-l);
|
||||
font: var(--tui-typography-body-l);
|
||||
padding: 1rem;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
|
||||
@@ -5,7 +5,6 @@ import {
|
||||
DocsLinkDirective,
|
||||
ErrorService,
|
||||
i18nPipe,
|
||||
LoadingService,
|
||||
SafeLinksDirective,
|
||||
} from '@start9labs/shared'
|
||||
import {
|
||||
@@ -15,6 +14,7 @@ import {
|
||||
TuiHint,
|
||||
TuiIcon,
|
||||
} from '@taiga-ui/core'
|
||||
import { TuiNotificationMiddleService } from '@taiga-ui/kit'
|
||||
import { filter } from 'rxjs'
|
||||
import { ApiService } from 'src/app/services/api/embassy-api.service'
|
||||
import { AuthService } from 'src/app/services/auth.service'
|
||||
@@ -43,71 +43,60 @@ import { ABOUT } from './about.component'
|
||||
{{ status().message | i18n }}
|
||||
</div>
|
||||
}
|
||||
<tui-data-list [style.width.rem]="13">
|
||||
<tui-opt-group>
|
||||
<button tuiOption iconStart="@tui.info" new (click)="about()">
|
||||
{{ 'About this server' | i18n }}
|
||||
</button>
|
||||
</tui-opt-group>
|
||||
<tui-opt-group label="" safeLinks>
|
||||
<a
|
||||
tuiOption
|
||||
docsLink
|
||||
new
|
||||
iconStart="@tui.book-open-text"
|
||||
path="/start-os/user-manual"
|
||||
>
|
||||
{{ 'User manual' | i18n }}
|
||||
</a>
|
||||
<a
|
||||
tuiOption
|
||||
new
|
||||
iconStart="@tui.headphones"
|
||||
href="https://start9.com/contact"
|
||||
>
|
||||
{{ 'Contact support' | i18n }}
|
||||
</a>
|
||||
<a
|
||||
tuiOption
|
||||
new
|
||||
iconStart="@tui.dollar-sign"
|
||||
href="https://donate.start9.com"
|
||||
>
|
||||
{{ 'Donate to Start9' | i18n }}
|
||||
</a>
|
||||
</tui-opt-group>
|
||||
<tui-opt-group label="">
|
||||
<a
|
||||
tuiOption
|
||||
new
|
||||
iconStart="@tui.settings"
|
||||
routerLink="/system"
|
||||
(click)="open = false"
|
||||
>
|
||||
{{ 'System Settings' | i18n }}
|
||||
</a>
|
||||
</tui-opt-group>
|
||||
<tui-opt-group label="">
|
||||
<button
|
||||
tuiOption
|
||||
new
|
||||
iconStart="@tui.refresh-cw"
|
||||
(click)="promptPower('restart')"
|
||||
>
|
||||
{{ 'Restart' | i18n }}
|
||||
</button>
|
||||
<button
|
||||
tuiOption
|
||||
new
|
||||
iconStart="@tui.power"
|
||||
(click)="promptPower('shutdown')"
|
||||
>
|
||||
{{ 'Shutdown' | i18n }}
|
||||
</button>
|
||||
<button tuiOption new iconStart="@tui.log-out" (click)="logout()">
|
||||
{{ 'Logout' | i18n }}
|
||||
</button>
|
||||
</tui-opt-group>
|
||||
<tui-data-list safeLinks [style.width.rem]="13">
|
||||
<button tuiOption iconStart="@tui.info" (click)="about()">
|
||||
{{ 'About this server' | i18n }}
|
||||
</button>
|
||||
<hr />
|
||||
<a
|
||||
tuiOption
|
||||
docsLink
|
||||
iconStart="@tui.book-open-text"
|
||||
path="/start-os/user-manual"
|
||||
>
|
||||
{{ 'User manual' | i18n }}
|
||||
</a>
|
||||
<a
|
||||
tuiOption
|
||||
iconStart="@tui.headphones"
|
||||
href="https://start9.com/contact"
|
||||
>
|
||||
{{ 'Contact support' | i18n }}
|
||||
</a>
|
||||
<a
|
||||
tuiOption
|
||||
iconStart="@tui.dollar-sign"
|
||||
href="https://donate.start9.com"
|
||||
>
|
||||
{{ 'Donate to Start9' | i18n }}
|
||||
</a>
|
||||
<hr />
|
||||
<a
|
||||
tuiOption
|
||||
iconStart="@tui.settings"
|
||||
routerLink="/system"
|
||||
(click)="open = false"
|
||||
>
|
||||
{{ 'System Settings' | i18n }}
|
||||
</a>
|
||||
<hr />
|
||||
<button
|
||||
tuiOption
|
||||
iconStart="@tui.refresh-cw"
|
||||
(click)="promptPower('restart')"
|
||||
>
|
||||
{{ 'Restart' | i18n }}
|
||||
</button>
|
||||
<button
|
||||
tuiOption
|
||||
iconStart="@tui.power"
|
||||
(click)="promptPower('shutdown')"
|
||||
>
|
||||
{{ 'Shutdown' | i18n }}
|
||||
</button>
|
||||
<button tuiOption iconStart="@tui.log-out" (click)="logout()">
|
||||
{{ 'Logout' | i18n }}
|
||||
</button>
|
||||
</tui-data-list>
|
||||
</ng-template>
|
||||
`,
|
||||
@@ -151,7 +140,7 @@ import { ABOUT } from './about.component'
|
||||
export class HeaderMenuComponent {
|
||||
private readonly api = inject(ApiService)
|
||||
private readonly auth = inject(AuthService)
|
||||
private readonly loader = inject(LoadingService)
|
||||
private readonly loader = inject(TuiNotificationMiddleService)
|
||||
private readonly errorService = inject(ErrorService)
|
||||
private readonly dialog = inject(DialogService)
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ import { getMenu } from 'src/app/utils/system-utilities'
|
||||
}
|
||||
`,
|
||||
styles: `
|
||||
@use '@taiga-ui/core/styles/taiga-ui-local' as taiga;
|
||||
@use '@taiga-ui/styles/utils' as taiga;
|
||||
|
||||
:host {
|
||||
position: relative;
|
||||
|
||||
@@ -18,7 +18,7 @@ import { STATUS } from 'src/app/services/status.service'
|
||||
<span>{{ status().message | i18n }}</span>
|
||||
`,
|
||||
styles: `
|
||||
@use '@taiga-ui/core/styles/taiga-ui-local' as taiga;
|
||||
@use '@taiga-ui/styles/utils' as taiga;
|
||||
|
||||
:host {
|
||||
@include taiga.transition(all);
|
||||
|
||||
@@ -5,21 +5,21 @@ import {
|
||||
input,
|
||||
signal,
|
||||
} from '@angular/core'
|
||||
import { WA_IS_MOBILE } from '@ng-web-apis/platform'
|
||||
import {
|
||||
CopyService,
|
||||
DialogService,
|
||||
ErrorService,
|
||||
i18nPipe,
|
||||
LoadingService,
|
||||
} from '@start9labs/shared'
|
||||
import { TUI_IS_MOBILE } from '@taiga-ui/cdk'
|
||||
import {
|
||||
TuiButton,
|
||||
tuiButtonOptionsProvider,
|
||||
TuiDataList,
|
||||
TuiDropdown,
|
||||
TuiTextfield,
|
||||
TuiInput,
|
||||
} from '@taiga-ui/core'
|
||||
import { TuiNotificationMiddleService } from '@taiga-ui/kit'
|
||||
import { PolymorpheusComponent } from '@taiga-ui/polymorpheus'
|
||||
import { QRModal } from 'src/app/routes/portal/modals/qr.component'
|
||||
import { ApiService } from 'src/app/services/api/embassy-api.service'
|
||||
@@ -114,11 +114,10 @@ import { DomainHealthService } from './domain-health.service'
|
||||
[(tuiDropdownOpen)]="open"
|
||||
>
|
||||
{{ 'Actions' | i18n }}
|
||||
<tui-data-list *tuiTextfieldDropdown (click)="open.set(false)">
|
||||
<tui-data-list *tuiDropdown (click)="open.set(false)">
|
||||
@if (address().ui) {
|
||||
<a
|
||||
tuiOption
|
||||
new
|
||||
iconStart="@tui.external-link"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
@@ -130,7 +129,6 @@ import { DomainHealthService } from './domain-health.service'
|
||||
}
|
||||
<button
|
||||
tuiOption
|
||||
new
|
||||
[iconStart]="
|
||||
address().enabled ? '@tui.toggle-right' : '@tui.toggle-left'
|
||||
"
|
||||
@@ -138,12 +136,11 @@ import { DomainHealthService } from './domain-health.service'
|
||||
>
|
||||
{{ (address().enabled ? 'Disable' : 'Enable') | i18n }}
|
||||
</button>
|
||||
<button tuiOption new iconStart="@tui.qr-code" (click)="showQR()">
|
||||
<button tuiOption iconStart="@tui.qr-code" (click)="showQR()">
|
||||
{{ 'Show QR' | i18n }}
|
||||
</button>
|
||||
<button
|
||||
tuiOption
|
||||
new
|
||||
iconStart="@tui.copy"
|
||||
(click)="copyService.copy(address().url)"
|
||||
>
|
||||
@@ -152,7 +149,6 @@ import { DomainHealthService } from './domain-health.service'
|
||||
@if (address().hostnameInfo.metadata.kind === 'public-domain') {
|
||||
<button
|
||||
tuiOption
|
||||
new
|
||||
iconStart="@tui.settings"
|
||||
(click)="showDnsValidation()"
|
||||
>
|
||||
@@ -162,7 +158,6 @@ import { DomainHealthService } from './domain-health.service'
|
||||
@if (address().hostnameInfo.metadata.kind === 'private-domain') {
|
||||
<button
|
||||
tuiOption
|
||||
new
|
||||
iconStart="@tui.settings"
|
||||
(click)="showPrivateDnsValidation()"
|
||||
>
|
||||
@@ -175,7 +170,6 @@ import { DomainHealthService } from './domain-health.service'
|
||||
) {
|
||||
<button
|
||||
tuiOption
|
||||
new
|
||||
iconStart="@tui.settings"
|
||||
(click)="showPortForwardValidation()"
|
||||
>
|
||||
@@ -183,12 +177,7 @@ import { DomainHealthService } from './domain-health.service'
|
||||
</button>
|
||||
}
|
||||
@if (address().deletable) {
|
||||
<button
|
||||
tuiOption
|
||||
new
|
||||
iconStart="@tui.trash"
|
||||
(click)="deleteDomain()"
|
||||
>
|
||||
<button tuiOption iconStart="@tui.trash" (click)="deleteDomain()">
|
||||
{{ 'Delete' | i18n }}
|
||||
</button>
|
||||
}
|
||||
@@ -224,15 +213,15 @@ import { DomainHealthService } from './domain-health.service'
|
||||
}
|
||||
}
|
||||
`,
|
||||
imports: [TuiButton, TuiDropdown, TuiDataList, i18nPipe, TuiTextfield],
|
||||
imports: [TuiButton, TuiDropdown, TuiDataList, i18nPipe, TuiInput],
|
||||
providers: [tuiButtonOptionsProvider({ appearance: 'icon' })],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class AddressActionsComponent {
|
||||
private readonly isMobile = inject(TUI_IS_MOBILE)
|
||||
private readonly isMobile = inject(WA_IS_MOBILE)
|
||||
private readonly dialog = inject(DialogService)
|
||||
private readonly api = inject(ApiService)
|
||||
private readonly loader = inject(LoadingService)
|
||||
private readonly loader = inject(TuiNotificationMiddleService)
|
||||
private readonly errorService = inject(ErrorService)
|
||||
private readonly domainHealth = inject(DomainHealthService)
|
||||
readonly copyService = inject(CopyService)
|
||||
@@ -247,8 +236,8 @@ export class AddressActionsComponent {
|
||||
showQR() {
|
||||
this.dialog
|
||||
.openComponent(new PolymorpheusComponent(QRModal), {
|
||||
size: 'auto',
|
||||
closeable: this.isMobile,
|
||||
size: 's',
|
||||
closable: this.isMobile,
|
||||
data: this.address().url,
|
||||
})
|
||||
.subscribe()
|
||||
|
||||
@@ -5,14 +5,10 @@ import {
|
||||
input,
|
||||
signal,
|
||||
} from '@angular/core'
|
||||
import { ErrorService, i18nPipe, LoadingService } from '@start9labs/shared'
|
||||
import { ErrorService, i18nPipe } from '@start9labs/shared'
|
||||
import { ISB, utils } from '@start9labs/start-sdk'
|
||||
import {
|
||||
TuiButton,
|
||||
TuiDataList,
|
||||
TuiDropdown,
|
||||
TuiTextfield,
|
||||
} from '@taiga-ui/core'
|
||||
import { TuiButton, TuiDataList, TuiDropdown, TuiInput } from '@taiga-ui/core'
|
||||
import { TuiNotificationMiddleService } from '@taiga-ui/kit'
|
||||
import { PatchDB } from 'patch-db-client'
|
||||
import { firstValueFrom } from 'rxjs'
|
||||
import {
|
||||
@@ -46,11 +42,11 @@ import { InterfaceAddressItemComponent } from './item.component'
|
||||
[(tuiDropdownOpen)]="addOpen"
|
||||
>
|
||||
{{ 'Add Domain' | i18n }}
|
||||
<tui-data-list *tuiTextfieldDropdown (click)="addOpen.set(false)">
|
||||
<button tuiOption new (click)="addPublicDomain()">
|
||||
<tui-data-list *tuiDropdown (click)="addOpen.set(false)">
|
||||
<button tuiOption (click)="addPublicDomain()">
|
||||
{{ 'Public Domain' | i18n }}
|
||||
</button>
|
||||
<button tuiOption new (click)="addPrivateDomain()">
|
||||
<button tuiOption (click)="addPrivateDomain()">
|
||||
{{ 'Private Domain' | i18n }}
|
||||
</button>
|
||||
</tui-data-list>
|
||||
@@ -97,7 +93,7 @@ import { InterfaceAddressItemComponent } from './item.component'
|
||||
TuiButton,
|
||||
TuiDropdown,
|
||||
TuiDataList,
|
||||
TuiTextfield,
|
||||
TuiInput,
|
||||
TableComponent,
|
||||
PlaceholderComponent,
|
||||
i18nPipe,
|
||||
@@ -108,7 +104,7 @@ import { InterfaceAddressItemComponent } from './item.component'
|
||||
export class InterfaceAddressesComponent {
|
||||
private readonly patch = inject<PatchDB<DataModel>>(PatchDB)
|
||||
private readonly formDialog = inject(FormDialogService)
|
||||
private readonly loader = inject(LoadingService)
|
||||
private readonly loader = inject(TuiNotificationMiddleService)
|
||||
private readonly errorService = inject(ErrorService)
|
||||
private readonly api = inject(ApiService)
|
||||
private readonly i18n = inject(i18nPipe)
|
||||
|
||||
@@ -189,7 +189,7 @@ export type DomainValidationData = {
|
||||
td,
|
||||
th {
|
||||
padding: 0.5rem 0.5rem !important;
|
||||
font: var(--tui-font-text-s) !important;
|
||||
font: var(--tui-typography-body-s) !important;
|
||||
color: var(--tui-text-primary) !important;
|
||||
font-weight: normal !important;
|
||||
}
|
||||
|
||||
@@ -6,11 +6,15 @@ import {
|
||||
input,
|
||||
signal,
|
||||
} from '@angular/core'
|
||||
import { ErrorService, i18nPipe, LoadingService } from '@start9labs/shared'
|
||||
import { FormsModule } from '@angular/forms'
|
||||
import { ErrorService, i18nPipe } from '@start9labs/shared'
|
||||
import { TuiObfuscatePipe } from '@taiga-ui/cdk'
|
||||
import { TuiButton, TuiIcon } from '@taiga-ui/core'
|
||||
import { FormsModule } from '@angular/forms'
|
||||
import { TuiBadge, TuiSwitch } from '@taiga-ui/kit'
|
||||
import {
|
||||
TuiBadge,
|
||||
TuiNotificationMiddleService,
|
||||
TuiSwitch,
|
||||
} from '@taiga-ui/kit'
|
||||
import { ApiService } from 'src/app/services/api/embassy-api.service'
|
||||
import { GatewayAddress, MappedServiceInterface } from '../interface.service'
|
||||
import { AddressActionsComponent } from './actions.component'
|
||||
@@ -45,12 +49,13 @@ import { DomainHealthService } from './domain-health.service'
|
||||
</span>
|
||||
</td>
|
||||
<td class="type">
|
||||
<tui-badge
|
||||
<span
|
||||
tuiBadge
|
||||
size="s"
|
||||
[appearance]="typeAppearance(address.hostnameInfo.metadata.kind)"
|
||||
>
|
||||
{{ address.type }}
|
||||
</tui-badge>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<div class="cert">
|
||||
@@ -177,7 +182,7 @@ import { DomainHealthService } from './domain-health.service'
|
||||
|
||||
.access {
|
||||
padding-right: 0;
|
||||
font: var(--tui-font-text-m);
|
||||
font: var(--tui-typography-body-m);
|
||||
font-weight: bold;
|
||||
|
||||
tui-icon {
|
||||
@@ -186,7 +191,7 @@ import { DomainHealthService } from './domain-health.service'
|
||||
}
|
||||
|
||||
.type {
|
||||
font: var(--tui-font-text-m);
|
||||
font: var(--tui-typography-body-m);
|
||||
font-weight: bold;
|
||||
color: var(--tui-text-primary);
|
||||
padding-inline-end: 0.5rem;
|
||||
@@ -226,7 +231,7 @@ import { DomainHealthService } from './domain-health.service'
|
||||
export class InterfaceAddressItemComponent {
|
||||
private readonly api = inject(ApiService)
|
||||
private readonly errorService = inject(ErrorService)
|
||||
private readonly loader = inject(LoadingService)
|
||||
private readonly loader = inject(TuiNotificationMiddleService)
|
||||
private readonly domainHealth = inject(DomainHealthService)
|
||||
|
||||
readonly address = input.required<GatewayAddress>()
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { WA_IS_MOBILE } from '@ng-web-apis/platform'
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
@@ -7,13 +8,7 @@ import {
|
||||
} from '@angular/core'
|
||||
import { CopyService, DialogService, i18nPipe } from '@start9labs/shared'
|
||||
import { T } from '@start9labs/start-sdk'
|
||||
import { TUI_IS_MOBILE } from '@taiga-ui/cdk'
|
||||
import {
|
||||
TuiButton,
|
||||
TuiDataList,
|
||||
TuiDropdown,
|
||||
TuiTextfield,
|
||||
} from '@taiga-ui/core'
|
||||
import { TuiButton, TuiDataList, TuiDropdown, TuiInput } from '@taiga-ui/core'
|
||||
import { PolymorpheusComponent } from '@taiga-ui/polymorpheus'
|
||||
import { PlaceholderComponent } from 'src/app/routes/portal/components/placeholder.component'
|
||||
import { TableComponent } from 'src/app/routes/portal/components/table.component'
|
||||
@@ -109,7 +104,7 @@ import {
|
||||
>
|
||||
{{ 'More' | i18n }}
|
||||
<tui-data-list
|
||||
*tuiTextfieldDropdown
|
||||
*tuiDropdown
|
||||
(click)="overflowOpen.set(null)"
|
||||
>
|
||||
@for (
|
||||
@@ -120,7 +115,6 @@ import {
|
||||
@if (pluginGroup().pluginActions[actionId]; as meta) {
|
||||
<button
|
||||
tuiOption
|
||||
new
|
||||
(click)="runRowAction(actionId, meta, address)"
|
||||
>
|
||||
{{ meta.name }}
|
||||
@@ -142,7 +136,7 @@ import {
|
||||
[(tuiDropdownOpen)]="open"
|
||||
>
|
||||
{{ 'Actions' | i18n }}
|
||||
<tui-data-list *tuiTextfieldDropdown (click)="open.set(false)">
|
||||
<tui-data-list *tuiDropdown (click)="open.set(false)">
|
||||
@if (address.hostnameInfo.metadata.kind === 'plugin') {
|
||||
@if (address.hostnameInfo.metadata.removeAction) {
|
||||
@if (
|
||||
@@ -153,7 +147,6 @@ import {
|
||||
) {
|
||||
<button
|
||||
tuiOption
|
||||
new
|
||||
iconStart="@tui.trash"
|
||||
(click)="
|
||||
runRowAction(
|
||||
@@ -170,7 +163,6 @@ import {
|
||||
}
|
||||
<button
|
||||
tuiOption
|
||||
new
|
||||
iconStart="@tui.qr-code"
|
||||
(click)="showQR(address.url)"
|
||||
>
|
||||
@@ -178,7 +170,6 @@ import {
|
||||
</button>
|
||||
<button
|
||||
tuiOption
|
||||
new
|
||||
iconStart="@tui.copy"
|
||||
(click)="copyService.copy(address.url)"
|
||||
>
|
||||
@@ -192,7 +183,6 @@ import {
|
||||
@if (pluginGroup().pluginActions[actionId]; as meta) {
|
||||
<button
|
||||
tuiOption
|
||||
new
|
||||
(click)="runRowAction(actionId, meta, address)"
|
||||
>
|
||||
{{ meta.name }}
|
||||
@@ -271,7 +261,7 @@ import {
|
||||
TuiButton,
|
||||
TuiDropdown,
|
||||
TuiDataList,
|
||||
TuiTextfield,
|
||||
TuiInput,
|
||||
TableComponent,
|
||||
PlaceholderComponent,
|
||||
i18nPipe,
|
||||
@@ -279,7 +269,7 @@ import {
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class PluginAddressesComponent {
|
||||
private readonly isMobile = inject(TUI_IS_MOBILE)
|
||||
private readonly isMobile = inject(WA_IS_MOBILE)
|
||||
private readonly dialog = inject(DialogService)
|
||||
private readonly actionService = inject(ActionService)
|
||||
readonly copyService = inject(CopyService)
|
||||
@@ -290,12 +280,12 @@ export class PluginAddressesComponent {
|
||||
readonly packageId = input('')
|
||||
readonly value = input<MappedServiceInterface | undefined>()
|
||||
|
||||
showQR(url: string) {
|
||||
showQR(data: string) {
|
||||
this.dialog
|
||||
.openComponent(new PolymorpheusComponent(QRModal), {
|
||||
size: 'auto',
|
||||
closeable: this.isMobile,
|
||||
data: url,
|
||||
size: 's',
|
||||
closable: this.isMobile,
|
||||
data,
|
||||
})
|
||||
.subscribe()
|
||||
}
|
||||
|
||||
@@ -116,7 +116,7 @@ export type PortForwardValidationData = {
|
||||
td,
|
||||
th {
|
||||
padding: 0.5rem 0.5rem !important;
|
||||
font: var(--tui-font-text-s) !important;
|
||||
font: var(--tui-typography-body-s) !important;
|
||||
color: var(--tui-text-primary) !important;
|
||||
font-weight: normal !important;
|
||||
}
|
||||
|
||||
@@ -119,7 +119,7 @@ export type PrivateDnsValidationData = {
|
||||
td,
|
||||
th {
|
||||
padding: 0.5rem 0.5rem !important;
|
||||
font: var(--tui-font-text-s) !important;
|
||||
font: var(--tui-typography-body-s) !important;
|
||||
color: var(--tui-text-primary) !important;
|
||||
font-weight: normal !important;
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ import { PluginAddressesComponent } from './addresses/plugin.component'
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
color: var(--tui-text-secondary);
|
||||
font: var(--tui-font-text-l);
|
||||
font: var(--tui-typography-body-l);
|
||||
|
||||
::ng-deep [tuiSkeleton] {
|
||||
width: 100%;
|
||||
|
||||
@@ -3,9 +3,9 @@ import {
|
||||
convertAnsi,
|
||||
DownloadHTMLService,
|
||||
ErrorService,
|
||||
LoadingService,
|
||||
} from '@start9labs/shared'
|
||||
import { T } from '@start9labs/start-sdk'
|
||||
import { TuiNotificationMiddleService } from '@taiga-ui/kit'
|
||||
import { LogsComponent } from './logs.component'
|
||||
|
||||
@Directive({
|
||||
@@ -13,7 +13,7 @@ import { LogsComponent } from './logs.component'
|
||||
})
|
||||
export class LogsDownloadDirective {
|
||||
private readonly component = inject(LogsComponent)
|
||||
private readonly loader = inject(LoadingService)
|
||||
private readonly loader = inject(TuiNotificationMiddleService)
|
||||
private readonly errorService = inject(ErrorService)
|
||||
private readonly downloadHtml = inject(DownloadHTMLService)
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Directive, inject, Output } from '@angular/core'
|
||||
import { IntersectionObserveeService } from '@ng-web-apis/intersection-observer'
|
||||
import { WaIntersectionObserveeService } from '@ng-web-apis/intersection-observer'
|
||||
import { convertAnsi, ErrorService } from '@start9labs/shared'
|
||||
import { catchError, defer, filter, from, map, of, switchMap, tap } from 'rxjs'
|
||||
import { LogsComponent } from './logs.component'
|
||||
@@ -8,7 +8,7 @@ import { LogsComponent } from './logs.component'
|
||||
selector: '[logsFetch]',
|
||||
})
|
||||
export class LogsFetchDirective {
|
||||
private readonly observer = inject(IntersectionObserveeService)
|
||||
private readonly observer = inject(WaIntersectionObserveeService)
|
||||
private readonly component = inject(LogsComponent)
|
||||
private readonly errors = inject(ErrorService)
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ import { TuiIcon } from '@taiga-ui/core'
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
padding: 1rem;
|
||||
font: var(--tui-font-text-l);
|
||||
font: var(--tui-typography-body-l);
|
||||
color: var(--tui-text-tertiary);
|
||||
|
||||
tui-icon {
|
||||
|
||||
@@ -75,7 +75,7 @@ const FILTER = ['services', 'system', 'marketplace']
|
||||
</nav>
|
||||
`,
|
||||
styles: `
|
||||
@use '@taiga-ui/core/styles/taiga-ui-local' as taiga;
|
||||
@use '@taiga-ui/styles/utils' as taiga;
|
||||
|
||||
:host {
|
||||
display: none;
|
||||
|
||||
@@ -14,14 +14,14 @@ import { tuiIsNumber } from '@taiga-ui/cdk'
|
||||
selector: 'task-info',
|
||||
template: `
|
||||
@if (diff.length) {
|
||||
<tui-notification>
|
||||
<div tuiNotification>
|
||||
{{ 'The following modifications were made' | i18n }}:
|
||||
<ul>
|
||||
@for (d of diff; track d) {
|
||||
<li [innerHTML]="d"></li>
|
||||
}
|
||||
</ul>
|
||||
</tui-notification>
|
||||
</div>
|
||||
}
|
||||
`,
|
||||
imports: [TuiNotification, i18nPipe],
|
||||
|
||||
@@ -6,9 +6,19 @@ import {
|
||||
} from '@angular/core'
|
||||
import { toSignal } from '@angular/core/rxjs-interop'
|
||||
import { RouterOutlet } from '@angular/router'
|
||||
import { ErrorService, LoadingService } from '@start9labs/shared'
|
||||
import { TuiButton, TuiIcon, TuiLoader, TuiScrollbar } from '@taiga-ui/core'
|
||||
import { TuiActionBar, TuiProgress } from '@taiga-ui/kit'
|
||||
import { ErrorService } from '@start9labs/shared'
|
||||
import {
|
||||
TuiButton,
|
||||
TuiIcon,
|
||||
TuiLoader,
|
||||
TuiPopup,
|
||||
TuiScrollbar,
|
||||
} from '@taiga-ui/core'
|
||||
import {
|
||||
TuiActionBar,
|
||||
TuiNotificationMiddleService,
|
||||
TuiProgress,
|
||||
} from '@taiga-ui/kit'
|
||||
import { PatchDB } from 'patch-db-client'
|
||||
import { TabsComponent } from 'src/app/routes/portal/components/tabs.component'
|
||||
import { ApiService } from 'src/app/services/api/embassy-api.service'
|
||||
@@ -26,7 +36,7 @@ import { HeaderComponent } from './components/header/header.component'
|
||||
</main>
|
||||
<app-tabs />
|
||||
@if (update(); as update) {
|
||||
<tui-action-bar *tuiActionBar="bar()">
|
||||
<tui-action-bar *tuiPopup="bar()">
|
||||
@if (update === true) {
|
||||
<tui-icon icon="@tui.check" class="g-positive" />
|
||||
Download complete, restart to apply changes
|
||||
@@ -52,7 +62,7 @@ import { HeaderComponent } from './components/header/header.component'
|
||||
}
|
||||
`,
|
||||
styles: `
|
||||
@use '@taiga-ui/core/styles/taiga-ui-local' as taiga;
|
||||
@use '@taiga-ui/styles/utils' as taiga;
|
||||
|
||||
:host {
|
||||
height: 100%;
|
||||
@@ -93,10 +103,11 @@ import { HeaderComponent } from './components/header/header.component'
|
||||
TuiLoader,
|
||||
TuiIcon,
|
||||
TuiButton,
|
||||
TuiPopup,
|
||||
],
|
||||
})
|
||||
export class PortalComponent {
|
||||
private readonly loader = inject(LoadingService)
|
||||
private readonly loader = inject(TuiNotificationMiddleService)
|
||||
private readonly errorService = inject(ErrorService)
|
||||
private readonly patch = inject<PatchDB<DataModel>>(PatchDB)
|
||||
private readonly api = inject(ApiService)
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { ChangeDetectionStrategy, Component, inject } from '@angular/core'
|
||||
import { TuiDialogService, TuiIcon, TuiTitle } from '@taiga-ui/core'
|
||||
import { TuiCell } from '@taiga-ui/layout'
|
||||
import { TuiDialogService, TuiIcon, TuiTitle, TuiCell } from '@taiga-ui/core'
|
||||
import { BackupsUpcomingComponent } from './components/upcoming.component'
|
||||
import { HISTORY } from './modals/history.component'
|
||||
import { JOBS } from './modals/jobs.component'
|
||||
|
||||
@@ -2,16 +2,14 @@ import { Component, inject } from '@angular/core'
|
||||
import { FormsModule } from '@angular/forms'
|
||||
import {
|
||||
TuiButton,
|
||||
TuiCheckbox,
|
||||
TuiDialogContext,
|
||||
TuiDialogOptions,
|
||||
TuiGroup,
|
||||
TuiLoader,
|
||||
} from '@taiga-ui/core'
|
||||
import { TuiBlock, TuiCheckbox } from '@taiga-ui/kit'
|
||||
import {
|
||||
POLYMORPHEUS_CONTEXT,
|
||||
PolymorpheusComponent,
|
||||
} from '@taiga-ui/polymorpheus'
|
||||
import { TuiBlock } from '@taiga-ui/kit'
|
||||
import { injectContext, PolymorpheusComponent } from '@taiga-ui/polymorpheus'
|
||||
import { PatchDB } from 'patch-db-client'
|
||||
import { firstValueFrom, map } from 'rxjs'
|
||||
import { DataModel } from 'src/app/services/patch-db/data-model'
|
||||
@@ -74,9 +72,7 @@ interface Package {
|
||||
export class BackupsBackupModal {
|
||||
private readonly patch = inject<PatchDB<DataModel>>(PatchDB)
|
||||
readonly context =
|
||||
inject<TuiDialogContext<string[], { btnText: string } | undefined>>(
|
||||
POLYMORPHEUS_CONTEXT,
|
||||
)
|
||||
injectContext<TuiDialogContext<string[], { btnText: string } | undefined>>()
|
||||
|
||||
hasSelection = false
|
||||
|
||||
|
||||
@@ -1,17 +1,21 @@
|
||||
import { Component, inject } from '@angular/core'
|
||||
import { toSignal } from '@angular/core/rxjs-interop'
|
||||
import { FormsModule } from '@angular/forms'
|
||||
import { ErrorService, LoadingService } from '@start9labs/shared'
|
||||
import { ErrorService } from '@start9labs/shared'
|
||||
import { T } from '@start9labs/start-sdk'
|
||||
import {
|
||||
TuiButton,
|
||||
TuiDialogContext,
|
||||
TuiDialogService,
|
||||
TuiTextfield,
|
||||
TuiInput,
|
||||
} from '@taiga-ui/core'
|
||||
import { TuiBadge, TuiSwitch } from '@taiga-ui/kit'
|
||||
import {
|
||||
TuiBadge,
|
||||
TuiNotificationMiddleService,
|
||||
TuiSwitch,
|
||||
} from '@taiga-ui/kit'
|
||||
import { injectContext, PolymorpheusComponent } from '@taiga-ui/polymorpheus'
|
||||
import { from, map } from 'rxjs'
|
||||
import { T } from '@start9labs/start-sdk'
|
||||
import { BackupJob } from 'src/app/services/api/api.types'
|
||||
import { ApiService } from 'src/app/services/api/embassy-api.service'
|
||||
import { ToHumanCronPipe } from '../pipes/to-human-cron.pipe'
|
||||
@@ -25,7 +29,7 @@ import { TARGET, TARGET_CREATE } from './target.component'
|
||||
<tui-textfield>
|
||||
<label tuiLabel>Job Name</label>
|
||||
<input
|
||||
tuiTextfield
|
||||
tuiInput
|
||||
name="name"
|
||||
[(ngModel)]="job.name"
|
||||
placeholder="My Backup Job"
|
||||
@@ -40,11 +44,12 @@ import { TARGET, TARGET_CREATE } from './target.component'
|
||||
(click)="selectTarget()"
|
||||
>
|
||||
Target
|
||||
<tui-badge
|
||||
<span
|
||||
tuiBadge
|
||||
[appearance]="target()?.[job.targetId]?.type ? 'success' : 'warning'"
|
||||
>
|
||||
{{ target()?.[job.targetId]?.type || 'Select target' }}
|
||||
</tui-badge>
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
tuiButton
|
||||
@@ -55,14 +60,17 @@ import { TARGET, TARGET_CREATE } from './target.component'
|
||||
(click)="selectPackages()"
|
||||
>
|
||||
Packages
|
||||
<tui-badge [appearance]="job.packageIds.length ? 'success' : 'warning'">
|
||||
<span
|
||||
tuiBadge
|
||||
[appearance]="job.packageIds.length ? 'success' : 'warning'"
|
||||
>
|
||||
{{ job.packageIds.length + ' selected' }}
|
||||
</tui-badge>
|
||||
</span>
|
||||
</button>
|
||||
<tui-textfield>
|
||||
<label tuiLabel>Schedule</label>
|
||||
<input
|
||||
tuiTextfield
|
||||
tuiInput
|
||||
name="cron"
|
||||
[(ngModel)]="job.cron"
|
||||
placeholder="* * * * *"
|
||||
@@ -109,7 +117,7 @@ import { TARGET, TARGET_CREATE } from './target.component'
|
||||
`,
|
||||
imports: [
|
||||
FormsModule,
|
||||
TuiTextfield,
|
||||
TuiInput,
|
||||
TuiSwitch,
|
||||
TuiButton,
|
||||
TuiBadge,
|
||||
@@ -119,7 +127,7 @@ import { TARGET, TARGET_CREATE } from './target.component'
|
||||
export class BackupsEditModal {
|
||||
private readonly api = inject(ApiService)
|
||||
private readonly errorService = inject(ErrorService)
|
||||
private readonly loader = inject(LoadingService)
|
||||
private readonly loader = inject(TuiNotificationMiddleService)
|
||||
private readonly dialogs = inject(TuiDialogService)
|
||||
private readonly context =
|
||||
injectContext<TuiDialogContext<BackupJob, BackupJobBuilder>>()
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import { toSignal } from '@angular/core/rxjs-interop'
|
||||
import { TuiCheckbox, TuiSkeleton } from '@taiga-ui/kit'
|
||||
import { CommonModule } from '@angular/common'
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
@@ -7,10 +5,18 @@ import {
|
||||
inject,
|
||||
signal,
|
||||
} from '@angular/core'
|
||||
import { toSignal } from '@angular/core/rxjs-interop'
|
||||
import { FormsModule } from '@angular/forms'
|
||||
import { ErrorService, LoadingService } from '@start9labs/shared'
|
||||
import { TUI_TRUE_HANDLER, TUI_FALSE_HANDLER } from '@taiga-ui/cdk'
|
||||
import { TuiDialogService, TuiIcon, TuiLink, TuiButton } from '@taiga-ui/core'
|
||||
import { ErrorService } from '@start9labs/shared'
|
||||
import { TUI_FALSE_HANDLER, TUI_TRUE_HANDLER } from '@taiga-ui/cdk'
|
||||
import {
|
||||
TuiButton,
|
||||
TuiCheckbox,
|
||||
TuiDialogService,
|
||||
TuiIcon,
|
||||
TuiLink,
|
||||
} from '@taiga-ui/core'
|
||||
import { TuiNotificationMiddleService, TuiSkeleton } from '@taiga-ui/kit'
|
||||
import { PolymorpheusComponent } from '@taiga-ui/polymorpheus'
|
||||
import { from } from 'rxjs'
|
||||
import { REPORT } from 'src/app/components/backup-report.component'
|
||||
@@ -101,7 +107,7 @@ import { HasErrorPipe } from '../pipes/has-error.pipe'
|
||||
</table>
|
||||
`,
|
||||
styles: `
|
||||
@use '@taiga-ui/core/styles/taiga-ui-local' as taiga;
|
||||
@use '@taiga-ui/styles/utils' as taiga;
|
||||
|
||||
tui-icon {
|
||||
font-size: 1rem;
|
||||
@@ -170,7 +176,7 @@ export class BackupsHistoryModal {
|
||||
private readonly api = inject(ApiService)
|
||||
private readonly dialogs = inject(TuiDialogService)
|
||||
private readonly errorService = inject(ErrorService)
|
||||
private readonly loader = inject(LoadingService)
|
||||
private readonly loader = inject(TuiNotificationMiddleService)
|
||||
|
||||
readonly targets = toSignal(from(this.api.getBackupTargets({})))
|
||||
readonly runs = signal<BackupRun[] | null>(null)
|
||||
|
||||
@@ -1,16 +1,22 @@
|
||||
import { Component, inject, OnInit } from '@angular/core'
|
||||
import { toSignal } from '@angular/core/rxjs-interop'
|
||||
import { ErrorService, LoadingService } from '@start9labs/shared'
|
||||
import { ErrorService } from '@start9labs/shared'
|
||||
import {
|
||||
TuiButton,
|
||||
TuiDialogOptions,
|
||||
TuiDialogService,
|
||||
TuiIcon,
|
||||
TuiButton,
|
||||
TuiNotification,
|
||||
TuiLink,
|
||||
TuiNotification,
|
||||
} from '@taiga-ui/core'
|
||||
import { TuiConfirmData, TUI_CONFIRM, TuiSkeleton } from '@taiga-ui/kit'
|
||||
import {
|
||||
TUI_CONFIRM,
|
||||
TuiConfirmData,
|
||||
TuiNotificationMiddleService,
|
||||
TuiSkeleton,
|
||||
} from '@taiga-ui/kit'
|
||||
import { PolymorpheusComponent } from '@taiga-ui/polymorpheus'
|
||||
import { DocsLinkDirective } from 'projects/shared/src/public-api'
|
||||
import { BehaviorSubject, filter, from } from 'rxjs'
|
||||
import { BackupJob } from 'src/app/services/api/api.types'
|
||||
import { ApiService } from 'src/app/services/api/embassy-api.service'
|
||||
@@ -18,18 +24,17 @@ import { GetBackupIconPipe } from '../pipes/get-backup-icon.pipe'
|
||||
import { ToHumanCronPipe } from '../pipes/to-human-cron.pipe'
|
||||
import { BackupJobBuilder } from '../utils/job-builder'
|
||||
import { EDIT } from './edit.component'
|
||||
import { DocsLinkDirective } from 'projects/shared/src/public-api'
|
||||
|
||||
@Component({
|
||||
template: `
|
||||
<tui-notification>
|
||||
<div tuiNotification>
|
||||
Scheduling automatic backups is an excellent way to ensure your StartOS
|
||||
data is safely backed up. StartOS will issue a notification whenever one
|
||||
of your scheduled backups succeeds or fails.
|
||||
<a tuiLink docsLink path="/start-os/user-manual/backup-create.html">
|
||||
View instructions
|
||||
</a>
|
||||
</tui-notification>
|
||||
</div>
|
||||
<h3 class="g-title">
|
||||
Saved Jobs
|
||||
<button tuiButton size="s" iconStart="@tui.plus" (click)="create()">
|
||||
@@ -147,7 +152,7 @@ import { DocsLinkDirective } from 'projects/shared/src/public-api'
|
||||
})
|
||||
export class BackupsJobsModal implements OnInit {
|
||||
private readonly dialogs = inject(TuiDialogService)
|
||||
private readonly loader = inject(LoadingService)
|
||||
private readonly loader = inject(TuiNotificationMiddleService)
|
||||
private readonly errorService = inject(ErrorService)
|
||||
private readonly api = inject(ApiService)
|
||||
|
||||
|
||||
@@ -1,14 +1,19 @@
|
||||
import { CommonModule } from '@angular/common'
|
||||
import { ChangeDetectionStrategy, Component, inject } from '@angular/core'
|
||||
import { FormsModule } from '@angular/forms'
|
||||
import { ErrorService, LoadingService } from '@start9labs/shared'
|
||||
import { ErrorService } from '@start9labs/shared'
|
||||
import { T } from '@start9labs/start-sdk'
|
||||
import { TuiMapperPipe } from '@taiga-ui/cdk'
|
||||
import { TuiButton, TuiDialogContext, TuiGroup } from '@taiga-ui/core'
|
||||
import { TuiBlock, TuiCheckbox } from '@taiga-ui/kit'
|
||||
import {
|
||||
TuiButton,
|
||||
TuiCheckbox,
|
||||
TuiDialogContext,
|
||||
TuiGroup,
|
||||
} from '@taiga-ui/core'
|
||||
import { TuiBlock, TuiNotificationMiddleService } from '@taiga-ui/kit'
|
||||
import { injectContext, PolymorpheusComponent } from '@taiga-ui/polymorpheus'
|
||||
import { PatchDB } from 'patch-db-client'
|
||||
import { take } from 'rxjs'
|
||||
import { T } from '@start9labs/start-sdk'
|
||||
import { ApiService } from 'src/app/services/api/embassy-api.service'
|
||||
import { DataModel } from 'src/app/services/patch-db/data-model'
|
||||
import { ToOptionsPipe } from '../pipes/to-options.pipe'
|
||||
@@ -68,7 +73,7 @@ import { RecoverOption } from '../types/recover-option'
|
||||
})
|
||||
export class BackupsRecoverModal {
|
||||
private readonly api = inject(ApiService)
|
||||
private readonly loader = inject(LoadingService)
|
||||
private readonly loader = inject(TuiNotificationMiddleService)
|
||||
private readonly errorService = inject(ErrorService)
|
||||
private readonly context =
|
||||
injectContext<TuiDialogContext<void, RecoverData>>()
|
||||
|
||||
@@ -15,8 +15,8 @@ import {
|
||||
TuiIcon,
|
||||
TuiLoader,
|
||||
TuiTitle,
|
||||
TuiCell,
|
||||
} from '@taiga-ui/core'
|
||||
import { TuiCell } from '@taiga-ui/layout'
|
||||
import { injectContext, PolymorpheusComponent } from '@taiga-ui/polymorpheus'
|
||||
import { PatchDB } from 'patch-db-client'
|
||||
import { ApiService } from 'src/app/services/api/embassy-api.service'
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user