From 56d1f0af538ed0dbf7338b046ee5b0893869b14a Mon Sep 17 00:00:00 2001 From: Ikhun Um Date: Fri, 1 Nov 2024 14:00:39 +0900 Subject: [PATCH] Remove the legacy webapp (#1045) Motivation: The new UI becomes stablized and we don't get addtional bug reports for them. So I think it is safe to remove the legacy webapp to improve build speed and reduce the artifact size. Modifications: - Remove `server/src/main/resource` folder - Remove build scripts for the legacy webapp in `build.gradle` - Remove `/legacy-webapp` route path from the server. Result: The legacy webapp is no longer supported. --- server/build.gradle | 59 - server/package-lock.json | 319 ---- server/package.json | 30 - .../centraldogma/server/CentralDogma.java | 7 - .../server/internal/mirror/short_wordlist.txt | 1296 ----------------- .../fonts/glyphicons-halflings-regular.eot | Bin 20127 -> 0 bytes .../fonts/glyphicons-halflings-regular.svg | 288 ---- .../fonts/glyphicons-halflings-regular.ttf | Bin 45386 -> 0 bytes .../fonts/glyphicons-halflings-regular.woff | Bin 23424 -> 0 bytes .../fonts/glyphicons-halflings-regular.woff2 | Bin 18028 -> 0 bytes .../main/resources/webapp/i18n/en.main.json | 151 -- server/src/main/resources/webapp/index.html | 110 -- server/src/main/resources/webapp/robots.txt | 3 - .../main/resources/webapp/scripts/app/app.js | 165 --- .../webapp/scripts/app/entities/entity.js | 10 - .../scripts/app/entities/metadata/metadata.js | 27 - .../metadata/metadata.project.controller.js | 223 --- .../entities/metadata/metadata.project.html | 279 ---- .../metadata.repository.controller.js | 178 --- .../metadata/metadata.repository.html | 156 -- .../entities/projects/project.controller.js | 15 - .../app/entities/projects/project.html | 29 - .../projects/project.new.controller.js | 21 - .../app/entities/projects/project.new.html | 24 - .../entities/projects/projects.controller.js | 41 - .../app/entities/projects/projects.html | 50 - .../scripts/app/entities/projects/projects.js | 41 - .../app/entities/repositories/repositories.js | 111 -- .../repository.file.controller.js | 66 - .../repository.file.delete.controller.js | 42 - .../repositories/repository.file.delete.html | 21 - .../repository.file.edit.controller.js | 153 -- .../repositories/repository.file.edit.html | 83 -- .../repositories/repository.file.html | 70 - .../repository.file.new.controller.js | 149 -- .../repositories/repository.file.new.html | 66 - .../repository.history.controller.js | 40 - .../repositories/repository.history.html | 69 - .../repositories/repository.new.controller.js | 22 - .../entities/repositories/repository.new.html | 34 - .../repository.query.controller.js | 109 -- .../repositories/repository.query.html | 68 - .../repository.search.controller.js | 46 - .../repositories/repository.search.html | 49 - .../repository.tree.controller.js | 74 - .../repositories/repository.tree.html | 89 -- .../webapp/scripts/app/settings/setting.js | 9 - .../tokens/token.generated.controller.js | 9 - .../app/settings/tokens/token.generated.html | 41 - .../settings/tokens/token.new.controller.js | 27 - .../app/settings/tokens/token.new.html | 23 - .../app/settings/tokens/tokens.controller.js | 101 -- .../scripts/app/settings/tokens/tokens.html | 70 - .../scripts/app/settings/tokens/tokens.js | 15 - .../resources/webapp/scripts/app/user/user.js | 10 - .../components/auth/authority.directive.js | 81 -- .../components/auth/principal.service.js | 104 -- .../components/auth/security.service.js | 31 - .../components/entities/entities.util.js | 45 - .../entities/identifier.with.role.js | 24 - .../scripts/components/entities/permission.js | 61 - .../components/entities/project.service.js | 36 - .../components/entities/repository.service.js | 248 ---- .../components/entities/settings.service.js | 49 - .../language/language.controller.js | 13 - .../components/language/language.service.js | 32 - .../components/navbar/navbar.controller.js | 14 - .../components/navbar/navbar.directive.js | 40 - .../scripts/components/navbar/navbar.html | 46 - .../scripts/components/title/title.service.js | 17 - .../scripts/components/user/user.service.js | 11 - .../components/util/ace-editor.directive.js | 211 --- .../scripts/components/util/api.service.js | 102 -- .../scripts/components/util/api.v1.service.js | 91 -- .../components/util/confirmation-dialog.html | 11 - .../components/util/confirmation-dialog.js | 68 - .../util/notification-util.service.js | 77 - .../components/util/revision.directive.js | 148 -- .../components/util/search.directive.js | 37 - .../components/util/string-util.service.js | 104 -- .../components/util/truncate.filter.js | 48 - .../src/main/resources/webapp/styles/main.css | 254 ---- 82 files changed, 7191 deletions(-) delete mode 100644 server/package-lock.json delete mode 100644 server/package.json delete mode 100644 server/src/main/resources/com/linecorp/centraldogma/server/internal/mirror/short_wordlist.txt delete mode 100644 server/src/main/resources/webapp/fonts/glyphicons-halflings-regular.eot delete mode 100644 server/src/main/resources/webapp/fonts/glyphicons-halflings-regular.svg delete mode 100644 server/src/main/resources/webapp/fonts/glyphicons-halflings-regular.ttf delete mode 100644 server/src/main/resources/webapp/fonts/glyphicons-halflings-regular.woff delete mode 100644 server/src/main/resources/webapp/fonts/glyphicons-halflings-regular.woff2 delete mode 100644 server/src/main/resources/webapp/i18n/en.main.json delete mode 100644 server/src/main/resources/webapp/index.html delete mode 100644 server/src/main/resources/webapp/robots.txt delete mode 100644 server/src/main/resources/webapp/scripts/app/app.js delete mode 100644 server/src/main/resources/webapp/scripts/app/entities/entity.js delete mode 100644 server/src/main/resources/webapp/scripts/app/entities/metadata/metadata.js delete mode 100644 server/src/main/resources/webapp/scripts/app/entities/metadata/metadata.project.controller.js delete mode 100644 server/src/main/resources/webapp/scripts/app/entities/metadata/metadata.project.html delete mode 100644 server/src/main/resources/webapp/scripts/app/entities/metadata/metadata.repository.controller.js delete mode 100644 server/src/main/resources/webapp/scripts/app/entities/metadata/metadata.repository.html delete mode 100644 server/src/main/resources/webapp/scripts/app/entities/projects/project.controller.js delete mode 100644 server/src/main/resources/webapp/scripts/app/entities/projects/project.html delete mode 100644 server/src/main/resources/webapp/scripts/app/entities/projects/project.new.controller.js delete mode 100644 server/src/main/resources/webapp/scripts/app/entities/projects/project.new.html delete mode 100644 server/src/main/resources/webapp/scripts/app/entities/projects/projects.controller.js delete mode 100644 server/src/main/resources/webapp/scripts/app/entities/projects/projects.html delete mode 100644 server/src/main/resources/webapp/scripts/app/entities/projects/projects.js delete mode 100644 server/src/main/resources/webapp/scripts/app/entities/repositories/repositories.js delete mode 100644 server/src/main/resources/webapp/scripts/app/entities/repositories/repository.file.controller.js delete mode 100644 server/src/main/resources/webapp/scripts/app/entities/repositories/repository.file.delete.controller.js delete mode 100644 server/src/main/resources/webapp/scripts/app/entities/repositories/repository.file.delete.html delete mode 100644 server/src/main/resources/webapp/scripts/app/entities/repositories/repository.file.edit.controller.js delete mode 100644 server/src/main/resources/webapp/scripts/app/entities/repositories/repository.file.edit.html delete mode 100644 server/src/main/resources/webapp/scripts/app/entities/repositories/repository.file.html delete mode 100644 server/src/main/resources/webapp/scripts/app/entities/repositories/repository.file.new.controller.js delete mode 100644 server/src/main/resources/webapp/scripts/app/entities/repositories/repository.file.new.html delete mode 100644 server/src/main/resources/webapp/scripts/app/entities/repositories/repository.history.controller.js delete mode 100644 server/src/main/resources/webapp/scripts/app/entities/repositories/repository.history.html delete mode 100644 server/src/main/resources/webapp/scripts/app/entities/repositories/repository.new.controller.js delete mode 100644 server/src/main/resources/webapp/scripts/app/entities/repositories/repository.new.html delete mode 100644 server/src/main/resources/webapp/scripts/app/entities/repositories/repository.query.controller.js delete mode 100644 server/src/main/resources/webapp/scripts/app/entities/repositories/repository.query.html delete mode 100644 server/src/main/resources/webapp/scripts/app/entities/repositories/repository.search.controller.js delete mode 100644 server/src/main/resources/webapp/scripts/app/entities/repositories/repository.search.html delete mode 100644 server/src/main/resources/webapp/scripts/app/entities/repositories/repository.tree.controller.js delete mode 100644 server/src/main/resources/webapp/scripts/app/entities/repositories/repository.tree.html delete mode 100644 server/src/main/resources/webapp/scripts/app/settings/setting.js delete mode 100644 server/src/main/resources/webapp/scripts/app/settings/tokens/token.generated.controller.js delete mode 100644 server/src/main/resources/webapp/scripts/app/settings/tokens/token.generated.html delete mode 100644 server/src/main/resources/webapp/scripts/app/settings/tokens/token.new.controller.js delete mode 100644 server/src/main/resources/webapp/scripts/app/settings/tokens/token.new.html delete mode 100644 server/src/main/resources/webapp/scripts/app/settings/tokens/tokens.controller.js delete mode 100644 server/src/main/resources/webapp/scripts/app/settings/tokens/tokens.html delete mode 100644 server/src/main/resources/webapp/scripts/app/settings/tokens/tokens.js delete mode 100644 server/src/main/resources/webapp/scripts/app/user/user.js delete mode 100644 server/src/main/resources/webapp/scripts/components/auth/authority.directive.js delete mode 100644 server/src/main/resources/webapp/scripts/components/auth/principal.service.js delete mode 100644 server/src/main/resources/webapp/scripts/components/auth/security.service.js delete mode 100644 server/src/main/resources/webapp/scripts/components/entities/entities.util.js delete mode 100644 server/src/main/resources/webapp/scripts/components/entities/identifier.with.role.js delete mode 100644 server/src/main/resources/webapp/scripts/components/entities/permission.js delete mode 100644 server/src/main/resources/webapp/scripts/components/entities/project.service.js delete mode 100644 server/src/main/resources/webapp/scripts/components/entities/repository.service.js delete mode 100644 server/src/main/resources/webapp/scripts/components/entities/settings.service.js delete mode 100644 server/src/main/resources/webapp/scripts/components/language/language.controller.js delete mode 100644 server/src/main/resources/webapp/scripts/components/language/language.service.js delete mode 100644 server/src/main/resources/webapp/scripts/components/navbar/navbar.controller.js delete mode 100644 server/src/main/resources/webapp/scripts/components/navbar/navbar.directive.js delete mode 100644 server/src/main/resources/webapp/scripts/components/navbar/navbar.html delete mode 100644 server/src/main/resources/webapp/scripts/components/title/title.service.js delete mode 100644 server/src/main/resources/webapp/scripts/components/user/user.service.js delete mode 100644 server/src/main/resources/webapp/scripts/components/util/ace-editor.directive.js delete mode 100644 server/src/main/resources/webapp/scripts/components/util/api.service.js delete mode 100644 server/src/main/resources/webapp/scripts/components/util/api.v1.service.js delete mode 100644 server/src/main/resources/webapp/scripts/components/util/confirmation-dialog.html delete mode 100644 server/src/main/resources/webapp/scripts/components/util/confirmation-dialog.js delete mode 100644 server/src/main/resources/webapp/scripts/components/util/notification-util.service.js delete mode 100644 server/src/main/resources/webapp/scripts/components/util/revision.directive.js delete mode 100644 server/src/main/resources/webapp/scripts/components/util/search.directive.js delete mode 100644 server/src/main/resources/webapp/scripts/components/util/string-util.service.js delete mode 100644 server/src/main/resources/webapp/scripts/components/util/truncate.filter.js delete mode 100644 server/src/main/resources/webapp/styles/main.css diff --git a/server/build.gradle b/server/build.gradle index 7568877088..607838e055 100644 --- a/server/build.gradle +++ b/server/build.gradle @@ -1,14 +1,3 @@ -plugins { - alias libs.plugins.node.gradle -} - -node { - version = '22.3.0' - npmVersion = '10.8.1' - download = true - npmInstallCommand = "ci" -} - dependencies { implementation project(':common-legacy') @@ -73,52 +62,4 @@ if (!rootProject.hasProperty('noWeb')) { } } -def clientRelocations = [ - 'ace-builds/src-min-noconflict/', - 'angular/angular.min.js', - 'angular-cache-buster/angular-cache-buster.js', - 'angular-cookies/angular-cookies.min.js', - 'angular-dynamic-locale/dist/tmhDynamicLocale.min.js', - 'angular-ui-ace/src/ui-ace.js', - 'angular-i18n', - 'angular-local-storage/dist/angular-local-storage.min.js', - 'angular-resource/angular-resource.min.js', - 'angular-sanitize/angular-sanitize.min.js', - 'angular-translate/dist/angular-translate.min.js', - 'angular-translate-loader-partial/angular-translate-loader-partial.min.js', - 'angular-translate-storage-cookie/angular-translate-storage-cookie.min.js', - 'angular-ui-ace/src/ui-ace.js', - 'angular-ui-bootstrap/dist/', - 'angular-ui-notification/dist/', - 'angular-ui-router/release/angular-ui-router.min.js', - 'bootstrap/dist/', - 'bootswatch/cerulean/bootstrap.min.css', - 'diff/dist/diff.min.js', - 'fast-json-patch/dist/json-patch-duplex.min.js', - 'jquery/dist/jquery.min.js', - 'json3/lib/json3.min.js', - 'moment/min/moment.min.js' -] - -task copyClientDependencies { - dependsOn tasks.npmInstall - - doLast { - clientRelocations.each { location -> - def paths = location.split('/') - def folder = paths[0] - copy { - from "${project.projectDir}/node_modules/$location" - into "${project.projectDir}/src/main/resources/webapp/vendor/$folder" - } - } - } -} - -task cleanClientDependencies(type: Delete) { - delete "${project.projectDir}/src/main/resources/webapp/vendor" -} - tasks.sourcesJar.dependsOn(tasks.versionProperties) -tasks.clean.dependsOn(tasks.cleanClientDependencies) -tasks.processResources.dependsOn(tasks.copyClientDependencies) diff --git a/server/package-lock.json b/server/package-lock.json deleted file mode 100644 index 990a8f3739..0000000000 --- a/server/package-lock.json +++ /dev/null @@ -1,319 +0,0 @@ -{ - "name": "@centraldogma/webapp", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "@centraldogma/webapp", - "license": "Apache-2.0", - "dependencies": { - "ace-builds": "1.32.2", - "angular": "1.5.8", - "angular-cache-buster": "0.4.3", - "angular-cookies": "1.5.8", - "angular-dynamic-locale": "0.1.32", - "angular-i18n": "1.5.8", - "angular-local-storage": "0.5.0", - "angular-resource": "1.5.8", - "angular-sanitize": "1.5.8", - "angular-translate": "2.13.0", - "angular-translate-loader-partial": "2.13.0", - "angular-translate-storage-cookie": "2.13.0", - "angular-ui-ace": "0.2.3", - "angular-ui-bootstrap": "2.2.0", - "angular-ui-notification": "0.2.0", - "angular-ui-router": "0.3.2", - "bootstrap": "3.3.7", - "bootswatch": "3.3.7", - "diff": "3.0.1", - "fast-json-patch": "1.1.1", - "jquery": "2.2.4", - "json3": "3.3.2", - "moment": "2.16.0" - } - }, - "node_modules/ace-builds": { - "version": "1.32.2", - "resolved": "https://registry.npmjs.org/ace-builds/-/ace-builds-1.32.2.tgz", - "integrity": "sha512-mnJAc803p+7eeDt07r6XI7ufV7VdkpPq4gJZT8Jb3QsowkaBTVy4tdBgPrVT0WbXLm0toyEQXURKSVNj/7dfJQ==" - }, - "node_modules/angular": { - "version": "1.5.8", - "resolved": "https://registry.npmjs.org/angular/-/angular-1.5.8.tgz", - "integrity": "sha512-NvzSfusQ5J70ZFVui9Y+sv453kkaqGuke3ZjLSzuKNnXJx5WytGSsJEDpoDmKUDKn3goiToVtu3ptW3nEBRs3Q==", - "deprecated": "For the actively supported Angular, see https://www.npmjs.com/package/@angular/core. AngularJS support has officially ended. For extended AngularJS support options, see https://goo.gle/angularjs-path-forward." - }, - "node_modules/angular-cache-buster": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/angular-cache-buster/-/angular-cache-buster-0.4.3.tgz", - "integrity": "sha512-VQgq+RR6ZMxbOLTOLgQB7EsCbMsqraxvwV23M4GRg604usL53bz0N+oYLLCfEAEJ+cvd6QH9kcMCBoyKTjx3aw==" - }, - "node_modules/angular-cookies": { - "version": "1.5.8", - "resolved": "https://registry.npmjs.org/angular-cookies/-/angular-cookies-1.5.8.tgz", - "integrity": "sha512-yT7xzQ7qD2VDF8pukyQ/ly3/pPtdtiUesl0Bg6CNNINttS7GujriU8gnQIEGeZfetmrft80aTYcD3J9nyi3/pA==", - "deprecated": "For the actively supported Angular, see https://www.npmjs.com/package/@angular/core. AngularJS support has officially ended. For extended AngularJS support options, see https://goo.gle/angularjs-path-forward." - }, - "node_modules/angular-dynamic-locale": { - "version": "0.1.32", - "resolved": "https://registry.npmjs.org/angular-dynamic-locale/-/angular-dynamic-locale-0.1.32.tgz", - "integrity": "sha512-Q+8Vbb9hlM+mXD09JO/BJanmk9wvcDbovTOIDYc6efFWgS6QqBXpiAD86YZaHbyJ45hM6MEWqbkJv+pnJKQgpQ==" - }, - "node_modules/angular-i18n": { - "version": "1.5.8", - "resolved": "https://registry.npmjs.org/angular-i18n/-/angular-i18n-1.5.8.tgz", - "integrity": "sha512-Tg/z1PDGR1Va7QHANmtMI1k3WxlL59PiWNNHRVa0lcz+CiuuuqCki/tteGDi3taUM2t8HYIOLvNlnRbxy3C/Zw==", - "deprecated": "For the actively supported Angular, see https://www.npmjs.com/package/@angular/core. AngularJS support has officially ended. For extended AngularJS support options, see https://goo.gle/angularjs-path-forward." - }, - "node_modules/angular-local-storage": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/angular-local-storage/-/angular-local-storage-0.5.0.tgz", - "integrity": "sha512-GksrqEpE9af70hqFN/xcVvTaUDcyhTDCedG560lgfTzfVsEeYza1kikK240OfKkJa9NVjbmfMlOP7CdTRNjiow==" - }, - "node_modules/angular-resource": { - "version": "1.5.8", - "resolved": "https://registry.npmjs.org/angular-resource/-/angular-resource-1.5.8.tgz", - "integrity": "sha512-Ckp4gsMbQOE8HvUECZOnx+FWGv/yL7K4q5SOihY2ifav6FkaItRFM4exBLUnwYDXUKebtbfkHaDDQMoILx0jfw==", - "deprecated": "For the actively supported Angular, see https://www.npmjs.com/package/@angular/core. AngularJS support has officially ended. For extended AngularJS support options, see https://goo.gle/angularjs-path-forward." - }, - "node_modules/angular-sanitize": { - "version": "1.5.8", - "resolved": "https://registry.npmjs.org/angular-sanitize/-/angular-sanitize-1.5.8.tgz", - "integrity": "sha512-SCr0ekZLacVt5RzgufvfYQRYr34pJSL+lVcbBBtvXyMXNC2g9RcTxA+Uwgaq4AoxnxGiZb2WYrXMtL9nYGAo+Q==", - "deprecated": "For the actively supported Angular, see https://www.npmjs.com/package/@angular/core. AngularJS support has officially ended. For extended AngularJS support options, see https://goo.gle/angularjs-path-forward." - }, - "node_modules/angular-translate": { - "version": "2.13.0", - "resolved": "https://registry.npmjs.org/angular-translate/-/angular-translate-2.13.0.tgz", - "integrity": "sha512-x5u+IK3Zw0CPJEKs12qGyAlCcqIT6SKXPAol6UfCzPkXl0pIkKzMOqQhRjsfXafRIm4/uAE5o9bM7fM3RdxQxw==", - "dependencies": { - "angular": ">=1.2.26 <=1.6" - }, - "engines": { - "node": ">=6.9" - } - }, - "node_modules/angular-translate-loader-partial": { - "version": "2.13.0", - "resolved": "https://registry.npmjs.org/angular-translate-loader-partial/-/angular-translate-loader-partial-2.13.0.tgz", - "integrity": "sha512-SCVtUDddPynRdG1KHuqfJ1eJu0hzndD/BbjdbkQSyeKjpYhCAxR7NjgCsffVmsA8KU46Kcj1nvedUfR2hrwAcQ==", - "dependencies": { - "angular-translate": "~2.13.0" - } - }, - "node_modules/angular-translate-storage-cookie": { - "version": "2.13.0", - "resolved": "https://registry.npmjs.org/angular-translate-storage-cookie/-/angular-translate-storage-cookie-2.13.0.tgz", - "integrity": "sha512-dgaw36cSXXo+HwHJZ1JjfgjMUnO29G0AJ8tQkibp5o+jUkRv6OKIzteJM9qNgxA6+qNVeTQdFmxq7YRHvIpDNA==", - "dependencies": { - "angular-cookies": ">=1.2.26 <1.6", - "angular-translate": "~2.13.0" - } - }, - "node_modules/angular-ui-ace": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/angular-ui-ace/-/angular-ui-ace-0.2.3.tgz", - "integrity": "sha512-uh3840Jvs6+uUW3u3T5D17AbKeAirPS+chpIMokJECNBpPOoK0ZoS61UKlHb6hsx6o0LCM9KlnAi84BDtmIkUA==" - }, - "node_modules/angular-ui-bootstrap": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/angular-ui-bootstrap/-/angular-ui-bootstrap-2.2.0.tgz", - "integrity": "sha512-+OVf6od0euS6HmbpYZhb6Xx/pqNyByFIc/t20us+Q6KAU79muPvQ0Uzc39eCbnc9Uz1+pNk/yKOlJTezdEBiyg==" - }, - "node_modules/angular-ui-notification": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/angular-ui-notification/-/angular-ui-notification-0.2.0.tgz", - "integrity": "sha512-hiUGiCs5mb7oBbqp83BWKEwUHBTY+1JPrMp6KgXGFk9srizz3OwzRkd3rOT3SIQdkJPMWp/SkpZsRErFXy3/XA==" - }, - "node_modules/angular-ui-router": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/angular-ui-router/-/angular-ui-router-0.3.2.tgz", - "integrity": "sha512-FXtC3D7z7SNtSIdMDXCVO+v4Q6jPABneDvRu6NyOeeZlo09mQFqVCjhKqJWnf94ZlNSmyOXoFSqKD5tL2JTFEg==", - "deprecated": "This npm package 'angular-ui-router' has been renamed to '@uirouter/angularjs'. Please update your package.json. See https://ui-router.github.io/blog/uirouter-scoped-packages/", - "dependencies": { - "angular": "^1.0.8" - } - }, - "node_modules/bootstrap": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-3.3.7.tgz", - "integrity": "sha512-qcFaisBrcBhTFkz1IUnGDYnX6ZWfFzH8zOixUDtHW9Ip+r+7MfMFav2rzy7cIHc7rgIg7xjhWBoo1mS/U26j4g==", - "engines": { - "node": ">=0.10.1" - } - }, - "node_modules/bootswatch": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/bootswatch/-/bootswatch-3.3.7.tgz", - "integrity": "sha512-8tHnBRrEHX+CtFyth9XPyR7Tl97VaU/w14eRRm+/mZrEs9JSe8Ren9UEkdFjDMlxIeDREKichmrb90EzXgtKSQ==", - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/diff": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.0.1.tgz", - "integrity": "sha512-womO+WMwc3Pikbop4DWrncrN2M0GSDwG8pwxAEhzS7g0qYrtrUmIQkD8ewWedlLYp0Kp3HR8nwRE5cMzwIBrtQ==", - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/fast-json-patch": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/fast-json-patch/-/fast-json-patch-1.1.1.tgz", - "integrity": "sha512-6E4IY1bdWejJPHLdP0qjeQehvTgqifd5KjBz2RgPw+XaZGRGOY7PbQP8aoQVVefJNSR26G3dLQYGJIo6890IzA==", - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/jquery": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/jquery/-/jquery-2.2.4.tgz", - "integrity": "sha512-lBHj60ezci2u1v2FqnZIraShGgEXq35qCzMv4lITyHGppTnA13rwR0MgwyNJh9TnDs3aXUvd1xjAotfraMHX/Q==" - }, - "node_modules/json3": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", - "integrity": "sha512-I5YLeauH3rIaE99EE++UeH2M2gSYo8/2TqDac7oZEH6D/DSQ4Woa628Qrfj1X9/OY5Mk5VvIDQaKCDchXaKrmA==", - "deprecated": "Please use the native JSON object instead of JSON 3" - }, - "node_modules/moment": { - "version": "2.16.0", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.16.0.tgz", - "integrity": "sha512-Jmy+b0/BMklLlYBzrClLstnS9Wn/WzYnmM2ub8wjdIJhp8UnbTTIHLLZpEsgmPTPgjFnXbTe32XYKYkadf9qJQ==", - "engines": { - "node": "*" - } - } - }, - "dependencies": { - "ace-builds": { - "version": "1.32.2", - "resolved": "https://registry.npmjs.org/ace-builds/-/ace-builds-1.32.2.tgz", - "integrity": "sha512-mnJAc803p+7eeDt07r6XI7ufV7VdkpPq4gJZT8Jb3QsowkaBTVy4tdBgPrVT0WbXLm0toyEQXURKSVNj/7dfJQ==" - }, - "angular": { - "version": "1.5.8", - "resolved": "https://registry.npmjs.org/angular/-/angular-1.5.8.tgz", - "integrity": "sha512-NvzSfusQ5J70ZFVui9Y+sv453kkaqGuke3ZjLSzuKNnXJx5WytGSsJEDpoDmKUDKn3goiToVtu3ptW3nEBRs3Q==" - }, - "angular-cache-buster": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/angular-cache-buster/-/angular-cache-buster-0.4.3.tgz", - "integrity": "sha512-VQgq+RR6ZMxbOLTOLgQB7EsCbMsqraxvwV23M4GRg604usL53bz0N+oYLLCfEAEJ+cvd6QH9kcMCBoyKTjx3aw==" - }, - "angular-cookies": { - "version": "1.5.8", - "resolved": "https://registry.npmjs.org/angular-cookies/-/angular-cookies-1.5.8.tgz", - "integrity": "sha512-yT7xzQ7qD2VDF8pukyQ/ly3/pPtdtiUesl0Bg6CNNINttS7GujriU8gnQIEGeZfetmrft80aTYcD3J9nyi3/pA==" - }, - "angular-dynamic-locale": { - "version": "0.1.32", - "resolved": "https://registry.npmjs.org/angular-dynamic-locale/-/angular-dynamic-locale-0.1.32.tgz", - "integrity": "sha512-Q+8Vbb9hlM+mXD09JO/BJanmk9wvcDbovTOIDYc6efFWgS6QqBXpiAD86YZaHbyJ45hM6MEWqbkJv+pnJKQgpQ==" - }, - "angular-i18n": { - "version": "1.5.8", - "resolved": "https://registry.npmjs.org/angular-i18n/-/angular-i18n-1.5.8.tgz", - "integrity": "sha512-Tg/z1PDGR1Va7QHANmtMI1k3WxlL59PiWNNHRVa0lcz+CiuuuqCki/tteGDi3taUM2t8HYIOLvNlnRbxy3C/Zw==" - }, - "angular-local-storage": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/angular-local-storage/-/angular-local-storage-0.5.0.tgz", - "integrity": "sha512-GksrqEpE9af70hqFN/xcVvTaUDcyhTDCedG560lgfTzfVsEeYza1kikK240OfKkJa9NVjbmfMlOP7CdTRNjiow==" - }, - "angular-resource": { - "version": "1.5.8", - "resolved": "https://registry.npmjs.org/angular-resource/-/angular-resource-1.5.8.tgz", - "integrity": "sha512-Ckp4gsMbQOE8HvUECZOnx+FWGv/yL7K4q5SOihY2ifav6FkaItRFM4exBLUnwYDXUKebtbfkHaDDQMoILx0jfw==" - }, - "angular-sanitize": { - "version": "1.5.8", - "resolved": "https://registry.npmjs.org/angular-sanitize/-/angular-sanitize-1.5.8.tgz", - "integrity": "sha512-SCr0ekZLacVt5RzgufvfYQRYr34pJSL+lVcbBBtvXyMXNC2g9RcTxA+Uwgaq4AoxnxGiZb2WYrXMtL9nYGAo+Q==" - }, - "angular-translate": { - "version": "2.13.0", - "resolved": "https://registry.npmjs.org/angular-translate/-/angular-translate-2.13.0.tgz", - "integrity": "sha512-x5u+IK3Zw0CPJEKs12qGyAlCcqIT6SKXPAol6UfCzPkXl0pIkKzMOqQhRjsfXafRIm4/uAE5o9bM7fM3RdxQxw==", - "requires": { - "angular": ">=1.2.26 <=1.6" - } - }, - "angular-translate-loader-partial": { - "version": "2.13.0", - "resolved": "https://registry.npmjs.org/angular-translate-loader-partial/-/angular-translate-loader-partial-2.13.0.tgz", - "integrity": "sha512-SCVtUDddPynRdG1KHuqfJ1eJu0hzndD/BbjdbkQSyeKjpYhCAxR7NjgCsffVmsA8KU46Kcj1nvedUfR2hrwAcQ==", - "requires": { - "angular-translate": "~2.13.0" - } - }, - "angular-translate-storage-cookie": { - "version": "2.13.0", - "resolved": "https://registry.npmjs.org/angular-translate-storage-cookie/-/angular-translate-storage-cookie-2.13.0.tgz", - "integrity": "sha512-dgaw36cSXXo+HwHJZ1JjfgjMUnO29G0AJ8tQkibp5o+jUkRv6OKIzteJM9qNgxA6+qNVeTQdFmxq7YRHvIpDNA==", - "requires": { - "angular-cookies": ">=1.2.26 <1.6", - "angular-translate": "~2.13.0" - } - }, - "angular-ui-ace": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/angular-ui-ace/-/angular-ui-ace-0.2.3.tgz", - "integrity": "sha512-uh3840Jvs6+uUW3u3T5D17AbKeAirPS+chpIMokJECNBpPOoK0ZoS61UKlHb6hsx6o0LCM9KlnAi84BDtmIkUA==" - }, - "angular-ui-bootstrap": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/angular-ui-bootstrap/-/angular-ui-bootstrap-2.2.0.tgz", - "integrity": "sha512-+OVf6od0euS6HmbpYZhb6Xx/pqNyByFIc/t20us+Q6KAU79muPvQ0Uzc39eCbnc9Uz1+pNk/yKOlJTezdEBiyg==" - }, - "angular-ui-notification": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/angular-ui-notification/-/angular-ui-notification-0.2.0.tgz", - "integrity": "sha512-hiUGiCs5mb7oBbqp83BWKEwUHBTY+1JPrMp6KgXGFk9srizz3OwzRkd3rOT3SIQdkJPMWp/SkpZsRErFXy3/XA==" - }, - "angular-ui-router": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/angular-ui-router/-/angular-ui-router-0.3.2.tgz", - "integrity": "sha512-FXtC3D7z7SNtSIdMDXCVO+v4Q6jPABneDvRu6NyOeeZlo09mQFqVCjhKqJWnf94ZlNSmyOXoFSqKD5tL2JTFEg==", - "requires": { - "angular": "^1.0.8" - } - }, - "bootstrap": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-3.3.7.tgz", - "integrity": "sha512-qcFaisBrcBhTFkz1IUnGDYnX6ZWfFzH8zOixUDtHW9Ip+r+7MfMFav2rzy7cIHc7rgIg7xjhWBoo1mS/U26j4g==" - }, - "bootswatch": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/bootswatch/-/bootswatch-3.3.7.tgz", - "integrity": "sha512-8tHnBRrEHX+CtFyth9XPyR7Tl97VaU/w14eRRm+/mZrEs9JSe8Ren9UEkdFjDMlxIeDREKichmrb90EzXgtKSQ==" - }, - "diff": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.0.1.tgz", - "integrity": "sha512-womO+WMwc3Pikbop4DWrncrN2M0GSDwG8pwxAEhzS7g0qYrtrUmIQkD8ewWedlLYp0Kp3HR8nwRE5cMzwIBrtQ==" - }, - "fast-json-patch": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/fast-json-patch/-/fast-json-patch-1.1.1.tgz", - "integrity": "sha512-6E4IY1bdWejJPHLdP0qjeQehvTgqifd5KjBz2RgPw+XaZGRGOY7PbQP8aoQVVefJNSR26G3dLQYGJIo6890IzA==" - }, - "jquery": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/jquery/-/jquery-2.2.4.tgz", - "integrity": "sha512-lBHj60ezci2u1v2FqnZIraShGgEXq35qCzMv4lITyHGppTnA13rwR0MgwyNJh9TnDs3aXUvd1xjAotfraMHX/Q==" - }, - "json3": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", - "integrity": "sha512-I5YLeauH3rIaE99EE++UeH2M2gSYo8/2TqDac7oZEH6D/DSQ4Woa628Qrfj1X9/OY5Mk5VvIDQaKCDchXaKrmA==" - }, - "moment": { - "version": "2.16.0", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.16.0.tgz", - "integrity": "sha512-Jmy+b0/BMklLlYBzrClLstnS9Wn/WzYnmM2ub8wjdIJhp8UnbTTIHLLZpEsgmPTPgjFnXbTe32XYKYkadf9qJQ==" - } - } -} diff --git a/server/package.json b/server/package.json deleted file mode 100644 index f9d3ab300d..0000000000 --- a/server/package.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "name": "@centraldogma/webapp", - "description": "The admin page for the Central Dogma", - "license": "Apache-2.0", - "dependencies": { - "ace-builds": "1.32.2", - "angular": "1.5.8", - "angular-cache-buster": "0.4.3", - "angular-cookies": "1.5.8", - "angular-dynamic-locale": "0.1.32", - "angular-i18n": "1.5.8", - "angular-local-storage": "0.5.0", - "angular-resource": "1.5.8", - "angular-sanitize": "1.5.8", - "angular-translate": "2.13.0", - "angular-translate-loader-partial": "2.13.0", - "angular-translate-storage-cookie": "2.13.0", - "angular-ui-ace": "0.2.3", - "angular-ui-bootstrap": "2.2.0", - "angular-ui-notification": "0.2.0", - "angular-ui-router": "0.3.2", - "bootstrap": "3.3.7", - "bootswatch": "3.3.7", - "diff": "3.0.1", - "fast-json-patch": "1.1.1", - "jquery": "2.2.4", - "json3": "3.3.2", - "moment": "2.16.0" - } -} diff --git a/server/src/main/java/com/linecorp/centraldogma/server/CentralDogma.java b/server/src/main/java/com/linecorp/centraldogma/server/CentralDogma.java index 99cbd72aaa..f6fd3c6d1c 100644 --- a/server/src/main/java/com/linecorp/centraldogma/server/CentralDogma.java +++ b/server/src/main/java/com/linecorp/centraldogma/server/CentralDogma.java @@ -900,13 +900,6 @@ protected HttpResponse doGet(ServiceRequestContext ctx, HttpRequest req) { .serveCompressedFiles(true) .fallbackFileExtensions("html") .build()); - - sb.serviceUnder("/legacy-web", - FileService.builder(CentralDogma.class.getClassLoader(), "webapp") - .cacheControl(ServerCacheControl.REVALIDATED) - .autoDecompress(true) - .serveCompressedFiles(true) - .build()); } sb.errorHandler(new HttpApiExceptionHandler()); diff --git a/server/src/main/resources/com/linecorp/centraldogma/server/internal/mirror/short_wordlist.txt b/server/src/main/resources/com/linecorp/centraldogma/server/internal/mirror/short_wordlist.txt deleted file mode 100644 index 9ac732fe36..0000000000 --- a/server/src/main/resources/com/linecorp/centraldogma/server/internal/mirror/short_wordlist.txt +++ /dev/null @@ -1,1296 +0,0 @@ -aardvark -abandoned -abbreviate -abdomen -abhorrence -abiding -abnormal -abrasion -absorbing -abundant -abyss -academy -accountant -acetone -achiness -acid -acoustics -acquire -acrobat -actress -acuteness -aerosol -aesthetic -affidavit -afloat -afraid -aftershave -again -agency -aggressor -aghast -agitate -agnostic -agonizing -agreeing -aidless -aimlessly -ajar -alarmclock -albatross -alchemy -alfalfa -algae -aliens -alkaline -almanac -alongside -alphabet -already -also -altitude -aluminum -always -amazingly -ambulance -amendment -amiable -ammunition -amnesty -amoeba -amplifier -amuser -anagram -anchor -android -anesthesia -angelfish -animal -anklet -announcer -anonymous -answer -antelope -anxiety -anyplace -aorta -apartment -apnea -apostrophe -apple -apricot -aquamarine -arachnid -arbitrate -ardently -arena -argument -aristocrat -armchair -aromatic -arrowhead -arsonist -artichoke -asbestos -ascend -aseptic -ashamed -asinine -asleep -asocial -asparagus -astronaut -asymmetric -atlas -atmosphere -atom -atrocious -attic -atypical -auctioneer -auditorium -augmented -auspicious -automobile -auxiliary -avalanche -avenue -aviator -avocado -awareness -awhile -awkward -awning -awoke -axially -azalea -babbling -backpack -badass -bagpipe -bakery -balancing -bamboo -banana -barracuda -basket -bathrobe -bazooka -blade -blender -blimp -blouse -blurred -boatyard -bobcat -body -bogusness -bohemian -boiler -bonnet -boots -borough -bossiness -bottle -bouquet -boxlike -breath -briefcase -broom -brushes -bubblegum -buckle -buddhist -buffalo -bullfrog -bunny -busboy -buzzard -cabin -cactus -cadillac -cafeteria -cage -cahoots -cajoling -cakewalk -calculator -camera -canister -capsule -carrot -cashew -cathedral -caucasian -caviar -ceasefire -cedar -celery -cement -census -ceramics -cesspool -chalkboard -cheesecake -chimney -chlorine -chopsticks -chrome -chute -cilantro -cinnamon -circle -cityscape -civilian -clay -clergyman -clipboard -clock -clubhouse -coathanger -cobweb -coconut -codeword -coexistent -coffeecake -cognitive -cohabitate -collarbone -computer -confetti -copier -cornea -cosmetics -cotton -couch -coverless -coyote -coziness -crawfish -crewmember -crib -croissant -crumble -crystal -cubical -cucumber -cuddly -cufflink -cuisine -culprit -cup -curry -cushion -cuticle -cybernetic -cyclist -cylinder -cymbal -cynicism -cypress -cytoplasm -dachshund -daffodil -dagger -dairy -dalmatian -dandelion -dartboard -dastardly -datebook -daughter -dawn -daytime -dazzler -dealer -debris -decal -dedicate -deepness -defrost -degree -dehydrator -deliverer -democrat -dentist -deodorant -depot -deranged -desktop -detergent -device -dexterity -diamond -dibs -dictionary -diffuser -digit -dilated -dimple -dinnerware -dioxide -diploma -directory -dishcloth -ditto -dividers -dizziness -doctor -dodge -doll -dominoes -donut -doorstep -dorsal -double -downstairs -dozed -drainpipe -dresser -driftwood -droppings -drum -dryer -dubiously -duckling -duffel -dugout -dumpster -duplex -durable -dustpan -dutiful -duvet -dwarfism -dwelling -dwindling -dynamite -dyslexia -eagerness -earlobe -easel -eavesdrop -ebook -eccentric -echoless -eclipse -ecosystem -ecstasy -edged -editor -educator -eelworm -eerie -effects -eggnog -egomaniac -ejection -elastic -elbow -elderly -elephant -elfishly -eliminator -elk -elliptical -elongated -elsewhere -elusive -elves -emancipate -embroidery -emcee -emerald -emission -emoticon -emperor -emulate -enactment -enchilada -endorphin -energy -enforcer -engine -enhance -enigmatic -enjoyably -enlarged -enormous -enquirer -enrollment -ensemble -entryway -enunciate -envoy -enzyme -epidemic -equipment -erasable -ergonomic -erratic -eruption -escalator -eskimo -esophagus -espresso -essay -estrogen -etching -eternal -ethics -etiquette -eucalyptus -eulogy -euphemism -euthanize -evacuation -evergreen -evidence -evolution -exam -excerpt -exerciser -exfoliate -exhale -exist -exorcist -explode -exquisite -exterior -exuberant -fabric -factory -faded -failsafe -falcon -family -fanfare -fasten -faucet -favorite -feasibly -february -federal -feedback -feigned -feline -femur -fence -ferret -festival -fettuccine -feudalist -feverish -fiberglass -fictitious -fiddle -figurine -fillet -finalist -fiscally -fixture -flashlight -fleshiness -flight -florist -flypaper -foamless -focus -foggy -folksong -fondue -footpath -fossil -fountain -fox -fragment -freeway -fridge -frosting -fruit -fryingpan -gadget -gainfully -gallstone -gamekeeper -gangway -garlic -gaslight -gathering -gauntlet -gearbox -gecko -gem -generator -geographer -gerbil -gesture -getaway -geyser -ghoulishly -gibberish -giddiness -giftshop -gigabyte -gimmick -giraffe -giveaway -gizmo -glasses -gleeful -glisten -glove -glucose -glycerin -gnarly -gnomish -goatskin -goggles -goldfish -gong -gooey -gorgeous -gosling -gothic -gourmet -governor -grape -greyhound -grill -groundhog -grumbling -guacamole -guerrilla -guitar -gullible -gumdrop -gurgling -gusto -gutless -gymnast -gynecology -gyration -habitat -hacking -haggard -haiku -halogen -hamburger -handgun -happiness -hardhat -hastily -hatchling -haughty -hazelnut -headband -hedgehog -hefty -heinously -helmet -hemoglobin -henceforth -herbs -hesitation -hexagon -hubcap -huddling -huff -hugeness -hullabaloo -human -hunter -hurricane -hushing -hyacinth -hybrid -hydrant -hygienist -hypnotist -ibuprofen -icepack -icing -iconic -identical -idiocy -idly -igloo -ignition -iguana -illuminate -imaging -imbecile -imitator -immigrant -imprint -iodine -ionosphere -ipad -iphone -iridescent -irksome -iron -irrigation -island -isotope -issueless -italicize -itemizer -itinerary -itunes -ivory -jabbering -jackrabbit -jaguar -jailhouse -jalapeno -jamboree -janitor -jarring -jasmine -jaundice -jawbreaker -jaywalker -jazz -jealous -jeep -jelly -jeopardize -jersey -jetski -jezebel -jiffy -jigsaw -jingling -jobholder -jockstrap -jogging -john -joinable -jokingly -journal -jovial -joystick -jubilant -judiciary -juggle -juice -jujitsu -jukebox -jumpiness -junkyard -juror -justifying -juvenile -kabob -kamikaze -kangaroo -karate -kayak -keepsake -kennel -kerosene -ketchup -khaki -kickstand -kilogram -kimono -kingdom -kiosk -kissing -kite -kleenex -knapsack -kneecap -knickers -koala -krypton -laboratory -ladder -lakefront -lantern -laptop -laryngitis -lasagna -latch -laundry -lavender -laxative -lazybones -lecturer -leftover -leggings -leisure -lemon -length -leopard -leprechaun -lettuce -leukemia -levers -lewdness -liability -library -licorice -lifeboat -lightbulb -likewise -lilac -limousine -lint -lioness -lipstick -liquid -listless -litter -liverwurst -lizard -llama -luau -lubricant -lucidity -ludicrous -luggage -lukewarm -lullaby -lumberjack -lunchbox -luridness -luscious -luxurious -lyrics -macaroni -maestro -magazine -mahogany -maimed -majority -makeover -malformed -mammal -mango -mapmaker -marbles -massager -matchstick -maverick -maximum -mayonnaise -moaning -mobilize -moccasin -modify -moisture -molecule -momentum -monastery -moonshine -mortuary -mosquito -motorcycle -mousetrap -movie -mower -mozzarella -muckiness -mudflow -mugshot -mule -mummy -mundane -muppet -mural -mustard -mutation -myriad -myspace -myth -nail -namesake -nanosecond -napkin -narrator -nastiness -natives -nautically -navigate -nearest -nebula -nectar -nefarious -negotiator -neither -nemesis -neoliberal -nephew -nervously -nest -netting -neuron -nevermore -nextdoor -nicotine -niece -nimbleness -nintendo -nirvana -nuclear -nugget -nuisance -nullify -numbing -nuptials -nursery -nutcracker -nylon -oasis -oat -obediently -obituary -object -obliterate -obnoxious -observer -obtain -obvious -occupation -oceanic -octopus -ocular -office -oftentimes -oiliness -ointment -older -olympics -omissible -omnivorous -oncoming -onion -onlooker -onstage -onward -onyx -oomph -opaquely -opera -opium -opossum -opponent -optical -opulently -oscillator -osmosis -ostrich -otherwise -ought -outhouse -ovation -oven -owlish -oxford -oxidize -oxygen -oyster -ozone -pacemaker -padlock -pageant -pajamas -palm -pamphlet -pantyhose -paprika -parakeet -passport -patio -pauper -pavement -payphone -pebble -peculiarly -pedometer -pegboard -pelican -penguin -peony -pepperoni -peroxide -pesticide -petroleum -pewter -pharmacy -pheasant -phonebook -phrasing -physician -plank -pledge -plotted -plug -plywood -pneumonia -podiatrist -poetic -pogo -poison -poking -policeman -poncho -popcorn -porcupine -postcard -poultry -powerboat -prairie -pretzel -princess -propeller -prune -pry -pseudo -psychopath -publisher -pucker -pueblo -pulley -pumpkin -punchbowl -puppy -purse -pushup -putt -puzzle -pyramid -python -quarters -quesadilla -quilt -quote -racoon -radish -ragweed -railroad -rampantly -rancidity -rarity -raspberry -ravishing -rearrange -rebuilt -receipt -reentry -refinery -register -rehydrate -reimburse -rejoicing -rekindle -relic -remote -renovator -reopen -reporter -request -rerun -reservoir -retriever -reunion -revolver -rewrite -rhapsody -rhetoric -rhino -rhubarb -rhyme -ribbon -riches -ridden -rigidness -rimmed -riptide -riskily -ritzy -riverboat -roamer -robe -rocket -romancer -ropelike -rotisserie -roundtable -royal -rubber -rudderless -rugby -ruined -rulebook -rummage -running -rupture -rustproof -sabotage -sacrifice -saddlebag -saffron -sainthood -saltshaker -samurai -sandworm -sapphire -sardine -sassy -satchel -sauna -savage -saxophone -scarf -scenario -schoolbook -scientist -scooter -scrapbook -sculpture -scythe -secretary -sedative -segregator -seismology -selected -semicolon -senator -septum -sequence -serpent -sesame -settler -severely -shack -shelf -shirt -shovel -shrimp -shuttle -shyness -siamese -sibling -siesta -silicon -simmering -singles -sisterhood -sitcom -sixfold -sizable -skateboard -skeleton -skies -skulk -skylight -slapping -sled -slingshot -sloth -slumbering -smartphone -smelliness -smitten -smokestack -smudge -snapshot -sneezing -sniff -snowsuit -snugness -speakers -sphinx -spider -splashing -sponge -sprout -spur -spyglass -squirrel -statue -steamboat -stingray -stopwatch -strawberry -student -stylus -suave -subway -suction -suds -suffocate -sugar -suitcase -sulphur -superstore -surfer -sushi -swan -sweatshirt -swimwear -sword -sycamore -syllable -symphony -synagogue -syringes -systemize -tablespoon -taco -tadpole -taekwondo -tagalong -takeout -tallness -tamale -tanned -tapestry -tarantula -tastebud -tattoo -tavern -thaw -theater -thimble -thorn -throat -thumb -thwarting -tiara -tidbit -tiebreaker -tiger -timid -tinsel -tiptoeing -tirade -tissue -tractor -tree -tripod -trousers -trucks -tryout -tubeless -tuesday -tugboat -tulip -tumbleweed -tupperware -turtle -tusk -tutorial -tuxedo -tweezers -twins -tyrannical -ultrasound -umbrella -umpire -unarmored -unbuttoned -uncle -underwear -unevenness -unflavored -ungloved -unhinge -unicycle -unjustly -unknown -unlocking -unmarked -unnoticed -unopened -unpaved -unquenched -unroll -unscrewing -untied -unusual -unveiled -unwrinkled -unyielding -unzip -upbeat -upcountry -update -upfront -upgrade -upholstery -upkeep -upload -uppercut -upright -upstairs -uptown -upwind -uranium -urban -urchin -urethane -urgent -urologist -username -usher -utensil -utility -utmost -utopia -utterance -vacuum -vagrancy -valuables -vanquished -vaporizer -varied -vaseline -vegetable -vehicle -velcro -vendor -vertebrae -vestibule -veteran -vexingly -vicinity -videogame -viewfinder -vigilante -village -vinegar -violin -viperfish -virus -visor -vitamins -vivacious -vixen -vocalist -vogue -voicemail -volleyball -voucher -voyage -vulnerable -waffle -wagon -wakeup -walrus -wanderer -wasp -water -waving -wheat -whisper -wholesaler -wick -widow -wielder -wifeless -wikipedia -wildcat -windmill -wipeout -wired -wishbone -wizardry -wobbliness -wolverine -womb -woolworker -workbasket -wound -wrangle -wreckage -wristwatch -wrongdoing -xerox -xylophone -yacht -yahoo -yard -yearbook -yesterday -yiddish -yield -yo-yo -yodel -yogurt -yuppie -zealot -zebra -zeppelin -zestfully -zigzagged -zillion -zipping -zirconium -zodiac -zombie -zookeeper -zucchini diff --git a/server/src/main/resources/webapp/fonts/glyphicons-halflings-regular.eot b/server/src/main/resources/webapp/fonts/glyphicons-halflings-regular.eot deleted file mode 100644 index b93a4953fff68df523aa7656497ee339d6026d64..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20127 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 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/server/src/main/resources/webapp/fonts/glyphicons-halflings-regular.ttf b/server/src/main/resources/webapp/fonts/glyphicons-halflings-regular.ttf deleted file mode 100644 index 1f853124540d93345e0db30b84b2713fb7a04b6b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 45386 zcmd?Sd0-pWwLh*qi$?oCk~i6sWlOeWJC3|4juU5JNSu9hSVACzERcmjLIPn6VTTf0 za0vTL3Zx+cvy?S$DU_mDURw&LEfiXZSNQT;%A+(bkXV!7=iHGjSy|}Y{`$$DnL9Ig z=AOHqd-gFfgTdf5Tx}2y>!(avFmp}a&i8R;09)DANt36rNe0PaU`03&&7MCzzT$-o zZo>IUoG)9x=A8BK9r*WaaDKPJVBD~L(p-(7j$IZ1iu@ZTB?_Z`Ijww1VGnIyS!ei-LfE7x4I`K{MO%M6D5 zkzc&z!gb5fS$FiVUl55Cyq>K#;Q8J3d}!@CYtDPR{-Jwujyj0D*RQ+y zk{9=U)M_w1a<#!=`PHT8oqPVPMGNK_3{NgVej_%jz2V=+?EWPk-`sS~M*Vp4PJYLM zGn9;D>PH{a5$zIK&RQ4uuXi9U6CN+MzjzmK|Du z=;}i|4(}aR#zk|mRForvAAMx z#f*x{6_d(;U;cjiugl*l|3&%F%U>)1QTYqyPn%S|by2JT`yb5?gMcy2e;A)=NqwXK zuERDA8;!JwG8>K6hcla!$&S7^n2;W>Zw4=pXX~56hvR;IGpIQJK;I00gQ3!+Z-#)u z5GmC+8s*iP^RyX?4TdPj7j1?T9FORm0eNF)eKVBd=+rku&|v6C-hP6;97h=&@)^Q7 zVtn`GeTFEGA#AlsH{nQIJJO?Y9Ea^Rq$lAx2ip>)XW_U^-wfS2o{Mc2uH#<+dTd*e zJ_pCEvE7991vu`&wi9X0;X{DukQwPKaCBiSM*4ajL)dDOM&3hB*xHf42gh;PrXc-Y z9H(JB4e7^loP!Nz8V=yN4BINCpTluIHiF^DI9`qICZylMk=}b3((m91SPtz%`gaDy zhd6vlefWDE&H85e2uBw-^oikP9MK0K79;%^9K-r%_)i=o*kZW;IgU-(+L8V{j^nTq zoS2Cp&cU_>ID+22Oy3yB!&kUR8}k|1-`#vOFpTtn?BkmO7|kfqI5MEY@IU0oIG&?R z!jS97pXg6g{}=wGA!xAh?*Bi}F@OK*AB~w)|I}08&fUcr_@*CUyA2GuUBF)rhQvxS zgjGf{G(O1;!$&`*NQS?}pESzvkA6xNkTg6g(q)-0KcyJi!04wKU2k@W-PO(RNDUjO zee(I|VrZbh2CF19Bn?TaOX@P5fp^FK6|9^ES)!9wFu&2sn&bX}U-cp7V8d9ToH>~> zI-KE(VvJNG)yT#$#leQNXxmtZE3s&63sRk|gT)%zSk{I&;!2`T=ypb}R*Uli#cx`z z2+9Nf7Pnv&1tz#H{SV;6YLj1iz-g(i{3r8CUH^lJPgn@`1)n#(Jut_q`l>q|_XnBJ z7zw+5#$l{7+UgEhM#r$0w&t+ArH#FkQiE)%8Vsu1?x2bjZ8x2;r9r9d_-mAba_eQS z$C5G*Z9iErOJPO@rRj~W=2CjOV;IWSo3?c@6^)_gJ6Igu6-R4}?ME!KNxRc1Gn>U| z+-xkeT*18Al+${r)v5g@dpelfBpbCmO|s=kvFE!cpXs|EsmnqyvDr)ynQTeEf86SH zS|885U^B7{O%^lTAz{iU~g_}pU|TE+sCy;9xp%l zf=7R`scM4l-Q;>Ezn8q;*IBVqdi)0~S2fIN3OlXkjkDv)csx1%k_p3{&dR3g!yda} z;{#3mE=>+^O)kE!`ZmIym!sXgq+Ua(VJe^v$IE5441?Ms4`X>9aEfL}#|PZa@wV2M zXoT%&ODC?L(B!u)--JaA#!-8x*bb>nI0#O`;2j*I`oKIQ zhG+;5^kXj^(S4WI7=l*FE6siN5^eN%SZS03_ql#ZDHP$z;;LGFdF* ztw>rhi@!3RiFqnpj&4Inq%ghpjplgzUri<TZE`Z);`C>vL*c*=hBPPiw3j7ZgAlW!Q^wYSi;LZ{-|S@-M;+SXIG|o z{aQF*tI(caE4^sn<%l}Y{Pi;JlJq^eI=2F0)UILj*sew>&aD6U(w4~+rHM; z`K-2od}*`#*p8z%w?W8zf8{AkkRt&l5r`!sv2Q4g{q6JDrvLcW=`a6j*2#-ae(S?q zZvE)iw^1PKXu#a-CH@C^gRks_-ef|6I{u)wJyA`_O-H9f_txIdsLjmIH`|;vk(_!u z+KKn{Zavbta)u>f{8$cH&ayb2*ahT|jRDJym5oQX_M$j@rpzvkZ7=3~47}uULo??6 zRKpCzY{PuRVjTm}Oy>xUmKU|TwU$*Han0Wx#!BOEi8kY!j4hmZRKi2^6y7Hc0iXzK z=fb402a_77nB`9A#mRx9q!`NV59Qq%_|M#RsS8hkObfJ7934w$%K}+@Hd?6i^~69{y2zBeYIx~ zpC~!-_Y+;s%lnNPs1XO>ae|b#{(p9#O8{wp=Ee%O_i-&v;~{^#7Pjnv^?rWK2?wba z)042*t{bc@d-$KYe&Xgiaig60Dh)RV+*B`pB85mE1PXw!tQqQ{1w=ky{n@XC4wFxL z(qtO=D{!%PwaN6P;xj#__}K@z!%qf2H<{SgdalP5ymzf(tu#TJ032js0ZJr$A2pomow$r%Wj0uy$Bcku))@_ILdnvoV{ZN*zz1@;*I- z_t+G0u7P8JmR^%~Va=*GkgSAOPg*-cJLqfY@hhjy=hfik;xsFvW=@=Ds8zP>Cr@vi zIg8bsOltt7)_3W*&VA;ZnKQ3p>z=;5yZi2^cXfAb2YW2e8HBrLI4!xPv}@+Jr_aS| z`;JL9fyQCO@Ypl-y6#<>XCnoVWS%BzaDIJS|H=9QyA2t={|xNigl{vr_n(0H23|wH zqcJ65ECr-poW5#6@1rpZ-|GBqOPk#4_keg1(Dtn@o`mWEPr%6*(E36&NfUy0%=zeB zXWaYiKmGdNGv0c1#nuh4ee&9dtx|73`aJYVr}pmi8<7JUH$Kl|osT3^n=g57!-m%` z*_;CH3u>OPzk_Q*AuQi?u8)Qs7L^#fQm?J{`)^1}y_u!ZLd&AI-f2mD=wabAob{n~ zJL!zQ0#3_mIYMdd^!6(;luA8P57unZt6;bV;t2c!CE!O=^*IF)e*vQsQ;bMPDu)Y@ zjwsPsA{IrmwPmaTu}G{f5lFNl>8UjO{PDIHp*vg~l}9wl*N+)CM=W-*yJh)q<}4ED zG>yDou8+&nVHMdNqwA5wF6=ZKcMA4manA5j*U1edkYn>xS6=zll~NC$bQBA7n%eQ? z2xD|ud1X!1IHDf!uAhr{3p-_br{E|S=TeS_CS$ZN6h@9FD!qP=z)RP5UHRmdS3U{( z67MHyLcAC`Va(N9Ljz~L_}JBV;IW#CT@0wr25)S5Xz+;fs%O>epMDKeE zS%LB%MgU~QGlMB02#;_fP?N9>{LB-)H>sP^sZUsBVYRSKQPK~YEa@NfZogE!i4TUc z7R(papYzFX!oqktsIb8*qTV|45xS{18CF{r=Yda=dbRbn9qCOpXQVEOgRmqXAw0q7 z-!9NVrG_RQPv{e_fK8y`t?CR=wnE@q{+;GrX6l`BFZ&TD9-n<1w5@Tfj6PDG(yqZg zG)p`5Jea0-jP1WTEy$}AZhTB1yN`5TzzJ63x@wsi5yPxm#2>>>_N70r{h~JgF?-@y z>Tchg+5@HirEG_`9yRP^_1b#c>vJPJr&UmQ8Qg+eWEt8HMsl(Y#>vvRkXdC|JRyoj z_D4ReU3o=2N4Pm!KsI+8V+F zT4PS#){2O=M%=0s~M12>)m(cmo8U-iz3C%v@}MK7-i4fR`^45cNXr z0LiYmCE@L4GB^&jm!Eo&#KkyfB);*snApe;0hxNm7ZsCiD?a*+tz0lN`eDr zJi=nZ1{l3y-MyHG`mx7i!*!3;>#(FRDJs?$(?cf7Ud+B%TqN9Taiknpt<&moSnjrD zc2@R^)ltx#q>(vkPlMbc*)<7OPSJ?Bq}}ectElLtZFklWZB@1(+N{JlSb>SMt13z6 z6T0Mq8fz?zLiU+q{ac%}gHLFVi%;L6STSgOtderwnrryNh{@cOo3|TZma1-0B&&w5 zv?|wiW#;fDnKhLVf!<#M1LG@ti2-!S2})NZkOMTwy;OXp5(^WrJ(x*InEjB&G94DH zwiB>izm{MjFgCvYXZ>*B^?=mMRzeDN-P&!qn}KU5t}55hz=BR7rGG^GP1gg#vXyj) zAO?Vz<5v0{=k%aHzVbOf8ddqcZs96VVCU0J3h)V?6Ux_x@&CK`uOMzW!}*FY4?IpM z;ymorCXShC_ZATf8KU8b|KqDeX%o;Nxk9lt4!(Xcg&hBri~1PCo=d`uIZr_1Z1h7A zi`$USi0DFLYGHBv#`#*`yiHi9u{v+3eR^-XFXby2L#g>2H_c1Y1-dMB*LFa}3(>B= znsP4M%%z=tEr?($%Fq;`*A)j;1<(jIVw{p<3An~hT7hygP>vCtXuAS6O*+MwCD|p0 zCypCYRx-9OR$D){eBlhmWRxBL%^iW7MsK@R+b}t}VvfRv7C)DoEzTwZBC0ct#*R5v zcDuvjbUNE*QE{?o6N^Pbv>JWP;czU5NR#VIf&X@b+8IHzan6|xk`gVAECi}JcaG_k zS<9#*=NB(#lPcGk62c-&^>)V87gGp)U@;$%5MC+pg#pRcZP(+t@!Z%`%E6B#wtK$;{XM%RN__88ZeHuW7}V+gF22_R9npjf0;^ z=Zc?#P8$LF9OxNc2dWqqko6fLupAN;@_!L(@pTNj8zzlYEP%1jBpBCqB#eT&PDyV& zuHjEsollwh>33JXv4D7XqtDdy)am=DntjHw{KMn=;Y9URje0$^QpsM(xKwcCK~Cj2 zKz}#ZFfk*UMBUYh8df9jFpH?oYSK|1wR4FNFw5H_F`jsM<~6*0n~vusxg0W5)%Cs%EQZ31O1soGUqArlYye4+tE46 zP;^qZA}w& zH~UB_`16jA1szbk>SNa;zs28MjQ%Wmb2wAZaAsyFD@8O8mO7H{O;6I^K1r#AK#XMj zgo8O4NE4isu!rM7nHj>1))pj5oXzPD zZUJRDV_>U(U3?Z-c+P?8ltcVwF*2a;(1;#8#@8}f&k*&hy3It*b7iR3sda)g3#v!A zv4h$~=_*|VpT+sT=!MCKg?Nch+Y(s|C~1ZhMN7*eDdh=ZLI6Oje0e0wH;?upikQpk z=`ERxwo!huO`BwOu~~|v9eM!}4FO}PLz&N9Y*CNJFU^wtq-)a?Ao?V<@@FI05=CLR?`I2kOHT}x#Ou5&6DCYp-0=H5mQ*&D*(OXVDzjDF?c!(Y)7igL z`6B23KgT?Z8RFccq1;HiHPAtw3`4e2inYpIaOn_~YHkP6D1ckjEdquy;jgl{wW*^n znCM<}VUuQq_`_%ogiF|O+BYumtY~O(X}8}pYn8ihe&?p&&Y5?`(g%fWm{JsM9yPCV z;>KBtk|j!Wjo4A-E3>-H%2ZZ++Qk!_&lok#JmQ?`wH+;`1CO6K=k#m%mz$_A!(O9dvMwmZA*>0|%uGwC691umPtwIghjZ$yBx3y;Ag%LHzbIx(i z6UVtrye_j9tepT70)24o`x)s#HRtMK&jIrY$U*defF*|;ERIZTgA7cm#9&;MkbQBJ zwb&aiDo(|ViyG<2S(p>ed{lq^AQ*;XXSYRC7&D z0=Zmcr*JaZ+SI7II*HF_8#}1|$2TN(T>8H~K60?+!*$a1f4QwWAwFbGXL6X(I>7B+AtlaQFJ$UdsQV^rnY8x#_)jK&AeQ*13gx<5T#-x;Jf2r0X?QC2=%YtJ z{wJz*^ckruA1S7iz}qLU7Uw@xQm^<4sDIFp)XK!&XNb}^voJ&WtfIcYBJIIm+D_!X z_z6xo(M93r3eJ~60G_2GseJ-mBT?|CfIA__nAa_3Xr_9p+f!2FIl347>0h$C>8$$G zfw$JrnzeqG)K%gcu+d%du%{%Mu6Xv^`&g&e&kkQQYu)VG>-f41>vdUblkR}!8?4n> zyd1hZ80I+{t@mX5FL}s;$i&UfR8;cJ!o+AAIh)ZQGvPCf%|5XB#iR zea(N2?KFkYUwQYm?HjxIY?=1zw&$<8=6PECGjdJRRzUkPM5@Z%x?r^Tz*OK+-MNRKgdp4*@3!aIz^>4iU3&_9YUa73iyfQhH;?~izeD4QK3#fZT8|> zoz=~Y)?YDp!M$6jSB>pjJm<87f!Z38m4-)@c~!pv{@E;hYHcMU0ak0yX}52@^x};- zOrCo6(kW3%9<_YulF2u0x_I-Z9ce8*W80|e@v(@*q}W`QmLf%Rjjvtutd*gTdOyA) zT?p+`9jAB_WJN_b&q8%L9>_Pe8N(9!Lxm{`*g;+>7=3Ec;kU@f3)3>&5l_6N?I41f z9j@(2y|hPL|L_Yhh$FS0e@U?A;@>Z3f*?5^{yMAW;*|ZRj#?rUJ8GXzY0n_v!)(XH zFKEBfdgA-oaz0iK(swWiOAT#kJ5a#+61qgz@R1~HI*$j!FA7_*PGbTTD_hD|eYfS+ zL0DdRn8PAm#pZ*-+^<+!NqcfZcZsF3{j_mY>b%S9>S$Imdx5?Dt7e>ka z1{3W5rf|o(<6DB@UEi{B*$K&X4AT98Gsye+_-4z4G~cp;Y!A@&x@E&swsiEwr?fqV z@Uow=TTuRa(AoV3$FCG5Rb`zCxGC^t7TU?F-(|tonvtL9Nq?#!JAZT?+4?g`r-}c5 zglKz$L)RdJ!GSU}(||B9P_ahklvu4108fUPFu(+wgN&mx3PX3;N1B+V$d-L6m`G;q zFH`$0vZ4)SjVhnOEm&95ZA%K8N3mxx;{l6=jDSu1QjshN@-xycX2vbNp5G!K7Xx)W z+86XbVPMq_SO{&!a_Ud8yjUIBn@&}AYE3#`r{zwY&R%nvh{7~E*lXH!S{{fF;_X5G zMzk%st-SZ9_(ymC@6y&Id)>13bk zB}yf^O5mOSjyl?zGBxD&Ng4c7v(yIJ4m89$d)mK=jULayTb|-#DXuxJZd>?Bhowd9hD?zc2ZH&S1$AMBxoZXs-VT4s*Fq+jlb7tG6H-n3-Jh~^C{u)|*f~GN*vnZ5G-LecYcXYDdajTGWd#Wn zY*lr!6J!mb4k6%&(xz}Nz5;Egt6n(ZnPkD*{30|n`L~I+L{1bx1Rl(VA@DG+AkvLe z34nsKg~^;0)ydL=616My+VNC%mLMmLMM+rbtALUMJMwM`a2J=B;m`tLS5PkdsMx%D zv$@!Oo0*O{6r2~pa^S?d2A>+z233V^FbJGKj)4VeqLoS^KmxQcIC?@n?7OyHHU=wv0f(0rJ4!rWo51Xj14?;Kq^Poa(&$lxvd99k@358+ zpB*ojT|SrU3HTM0;_#K#6`S0ynvrL=4WCw5YEJ)qMv94d46RQEylx8WQvfY=ff(_8 zuxC<0k(t2`E9k;@?imDAx7Z>hB3%tdMtcRIFUo;MhCom&=BZJ+k%msgkZxc&S)S^A zD(FD8w9cj(O9sS1Gxx-Lub=D#T9Ld2^LpCh|G$ZJLNp-$Ra;2LT?;KLi}06%x+X7Y zM!wt9S<+WfYQkTypvXKD7j7mi*(bF0$eCE^SS_DM+zN2b$Mm8G(30M`UJ`j0Jzg95zd?sX6kIn&6R$p)tEhfMS`!s2Vv;r+g@MPxopd3V> z$tQ$T{6_`|H3vi5c07#IvMdle5Ym4ILsAGMz!`#q$XTRdieNzqcy*gIs5qjzr9xjI z3Mb6dZ~BU)QBuU$=8NE1G-7bAD404g27TIFzF^SD8ht?xZa&$J1QX|NK~najtrjB4 z!AdxQK=1-h2>l2AFzF>7TX%oymAPARi&b2XtH zi*mIg(RW@x0&0mT!i->&*(b|>|4&qB&}5DN#2;|0fhO3qNW~^-hR4vlfTc`ZpCXfH zZWT1f>M$3}4#B7bqWd2K1Nl361vZN=t@TNh3ki$m|5?RyvUp`X;GAvIZbA(O!D8QJ zx2k5lf0IQCyIpG0<@ILRtMPX}K`M4`Yl>5&EHzzS>=R9Xw`0q0#o~aYtF-Ta6m&b% z0~@deb9-8ZWWkSyy$!xYvb%QE*6DKch;NgjZlWT0qa>AHJn@GzOyNZwkGu zgo7WAB_ujU+?Q@Ml?V+JE8g8lMdIwMt{dAty|p@0I((A3C_4P2aJal}-s}~vBS%ZIn({Noji?@X z_Eihxh~;27%TO+DkbcRn!yOF5tVRXZC>K!)NimW@3*C+S`W+&<&%&ovN*K$jLL~0$ z6ouPj6_(h@sS`p{sinx`5}DcKSa$QYkkMuDoIbzPKP^$=F+-oH{bqaPxbX|a z3wN!YTTA^Y9(&)gTI!RgfVUcJn2RfLo`&OeWux4J(Hu4MZ~?$xEs3@$EM^=Kphl4J zqqn_tEBy635?-To^2M$Zo~kKJCyi*DymWGvXM}rWd6jdxXHt`0a#lL4o%N@ANINc} zz6R8{7x7zSkQQ~3BtOAjEMcJ-NHlvBB!9(AAehp1NsWD_d(XxE+nKb+EcN zzeu&+>^tX@%g!xT^~yT8X!E|m@YgLRr*BxhyyU=$8^@wjQ#SC5mXDr0zTJM0=h3xP z`SpVpwJwq}^%Rdi06gcB9s}20L~$l!n4%;VBPm5Suvdn74RfMak5E9y5Ye{Ng>Al( zK4F_$T7Be;>QZK5OE~sqOSFkA3(#*;s;iL0NBculCvDgLaD=!25cCZY;>8Z_P1YkS zN40>#zy(~oV`i+{&50ITD2dcaxZ#aTBu4^99zxgFZgzpwU*y(yB}=?N|GBp$sqJzX z!O-;rskggRJD|Pf7~!k++2N7;^;y1gs>^)!)n=DE&UY45zP8zMYlMSMX7hYnA7-tr?*nBsgTm~H!bGm&q@B9`5XCa=AUQ%I}5LI83_EH zk3IvxXU;-Hqsg4QpaP~yncu+HY$}Aj#S z0n4w1?!T((@7;FUujq_L#1cKjU%!9bWe=*-Z68B)^)W;SZ@r2Ob1J|y*Z@Y}2 zX)_1!BR}o{P9jfrN#+op4uh=%r>K(RCnQ!*@7LZW3s$L1w?`rEj&8Av$GP_{cqgr4V^|L)gHS{XztWG)X)LPgI{&_x?>oP% zrpO2_l4AE&#M&mb#VWi`S!UEhN8mW3@5!yA_O#WD&g`tI={$4M>eJv~a>VRWhsCPH zrGA&m>8T)k-{L1iZQ9{rzC`WO^C63Unfb^>q3mT%V*L| z@qJxt1wTJ&X8OI107_KT?+UTkwFlWb)O^CRxrU^CHYAlk@^9BkR8$;`H1SI4Yj?OB z^eC)B!U0aFpm9lh&+ZidL^323IxW+2+O=94??HCWZ)nVAZjzuh{jTcJyPMtdJVphm z7vdG@A_^tFqx1mqE_`LE{VNCzMIYBP>g(ql~|Fz9mUM}_eUAwD`v}$!&3O5F)2r~Q37V*cp z#@mE;z)KXffxv@}NwaR0pvo|XlzNZOf#EYbI;AJkiTFv9TS&ufZFOOZ-qdJo#wJNmh!0JX*IlZank>_9WM!(`m>L)?>aeQ7(1>jQNzjuO z@5mW!DBZDNuJWaq`KsjoQiE<)#^b!lmS91INKO5psZp1JDY!OMM=r zXZ~f*v76l9vJ#J}Jh}S8+3lB{xv+D%&FU#B^SU>UbzU~#WAs+VTUtlh5>rM(b>gk| zUNuvD;Xtsq1|B74evifB_Bdq8R8t!~z^2Z;(iifU9Q~ouIAY8gj02y+C*6lQ8sK(W zLV<6i5{SX0F{UKo$C!u(;Jqk@`e*&=nP>hqtH0sidmHl7;#0?6(r@$igZiWw5|0MM z7`z*G4)RDl=zW^g)FH#kqmIl$g-#Z5Vsr*I znX5i~n5?&lPj)lMO*_Z&4U_X;m?{ zqpI{LKP{_C_PwLslw_A)ap(!M9mt8UY1rx-VVd(HV4=}E-0+FgWheZ=0T=kn(gADm z0#L(B#0^u*)>ybz6uOTD>Rq1&N7rc2myNE8myWP6yTg}g7_&8+Nz7aKu$Jr}K zq^@w0wl~<2te?9{>8YPvQ})xJlvc4Fv8p7Z<>UZOYB#;p_r#$q*rj?q%MNICN_lJv zvZ*IaRwtoOYCw)X^>r{2a0kK|WyEVnBjGxcj0fNcP*??)WEWKU*V>tF0c%`v;o1eO zuQirBwSCGXWsXrvR!wJbs9uj>8!1=>vxrG8GMoF`i_)_PJ3w6ZvCF^S9(8W%+A&Kz zpw{fR3wC$4WtwJQ!se?rsIMT1vQX@QZvG$h>qdQ$na{JKQEoF#K_AHFQr1o*repi& zux^YGd7k2s>x2m6W03P&IN`27u0FqGYXy_fW#6x8`<$i5YgaE^b0Mm>(8}y<{nNkg zwgD2tR{epq%(#t3S8Mx(IfK=aW`E3Nmpfoh|INO;MrHG7?daO#jM~@xAAinY zEXblDuw;#@9azG?{Pei`P>e*WOLk=Y2>2<8I&seuqP4Mv@gQFnAZx*hMPX=MCK3k; z!k56<>CKiK5)IQ7Mne8aARk5?~P zOTD|mM!j3XE)Yy!r|l8F>)9{01B=k%Oz&_EUu~q{<5l0FVZo}Cz}bFik?)c2LA|Om z7W1`otU5}Po$UGrtz4qIt%ZH~sqUt$AB5|V^R$%ifrni#lh$77wMk3G$&0l^BNmXU zod%nj)PF;ZW!3p!r;zOYB~Vc8Cxia0B!M8)Hmf8FK3M{SQj)wn)pTrtMz=zI&5>5c8PZFI<7=uI5 z)7FY~TO(rm=~5qhM65u3CJG})BCIHs?eVrmqZk9l5sj5om_*2cj0!?7s7N4}AL4(w zkG*s6nP=Ynj(%WC=diL-7UvkJZ>%VKnK(i=ml-P&a;{i$RSvhRW7~s@uUNGEB3?ya zxv@N4CEA;8&dF|1V@}On8wz*#1hfsvACtX2Vo-+-8Q#k7DS`0#GKZE zQn|rjxv9)NwaDU=Ob(Z1ZY-Ca(K@$US|%wTIQ(u1R&|CzS7vzrDVNyZr7?1-AKM81J8NE*e{ETq;yWi5%cN{g&nK}CUj`V)# zFy}g_Q|PXoEnRo!c{hJ@<&qnQRa*V&{Vvy9=P;MB_`HARR*}m<)9lCi(PKI#$d<@k zfSP645EYs~%3(EpqH7t}l#{!X8!kogA0p~DbAeo%3NL|cmGlCZAXs&KN0L)0h_luMb9f-#fvwmJ9Vu-$OpSU$4dWkfV*Lb^$JS8fE+el>xsTc z1PC4k0*_;Nmwaa~RFx~@BU z9lDdC*qYI5ysm3raM7d_Q^#iXq!%?iY-Jd~&bd=d;Y!4$zU3tS|eg%$W^!6eTB@hjx9z|b_kfqKDA z02L!2>18t4k(K1HmF%4}OvP6HZMs`Zx*VmTuRVWQe-dD z9&^@~IoQ<7$oNKwvwn=-Q53P&T)Os_3l=#>j+?TnvZ-VeJ2tiEj0@&Wo3+B}9yviP zchCEDXoR#xj^GbSEFqrs)+T5^@2eI+v)|f?H9!K(|URsw(vrM8j2EtcH z_{=c0LoEoubv-L}2J0ME+JE$E|E7KN25Wu`&aT!7E=vEReeA3YIwRWOwZ6BspTEJ1 zSW6!ZR5^5cmB?ZSw`7+3;lDPHdoim}Nku?&xG^Ho;tCvfxgM$+bH*LhgGMG=iy7G# zm5UfS?oO$tQ4kJBC(j#QFFYvOgUzvVm80h*YM#0`*|WH&SiD7EJiWAW!mOrHeBsJb zLBu!;NjXKEhiksQIcXmD7u&tw$e)P5$I{h^kLE!D7jMY|;p=Zkkr z2S}d6ZQtRShNuCU@f5KNV8iDCD8LBiTXP$UPXc;u0j&A3DeIJhCt`5mMb#l^K-}RG z3wABt6&u}AQoX=eTUt_N6#x2~NmU!#D$n(YZmpc(8n0*@Sr!Vcz9br3R1`=^MT*zv zHaFR-K6oUcDi*=fP<4)UV9qVGYQ|Q2f@*zx$@Hc=vz&}?EANDwlvS30#~U!Q$_hy= zv03jBU9#Qkwj^$!njGHl8#ZZtR~XUsF)xbYy}A?Qf#PEE6*W)X+AQl5KX_kfB&|D! z2>4P$fJ^;SnX9bc?>ORg9&z}^?JfxY2DV~l=WFTmg1xj}E~k5(n9t!a$Vmpt7*%MHQ4)eB!dQrHH)L<7#)1eA-bC_kPb+48HEX z7&y%D;O!~%F+(^c=f8ej&B$Bb3-9&pR#+OSGTnI|e))JWQJMLziH0U>jsBrIpfUPQ z<)JJwyP@pD@*vsfzWKZ`(64B>la;5N%4B128c2$jhlSe;BgQ~xuw(bZjGu+DLU*Si z-wSAYGFQ1*1!&~lJsOv~oG)8Wo>30bg^)-dR}yAp)~CIVN+pK_ZT+5?4hm>L!uPyX zZCy5)P*=v`0>$rnX-M(ghJ+LPZ^43A$!aj0umb6EI{;8GoHv=lT;x4{Wy#Y0V)er2| zk6*dyqE~3AUH;I94G(RQb`Rd9JX7_X$Z;`lZg?n%Yp6YVv=Lpsfu%QVq^O6WLp$j@ zH?k4n-&?a!7AniFFagdnLf_%unt?22$~u3TX%y9`79aHT)xD>~w{I@nc?So-U{av#uU zIzvZ%QiO#cm5^ARx3l>4n*xw@>NOS+fq94X$m!OLSGDIlvk&rgaFne+UK zp*6nYTTooj?3?Kj{BOa-1&%D~$1tAWyr)kalLJ9K_ALi;bvf(qc?XVsTPiHhzVu#{@hZx4P@&q992f|N zp9dg7QPXo~I*<)j(7JPw2(V)M6zldASixZpuNeKg;f4oQwlNzK->qc@g#HaNl)T#CP#?sLbRSw zNIgo?BFV|jSI(p3fEc4OFK$iWoom=7sjo z*>KaiO9QnFB$X+U^+GtJor%$qHP2?X3W~mqa+|+16pr*SxOw&&IrD5}=CIjiB?B8Q zfglxwyg)e_Y(s=k87MKr$P$8E%}QM>u6I_uw0~&N4T1C@Q=HCguXQ@7072nci^Py~ z@e}QDcv5uW$sx^`zV&2}WL}}Sugdud>N9Fzm}cuXs5&i^>owh~WeCxaNeCxue7{Ds zthP`i$|44AJshOmWOU|@r;)aN!>h>ZMUE?~{XG1Hao5C(wi z1qlNsBw|NG8J|_Z^E;gs_zt(4-J>CY%BEX7MR6(f6<2e@h+9fjYlol^WtgQ_OYSP9 z`d+)QSP+v4`Qi)|Gw7I+l15zO@l_nVs>}72eyBU|!@Ve}lcnurA*cUQX!Pc?`(D8LQBEwW5!IcB~j1CX4EVow6 z09M9uiQr>O$k#0FVVA1GRoc6-`i2dIR!zcnkUD*wGy*$L!)Ks~7<14?H^EW>gE+N{ zY_EFGJr{A&vSbmlE8xSlFR$Bk-A_}g^S{DpdXg!$pUdEq9+V!WZ)IQwC6OE?b&#@v zpw$fvjFpYXSfiY9?{+sjZgCjhm!3ax+ogz~_Oe%T?-A{dBf4gvcmC#%>6cE4d#z0T z&)sgL_Z8m=_oiIc{_eckgDBNe#75T;4H#*Vc;{j?2-s)OV3gEJg`&hiIzM zSBat_a>3FkSEuZOcn&uKSiV*~!6+628+iVajmfd~W^>T@GhgsF?UmbjLbQ+QIRBEL zt)Cb5Gsf1C)Sg1@An^Gb!5_uk57*RGS}ZBGNURhq)o&LSeOpCBEK*aFJyta=r2Wxb zR%WrpwO={oKDb~6)jnU`$%e-zdl-wQj`xV}wL^jk3IygZG54ThC-pbYsX&-~!C+Z6 zNOwtHsq|i0gyA>vxE@o-cGJN0n`|h8$J+r;qTqSNw^P_TGFD1rNBEe&iGwkw+b?Eu z9Ioi}HI3`M6lrP5PeFy)hV(KWY=wSImlDB@G#N+g8Yj9y(#zV8fqqiYbZ}d6c`(um z$sZ~p&%tHVDh(ODm`|hybHiYcToGX5|l^p zR?S9P*x{|cDJq{N6(ohC1LzDQDp22l8V;t*lz16{7w!9^-o4@G6;nujHlTQj)D~c9PS6C|s-tMseQ3FUqSH>)1FV7B+3_t-Wnejh0qJo~ z4GI9i6SQvtSnDMHETTp{Fa;S2kbNTmK3YK?xjkcYTeQ8ccAI9~R@>H&>2_T4>AmRR zMdQaWAdAQavp9|UlD(S2yllYCF-FHSV- zc~nfje9qb&4+F)z>_Zq!VB7Rw8rLTr^g!c>IRKdO$X?J6W#Fs`Kc4^s2I4$Hp*T;` z2(Kq!hX4+PJ(+s_gvG-wH=e>*_(;-8EkO9iY%oiYN{@2BxzI8upKn%(z6r-#6Jgf> z`R^WBy7YnH=?C`OABl6O-Gwv=Q7u$odUP-YOfKOl6bfUS0xDW z{;~Gi`eBV*_OZ>UYuDSW?b@~G*%uLT-}`uo(bDTh-eUT$p7X%w<=-u1DZo(uov-siNTYwf5;QopGLB+{GhYVdnI90~ftbC)nl~lxV z&>=4!QW3XMX9?X)zf-d0@{YK9)$~LIx8qkE64O^n!`oL)mp#HB>E4T$7_U8j%!-O& z$@Ep_NA+@#mam%b@u}Ud(^mS)BO?~`tVHLV-*geE{=buN8(lKDLXbWx<8 z7CfM%;(obOH!%WrMWL?APmI2&8jA*o+<>+!bKRc_5S!rl9rUTz06j|jEReDE94Ww# zzaf4>L8Rut`~JK0vk7gCByD-JQnK5sL@8h_ojPTi)eh@Nt5PP(b2b)9HhZNc`Hh~r z?KT^~{`K-(m*amCT^nW9ubK3`c3Y)%+mM%-a&JfB+B@1i>*gYvf}Yugbvbu7gW z-rd)?JNb;Zk$;H7@+y=V+fymwZ}ia^&|rOi(2v01@s`x9`qyG|<(fg~dm-rv^KyAW zT6o4pTD?3_a)JsS!)kRoTq_l;?M}a!DYbJq%H5~k4<+JO!Q`~uD~8fvv8Czvq^Wwr zTT`h%E$Or*5*FtiR5wd?iiaWR(RELtyaK3i0(P*_VWZaMd;qc-)n#Gn=H1{a`*!!G zJ*m=?u!GclsiY%ZB3%6W=b-fJ*iX|O!vW{RO_ zZbuz~;WFP5&6@oXm5G@pw+_;UF>={zYlh7v34ECz^-j1MoGE8?$(b0_D#$J-LKB35 z_aEAe9ktz^tiH25{R~)cV#IYnD9+E~sUtlgRq??X=^tzgn}oRYo!#B(kI`qlGt}@w z4r5!+`kVuLLKs1w(gzdxa5xT3_R5LCOr_9hrFvjn9Zq)NN#R6v>ON{k`nb&yNYQ`C zc4N@`r9N0_aXlqTX$cbYgQuV#Lwuhh85X`RToDM>AC>Au0pSY&xJd;Lcl{~pz|r1l zA`zA5#I&xVPR{wUu(R4P`Z`}W2ITG8{?wNS(zEC?quhBo(~Pr6Fi0L#k=pxsPLZqImv)XQn^0RbFi=xFp=?AaTM9x+>&)?uH{0|0 zMyWTIoSoP{zqxt-_QY&ZRL~I|$39AgNF;&{`d-jitvJQhjkG9XtfBhnk;4#OH;1uc z65mSD!3nCG;-TepvO?3G_E$!;Q67;^t5qtWNT2>xrKOfl6Q9t*>tWu3>C8)Fy)0u( zpMk2qtvYIQhy8cl;Sak_QSB~(NUSanw*iqMzw1j zj%&1Bn>n$@)aw)>r#m=_5lF=N%t3IEZ-lFR_!-UX?ps&6W8I$0if@Ka_FZsG+pKl# zW_8ZJechfC&2kDT2iFJLgNT=vfD_&nYM88j!bAnZkogo1)=gA;_1Lj9z3IE0wrT6z8o{HtomsMtPFJWf2t>!h!+9>+Q9vKT540$kEQgrTG%u|8j`v64ZOlW!?2QAm0a z;UD$eORDYN>BEcd(Gq*V_6J;L`;u%Dm^u*mB*5WOvC;^)1H+(xdv&S3yW3t`ZO2Ef zZ~;*AsmFIDy&;`Z1OHwM+5+qZk04>hOpF5E;)sSKSh>V9FYXXYly!WZ5<~Mh!m9QN z#C!UFqnm7skIv~p_zf&%Bnreq>e@J;TiVisi;uXFbuMvbWU9-TWSVrCdT2Y?Q%m2I z_Cu=W#tOwP*Py%6gCfSwqTY7Yg{)uLS5a}TR*^m$3b9zl5^X<&##(!9H%0RW;*oAk zFRWNnajjs)p4C)nYqfo>i7gx`%}jE%gFs(dmEc_oNj*{XgPwy%kPe_9NL>sm1ME#Q zR0g;ze0(lLgQ!yY2c{Tlgkz>3n7pcR5eDHEs&{Yt0H+_CQo}jPA>6=@K$z#%jNUS? zWaueN--;UJpT<1T3otVMLJ~a}_vO_vR=f)oVxkprqo1jq;w=tHO^(_1ql1&t24f}`ZSxzT`|#O zDfU`qXTVk~h>ON_DkIBckbov33AK%=d$p+6nmH?3Q2(H}EU0d^Hmq|g>Km7^$%Bip zGQa}KHTow~SWI!4#?kTq>F2d7Q56lnc=p*2?|Elu z0*zockfi0<$Ef#};P|T`BOh&;2M)?WnhISGU5$R`Ucn^wRS*pTM#7mX8qljp&TZhv zW6|tq3y6h+_?kQ}!1R**n3mdV#Yoa@Xq(830|vs^ut&X(j*vri-7+w2^~7oA=Zgt7 zSmsSv1S-vSqqIIymoLomdg`usSwmJ2yLwzh!?*^`dABE2?sb(ll#Fe%hnwdN-&(t^ z#>{HZuLxJ$gYGe2S@0=Vm$>~)lhqY<*4a0wD%)sysZnLS-P-COZZS=G>jj9UyMM^kH1oi|uc+eO8y5(ckh&H!0iEnIyA z;Z^R0aKD6@m%Y;Cz$dk|{$-_R*{^%RDwLKO$gm`6cf*NBS&Vr5MBAdvsyv?HHS^Lx znYXRXR8(`B5W4k>MN@|bjmGc^09qDb_^|O*a5Tr3COT)h-Y-49? zyGc0*_1rP-qkW_MdtSfuu2jzv$!@e5#hUS~G=1(Pk9_Chhxxk94okga2s9m!I_)9S z5({tEFClw8xV5_*;XXdeKZqe*8v0M@TBP7Z0`Y#CcY?~`@65hCd(6Bo{|!Q^aBr2MPn#m@$^mSSLpOY=JPec^7zb+{wbSWdI%SSkWLujd`ID(vT4AQ zTa$EHh?C$HL2eZ)w2~yxqx^Bkm5cDUD94bjPPlpT*s+VTXi*1S}`~staj~n%;~S!fFoD z0IgmQ$P7W4Dn`IA{Kw>CAFH$C%XlSD1gEx_#>Uou`+19RfogsJTTQ3MiWNa|78{Kw zE35OBboo?E#Mk_+c=@ySzKF#yuJsx{+Pl^Yr^9OxwoMrsFJqyifFu7!fHHTN|eb`sA?Y2}r>2?)aOi;-We$M4&UzJIFoS}ySW+{$lOe^t|;&O*y zmb5=i*7`iExx#8??hzfH$*g*eJsi_My?zUOG80{xqA-KHjE5YR_@L9D(~gL0_R4ZR zKCH3#k;?ILb^}|a?MweVsB=!D2Q%7GY6u#LJCcG9PjgrcANR+BtTvCPtLb=!*g zHwfEJHmk{9TUy-7uqN+hDrr%ZFnr-& zjjHb92$q1DG0Z((hddOIo=~G#h*zm>vZ;^fl~q`9ia?{L$(60yfF_5Q4$U78J(@Sb zm592-wOV@bQq&|GT9B!N5zY>`NdB4*I5-Tzzq~?(hfzT05ELGy?^fX2Zk@GB>IX9N z(j$|T`h?WHxi+9a2$0P}Gen^jY-h-Nf$|F50-S44UNfM{$#s+p;1!p8v%utR&hpsox9hj|wK!n})W)z~leL7NB_OP2xJ~YRqp?SzJ3sVsiR6floX~ z^8`E&m&@S^u+JPqD^5#`fpAI#n#X}<3loNoH^jy5;Fql2(w6rch0L$ zIg)PjD0T<&8vQv#oQ;>R6t~lJH0rX3$mEagrl(+j=Lx#S?fexEdKoVd&(-6(b$WR@ zIdx$n1Ur?F0_iz{Y)~;RYM>#r0Bn`DHZX9`tzmrTy^GziEtmEV^ot?kqi3}reDLER ze{l4-oR-MU58yv5wIfkKm>p=~A@f8JlatBOIoUNO z$!)kegOJRAn+!#6C!Hb`A~se3G+Fw+{BMFq2fqoHUE?U0f3*(F$-j+8Uy;bdDTeYP z$k>w&LLi1n|E$9b!CDRmgcH#}j|TsR?B~(wYnlIFYv&$bMRA7l{q~&PP7-p%+zb$t z5JC*$%$$3Sf!t0mC>Qa9H^3M$KnO@6ctL7g%0sD7Yn5Vay->7Dt))mQQj3-%wP4JH9IL%WOk8U_3L4e6egKCkRg@uY9?^o_;4@D6$0t=S0c^QL4c$sr7yl|xAe zp&Cf_o|Q7>fd*)mV!|+t)1SVwk$*2Xo5Gy9+E7qREV z_;YgOdh1*Zk!_gmuy?rsBR3w+#J%k*C_Ak?GeyiOGa0Kr(j9wtxTq9WB`SZHxp7kC z#^p2GS*~8wa=W@67wc2vl8efw`kKlwPK(3bteH9GzRN38t6GwWHHFe6vqGf_32E_Z zqswbTQ8nuRlvKBA?rqsykhL2VUM3{OrHu+qT3DZuH>v4{*1C+ixP*kf1xq_iiYIim zgbK3~Fo(jfOmvJJ&h}cUvS6p4Rtg<(u=~w^1}v z@0g09FJ&txI<(ggR1ZML(am$twZqIojny@A8Kcoth*OSS5Q5%`F_&V<)r>O@?V}_W z71OkekFQ_m+I|;i!IB*RnH$@Ox8twDL9{Pl^rCy#thDM6tx>QPpZz`E4-B~d)A}EZ zJA$iR3+3Kv8^VWlal`xZuq}S4^&N~m;wYIU1E0rahna;EQE>%lRI$K_v;M{QT9X=C zp)1cIZX*)B#$_Yc%{jd}=9+EPxDzhM09zQuWy0`0@>$*f_vjx6Hwg>&+5c*6IlJ!x zdyHF(r3*{WpvBmkkHxqtbg{kvp-=oye3O1?IukZHpM&=`*l*&PJPd?kysDE9VR&02 zX4)FGZ6FR@$A&@c)*FatY*;oVz6a|A`VZ6Z9J5%w{yz5>gP60=HSpuDwCChyaK6m` z2Co~x344~yfITgYH?V#q>^;KeQEVG}T(EAQM|A$fX>jpM%Yow|jqnS%nd9DyWq53T zAdYh^Zi2=cgl7*~a-Fz)oVcdM;DcES+R?|2%1Fk*mv_!L7RCG?cDzni$3R2jCm-kj z0anwUpmyBlJm+i1H(_ki``E+nXoKPUneo8$pby?9gEcYt$4z>yxnY^9DA6h6Y(w>6 z-r#x82Wil$k9GpSiO!b2=9G``VWuv}SQYc#YV}&ZGWkDzAIFQgitLs4YWr#XZCBLQ z<+{hU$DQcb?lwGAbtLYFxaZ=R#D9=bn9!E+O5(`Gw!{~bf=R2AwkI9+lzA@mtn(a8 z_9m}QekCO_Wkzaw>de$FcoTcaux)8&X-}jbPtQ!hGX384r!vYjdNQ_WdNRYAD>8Rw zWN8Y-; zJ$bL^oyZU7cjWKLKY8KI3%3>Mf^`MQMih)_7|}Um-H4qdj*qMy*)ww2sJ2lD3ZsQD zT%<4RxoAhx#G>^@JBo)D7Zrz#?JmLuKd6uTihMP`4&Qcvu79?Flm9@VBJfC{H&_!~ z5j+yg4^0l;7djYD57&iPhxbN2k=DqX$iAwAs?MqhtBzi>;gTcOxz$svH&&mzRA2f| zO;yc3H3uh@P3W5N)P&O$nR)L{ZilM7?v;7~KI{!+}TY~uGIm$7Y?=mGV@`i02Z z0%)2zbCExj_ck2yN{mo2OBj8*W(?B#?EUY#JpVs+{?O%?`Bvh1cj8}OjQ@Wgt?ovs zv45cxBTCbS)EQ?NG^YVuu(qZCA|*5~|sanwHHF?u%rbn8}7 zG7pR_fkr1vBHLuBE3_%FLq90rXyS-MOvXw%dM+z4I^Eo8 z^I`@tjWM8pTn+{$Bw>k26=tZcM(3q@f_kFVN}be8119Q@N|Q88i?qrlxlArcJvBw9 z$~3t`rpuLb6}pu~>WTkvc?v_u>XXLZ8NStnnS_40sxRlX(<%Gc!~c~~BiM`eS2LpI7|^0<6co{%SH6K+4^ z-6rz1d`C9RcV&w_BU|NrvQ54(+vQo=AwQ7k|5q~E8>+*&ik>AQu`JKEeZ^<$Fy}T`d zkmK@4>6JgppXD#|j{H?l$h-2M{7v4MzheT359Or%Lr%#@a$5c=AIll(lYZN>F;A!M zvfXwZ>iz^f(N4moiOF_~oob_d(N4EB?96!QRH7>y+kd1GQB zuOrgvjcteP7zfue4z6PqT*oN5j!|$Oqu@F^jb7zs60Wl!xYSY9QBEciPCZ3EMLk75 zMLkVDO+8ILO+8ILO+8ILO+8ILO+6p=eAM$%&qqBU^?cOxQO`#`AN73H^Ha}HJwNsQ z)bmr%Pdz{N{M7SP&riJo^#arjP!G5I08yhiK)nF<0@MpoFF?Hj^@7w3QYT2AAa#P& z2~sCWogj6B)Co~1M7u)N3sEmby%6<6)C*BBM7FHF5K^}^H(Q!h-tF!jRJ z3sWyby$JOp)QeCrLcIv}BGik-^c1;QUy*-B{uTLGUy*-B{uTLG zB$-gH5n%rx0ugSY6=bD^ra*hFxF+0h*CfAx=YjUm0 zwI+pp))v8{5gt_uj9!t5)^yb-JtjRGrhi zYInOUNJxNyf_yKX01)K=WP|Si>HqEj|B{eUl?MR<)%<1&{(~)D+NPwKxWqT-@~snp zg9KCz1VTZDiS?UH`PRk1VPM{29cgT9=D?!Wc_@}qzggFv;gb@2cJQAYWWtpEZ7?y@jSVqjx${B5UV@SO|wH<<0; z{><1KdVI%Ki}>~<`46C0AggwUwx-|QcU;iiZ{NZu`ur>hd*|Hb(|6veERqxu=b@5Bab=rqptGxd{QJg!4*-i_$sES~)AB46}Fjg|ea#e@?J}z%CUJ zOsLWRQR1#ng^sD)A4FDuY!iUhzlgfJh(J@BRqd&P#v2B`+saBx>m+M&q7vk-75$NH%T5pi%m z5FX?`2-5l53=a&GkC9^NZCLpN5(DMKMwwab$FDIs?q>4!!xBS}75gX_5;(luk;3Vl zLCLd5a_8`Iyz}K}+#RMwu6DVk3O_-}n>aE!4NaD*sQn`GxY?cHe!Bl9n?u&g6?aKm z-P8z&;Q3gr;h`YIxX%z^o&GZZg1=>_+hP2$$-DnL_?7?3^!WAsY4I7|@K;aL<>OTK zByfjl2PA$T83*LM9(;espx-qB%wv7H2i6CFsfAg<9V>Pj*OpwX)l?^mQfr$*OPPS$ z=`mzTYs{*(UW^ij1U8UfXjNoY7GK*+YHht(2oKE&tfZuvAyoN(;_OF>-J6AMmS5fB z^sY6wea&&${+!}@R1f$5oC-2J>J-A${@r(dRzc`wnK>a7~8{Y-scc|ETOI8 zjtNY%Y2!PI;8-@a=O}+{ap1Ewk0@T`C`q!|=KceX9gK8wtOtIC96}-^7)v23Mu;MH zhKyLGOQMujfRG$p(s`(2*nP4EH7*J57^=|%t(#PwCcW7U%e=8Jb>p6~>RAlY4a*ts=pl}_J{->@kKzxH|8XQ5{t=E zV&o`$D#ZHdv&iZWFa)(~oBh-Osl{~CS0hfM7?PyWUWsr5oYlsyC1cwULoQ4|Y5RHA2*rN+EnFPnu z`Y_&Yz*#550YJwDy@brZU>0pWV^RxRjL221@2ABq)AtA%Cz?+FG(}Yh?^v)1Lnh%D zeM{{3&-4#F9rZhS@DT0E(WRkrG!jC#5?OFjZv*xQjUP~XsaxL2rqRKvPW$zHqHr8Urp2Z)L z+)EvQeoeJ8c6A#Iy9>3lxiH3=@86uiTbnnJJJoypZ7gco_*HvKOH97B? zWiwp>+r}*Zf9b3ImxwvjL~h~j<<3shN8$k-$V1p|96I!=N6VBqmb==Bec|*;HUg?) z4!5#R*(#Fe)w%+RH#y{8&%%!|fQ5JcFzUE;-yVYR^&Ek55AXb{^w|@j|&G z|6C-+*On%j;W|f8mj?;679?!qY86c{(s1-PI2Wahoclf%1*8%JAvRh1(0)5Vu37Iz z`JY?RW@qKr+FMmBC{TC7k@}fv-k8t6iO}4K-i3WkF!Lc=D`nuD)v#Na zA|R*no51fkUN3^rmI;tty#IK284*2Zu!kG13!$OlxJAt@zLU`kvsazO25TpJLbK&;M8kw*0)*14kpf*)3;GiDh;C(F}$- z1;!=OBkW#ctacN=je*Pr)lnGzX=OwgNZjTpVbFxqb;8kTc@X&L2XR0A7oc!Mf2?u9 zcctQLCCr+tYipa_k=;1ETIpHt!Jeo;iy^xqBES^Ct6-+wHi%2g&)?7N^Yy zUrMIu){Jk)luDa@7We5U!$$3XFNbyRT!YPIbMKj5$IEpTX1IOtVP~(UPO2-+9ZFi6 z-$3<|{Xb#@tABt0M0s1TVCWKwveDy^S!!@4$s|DAqhsEv--Z}Dl)t%0G>U#ycJ7cy z^8%;|pg32=7~MJmqlC-x07Sd!2YX^|2D`?y;-$a!rZ3R5ia{v1QI_^>gi(HSS_e%2 zUbdg^zjMBBiLr8eSI^BqXM6HKKg#@-w`a**w(}RMe%XWl3MipvBODo*hi?+ykYq)z ziqy4goZw0@VIUY65+L7DaM5q=KWFd$;W3S!Zi>sOzpEF#(*3V-27N;^pDRoMh~(ZD zJLZXIam0lM7U#)119Hm947W)p3$%V`0Tv+*n=&ybF&}h~FA}7hEpA&1Y!BiYIb~~D z$TSo9#3ee02e^%*@4|*+=Nq6&JG5>zX4k5f?)z*#pI-G(+j|jye%13CUdcSP;rNlY z#Q!X%zHf|V)GWIcEz-=fW6AahfxI~y7w7i|PK6H@@twdgH>D_R@>&OtKl}%MuAQ7I zcpFmV^~w~8$4@zzh~P~+?B~%L@EM3x(^KXJSgc6I=;)B6 zpRco2LKIlURPE*XUmZ^|1vb?w*ZfF}EXvY13I4af+()bAI5V?BRbFp`Sb{8GRJHd* z4S2s%4A)6Uc=PK%4@PbJ<{1R6+2THMk0c+kif**#ZGE)w6WsqH z`r^DL&r8|OEAumm^qyrryd(HQ9olv$ltnVGB{aY?_76Uk%6p;e)2DTvF(;t=Q+|8b zqfT(u5@BP);6;jmRAEV057E*2d^wx@*aL1GqWU|$6h5%O@cQtVtC^isd%gD7PZ_Io z_BDP5w(2*)Mu&JxS@X%%ByH_@+l>y07jIc~!@;Raw)q_;9oy@*U#mCnc7%t85qa4? z%_Vr5tkN^}(^>`EFhag;!MpRh!&bKnveQZAJ4)gEJo1@wHtT$Gs6IpznN$Lk-$NcM z3ReVC&qcXvfGX$I0nfkS$a|Pm%x+lq{WweNc;K>a1M@EAVWs2IBcQPiEJNt}+Ea8~WiapASoMvo(&PdUO}AfC~>ZGzqWjd)4no( ziLi#e3lOU~sI*XPH&n&J0cWfoh*}eWEEZW%vX?YK!$?w}htY|GALx3;YZoo=JCF4@ zdiaA-uq!*L5;Yg)z-_`MciiIwDAAR3-snC4V+KA>&V%Ak;p{1u>{Lw$NFj)Yn0Ms2*kxUZ)OTddbiJM}PK!DM}Ot zczn?EZXhx3wyu6i{QMz_Ht%b?K&-@5r;8b076YDir`KXF0&2i9NQ~#JYaq*}Ylb}^ z<{{6xy&;dQ;|@k_(31PDr!}}W$zF7Jv@f%um0M$#=8ygpu%j(VU-d5JtQwT714#f0z+Cm$F9JjGr_G!~NS@L9P;C1? z;Ij2YVYuv}tzU+HugU=f9b1Wbx3418+xj$RKD;$gf$0j_A&c;-OhoF*z@DhEW@d9o zbQBjqEQnn2aG?N9{bmD^A#Um6SDKsm0g{g_<4^dJjg_l_HXdDMk!p`oFv8+@_v_9> zq;#WkQ!GNGfLT7f8m60H@$tu?p;o_It#TApmE`xnZr|_|cb3XXE)N^buLE`9R=Qbg zXJu}6r07me2HU<)S7m?@GzrQDTE3UH?FXM7V+-lT#l}P(U>Fvnyw8T7RTeP`R579m zj=Y>qDw1h-;|mX-)cSXCc$?hr;43LQt)7z$1QG^pyclQ1Bd!jbzsVEgIg~u9b38;> zfsRa%U`l%did6HzPRd;TK{_EW;n^Ivp-%pu0%9G-z@Au{Ry+EqEcqW=z-#6;-!{WA z;l+xC6Zke>dl+(R1q7B^Hu~HmrG~Kt575mzve>x*cL-shl+zqp6yuGX)DDGm`cid! znlnZY=+a5*xQ=$qM}5$N+o!^(TqTFHDdyCcL8NM4VY@2gnNXF|D?5a558Lb*Yfm4) z_;0%2EF7k{)i(tTvS`l5he^KvW%l&-suPwpIlWB_Za1Hfa$@J!emrcyPpTKKM@NqL z?X_SqHt#DucWm<3Lp}W|&YyQE27zbGP55=HtZmB(k*WZA79f##?TweCt{%5yuc+Kx zgfSrIZI*Y57FOD9l@H0nzqOu|Bhrm&^m_RK6^Z<^N($=DDxyyPLA z+J)E(gs9AfaO`5qk$IGGY+_*tEk0n_wrM}n4G#So>8Dw6#K7tx@g;U`8hN_R;^Uw9JLRUgOQ?PTMr4YD5H7=ryv)bPtl=<&4&% z*w6k|D-%Tg*F~sh0Ns(h&mOQ_Qf{`#_XU44(VDY8b})RFpLykg10uxUztD>gswTH} z&&xgt>zc(+=GdM2gIQ%3V4AGxPFW0*l0YsbA|nFZpN~ih4u-P!{39d@_MN)DC%d1w z7>SaUs-g@Hp7xqZ3Tn)e z7x^sC`xJ{V<3YrmbB{h9i5rdancCEyL=9ZOJXoVHo@$$-%ZaNm-75Z-Ry9Z%!^+STWyv~To>{^T&MW0-;$3yc9L2mhq z;ZbQ5LGNM+aN628)Cs16>p55^T^*8$Dw&ss_~4G5Go63gW^CY+0+Z07f2WB4Dh0^q z-|6QgV8__5>~&z1gq0FxDWr`OzmR}3aJmCA^d_eufde7;d|OCrKdnaM>4(M%4V`PxpCJc~UhEuddx9)@)9qe_|i z)0EA%&P@_&9&o#9eqZCUCbh?`j!zgih5sJ%c4(7_#|Xt#r7MVL&Q+^PQEg3MBW;4T zG^4-*8L%s|A}R%*eGdx&i}B1He(mLygTmIAc^G(9Si zK7e{Ngoq>r-r-zhyygK)*9cj8_%g z)`>ANlipCdzw(raeqP-+ldhyUv_VOht+!w*>Sh+Z7(7(l=9~_Vk ztsM|g1xW`?)?|@m2jyAgC_IB`Mtz(O`mwgP15`lPb2V+VihV#29>y=H6ujE#rdnK` zH`EaHzABs~teIrh`ScxMz}FC**_Ii?^EbL(n90b(F0r0PMQ70UkL}tv;*4~bKCiYm zqngRuGy`^c_*M6{*_~%7FmOMquOEZXAg1^kM`)0ZrFqgC>C%RJvQSo_OAA(WF3{euE}GaeA?tu5kF@#62mM$a051I zNhE>u>!gFE8g#Jj95BqHQS%|>DOj71MZ?EYfM+MiJcX?>*}vKfGaBfQFZ3f^Q-R1# znhyK1*RvO@nHb|^i4Ep_0s{lZwCNa;Ix<{E5cUReguJf+72QRZIc%`9-Vy)D zWKhb?FbluyDTgT^naN%l2|rm}oO6D0=3kfXO2L{tqj(kDqjbl(pYz9DykeZlk4iW5 zER`)vqJxx(NOa;so@buE!389-YLbEi@6rZG0#GBsC+Z0fzT6+d7deYVU;dy!rPXiE zmu73@Jr&~K{-9MVQD}&`)e>yLNWr>Yh8CXae9XqfvVQ&eC_;#zpoaMxZ0GpZz7xjx z`t_Q-F?u=vrRPaj3r<9&t6K=+egimiJ8D4gh-rUYvaVy zG($v+3zk5sMuOhjxkH7bQ}(5{PD3Mg?!@8PkK&w>n7tO8FmAmoF30_#^B~c(Q_`4L zYWOoDVSnK|1=p{+@`Fk^Qb81Xf89_S`RSTzv(a4ID%71nll%{Wad$!CKfeTKkyC?n zCkMKHU#*nz_(tO$M)UP&ZfJ#*q(0Gr!E(l5(ce<3xut+_i8XrK8?Xr7_oeHz(bZ?~8q5q~$Rah{5@@7SMN zx9PnJ-5?^xeW2m?yC_7A#WK*B@oIy*Y@iC1n7lYKj&m7vV;KP4TVll=II)$39dOJ^czLRU>L> z68P*PFMN+WXxdAu=Hyt3g$l(GTeTVOZYw3KY|W0Fk-$S_`@9`K=60)bEy?Z%tT+Iq z7f>%M9P)FGg3EY$ood+v$pdsXvG? zd2q3abeu-}LfAQWY@=*+#`CX8RChoA`=1!hS1x5dOF)rGjX4KFg!iPHZE2E=rv|A} zro(8h38LLFljl^>?nJkc+wdY&MOOlVa@6>vBki#gKhNVv+%Add{g6#-@Z$k*ps}0Y zQ=8$)+Nm||)mVz^aa4b-Vpg=1daRaOU)8@BY4jS>=5n#6abG@(F2`=k-eQ9@u# zxfNFHv=z2w@{p1dzSOgHokX1AUGT0DY4jQI@YMw)EWQ~q5wmR$KQ}Y;(HPMSQCwzu zdli|G?bj(>++CP)yQ4s6YfpDc3KqPmquQSxg%*EnTWumWugbDW5ef%8j-rT#3rJu? z)5n;4b2c*;2LIW%LmvUu6t1~di~}0&Svy}QX#ER|hDFZwl!~zUP&}B1oKAxIzt~so zb!GaJYOb#&qRUjEI1xe_`@7qv_-LggQ$JE8+{ryT4%ldwC5ete+{G3C#g@^oxfY3#F zcLlj(l2G8>tC<5XWV|6_DZQZ7ow?MD8EZ9mM2oV~WoV-uoExmbwpzc6eMV}%J_{3l zW(4t2a-o}XRlU|NSiYn!*nR(Sc>*@TuU*(S77gfCi7+WR%2b;4#RiyxWR3(u5BIdf zo@#g4wQjtG3T$PqdX$2z8Zi|QP~I^*9iC+(!;?qkyk&Q7v>DLJGjS44q|%yBz}}>i z&Ve%^6>xY<=Pi9WlwpWB%K10Iz`*#gS^YqMeV9$4qFchMFO}(%y}xs2Hn_E}s4=*3 z+lAeCKtS}9E{l(P=PBI;rsYVG-gw}-_x;KwUefIB@V%RLA&}WU2XCL_?hZHoR<7ED zY}4#P_MmX(_G_lqfp=+iX|!*)RdLCr-1w`4rB_@bI&Uz# z!>9C3&LdoB$r+O#n);WTPi;V52OhNeKfW6_NLnw zpFTuLC^@aPy~ZGUPZr;)=-p|b$-R8htO)JXy{ecE5a|b{{&0O%H2rN&9(VHxmvNly zbY?sVk}@^{aw)%#J}|UW=ucLWs%%j)^n7S%8D1Woi$UT}VuU6@Sd6zc2+t_2IMBxd zb4R#ykMr8s5gKy=v+opw6;4R&&46$V+OOpDZwp3iR0Osqpjx))joB*iX+diVl?E~Q zc|$qmb#T#7Kcal042LUNAoPTPUxF-iGFw>ZFnUqU@y$&s8%h-HGD`EoNBbe#S>Y-4 zlkeAP>62k~-N zHQqXXyN67hGD6CxQIq_zoepU&j0 zYO&}<4cS^2sp!;5))(aAD!KmUED#QGr48DVlwbyft31WlS2yU<1>#VMp?>D1BCFfB z_JJ-kxTB{OLI}5XcPHXUo}x~->VP%of!G_N-(3Snvq`*gX3u0GR&}*fFwHo3-vIw0 zeiWskq3ZT9hTg^je{sC^@+z3FAd}KNhbpE5RO+lsLgv$;1igG7pRwI|;BO7o($2>mS(E z$CO@qYf5i=Zh6-xB=U8@mR7Yjk%OUp;_MMBfe_v1A(Hqk6!D})x%JNl838^ZA13Xu zz}LyD@X2;5o1P61Rc$%jcUnJ>`;6r{h5yrEbnbM$$ntA@P2IS1PyW^RyG0$S2tUlh z8?E(McS?7}X3nAAJs2u_n{^05)*D7 zW{Y>o99!I9&KQdzgtG(k@BT|J*;{Pt*b|?A_})e98pXCbMWbhBZ$t&YbNQOwN^=F) z_yIb_az2Pyya2530n@Y@s>s>n?L79;U-O9oPY$==~f1gXro5Y z*3~JaenSl_I}1*&dpYD?i8s<7w%~sEojqq~iFnaYyLgM#so%_ZZ^WTV0`R*H@{m2+ zja4MX^|#>xS9YQo{@F1I)!%RhM{4ZUapHTKgLZLcn$ehRq(emb8 z9<&Nx*RLcS#)SdTxcURrJhxPM2IBP%I zf1bWu&uRf{60-?Gclb5(IFI*!%tU*7d`i!l@>TaHzYQqH4_Y*6!Wy0d-B#Lz7Rg3l zqKsvXUk9@6iKV6#!bDy5n&j9MYpcKm!vG7z*2&4G*Yl}iccl*@WqKZWQSJCgQSj+d ze&}E1mAs^hP}>`{BJ6lv*>0-ft<;P@`u&VFI~P3qRtufE11+|#Y6|RJccqo27Wzr}Tp|DH z`G4^v)_8}R24X3}=6X&@Uqu;hKEQV^-)VKnBzI*|Iskecw~l?+R|WKO*~(1LrpdJ? z0!JKnCe<|m*WR>m+Qm+NKNH<_yefIml z+x32qzkNRrhR^IhT#yCiYU{3oq196nC3ePkB)f%7X1G^Ibog$ZnYu4(HyHUiFB`6x zo$ty-8pknmO|B9|(5TzoHG|%>s#7)CM(i=M7Nl=@GyDi-*ng6ahK(&-_4h(lyUN-oOa$` zo+P;C4d@m^p9J4c~rbi$rq9nhGxayFjhg+Rqa{l#`Y z!(P6K7fK3T;y!VZhGiC#)|pl$QX?a)a9$(4l(usVSH>2&5pIu5ALn*CqBt)9$yAl; z-{fOmgu><7YJ5k>*0Q~>lq72!XFX6P5Z{vW&zLsraKq5H%Z26}$OKDMv=sim;K?vsoVs(JNbgTU8-M%+ zN(+7Xl}`BDl=KDkUHM9fLlV)gN&PqbyX)$86!Wv!y+r*~kAyjFUKPDWL3A)m$@ir9 zjJ;uQV9#3$*`Dqo1Cy5*;^8DQcid^Td=CivAP+D;gl4b7*xa9IQ-R|lY5tIpiM~9- z%Hm9*vDV@_1FfiR|Kqh_5Ml0sm?abD>@peo(cnhiSWs$uy&$RYcd+m`6%X9FN%?w}s~Q=3!pJzbN~iJ}bbM*PPi@!E0eN zhKcuT=kAsz8TQo76CMO+FW#hr6da({mqpGK2K4T|xv9SNIXZ}a=4_K5pbz1HE6T}9 zbApW~m0C`q)S^F}B9Kw5!eT)Bj_h9vlCX8%VRvMOg8PJ*>PU>%yt-hyGOhjg!2pZR4{ z=VR_*?Hw|aai##~+^H>3p$W@6Zi`o4^iO2Iy=FPdEAI58Ebc~*%1#sh8KzUKOVHs( z<3$LMSCFP|!>fmF^oESZR|c|2JI3|gucuLq4R(||_!8L@gHU8hUQZKn2S#z@EVf3? zTroZd&}JK(mJLe>#x8xL)jfx$6`okcHP?8i%dW?F%nZh=VJ)32CmY;^y5C1^?V0;M z<3!e8GZcPej-h&-Osc>6PU2f4x=XhA*<_K*D6U6R)4xbEx~{3*ldB#N+7QEXD^v=I z+i^L+V7_2ld}O2b-(#bmv*PyZI4|U#Q5|22a(-VLOTZc3!9ns1RI-? zA<~h|tPH0y*bO1#EMrsWN>4yJM7vqFZr?uw$H8*PhiHRQg1U9YoscX-G|gck+SSRX!(e7@~eeUEw+POsT;=W9J&=EV`cUc{PIg_#TQVGnZsQbCs7#Q-)v#BicxLw#Fb?#)8TYbu zN)5R=MI1i7FHhF|X}xEl=sW~`-kf;fOR^h1yjthSw?%#F{HqrY2$q>7!nbw~nZ8q9 zh{vY! z%i=H!!P&wh z7_E%pB7l5)*VU>_O-S~d5Z!+;f{pQ4e86*&);?G<9*Q$JEJ!ZxY;Oj5&@^eg0Zs!iLCAR`2K?MSFzjX;kHD6)^`&=EZOIdW>L#O`J zf~$M4}JiV}v6B-e{NUBGFgj-*H%NG zfY0X(@|S8?V)drF;2OQcpDl2LV=~=%gGx?_$fbSsi@%J~taHcMTLLpjNF8FkjnjyM zW;4sSf6RHaa~LijL#EJ0W2m!BmQP(f=%Km_N@hsBFw%q#7{Er?y1V~UEPEih87B`~ zv$jE%>Ug9&=o+sZVZL7^+sp)PSrS;ZIJac4S-M>#V;T--4FXZ*>CI7w%583<{>tb6 zOZ8gZ#B0jplyTbzto2VOs)s9U%trre`m=RlKf{I_Nwdxn(xNG%zaVNurEYiMV3*g| z``3;{j7`UyfFrjlEbIJN{0db|r>|LA@=vX9CHFZYiexnkn$b%8Rvw0TZOQIXa;oTI zv@j;ZP+#~|!J(aBz9S{wL7W%Dr1H)G-XUNt9-lP?ijJ-XEj1e*CI~-Xz@4(Xg;UoG z{uzBf-U+(SHe}6oG%;A*93Zb=oE>uTb^%qsL>|bQf?7_6=KIiPU`I|r;YcZ!YG7y~ zQu@UldAwz$^|uoz3mz1;An-WVBtefSh-pv<`n&TU3oM!hrEI?l@v8A4#^$4t&~T32 zl*J=1q~h+60sNc43>0aVvhzyfjshgPYZoQ(OOh>LbUIoblb@1z~zp?))n?^)q6WGuDh}gMUaA9|X z3qq-XlcNldy5==T4rq*~g@XVY!9sYZjo#R7 zr{n)r5^S{9+$+8l7IVB*3_k5%-TBY@C%`P@&tZf>82sm#nfw7L%92>nN$663yW!yt zhS>EfLcE_Z)gv-Y^h1;xj(<4nD4GY{C-nWUgQc9cMmH{qpa!uEznrGF^?bbJHApScQ$j>$JZHAX80DdXu z--AMgrA0$Otdd#N9#!cg2Z~N8&lj1d+wDh+^ZObWJ$J)_h(&2#msu>q0B$DEERy{1 zCJN{7M@%#E@8pda`@u!v@{gcT3bA*>g*xYLXlbb&o@1vX*x+l}Voys6o~^_7>#GB| z*r!R%kA9k%J`?m>1tMHB9x$ZRe0$r~ui}X}jOC)9LH=Po*2SLdtf3^4?VKnu2ox&mV~0oDgi` z;9d}P$g~9%ThTK8s}5ow2V4?(-lU*ed8ro|}mU}pk% z;bqB0bx3AOk<0Joeh}Vl@_7Po&C`Cg>>gff>e7fu41U3Ic{JQu1W%+!Gvz3GDO2ixKd;KF6UEw8F_cDAh08gB>@ zaRH2Q96sBJ>`4aXvrF0xPtIWoA1pPsRQtU~xDtnEfTJnl{A9u5pR^K8=UdNq%T8F$)FbN> zgK+_(BF#D>R>kK!M#OT~=@@}3yAYqm33?{Bv?2iBr|-aRK0@uapzuXI)wE0=R@m^7 zQ`wLBn(M*wg!mgmQT1d!@3<2z>~rmDW)KG0*B4>_R6LjiI0^9QT8gtDDT|Lclxppm z+OeL6H3QpearJAB%1ellZ6d*)wBQ(hPbE=%?y6i^uf%`RXm*JW*WQ%>&J+=V(=qf{ zri~yItvTZbII+7S0>4Q0U9@>HnMP$X>8TqAfD(vAh};2P{QK)ik`a6$W$nG<{bR2Ufd!^iE z#1K58$gW!xpeYHeehuhQCXZ9p%N8m zB+l~T_u-Ycr!U>!?xu!!*6rNxq37{`DhMMfY6NpD3Jw zkYQDstvt30Hc_SaZuuMP2YrdW@HsPMbf^Y9lI<9$bnMil2X7`Ba-DGLbzgqP>mxwe zf1&JkDH54D3nLar2KjJ3z`*R+rUABq4;>>4Kjc2iQEj7pVLcZYZ~pteAG4rm1{>PQy=!QiV5G|tVk)53 zP?Azw+N)Yq3zZ`dW7Q9Bq@Y*jSK0<1f`HM;_>GH57pf_S%Ounz_yhTY8lplQSM`xx zU{r-Deqs+*I~sLI$Oq`>i`J1kJ(+yNOYy$_>R3Jfi680<|^u#J@aY%Q>O zqfI~sCbk#3--^zMkV&Yj0D(R^rK}+_npgPr_4^kYuG=pO%$C_7v{s@-{M-P@RL3^<`kO@b=YdKMuccfO1ZW# zeRYE%D~CMAgPlo?T!O6?b|pOZv{iMWb;sN=jF%=?$Iz_5zH?K;aFGU^8l7u%zHgiy z%)~y|k;Es-7YX69AMj^epGX#&^c@pp+lc}kKc`5CjPN4Z$$e58$Yn*J?81%`0~A)D zPg-db*pj-t4-G9>ImW4IMi*v#9z^9VD9h@9t;3jMAUVxt=oor+16yHf{lT|G4 zya6{4#BxFw!!~UTRwXXawKU4iz$$GMY6=Z8VM{2@0{=5A0+A#p6$aT3ubRyWMWPq9 zCEH5(Il0v4e4=Yxg(tDglfYAy!UpC>&^4=x7#6_S&Ktds)a8^`^tp6RnRd{KImB^o z2n=t#>iKx<*evmvoE{+fH#@WXGWs$)Uxrtf?r>AaxV0?kf0o@oDboJ6z0cgP@A$;k>SK1UqC?Q_ zk_I?j74;}uNXhOf_5ZxQSgB4otDEb9JJrX1kq`-o%T>g%M5~xXf!2_4P~K64tKgXq z&KHZ0@!cPvUJG4kw-0;tPo$zJrU-Nop>Uo65Pm|yaNvKjhi7V1g98;^N1~V3% zTR>yWa+X2FJ_wpPwz3i^6AGwOa_VMS-&`*KoKgF2&oR10Jn6{!pvVG@n=Jk@vjNuY zL~P7aDGhg~O9G^!bHi$8?G9v9Gp0cmekYkK;(q=47;~gI>h-kx-ceM{ml$#8KI$4ltyjaqP zki^cyDERloAb)dcDBU4na9C(pfD{P@eBGA}0|Rb)p{ISqi60=^FUEdF!ok{Gs;vb) zfj9(#1QA64w*ud^YsN5&PeiI>c`VioE8h)e}W%S9NMA55Gs zrWL6l+@3CKd@8(UQLTwe12SGWMqRn+j)QZRj*g)Xua)%ayzpqs{pD(WWESJYL3{M$ z%qkpM`jFoqLYVv6{IbCkL?fEiJj$VG=$taup&RL9e{s(Sgse2xVJlw0h74EXJKt2eX|dxz{->0)3W`JN7Bv!rLvRZc z0tAOZ2yVe4g9iq826qXAg`f!*+}(o1;1FDb>kKexumFS40KvK0yH1_@Z=LgWZ+}(Y zwYsa;OLz6tTA%gS=>8$=Z7pLh>|K2QElL)E=Q*(n*H`8R`8={-@4mTD-SWBOYRxV? zmF(-rJB8^Wlp?319rTrh^?QEP?|Msxrv?WbJ-+id+V#F2Y4(JPJ6U9bv+U1cIIH^W z)lg$_=g^Ma>2~Pyd_YOAv29Cb-U6DJO?NxnW7~QP*SmYi*vdUVuW#LWQ_u0`hymZi zaQS3Nb^4`ro$>0G%zbXmr5|D|iq0R<;S@?kr0j5Ruq87-Z1>crx%EzVZ9#U;{?}ti zW2W%*9MQg3Nbh%Ti6LhDd|-aFSgXoPG`mHlUU1iCHr>ru>DX?W_#13(`u*!Plu2OP z6jk=2>BC0l)aw;HCmxoYD1i4b%m$1`DYC_^L~ zIEAnFcHvad=-aO3(_MI=9#`z6-9*_!&$?<%meb5;jGd5Qp=MGf z6BD{%`L#TAOq%z%@*ib95Ey7NbUF=BlszVk3Iu3imD&*91N-ij%hW?W@~2TtdHTfP z#n0@Xd7X8Dyu36n{k#PwQ~T~X7mAO^cNV+z<HO@3X-# z_@rAn$k~(l@kciCC;&Qd*fWRI>=;fL{UPlciNDWyj$bX<#r^(r;EE8wwUVQm&7~QY zCXRj!**r^xybAEPq>h3W$uvI1j=yNIyzkE_D7fpGw)OV{U*Uwm{xB;mEg2(|y|ICd zMdQVqzMb-=XM6|E-a9kNh)^9lY`-DjhhHD1w5lufRcy+QLgJ47!fFne86#F; zX{ufroVBEZJOY?rDo!;Te6aOZ^1SO!dYRxQ*2njyA~dCWawn)>!*k7~>8Ikt&e*0>>V5ZbO|*1+2LFOqVe zXHb!aMk03^h%&9L8GMy7UDI2Kev>V@(R}*Iu6x+!Hn4~D@wj`P%#Hdbf(lK{+DD7f zJ&(v*mhn_e(R$^5L#bM^^Q@-!*b!l|+Xrb(q*MRFJYnrE7*xko!SJOy9LngR2|q5k zY`Ioiu+YBfzF{Labszk-E#*BYQk>$()=xWEGZRKwY)*UxP}0dGuPLZOkNJDI9Hy zFjfwiK6RjhH#rHW#B0(MW}i%V`943<6@Z*Nd^JEP5uZonXm=u%AM>{H^U@&Jy*i0s za_Da^xI6pMtXzHc{e~_ZcnKP*;=YL2Z^RmzDl{dJTk7*}E_h*NvgnhnxVKB59Duh~ zqouS_WoOR*{UvUw_K#OWz;gMracr%8>QQ&V*jv!8)ho;U8}9~8EU{N<=Z_gR%IpMT zbkePUG_afm=#|iIfFmdqkpLMGxY5D$`?I}&T7>TexU@v zkBx09kG)O;09ckj#(_Uov6vv{{HOcr-%H#DUQ@*GzF8Zh{iSM13%fuB%>wjdU@3Nf zlnYE!GTyNrqes|;nLFXfWU*Wg-9wmr=NBd$nCk+H?iwNvcd0Wab^3CT9a`>3V~oWI z9=_H+N-Q=MQ(io4u4mpdQ;k&5FXnKV5M7R`@WJ9h(GrAirO#XXOU{qQpk^B^Vd=Dt{wiqT zg-#j9J~@o%H2;W9mg)o6@*Vo;BSs2*4HAHpDk02mndAsov08R_48zJZ@J)s7+hyCo zy*0L#y)?AqZt-wX%+_Vx`8*A95OLHvs1$k~{h-_N_vov_gHJE=`X>L?5K+ zD?u59=mjtImMvd1GsDytuYp{IyUkW&?h zF>$#`n$~bZ)KN0B$XGeMYh&`;g8 zo_2-koaO6+8O!+L>SpIQbG(i;QW9UJi{Ecewlo?s&D!^>i$|#jaW}#HJuxt|W48=? zb^Y&O$a1s5ddr8DIt!sD!t=y1g(d4GR(s;s-HfV$GXl&m;+sAAxB^rk(3_NjE$p#L z*t4em?tA0d+XwRxN^OQwzbDZMuSE0J1)Ky{mq)^t4bnSl*)s>zNM@mMdtd78&ebHN z`!(|lE5q-p+TsRaNnMXwALaN5QIZ2IUi^Z22tsN5>nvIO+YU}Q*xh6}ee6@rR~<&1 z(PB4z>9ZBUMXZwSMmd9-aKKsmJeJq^G|#JclOh*xf0?^e0(`40nsg1z)(48;4}B_( zGwPI)yo|{oX{dVDL-5-aMGr;~vU1cPtJP5JM(sswz&Q`e<@0?y{YhsO9YK8EYJA;L z>7oG_Mts+(wCBC*Md82#XdKw&J*IizR?9k^rf1r{Ot-&>V^ke{9nI9zavlcNkIJtN z7T>?o|4rENk-?|lewZ(EfdR;%BUrzKJ^UkCpsM)EA9QHBVV8trT&*O(9?FO{MLTFL z=5P0H+T6C^jAuX0k4U;~GM!x`!X2N~3_n?qXY$HI>x@(DHEy&Q3ucT1R6fj28wX!I zC=&d$@bJ_v^%?W2Ngl}e8ww`b%BrN-PzGH;$@B2Ky1?%GMkm#~Okj(-Admyy;qya| zOi73kr_pwt?5Nj3p=&H>81!w#>Agj z(QXx{j0r=pTl>micAI_5vUw<3`Sht?Z}-j2Wx~F8DKCUQrsXl2?W8hur42(F_ zsSJ)_36&x6A|YkY6c<2a94SXbv~d>4CC4nkDPvf9Z5Fys^6^5r0j5=E>Cgy_Dk@tS z%?c}9!qB?t6t8(XMH%le8UeNWp@Nsma~Ql+^3Bo%_npMryeQJz4V=BAqE~T?dejng z3ge{fjCHoNAfYBvsfq;G%VL|j7t z`X0sy1EEgpyD;)tS1x+fnv-?C@glP0{RCW}Ma?3qpoq_&IJAYOy3G#s`rsh5=3>`K zkj``=;|*x5HSjZC zXNvPLh372q;=+6ja|SC!R-`JcL}}wwskajjTUGTpL(1zkN-p?BA2lmf+J3WsB7!k`0Brx8^cLTF9h)r+LZ$vsZo}`OpOs)?c6$hclR!R#MAeh|_DY|9r zy+_3c%IO9h9X?ksp?an&>Lw;QeQ`T-Ku6HaK~H?E9-Z5$cZu{YU;1+-6B$|JD;%!^ zt(4l>F8}a-UkC4YtOxFHckhl4VKr6P$P_O*U!)IDory%}Wz`YeFx6TO{y2Y${SBm?H9cTWV=WWJ z`_*CGso!ZN>l@~_jkeXtV}fczfA{TUkyeD>)i3|NFGcCsBmK3HXp&ol_@GVs7PIpfULy!hi zs+%KYgS%(n7_z_}6)hblk~W#LZ@&2)fwm6xkFP%&Ju|MFWbNiTwy{{g-pV1RK`L&=RE2D z4|g;~vd8xd|teYS%w!IlT4W$&FTrk-hcTADX!P?*f1YWEIRwq$Ys%^(Z9w&HT$>} zsMD#6Df=uJrX!JHP7<>Or;e_Cf=}`!`qR=i8fBj)$6Lxx{HRzd8Tnzd0p>kSps{OG zKJkml>bUj8$u|F=``l(-aMxWBC@CGZ#FXClQZ<4|&%jN}Tkg#q8z)=>Ly{$i0`rjU zvt|QddO&i=91e?h3>s~i;+6{ z8X4i6a1wDLrSuE#W(zhan+U*Zq+8p3a))JFVF4ffaV51K^YgTso~3;Y*NmM; zx8T?y-N0uyWY(8=me-HUC9xtABvX5~%yg+Cp&XF$Bq=OcK6T*D7eZ2EmIoCFWm{$S z1PNw8HDpe5hHeCusN8kdeb&f2#=3M^A~7YwJ7FRrhq*)PG9x?JIAaC{MV}5}g#7R$-Ly%)4=IUkRCGOR|XTMjn&okRmFjaO^YF5^* z@)#MCBOBezD)*xQNxydlUyN?dW{fS(s-T`gv*0BEnk}`BdmrbmPO8q8y(X$AA}*RH%I7Av!~84pudHb&%Q5-j zt?=6x(iR?<^_7X0v6Ys#VAL}dKk^hcjI=|EY;kPcZ_w<*H`_*|N7SacaM1ERD@6ab zg`!iTm7$URV+lpW_{V$ruR&A>jrX68k4x2wo$45}&wf7o<|o(@B!u-L@bKyQBAGwy z4#}UrRAu>^>Vb6k2-th^>WjvP;Nl|i3WrjWv3ISkj{m{eAcQIW^_ndxSX@|8T(ASJ z?_$fcP2u*6uOBk-{d>^ z0vWlfGQMvysI%R=iE|A+!!Nw?C917EU*_$`;;)px?s83CRd3i_jBN)k#nR5t$dJ(+ z_sP;wG@Ad)^(3LRj7q}0b2O(b`|i0~5SYb%Sjk^*5ISZ-Ab+}DGu$-X1n^TF1Ndw_ zF|e*1)cI2%`TR&AW~XpqpFb!=3cHbS>np9hYD_Mr5}y5Y`SY^r7isA2Q4(z zazRQEqWDKT2zIEbjSYdCPi1ZOGz80Nsl}gxO^DWMY0AV<2K&OL{&^6#@L1?lXu#6xSMh%3^5c*}oM6DQGY#(a^@z<&D zF(43I9e&5`h|A$5!+UFuOH0>F3$shBV4`0#M4RSB8=6F0ZgIbq<2LQ$Hh^(kAJu=! zt8ZGXTacD{(3W{V1$j_{Jc)Ka7t6u}ho`4kF+4@t_0!mCBn z)}o%eA}L)_L?=jw6BIfll7tb3n}?*yLt&XADa=rW>qz=_6s9ziOd5sXjil>FVFx3r zf>Feewk0v#W9>Gp4GacTRr>Sd2T6dWi-{YX`v!D)kCWzG5xQB=?es5ON(%nkwUhNl zV>@xkWWWv*N+{e$(SrExvN6BXzU(Hxlx27{VYHf+LpIbTO+Yu(ltMk<;)3A(LU@ytVYFkYvTa79idMtUFhfxx?P!)2F`prNWW#Fub#l>N2s@nh&n_ zA4{#}|AIs9|A4P0ZF%fy=hDN!t#ifH<)4u2kirK~JUpjQ-J+~cXOZI&dIts;P}UeXslP6zKvpEKSN-$y>kJ^nw2tC9bv zo(|lT@?vZ!{_l|d^8Yh)eEBh*5ABh+Lzjw+?V)o z#P-W7361>E(Y4;@`sv;VKn G`u_lkUM?>H diff --git a/server/src/main/resources/webapp/fonts/glyphicons-halflings-regular.woff2 b/server/src/main/resources/webapp/fonts/glyphicons-halflings-regular.woff2 deleted file mode 100644 index 64539b54c3751a6d9adb44c8e3a45ba5a73b77f0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18028 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 diff --git a/server/src/main/resources/webapp/i18n/en.main.json b/server/src/main/resources/webapp/i18n/en.main.json deleted file mode 100644 index a1491cbcfe..0000000000 --- a/server/src/main/resources/webapp/i18n/en.main.json +++ /dev/null @@ -1,151 +0,0 @@ -{ - "window": { - "title": "Central Dogma" - }, - - "navbar": { - "home": "Home", - "language": "Language", - "login": "Log in", - "logout": "Log out", - "user": "User", - "tokens": "Application Tokens" - }, - - "login": { - "button_login": "Log in", - "button_cancel": "Cancel", - "logged_in": "Welcome to Central Dogma, {{username}}.", - "logged_out": "Logged out successfully", - "password": "Password", - "password.placeholder": "Your password", - "rememberme": "Remember me", - "title": "Log in", - "username": "Username", - "username.placeholder": "Your username" - }, - - "entities": { - "auto_merge_failed": "Failed to auto-merge due to conflicting changes", - "button_add_member": "Add a member", - "button_add_token": "Add a token", - "button_add_token_permission": "Add a token permission", - "button_add_user_permission": "Add a user permission", - "button_cancel": "Cancel", - "button_change": "Change", - "button_commit": "Commit", - "button_create": "Create", - "button_create_project": "Create a project", - "button_create_repository": "Create a repository", - "button_delete": "Delete", - "button_edit": "Edit", - "button_fetch_again": "Fetch again", - "button_go_to_metadata": "Go to metadata", - "button_history": "History", - "button_query": "Query", - "button_restore": "Restore", - "button_save": "Save", - "button_show_permission": "Permission", - "button_token_management": "Application Tokens", - "button_update_role_permission": "Update role permission", - "commit_author": "Author", - "commit_detail": "Detail", - "commit_message": "Message", - "commit_summary": "Summary", - "commit_timestamp": "Timestamp", - "conflict_occurred": "Someone else pushed a commit while you edit. Fetch and edit again.", - "created_project": "Project '{{name}}' has been created.", - "created_repository": "Repository '{{projectName}}/{{repositoryName}}' has been created.", - "dark_themes": "Dark themes", - "default_theme": "Default", - "deleted_file": "File '{{path}}' has been deleted.", - "empty_directory": "Directory contains no file.", - "entries_not_found": "Entries not found", - "go_to_head_revision": "Go to HEAD", - "invalid_file_path": "Enter a valid file name.", - "invalid_json": "Enter a valid JSON value.", - "invalid_repository_name": "Enter a valid repository name.", - "light_themes": "Light themes", - "new_file_name_placeholder": "Type 1) a file name 2) a directory name and '/' key or 3) 'backspace' key to go one directory up.", - "path": "Path", - "project_name": "Project name", - "recent_commits": "Recent commits", - "redundant_changes": "You did not change anything.", - "repository": "Repository", - "repository_name": "Repository name", - "resolved_conflicts": "Latest content is fetched and merged with your previous changes. Please check the content again.", - "revision": "Revision", - "revision_placeholder": "e.g. HEAD, 42, -3", - "saved_file": "File '{{path}}' has been saved.", - "title_added_at": "Added At", - "title_added_by": "Added By", - "title_app_id": "App ID", - "title_create_repository": "Create a repository", - "title_created_at": "Created At", - "title_created_by": "Created By", - "title_delete_target": "Delete '{{target}}'?", - "title_guest": "Guest", - "title_anonymous": "Anonymous", - "title_login_id": "Login ID", - "title_member": "Member", - "title_name": "Name", - "title_owner": "Owner", - "title_project_removed": "Project '{{target}}' has been removed.", - "title_project_restored": "Project '{{target}}' has been restored.", - "title_remove_member": "Remove a member '{{target}}'?", - "title_remove_project": "Remove a project '{{target}}'?", - "title_remove_repository": "Remove a repository '{{target}}'?", - "title_remove_token": "Remove a token '{{target}}'?", - "title_restore_project": "Restore a project '{{target}}'?", - "title_restore_repository": "Restore a repository '{{target}}'?", - "title_read": "Read", - "title_role": "Role", - "title_select_role": "Select a role", - "title_save_member": "Save a member '{{target}}'?", - "title_save_token": "Save a token '{{target}}'?", - "title_select_token": "Select a token", - "title_status": "Status", - "title_target_already_exists": "'{{target}}' already exists.", - "title_update_member": "Update a member '{{target}}'?", - "title_update_role_permission": "Update permission of the roles for the repository '{{target}}'?", - "title_update_token": "Update a token '{{target}}'?", - "title_write": "Write", - "unsupported_file_type": "Unsupported file type: {{type}}" - }, - - "settings": { - "button_activate_token": "Activate", - "button_cancel": "Cancel", - "button_close": "Close", - "button_create_token": "Create a token", - "button_deactivate_token": "Deactivate", - "button_delete": "Delete", - "button_delete_token": "Delete", - "button_generate": "Generate", - "button_invalidate_token": "Invalidate", - "deleted_token": "Application token '{{path}}' has been deleted.", - "title_activate_token": "Activate application token '{{token}}'?", - "title_deactivate_token": "Deactivate application token '{{token}}'?", - "title_delete_token": "Delete the application token '{{token}}'?", - "title_generate_token": "Generate a new application token", - "title_token_generated": "Application token generated", - "token_admin_level": "Administrator-Level Token", - "token_application_id": "Application ID", - "token_application_id.exist": "Application ID '{{appId}}' exists. Please try a different ID again.", - "token_application_id.placeholder": "Your application name", - "token_creation_time": "Created At", - "token_creator": "Created By", - "token_deactivation_time": "Deactivated At", - "token_deactivator": "Deactivated By", - "token_forbidden": "No permission for {{action}}", - "token_level": "Level", - "token_role": "Role", - "token_secret": "Secret", - "token_status": "Status" - }, - - "components": { - "button_no": "No", - "button_yes": "Yes" - } -} diff --git a/server/src/main/resources/webapp/index.html b/server/src/main/resources/webapp/index.html deleted file mode 100644 index d518e4b073..0000000000 --- a/server/src/main/resources/webapp/index.html +++ /dev/null @@ -1,110 +0,0 @@ - - - - - - - - - - centraldogma-admin - - - - - - - - - -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/server/src/main/resources/webapp/robots.txt b/server/src/main/resources/webapp/robots.txt deleted file mode 100644 index ee2cc216a6..0000000000 --- a/server/src/main/resources/webapp/robots.txt +++ /dev/null @@ -1,3 +0,0 @@ -# robotstxt.org/ - -User-agent: * diff --git a/server/src/main/resources/webapp/scripts/app/app.js b/server/src/main/resources/webapp/scripts/app/app.js deleted file mode 100644 index 055eb26a41..0000000000 --- a/server/src/main/resources/webapp/scripts/app/app.js +++ /dev/null @@ -1,165 +0,0 @@ -'use strict'; - -angular.module( - 'CentralDogmaAdmin', - ['LocalStorageModule', - 'ngCacheBuster', - 'ngCookies', - 'ngResource', - 'pascalprecht.translate', - 'tmh.dynamicLocale', - 'ui.ace', - 'ui.bootstrap', - 'ui-notification', - 'ui.router']) - .constant('CentralDogmaConstant', { - HEAD: 'head', - LEVEL_USER: 'LEVEL_USER', - LEVEL_ADMIN: 'LEVEL_ADMIN', - ENTITY_NAME_PATTERN: /^[0-9A-Za-z](?:[-+_0-9A-Za-z\.]*[0-9A-Za-z])?$/, - API_PREFIX: '/api/v0/', - API_V1_PREFIX: '/api/v1/', - PROJECT_ROLE_OWNER: "OWNER", - PROJECT_ROLE_MEMBER: "MEMBER", - PROJECT_ROLE_GUEST: "GUEST", - REFRESH_DELAY_MSEC: 500 - }) - .run(function ($rootScope, $location, $window, $http, $state, $translate, $uibModal, $q, - Principal, Language, NotificationUtil, Security) { - $rootScope.$on('$stateChangeStart', function (event, toState, toStateParams) { - $rootScope.toState = toState; - $rootScope.toStateParams = toStateParams; - - Security.resolve().then(function () { - Principal.refresh().then(function () { - if (!Principal.isAuthenticated()) { - $window.location.href= "/link/auth/login?ref=" + $location.path(); - } - }); - }); - - // Update the language - Language.getCurrent().then(function (language) { - $translate.use(language); - }); - }); - - $rootScope.$on('$stateChangeSuccess', function (event, toState, toParams, fromState, fromParams) { - var titleKey = 'window.title'; - - $rootScope.previousStateName = fromState.name; - $rootScope.previousStateParams = fromParams; - - // Set the page title key to the one configured in state or use default one - if (toState.data.pageTitle) { - titleKey = toState.data.pageTitle; - } - $translate(titleKey).then(function (title) { - // Change window title with translated one - $window.document.title = title; - }); - }); - - $rootScope.back = function () { - // If previous state do not exist go to 'home' - if ($state.get($rootScope.previousStateName) === null) { - $state.go('home'); - } else { - $state.go($rootScope.previousStateName, $rootScope.previousStateParams); - } - }; - }) - .config(function ($stateProvider, $urlRouterProvider, $urlMatcherFactoryProvider, - $httpProvider, $locationProvider, $translateProvider, - tmhDynamicLocaleProvider, httpRequestInterceptorCacheBusterProvider, - NotificationProvider) { - - //Cache everything except rest api requests - httpRequestInterceptorCacheBusterProvider.setMatchlist([/.*api.*/, /.*protected.*/], true); - - $urlMatcherFactoryProvider.type('repositoryPath', { - encode: function (val) { - var temp = val !== null ? val.toString() : val; - temp = temp.replace(/\/\/+/, '/'); - if (temp === '/') { - return ''; - } - - if (temp.indexOf('/') === 0) { - temp = temp.substring(1); - } - if (/\/$/.test(temp)) { - temp = temp.slice(0, -1); - } - - var split = temp.split('/'); - for (var index in split) { - split[index] = encodeURIComponent(split[index]); - } - return split.join('/'); - }, - decode: function (val) { - return val !== null ? decodeURIComponent(val.toString()) : val; - }, - is: function () { - return true; - } - }); - - $urlRouterProvider.otherwise('/projects'); - $stateProvider - .state('site', { - 'abstract': true, - views: { - 'navbar@': { - templateUrl: 'scripts/components/navbar/navbar.html', - controller: 'NavbarController' - } - }, - resolve: { - translatePartialLoader: [ - '$translate', '$translatePartialLoader', - function ($translate, $translatePartialLoader) { - $translatePartialLoader.addPart('main'); - return $translate.refresh(); - }] - } - }) - .state('home', { - parent: 'site', - url: '/', - data: { - roles: [] - }, - views: { - 'content@': { - templateUrl: 'scripts/app/entities/projects/projects.html', - controller: 'ProjectsController' - } - } - }); - - // Initialize angular-translate - $translateProvider.useLoader('$translatePartialLoader', { - urlTemplate: 'i18n/{lang}.{part}.json' - }); - - $translateProvider.preferredLanguage('en'); - $translateProvider.useCookieStorage(); - $translateProvider.useSanitizeValueStrategy('escapeParameters'); - - tmhDynamicLocaleProvider - .localeLocationPattern('node_modules/angular-i18n/angular-locale_{{locale}}.js'); - tmhDynamicLocaleProvider.useCookieStorage('NG_TRANSLATE_LANG_KEY'); - - // Configure angular-ui-notification - NotificationProvider.setOptions({ - delay: 5000, - startTop: 70, - startRight: 0, - verticalSpacing: 20, - horizontalSpacing: 20, - positionX: 'center', - positionY: 'top' - }); - }); diff --git a/server/src/main/resources/webapp/scripts/app/entities/entity.js b/server/src/main/resources/webapp/scripts/app/entities/entity.js deleted file mode 100644 index f5efd57e05..0000000000 --- a/server/src/main/resources/webapp/scripts/app/entities/entity.js +++ /dev/null @@ -1,10 +0,0 @@ -'use strict'; - -angular.module('CentralDogmaAdmin') - .config(function ($stateProvider) { - $stateProvider - .state('entity', { - abstract: true, - parent: 'site' - }); - }); diff --git a/server/src/main/resources/webapp/scripts/app/entities/metadata/metadata.js b/server/src/main/resources/webapp/scripts/app/entities/metadata/metadata.js deleted file mode 100644 index f240ad336d..0000000000 --- a/server/src/main/resources/webapp/scripts/app/entities/metadata/metadata.js +++ /dev/null @@ -1,27 +0,0 @@ -'use strict'; - -angular.module('CentralDogmaAdmin') - .config(function ($stateProvider, CentralDogmaConstant) { - $stateProvider - .state('projectMetadata', { - parent: 'entity', - url: '/metadata/:projectName', - data: {}, - views: { - 'content@': { - templateUrl: 'scripts/app/entities/metadata/metadata.project.html', - controller: 'MetadataProjectController' - } - } - }).state('repositoryMetadata', { - parent: 'entity', - url: '/metadata/:projectName/:repoName', - data: {}, - views: { - 'content@': { - templateUrl: 'scripts/app/entities/metadata/metadata.repository.html', - controller: 'MetadataRepositoryController' - } - } - }); - }); diff --git a/server/src/main/resources/webapp/scripts/app/entities/metadata/metadata.project.controller.js b/server/src/main/resources/webapp/scripts/app/entities/metadata/metadata.project.controller.js deleted file mode 100644 index 42af583d5f..0000000000 --- a/server/src/main/resources/webapp/scripts/app/entities/metadata/metadata.project.controller.js +++ /dev/null @@ -1,223 +0,0 @@ -'use strict'; - -angular.module('CentralDogmaAdmin') - .controller('MetadataProjectController', - function ($scope, $state, $stateParams, ApiService, ApiV1Service, $location, $window, $uibModal, - SettingsService, ConfirmationDialog, IdentifierWithRole, EntitiesUtil, - ProjectService, RepositoryService, Principal, CentralDogmaConstant, - NotificationUtil, StringUtil, Security, $timeout) { - $scope.project = { - name: $stateParams.projectName, - roles: [ - 'OWNER', 'MEMBER' - ] - }; - $scope.toDateTimeStr = EntitiesUtil.toDateTimeStr; - $scope.sanitizeEmail = EntitiesUtil.sanitizeEmail; - - $scope.removeProject = function () { - ConfirmationDialog.openModal('entities.title_remove_project', { - target: $scope.project.name - }).then(function () { - ProjectService.removeProject($scope.project.name).then(function () { - NotificationUtil.success('entities.title_project_removed', { - target: $scope.project.name - }); - $location.url('/projects'); - }); - }); - }; - - $scope.removeRepository = function (repo) { - ConfirmationDialog.openModal('entities.title_remove_repository', { - target: repo.name - }).then(function () { - RepositoryService.removeRepository($scope.project.name, repo.name).then(function () { - $scope.refresh(); - }); - }); - }; - $scope.restoreRepository = function (repo) { - ConfirmationDialog.openModal('entities.title_restore_repository', { - target: repo.name - }).then(function () { - RepositoryService.restoreRepository($scope.project.name, repo.name).then(function () { - $scope.refresh(); - }); - }); - }; - - // Member List. - $scope.updateMemberRole = function (member) { - ConfirmationDialog.openModal('entities.title_update_member', { - target: EntitiesUtil.sanitizeEmail(member.login) - }).then(function () { - ApiV1Service.jsonPatch(StringUtil.encodeUri(['metadata', $scope.project.name, - 'members', member.login]), - EntitiesUtil.toReplaceJsonPatch('/role', member.role)).then(function () { - $scope.refresh(); - }, function (error) { - NotificationUtil.error(error); - }); - }); - }; - $scope.removeMember = function (member) { - ConfirmationDialog.openModal('entities.title_remove_member', { - target: EntitiesUtil.sanitizeEmail(member.login) - }).then(function () { - ApiV1Service.delete(StringUtil.encodeUri(['metadata', $scope.project.name, - 'members', member.login])).then(function () { - $scope.refresh(); - }); - }); - }; - - // New member list. - $scope.newMemberList = new IdentifierWithRole(); - $scope.saveNewMember = function (newMember) { - const duplicated = $scope.memberList.filter(function (value) { - return angular.equals(value.login, newMember.id); - }); - if (duplicated.length > 0) { - NotificationUtil.error('entities.title_target_already_exists', { - target: newMember.id - }); - return; - } - ConfirmationDialog.openModal('entities.title_save_member', { - target: newMember.id - }).then(function () { - ApiV1Service.post(StringUtil.encodeUri(['metadata', $scope.project.name, - 'members']), newMember).then(function () { - $scope.newMemberList.remove(newMember); - $scope.refresh(); - }, function (error) { - NotificationUtil.error(error); - }); - }); - }; - - // Token list. - $scope.updateTokenRole = function (token) { - ConfirmationDialog.openModal('entities.title_update_token', { - target: token.appId - }).then(function () { - ApiV1Service.jsonPatch(StringUtil.encodeUri(['metadata', $scope.project.name, - 'tokens', token.appId]), - EntitiesUtil.toReplaceJsonPatch('/role', token.role)).then(function () { - $scope.refresh(); - }, function (error) { - NotificationUtil.error(error); - }); - }); - }; - $scope.removeToken = function (token) { - ConfirmationDialog.openModal('entities.title_remove_token', { - target: token.appId - }).then(function () { - ApiV1Service.delete(StringUtil.encodeUri(['metadata', $scope.project.name, - 'tokens', token.appId])).then(function () { - $scope.refresh(); - }, function (error) { - NotificationUtil.error(error); - }); - }); - }; - - // New token list. - $scope.newTokenList = new IdentifierWithRole(); - $scope.saveNewToken = function (newToken) { - ConfirmationDialog.openModal('entities.title_save_token', { - target: newToken.id - }).then(function () { - ApiV1Service.post(StringUtil.encodeUri(['metadata', $scope.project.name, - 'tokens']), newToken).then(function () { - $scope.newTokenList.remove(newToken); - $scope.refresh(); - }, function (error) { - NotificationUtil.error(error); - }); - }); - }; - - $scope.refreshNow = function() { - function refresh0(tokens) { - ApiV1Service.get(StringUtil.encodeUri(['projects', $scope.project.name])).then(function (metadata) { - var addedAppIds, allAppIds; - - // Mark whether each repository is active or not. - Object.entries(metadata.repos).forEach(function (entry) { - entry[1].isActive = angular.isUndefined(entry[1].removal) || - entry[1].removal === null; - }); - - $scope.metadata = metadata; - $scope.tokens = tokens; - $scope.role = Principal.projectRole(metadata); - $scope.isOwner = function () { - return angular.equals($scope.role, CentralDogmaConstant.PROJECT_ROLE_OWNER); - }; - $scope.isNotOwner = function () { - return !$scope.isOwner(); - }; - $scope.isNotOwnerOr = function (cond) { - return !$scope.isOwner() || cond; - }; - - // Prepare member and token list. - function convertList(list) { - var outputList = []; - if (angular.isUndefined(list) || list === null) { - return outputList; - } - Object.entries(list).forEach(function (entry) { - entry[1].isEditing = false; - entry[1].originalRole = entry[1].role; - outputList.push(entry[1]); - }); - return outputList.sort(function (a, b) { - if (a.originalRole === b.originalRole) { - return a - b; - } - if (a.originalRole === CentralDogmaConstant.PROJECT_ROLE_OWNER) { - return -1; - } else { - return 1; - } - }); - } - $scope.memberList = convertList(metadata.members); - $scope.tokenList = convertList(metadata.tokens); - - addedAppIds = EntitiesUtil.toKeySet(metadata.tokens); - allAppIds = tokens.filter(function (t) { - return t.isActive; - }).map(function (t) { - return t.appId; - }); - $scope.appIdList = EntitiesUtil.toUniqueSet(allAppIds, addedAppIds); - }, function (error) { - NotificationUtil.error(error); - $location.url('/projects'); - }); - } - - Security.resolve().then(function (isEnabled) { - if (isEnabled) { - SettingsService.listTokens().then(function (tokens) { - refresh0(tokens); - }); - } else { - refresh0([]); - } - }); - }; - - $scope.refresh = function() { - $timeout(function () { - $scope.refreshNow(); - }, CentralDogmaConstant.REFRESH_DELAY_MSEC); - }; - - $scope.refreshNow(); - }); diff --git a/server/src/main/resources/webapp/scripts/app/entities/metadata/metadata.project.html b/server/src/main/resources/webapp/scripts/app/entities/metadata/metadata.project.html deleted file mode 100644 index 68edda63e8..0000000000 --- a/server/src/main/resources/webapp/scripts/app/entities/metadata/metadata.project.html +++ /dev/null @@ -1,279 +0,0 @@ -
-

- Projects / {{project.name}} -
- - - -
-

-
- -

Repositories

- - - - - - - - - - - - - - - - - - - - - - -
{{ 'entities.title_name' | translate }}{{ 'entities.title_created_by' | translate }}{{ 'entities.title_created_at' | translate }}{{ 'entities.title_status' | translate }}
- - {{repo.name}} - - {{repo.name}}{{sanitizeEmail(repo.creation.user)}}{{toDateTimeStr(repo.creation.timestamp)}}ActiveDeleted -
- - - -
-
-
- - - -
-
-
- - -
-

Repository Permissions

- - - - - - - - - - - - - - - - - - - -
{{ 'entities.title_name' | translate }}{{ 'entities.title_owner' | translate }}{{ 'entities.title_member' | translate }}{{ 'entities.title_guest' | translate }}{{ 'entities.title_anonymous' | translate }}
- - {{repo.name}} - - - - - - - - - -
- -

Members

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
{{ 'entities.title_login_id' | translate }}{{ 'entities.title_role' | translate }}{{ 'entities.title_added_by' | translate }}{{ 'entities.title_added_at' | translate }}
{{sanitizeEmail(member.login)}} - - - {{member.role}} - - - - {{sanitizeEmail(member.creation.user)}}{{toDateTimeStr(member.creation.timestamp)}} -
- - -
-
-
- - - -
-
- - - - -
- - -
-
-
-
-
- -
-
- -

-
- Tokens - - - -
-

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
{{ 'entities.title_app_id' | translate }}{{ 'entities.title_role' | translate }}{{ 'entities.title_added_by' | translate }}{{ 'entities.title_added_at' | translate }}
{{token.appId}} - - - {{token.role}} - - - - {{sanitizeEmail(token.creation.user)}}{{toDateTimeStr(token.creation.timestamp)}} -
- - -
-
-
- - - -
-
- - - - -
- - -
-
-
-
-
- -
-
-
-
diff --git a/server/src/main/resources/webapp/scripts/app/entities/metadata/metadata.repository.controller.js b/server/src/main/resources/webapp/scripts/app/entities/metadata/metadata.repository.controller.js deleted file mode 100644 index 84074aea02..0000000000 --- a/server/src/main/resources/webapp/scripts/app/entities/metadata/metadata.repository.controller.js +++ /dev/null @@ -1,178 +0,0 @@ -'use strict'; - -angular.module('CentralDogmaAdmin') - .controller('MetadataRepositoryController', - function ($scope, $state, $stateParams, ApiV1Service, $uibModal, Permission, ConfirmationDialog, - Principal, CentralDogmaConstant, StringUtil, NotificationUtil, EntitiesUtil, $timeout) { - $scope.project = { - name: $stateParams.projectName - }; - $scope.repository = { - name: $stateParams.repoName - }; - $scope.sanitizeEmail = EntitiesUtil.sanitizeEmail; - - // Common functions. - $scope.onCheckboxClicked = function(perm) { - if (perm.write === true) { - perm.read = true; - } - }; - - function updatePerUserOrPerTokenPermissions(category, id, perm, translateId) { - ConfirmationDialog.openModal(translateId, { - target: EntitiesUtil.sanitizeEmail(id) - }).then(function () { - ApiV1Service.jsonPatch( - StringUtil.encodeUri(['metadata', $scope.project.name, - 'repos', $scope.repository.name, - 'perm', category, id]), - EntitiesUtil.toReplaceJsonPatch('/permissions', Permission.toSet(perm)) - ).then(function () { - $scope.refresh(); - }, function (error) { - NotificationUtil.error(error); - }); - }); - } - - function removePermTable(category, target, translateId) { - ConfirmationDialog.openModal(translateId, { - target: EntitiesUtil.sanitizeEmail(target) - }).then(function () { - ApiV1Service.delete( - StringUtil.encodeUri(['metadata', $scope.project.name, - 'repos', $scope.repository.name, - 'perm', category, target]) - ).then(function () { - $scope.refresh(); - }, function (error) { - NotificationUtil.error(error); - }); - }); - } - - function savePermission(category, target, list, translateId) { - ConfirmationDialog.openModal(translateId, { - target: EntitiesUtil.sanitizeEmail(target.name) - }).then(function () { - ApiV1Service.post( - StringUtil.encodeUri(['metadata', $scope.project.name, - 'repos', $scope.repository.name, - 'perm', category]), - Permission.toRequest(target.name, target) - ).then(function () { - list.remove(target); - $scope.refresh(); - }, function (error) { - NotificationUtil.error(error); - }); - }); - } - - // Role permission - $scope.onPerRolePermissionsTableCheckboxClicked = function(perm) { - $scope.onCheckboxClicked(perm); - $scope.rolePermTableChanged = !angular.equals($scope.rolePermTable, $scope.originalRolePermTable); - }; - $scope.updatePerRolePermissions = function () { - ConfirmationDialog.openModal('entities.title_update_role_permission', { - target: $scope.repository.name - }).then(function () { - var request = {}; - Object.entries($scope.rolePermTable).forEach(function (entry) { - request[entry[0]] = Permission.toSet(entry[1]); - }); - ApiV1Service.post( - StringUtil.encodeUri(['metadata', $scope.project.name, - 'repos', $scope.repository.name, - 'perm', 'role']), request - ).then(function () { - $scope.refresh(); - }, function (error) { - NotificationUtil.error(error); - }); - }); - }; - - // User permission - $scope.newUserPermission = new Permission(); - $scope.saveNewPerUserPermissions = function (userWithPermission) { - savePermission('users', userWithPermission, $scope.newUserPermission, 'entities.title_save_member'); - }; - $scope.isPerUserPermissionsChanged = function (user, perm) { - return !angular.equals(perm, $scope.originalUserPermTable[user]); - }; - $scope.updatePerUserPermissions = function (user, perm) { - updatePerUserOrPerTokenPermissions('users', user, perm, 'entities.title_update_member'); - }; - $scope.removePerUserPermissions = function (user) { - removePermTable('users', user, 'entities.title_remove_member'); - }; - - // Token permission - $scope.newTokenPermission = new Permission(); - $scope.saveNewPerTokenPermissions = function (tokenWithPermission) { - savePermission('tokens', tokenWithPermission, $scope.newTokenPermission, 'entities.title_save_token'); - }; - $scope.isPerTokenPermissionsChanged = function (appId, perm) { - return !angular.equals(perm, $scope.originalTokenPermTable[appId]); - }; - $scope.updatePerTokenPermissions = function (appId, perm) { - updatePerUserOrPerTokenPermissions('tokens', appId, perm, 'entities.title_update_token'); - }; - $scope.removePerTokenPermissions = function (appId) { - removePermTable('tokens', appId, 'entities.title_remove_token'); - }; - - $scope.refreshNow = function() { - ApiV1Service.get("projects/" + $scope.project.name).then(function (metadata) { - var registeredAppIdList, registeredMemberList; - - $scope.metadata = metadata; - $scope.currentRepo = metadata.repos[$scope.repository.name]; - $scope.role = Principal.projectRole(metadata); - $scope.isOwner = function () { - return angular.equals($scope.role, CentralDogmaConstant.PROJECT_ROLE_OWNER); - }; - $scope.isNotOwner = function () { - return !$scope.isOwner(); - }; - $scope.isNotOwnerOr = function (cond) { - return !$scope.isOwner() || (cond); - }; - - // Available member list on select box. - registeredMemberList = Object.keys($scope.currentRepo.perUserPermissions); - $scope.memberList = Object.keys(metadata.members).filter(function (value) { - return registeredMemberList.indexOf(value) === -1; // not exist - }); - - // Available token list on select box. - registeredAppIdList = Object.keys($scope.currentRepo.perTokenPermissions); - $scope.appIdList = Object.keys(metadata.tokens).filter(function (value) { - return registeredAppIdList.indexOf(value) === -1; // not exist - }); - - // Make permission tables. - $scope.rolePermTable = Permission.makePermissionTable($scope.currentRepo.perRolePermissions); - $scope.userPermTable = Permission.makePermissionTable($scope.currentRepo.perUserPermissions); - $scope.tokenPermTable = Permission.makePermissionTable($scope.currentRepo.perTokenPermissions); - - // Make a copy of the permission table in order to check whether it is changed. - $scope.originalRolePermTable = angular.copy($scope.rolePermTable); - $scope.originalUserPermTable = angular.copy($scope.userPermTable); - $scope.originalTokenPermTable = angular.copy($scope.tokenPermTable); - $scope.rolePermTableChanged = false; - }); - }; - - $scope.refresh = function() { - $timeout(function () { - $scope.refreshNow(); - }, CentralDogmaConstant.REFRESH_DELAY_MSEC); - }; - - $scope.refreshNow(); - }); - diff --git a/server/src/main/resources/webapp/scripts/app/entities/metadata/metadata.repository.html b/server/src/main/resources/webapp/scripts/app/entities/metadata/metadata.repository.html deleted file mode 100644 index 0c2e09291e..0000000000 --- a/server/src/main/resources/webapp/scripts/app/entities/metadata/metadata.repository.html +++ /dev/null @@ -1,156 +0,0 @@ -
-

Projects / {{project.name}} / - {{repository.name}}

-
- -
-

Role Permission

- - - - - - - - - - - - - - - -
{{ 'entities.title_role' | translate }}{{ 'entities.title_read' | translate }}{{ 'entities.title_write' | translate }}
{{role}}
-
-
-
- -
-
- - - -

User Permission

- - - - - - - - - - - - - - - - - - - - - - - -
{{ 'entities.title_login_id' | translate }}{{ 'entities.title_read' | translate }}{{ 'entities.title_write' | translate }}
{{sanitizeEmail(user)}} -
- - -
-
- - -
- - -
-
-
-
-
- -
-
- -

Token Permission

- - - - - - - - - - - - - - - - - - - - - - - -
{{ 'entities.title_app_id' | translate }}{{ 'entities.title_read' | translate }}{{ 'entities.title_write' | translate }}
{{token}} -
- - -
-
- - -
- - -
-
-
-
-
- -
-
-
-
diff --git a/server/src/main/resources/webapp/scripts/app/entities/projects/project.controller.js b/server/src/main/resources/webapp/scripts/app/entities/projects/project.controller.js deleted file mode 100644 index a2dd9491e4..0000000000 --- a/server/src/main/resources/webapp/scripts/app/entities/projects/project.controller.js +++ /dev/null @@ -1,15 +0,0 @@ -'use strict'; - -angular.module('CentralDogmaAdmin') - .controller('ProjectController', - function ($scope, $stateParams, RepositoryService) { - $scope.project = { - name: $stateParams.projectName - }; - - RepositoryService.listRepositories($scope.project.name).then( - function (repositories) { - $scope.repositories = repositories; - } - ); - }); diff --git a/server/src/main/resources/webapp/scripts/app/entities/projects/project.html b/server/src/main/resources/webapp/scripts/app/entities/projects/project.html deleted file mode 100644 index 605f1ec8dd..0000000000 --- a/server/src/main/resources/webapp/scripts/app/entities/projects/project.html +++ /dev/null @@ -1,29 +0,0 @@ - diff --git a/server/src/main/resources/webapp/scripts/app/entities/projects/project.new.controller.js b/server/src/main/resources/webapp/scripts/app/entities/projects/project.new.controller.js deleted file mode 100644 index de0fe7e2d5..0000000000 --- a/server/src/main/resources/webapp/scripts/app/entities/projects/project.new.controller.js +++ /dev/null @@ -1,21 +0,0 @@ -'use strict'; - -angular.module('CentralDogmaAdmin') - .controller('ProjectNewController', - function ($scope, $state, CentralDogmaConstant, - ProjectService, NotificationUtil) { - - $scope.entityNamePattern = CentralDogmaConstant.ENTITY_NAME_PATTERN; - - $scope.createProject = function () { - ProjectService.createProject($scope.project.name).then( - function () { - NotificationUtil.success('entities.created_project', { name: $scope.project.name }); - - $state.go('project', { - projectName: $scope.project.name - }); - } - ); - }; - }); diff --git a/server/src/main/resources/webapp/scripts/app/entities/projects/project.new.html b/server/src/main/resources/webapp/scripts/app/entities/projects/project.new.html deleted file mode 100644 index 2f878c6267..0000000000 --- a/server/src/main/resources/webapp/scripts/app/entities/projects/project.new.html +++ /dev/null @@ -1,24 +0,0 @@ -
-

New project

- -
- -
-
- - - -

- Enter a valid project name. -

-
- -
- -
-
-
diff --git a/server/src/main/resources/webapp/scripts/app/entities/projects/projects.controller.js b/server/src/main/resources/webapp/scripts/app/entities/projects/projects.controller.js deleted file mode 100644 index ca32eed1b7..0000000000 --- a/server/src/main/resources/webapp/scripts/app/entities/projects/projects.controller.js +++ /dev/null @@ -1,41 +0,0 @@ -'use strict'; - -angular.module('CentralDogmaAdmin') - .controller('ProjectsController', - function ($scope, ProjectService, $location, NotificationUtil, ConfirmationDialog) { - $scope.movePageIfAccessible = function (projectName) { - ProjectService.checkPermission(projectName).then(function () { - $location.url('/metadata/' + projectName); - }, function (error) { - NotificationUtil.error(error); - }) - }; - - $scope.restoreProject = function (projectName) { - ConfirmationDialog.openModal('entities.title_restore_project', { - target: projectName - }).then(function () { - ProjectService.restoreProject(projectName).then(function () { - NotificationUtil.success('entities.title_project_restored', { - target: projectName - }); - $scope.refresh(); - }); - }); - }; - - $scope.refresh = function () { - ProjectService.listProjects().then( - function (projects) { - $scope.projects = projects; - } - ); - ProjectService.listRemovedProjects().then( - function (removedProjects) { - $scope.removedProjects = removedProjects; - } - ) - }; - - $scope.refresh(); - }); diff --git a/server/src/main/resources/webapp/scripts/app/entities/projects/projects.html b/server/src/main/resources/webapp/scripts/app/entities/projects/projects.html deleted file mode 100644 index f193a6f071..0000000000 --- a/server/src/main/resources/webapp/scripts/app/entities/projects/projects.html +++ /dev/null @@ -1,50 +0,0 @@ -
-

Projects

- -
- - - - - -
-
- - - -
{{project.name}} - - - -
- -
- - - -
- -
-

Removed Projects

- - - - - - - - -
{{project.name}} - - - -
-
- -
diff --git a/server/src/main/resources/webapp/scripts/app/entities/projects/projects.js b/server/src/main/resources/webapp/scripts/app/entities/projects/projects.js deleted file mode 100644 index 02afd49dd7..0000000000 --- a/server/src/main/resources/webapp/scripts/app/entities/projects/projects.js +++ /dev/null @@ -1,41 +0,0 @@ -'use strict'; - -angular.module('CentralDogmaAdmin') - .config(function ($stateProvider, CentralDogmaConstant) { - $stateProvider - .state('projects', { - parent: 'entity', - url: '/projects', - data: {}, - views: { - 'content@': { - templateUrl: 'scripts/app/entities/projects/projects.html', - controller: 'ProjectsController' - } - } - }) - .state('projectNew', { - parent: 'entity', - url: '/new_project', - data: { - roles: [CentralDogmaConstant.LEVEL_USER] - }, - views: { - 'content@': { - templateUrl: 'scripts/app/entities/projects/project.new.html', - controller: 'ProjectNewController' - } - } - }) - .state('project', { - parent: 'entity', - url: '/projects/:projectName', - data: {}, - views: { - 'content@': { - templateUrl: 'scripts/app/entities/projects/project.html', - controller: 'ProjectController' - } - } - }); - }); diff --git a/server/src/main/resources/webapp/scripts/app/entities/repositories/repositories.js b/server/src/main/resources/webapp/scripts/app/entities/repositories/repositories.js deleted file mode 100644 index 61bdec9917..0000000000 --- a/server/src/main/resources/webapp/scripts/app/entities/repositories/repositories.js +++ /dev/null @@ -1,111 +0,0 @@ -'use strict'; - -angular.module('CentralDogmaAdmin') - .config(function ($stateProvider, CentralDogmaConstant) { - $stateProvider - .state('repositoryNew', { - parent: 'entity', - url: '/projects/:projectName/new_repo', - data: {}, - views: { - 'content@': { - templateUrl: 'scripts/app/entities/repositories/repository.new.html', - controller: 'RepositoryNewController' - } - } - }) - .state('repository', { - parent: 'entity', - url: '/projects/:projectName/repos/:repositoryName', - data: {}, - views: { - 'content@': { - templateUrl: 'scripts/app/entities/repositories/repository.tree.html', - controller: 'RepositoryTreeController' - } - } - }) - .state('repositoryTree', { - parent: 'entity', - url: '/projects/:projectName/repos/:repositoryName/list/:revision/{path:repositoryPath}', - data: {}, - views: { - 'content@': { - templateUrl: 'scripts/app/entities/repositories/repository.tree.html', - controller: 'RepositoryTreeController' - } - } - }) - .state('repositoryFile', { - parent: 'entity', - url: '/projects/:projectName/repos/:repositoryName/files/:revision/{path:repositoryPath}', - data: {}, - views: { - 'content@': { - templateUrl: 'scripts/app/entities/repositories/repository.file.html', - controller: 'RepositoryFileController' - } - } - }) - .state('repositoryFileNew', { - parent: 'entity', - url: '/projects/:projectName/repos/:repositoryName/new_file/:revision/{path:repositoryPath}', - data: { - roles: [CentralDogmaConstant.LEVEL_USER] - }, - views: { - 'content@': { - templateUrl: 'scripts/app/entities/repositories/repository.file.new.html', - controller: 'RepositoryFileNewController' - } - } - - }) - .state('repositoryFileEdit', { - parent: 'entity', - url: '/projects/:projectName/repos/:repositoryName/edit/:revision/{path:repositoryPath}', - data: { - roles: [CentralDogmaConstant.LEVEL_USER] - }, - views: { - 'content@': { - templateUrl: 'scripts/app/entities/repositories/repository.file.edit.html', - controller: 'RepositoryFileEditController' - } - } - - }) - .state('repositoryHistory', { - parent: 'entity', - url: '/projects/:projectName/repos/:repositoryName/history/:revision/{path:repositoryPath}', - data: {}, - views: { - 'content@': { - templateUrl: 'scripts/app/entities/repositories/repository.history.html', - controller: 'RepositoryHistoryController' - } - } - }) - .state('repositorySearch', { - parent: 'entity', - url: '/projects/:projectName/repos/:repositoryName/search/:revision?term', - data: {}, - views: { - 'content@': { - templateUrl: 'scripts/app/entities/repositories/repository.search.html', - controller: 'RepositorySearchController' - } - } - }) - .state('repositoryQuery', { - parent: 'entity', - url: '/projects/:projectName/repos/:repositoryName/query/:revision/{path:repositoryPath}?expression', - data: {}, - views: { - 'content@': { - templateUrl: 'scripts/app/entities/repositories/repository.query.html', - controller: 'RepositoryQueryController' - } - } - }); - }); diff --git a/server/src/main/resources/webapp/scripts/app/entities/repositories/repository.file.controller.js b/server/src/main/resources/webapp/scripts/app/entities/repositories/repository.file.controller.js deleted file mode 100644 index 1f3e7a32de..0000000000 --- a/server/src/main/resources/webapp/scripts/app/entities/repositories/repository.file.controller.js +++ /dev/null @@ -1,66 +0,0 @@ -'use strict'; - -angular.module('CentralDogmaAdmin') - .controller('RepositoryFileController', - function ($scope, $state, $stateParams, $timeout, $location, $uibModal, - CentralDogmaConstant, RepositoryService, - NotificationUtil, StringUtil) { - - $scope.project = { - name: $stateParams.projectName - }; - $scope.repository = { - name: $stateParams.repositoryName - }; - $scope.revision = StringUtil.isEmpty($stateParams.revision) ? - CentralDogmaConstant.HEAD : $stateParams.revision; - - $scope.path = StringUtil.normalizePath($stateParams.path); - $scope.parsedPaths = RepositoryService.parsePath($scope.path); - - $scope.aceLoaded = function (editor) { - $timeout(function() { editor.focus(); }); - }; - - $scope.setRevision = function (revision) { - $location.path('/projects/' + $scope.project.name + '/repos/' + $scope.repository.name + - '/files/' + revision + $scope.path); - }; - - $scope.deleteFile = function () { - var modalInstance = $uibModal.open({ - templateUrl: 'scripts/app/entities/repositories/repository.file.delete.html', - controller: 'RepositoryFileDeleteController', - resolve: { - project: function () { - return $scope.project; - }, - repository: function () { - return $scope.repository; - }, - revision: function () { - return $scope.revision; - }, - file: function () { - return $scope.file; - } - } - }); - - modalInstance.result.then( - function (message) { - NotificationUtil.success(message); - $scope.back(); - }); - }; - - RepositoryService.getFile($scope.project.name, $scope.repository.name, $scope.revision, - {path: $scope.path}).then( - function (file) { - if (file.type === 'JSON') { - file.content = JSON.stringify(JSON.parse(file.content), null, 2) + '\n'; - } - $scope.file = file; - } - ); - }); diff --git a/server/src/main/resources/webapp/scripts/app/entities/repositories/repository.file.delete.controller.js b/server/src/main/resources/webapp/scripts/app/entities/repositories/repository.file.delete.controller.js deleted file mode 100644 index ade0793d45..0000000000 --- a/server/src/main/resources/webapp/scripts/app/entities/repositories/repository.file.delete.controller.js +++ /dev/null @@ -1,42 +0,0 @@ -'use strict'; - -angular.module('CentralDogmaAdmin') - .controller('RepositoryFileDeleteController', - function ($scope, $uibModalInstance, project, repository, revision, file, - RepositoryService, StringUtil, NotificationUtil) { - - $scope.project = project; - $scope.repository = repository; - $scope.revision = revision; - $scope.file = file; - - $scope.message = { - summary: '', - detail: { - content: '', - markup: 'PLAINTEXT' - } - }; - - $scope.deleteFile = function () { - if (StringUtil.isEmpty($scope.message.summary)) { - $scope.message.summary = 'Delete ' + $scope.file.path; - } - - RepositoryService.deleteFile($scope.project.name, $scope.repository.name, $scope.revision, - $scope.message, $scope.file.path).then( - function () { - $uibModalInstance.close({ - translationId: 'entities.deleted_file', - interpolateParams: {path: $scope.file.path} - }); - }, function (error) { - NotificationUtil.error(error); - $uibModalInstance.dismiss(error.message); - }); - }; - - $scope.cancel = function () { - $uibModalInstance.dismiss(''); - }; - }); diff --git a/server/src/main/resources/webapp/scripts/app/entities/repositories/repository.file.delete.html b/server/src/main/resources/webapp/scripts/app/entities/repositories/repository.file.delete.html deleted file mode 100644 index 87fd22c6e5..0000000000 --- a/server/src/main/resources/webapp/scripts/app/entities/repositories/repository.file.delete.html +++ /dev/null @@ -1,21 +0,0 @@ -
- - - -
diff --git a/server/src/main/resources/webapp/scripts/app/entities/repositories/repository.file.edit.controller.js b/server/src/main/resources/webapp/scripts/app/entities/repositories/repository.file.edit.controller.js deleted file mode 100644 index 36a97dd138..0000000000 --- a/server/src/main/resources/webapp/scripts/app/entities/repositories/repository.file.edit.controller.js +++ /dev/null @@ -1,153 +0,0 @@ -'use strict'; - -angular.module('CentralDogmaAdmin') - .controller('RepositoryFileEditController', - function ($scope, $state, $stateParams, $timeout, - CentralDogmaConstant, RepositoryService, NotificationUtil, StringUtil) { - - $scope.project = { - name: $stateParams.projectName - }; - $scope.repository = { - name: $stateParams.repositoryName - }; - $scope.revision = StringUtil.isEmpty($stateParams.revision) ? - CentralDogmaConstant.HEAD : $stateParams.revision; - - $scope.path = StringUtil.normalizePath($stateParams.path); - $scope.parsedPaths = RepositoryService.parsePath($scope.path); - - $scope.file = null; - $scope.absRevision = null; - - $scope.message = { - summary: '', - detail: { - content: '', - markup: 'PLAINTEXT' - } - }; - - $scope.aceLoaded = function (editor) { - $timeout(function() { editor.focus(); }); - $scope.fetchAndMerge(); - }; - - var getDiffs = function (type, origContent, curContent) { - switch (type) { - case 'JSON': - return jsonpatch.compare(JSON.parse(origContent), JSON.parse(curContent)); - case 'TEXT': - return JsDiff.structuredPatch(null, null, origContent, curContent, null, null); - default: - throw new Error(JSON.stringify({ - translationId: 'entities.unsupported_file_type', - interpolateParams: { 'type': $scope.file.type } - })); - } - }; - - var applyJsonPatch = function (content, diffs) { - if (diffs.length == 0) { - return false; - } - - var contentJson = JSON.parse(content); - if (jsonpatch.apply(contentJson, diffs, true) === false) { - throw new Error('entities.auto_merge_failed'); - } - - return JSON.stringify(contentJson, null, 2) + '\n'; - }; - - var applyTextPatch = function (content, diffs) { - if (diffs.hunks.length == 0) { - return false; - } - - var textPatchApplied = JsDiff.applyPatch(content, diffs); - if (textPatchApplied === false) { - throw new Error('entities.auto_merge_failed'); - } - - return textPatchApplied; - }; - - var applyDiffs = function (type, content, diffs) { - if (diffs == null) { - return false; - } - - switch (type) { - case 'JSON': - return applyJsonPatch(content, diffs); - case 'TEXT': - return applyTextPatch(content, diffs); - default: - throw new Error(JSON.stringify({ - translationId: 'entities.unsupported_file_type', - interpolateParams: { 'type': type } - })); - } - }; - - $scope.editFile = function () { - $scope.message.summary = StringUtil.defaultString($scope.message.summary, - 'Edit ' + $scope.file.path); - - RepositoryService.editFile($scope.project.name, $scope.repository.name, $scope.absRevision, - $scope.message, $scope.file).then( - function () { - NotificationUtil.success('entities.saved_file', { path: $scope.path }); - - $scope.back(); - }, function (error) { - switch (error.status) { - case 409: - if (error.exception === 'com.linecorp.centraldogma.common.RedundantChangeException') { - NotificationUtil.error('entities.redundant_changes'); - } else { - NotificationUtil.error('entities.conflict_occurred'); - } - break; - default: - NotificationUtil.error(error); - } - }); - }; - - $scope.fetchAndMerge = function () { - try { - var diffs = null; - if ($scope.file != null) { - diffs = getDiffs($scope.file.type, $scope.origFileContent, $scope.file.content); - } - - RepositoryService.getFile($scope.project.name, $scope.repository.name, $scope.revision, - {path: $scope.path}).then( - function (file) { - $scope.absRevision = file.revision; - $scope.file = file; - if ($scope.file.type === 'JSON') { - $scope.file.content = - JSON.stringify(JSON.parse($scope.file.content), null, 2) + '\n'; - } - $scope.origFileContent = $scope.file.content; - - var diffsApplied = applyDiffs($scope.file.type, $scope.file.content, diffs); - if (diffsApplied === false) { - $scope.isDiffsApplied = false; - } else { - $scope.isDiffsApplied = true; - $scope.file.content = diffsApplied; - } - }); - } catch (error) { - var message = error.message; - try { - message = JSON.parse(message); - } catch (ignored) {} - NotificationUtil.error(message); - } - }; - }); diff --git a/server/src/main/resources/webapp/scripts/app/entities/repositories/repository.file.edit.html b/server/src/main/resources/webapp/scripts/app/entities/repositories/repository.file.edit.html deleted file mode 100644 index 15a404cd72..0000000000 --- a/server/src/main/resources/webapp/scripts/app/entities/repositories/repository.file.edit.html +++ /dev/null @@ -1,83 +0,0 @@ -
-

- -

- -
- -
-
- - -

- - {{project.name}} / - - - - {{repository.name}} - - - - @ {{revision}} - -

-
- -
- - - -
- -
- -
- -
- - - -
- -
- entities.commit_message - -
- - -
- -
- - -
-
- -
- -
-
-
diff --git a/server/src/main/resources/webapp/scripts/app/entities/repositories/repository.file.html b/server/src/main/resources/webapp/scripts/app/entities/repositories/repository.file.html deleted file mode 100644 index d3e9f63d12..0000000000 --- a/server/src/main/resources/webapp/scripts/app/entities/repositories/repository.file.html +++ /dev/null @@ -1,70 +0,0 @@ -
-

- -

- -
- -
- -
-

- -

-
-
- -
- -

- - - {{repository.name}} - - - - / - - {{parsedPath.name}} - - - / {{file.name}} -

- - - -
- - -
diff --git a/server/src/main/resources/webapp/scripts/app/entities/repositories/repository.file.new.controller.js b/server/src/main/resources/webapp/scripts/app/entities/repositories/repository.file.new.controller.js deleted file mode 100644 index 11981001bb..0000000000 --- a/server/src/main/resources/webapp/scripts/app/entities/repositories/repository.file.new.controller.js +++ /dev/null @@ -1,149 +0,0 @@ -'use strict'; - -angular.module('CentralDogmaAdmin') - .controller('RepositoryFileNewController', - function ($scope, $state, $stateParams, $timeout, - CentralDogmaConstant, RepositoryService, NotificationUtil, StringUtil) { - $scope.project = { - name: $stateParams.projectName - }; - $scope.repository = { - name: $stateParams.repositoryName - }; - $scope.revision = StringUtil.isEmpty($stateParams.revision) ? - CentralDogmaConstant.HEAD : $stateParams.revision; - - $scope.path = StringUtil.normalizePath($stateParams.path); - $scope.parsedPaths = RepositoryService.parsePath($scope.path); - - $scope.file = { - name: '', - type: 'JSON', - content: '' - }; - - $scope.message = { - summary: '', - detail: { - content: '', - markup: 'PLAINTEXT' - } - }; - - var generateNewPath = function (normalizedPath, newDirectories) { - var temp = normalizedPath; - if (temp === '/') { - temp = ''; - } - - return [temp].concat(newDirectories).join('/'); - }; - - $scope.newDirectories = []; - $scope.newPath = generateNewPath($scope.path, $scope.newDirectories); - - $scope.jsonEditorOptions = { - mode: 'code', - modes: ['tree', 'code'] - }; - - $scope.aceLoaded = function (editor) { - $scope.editor = editor; - }; - - // Auto-focus the file name field. - var focusFilenameField = function () { - $timeout(function () { - angular.element('#fileName').focus(); - }); - }; - - focusFilenameField(); - - var filenamePattern = /^[0-9A-Za-z](?:[-+_0-9A-Za-z\.]*[0-9A-Za-z])?$/; - - $scope.popOnBackspace = false; - $scope.keyUp = function (event) { - var filename = $scope.file.name; - if (StringUtil.isEmpty(filename)) { - if (event.keyCode === 8 && // backspace - $scope.newDirectories.length > 0) { - if ($scope.popOnBackspace) { - filename = $scope.newDirectories.pop(); - $scope.popOnBackspace = false; - } else { - $scope.popOnBackspace = true; - } - } else { - return; - } - } else if (filename.indexOf('/') >= 0) { // '/' - var filenameArray = filename.split('/'); - if (filenameArray.length === 0) { - $scope.file.name = filename = ''; - } else { - for (var i = 0; i < filenameArray.length - 1; i++) { - if (filenameArray[i].match(filenamePattern)) { - $scope.newDirectories.push(filenameArray[i]); - } - } - - filename = filenameArray[filenameArray.length - 1]; - $scope.popOnBackspace = StringUtil.isEmpty(filename); - } - } else { - $scope.popOnBackspace = false; - } - - $scope.file.name = filename; - - if (StringUtil.isEmpty(filename)) { - $scope.fileForm.fileName.$pristine = true; - } else if (!filename.match(filenamePattern)) { - $scope.fileForm.fileName.$invalid = true; - return; - } else { - $scope.fileForm.fileName.$invalid = false; - } - - $scope.newPath = generateNewPath($scope.path, $scope.newDirectories); - $scope.file.path = $scope.newPath + '/' + filename; - }; - - $scope.createFile = function () { - if (!$scope.file.name.match(filenamePattern)) { - $scope.fileForm.fileName.$invalid = true; - $scope.fileForm.fileName.$pristine = false; - NotificationUtil.error('entities.invalid_file_path'); - focusFilenameField(); - return; - } - - if (StringUtil.isEmpty($scope.message.summary)) { - $scope.message.summary = 'Add ' + $scope.file.path; - } - - if (StringUtil.endsWith($scope.file.name.toLowerCase(), '.json')) { - $scope.file.type = 'JSON'; - try { - JSON.parse($scope.file.content); - } catch (error) { - NotificationUtil.error('entities.invalid_json'); - $timeout(function() { - $scope.editor.focus(); - }); - return; - } - } else { - $scope.file.type = 'TEXT'; - } - - RepositoryService.addFile($scope.project.name, $scope.repository.name, $scope.revision, - $scope.message, $scope.file).then( - function () { - NotificationUtil.success('entities.saved_file', { path: $scope.file.path }); - - $scope.back(); - }); - }; - }); diff --git a/server/src/main/resources/webapp/scripts/app/entities/repositories/repository.file.new.html b/server/src/main/resources/webapp/scripts/app/entities/repositories/repository.file.new.html deleted file mode 100644 index 9225f4c1ff..0000000000 --- a/server/src/main/resources/webapp/scripts/app/entities/repositories/repository.file.new.html +++ /dev/null @@ -1,66 +0,0 @@ -
-

- -

- -
- -
-
- - -

- - {{project.name}} / - - - - {{repository.name}} - - - - @ {{revision}} - -

-
- -
- - -
- {{newPath}}/ - -
-

- entities.invalid_file_path -

-
- -
- -
- -
- entities.commit_message -
- - -
-
- - -
-
- -
- -
-
-
diff --git a/server/src/main/resources/webapp/scripts/app/entities/repositories/repository.history.controller.js b/server/src/main/resources/webapp/scripts/app/entities/repositories/repository.history.controller.js deleted file mode 100644 index 81971b45b1..0000000000 --- a/server/src/main/resources/webapp/scripts/app/entities/repositories/repository.history.controller.js +++ /dev/null @@ -1,40 +0,0 @@ -'use strict'; - -angular.module('CentralDogmaAdmin') - .controller('RepositoryHistoryController', - function ($scope, $stateParams, $location, - CentralDogmaConstant, RepositoryService, StringUtil) { - - $scope.project = { - name: $stateParams.projectName - }; - $scope.repository = { - name: $stateParams.repositoryName - }; - $scope.revision = StringUtil.isEmpty($stateParams.revision) ? - CentralDogmaConstant.HEAD : $stateParams.revision; - - $scope.path = StringUtil.normalizePath($stateParams.path); - $scope.parsedPaths = RepositoryService.parsePath($scope.path); - - $scope.commits = []; - - $scope.setRevision = function (revision) { - $location.path('/projects/' + $scope.project.name + '/repos/' + $scope.repository.name + - '/history/' + revision + $scope.path); - }; - - // TODO(trustin): Pagination - RepositoryService.getHistory($scope.project.name, $scope.repository.name, $scope.path, - $scope.revision, 1).then( - function (commits) { - angular.forEach(commits, function (commit) { - if (commit.revision.minor === 0) { - commit.revision.revisionNumber = commit.revision.major.toString(); - } - commit.timestampStr = moment(commit.timestamp).fromNow(); - this.push(commit); - }, $scope.commits); - } - ); - }); diff --git a/server/src/main/resources/webapp/scripts/app/entities/repositories/repository.history.html b/server/src/main/resources/webapp/scripts/app/entities/repositories/repository.history.html deleted file mode 100644 index 6ffecddd97..0000000000 --- a/server/src/main/resources/webapp/scripts/app/entities/repositories/repository.history.html +++ /dev/null @@ -1,69 +0,0 @@ -
-

- -

- -
- -
- -
-
- -
-
-
- -
- -

- - - {{repository.name}} - - - - / - - {{parsedPath.name}} - - - {{parsedPath.name}} - - - {{parsedPath.name}} - - -

- - - - - - - - - - - - - - - - - - -
entities.revisionentities.commit_summaryentities.commit_authorentities.commit_timestamp
- - {{commit.revision.revisionNumber}} - - {{commit.summary}}{{commit.author.name}}{{commit.timestampStr}}
-
diff --git a/server/src/main/resources/webapp/scripts/app/entities/repositories/repository.new.controller.js b/server/src/main/resources/webapp/scripts/app/entities/repositories/repository.new.controller.js deleted file mode 100644 index a603ed007f..0000000000 --- a/server/src/main/resources/webapp/scripts/app/entities/repositories/repository.new.controller.js +++ /dev/null @@ -1,22 +0,0 @@ -'use strict'; - -angular.module('CentralDogmaAdmin') - .controller('RepositoryNewController', - function ($scope, $state, $stateParams, RepositoryService, NotificationUtil) { - $scope.project = { - name: $stateParams.projectName - }; - - $scope.createRepository = function () { - RepositoryService.createRepository($scope.project.name, $scope.repository.name).then( - function () { - NotificationUtil.success('entities.created_repository', - { - projectName: $scope.project.name, - repositoryName: $scope.repository.name - }); - $scope.back(); - } - ); - }; - }); diff --git a/server/src/main/resources/webapp/scripts/app/entities/repositories/repository.new.html b/server/src/main/resources/webapp/scripts/app/entities/repositories/repository.new.html deleted file mode 100644 index 25e0c0f65b..0000000000 --- a/server/src/main/resources/webapp/scripts/app/entities/repositories/repository.new.html +++ /dev/null @@ -1,34 +0,0 @@ -
-

entities.title_create_repository

- -
- -
-
- - -

- {{project.name}} -

-
- -
- - - -

- entities.invalid_repository_name -

-
- -
- -
-
-
diff --git a/server/src/main/resources/webapp/scripts/app/entities/repositories/repository.query.controller.js b/server/src/main/resources/webapp/scripts/app/entities/repositories/repository.query.controller.js deleted file mode 100644 index ec466aac51..0000000000 --- a/server/src/main/resources/webapp/scripts/app/entities/repositories/repository.query.controller.js +++ /dev/null @@ -1,109 +0,0 @@ -'use strict'; - -angular.module('CentralDogmaAdmin') - .controller('RepositoryQueryController', - function ($scope, $state, $stateParams, $location, $window, - CentralDogmaConstant, RepositoryService, StringUtil) { - - $scope.project = { - name: $stateParams.projectName - }; - $scope.repository = { - name: $stateParams.repositoryName - }; - $scope.revision = StringUtil.isEmpty($stateParams.revision) ? - CentralDogmaConstant.HEAD : $stateParams.revision; - - $scope.path = StringUtil.normalizePath($stateParams.path); - $scope.parsedPaths = RepositoryService.parsePath($scope.path); - - $scope.file = null; - $scope.queryResult = ''; - - var filterInvalidExpressions = function (expressions) { - var ret = []; - for (var index in expressions) { - if (StringUtil.isEmpty(expressions[index].value)) { - continue; - } - ret.push(expressions[index]); - } - return ret; - }; - - var convertExpressionsIntoArray = function (expressions) { - var filtered = filterInvalidExpressions(expressions); - - var ret = []; - for (var index in filtered) { - ret.push(filtered[index].value); - } - return ret; - }; - - $scope.queryType = 'JSON_PATH'; - - if (angular.isString($stateParams.expression)) { - $scope.expressions = [{value: $stateParams.expression}]; - } else if (angular.isArray($stateParams.expression)) { - var expressions = []; - - for (var index in $stateParams.expression) { - expressions.push({value: $stateParams.expression[index]}); - } - - $scope.expressions = filterInvalidExpressions(expressions); - } else { - $scope.expressions = []; - } - - $scope.addNewExpression = function () { - $scope.expressions.push({value: ''}); - }; - - $scope.removeExpression = function (index) { - $scope.expressions.splice(index, 1); - }; - - if ($scope.expressions.length == 0) { - $scope.addNewExpression(); - } - - $scope.setRevision = function (revision) { - $location.path('/projects/' + $scope.project.name + '/repos/' + $scope.repository.name + - '/query/' + revision + $scope.path); - }; - - $scope.query = function () { - $state.go('repositoryQuery', { - projectName: $scope.project.name, - repositoryName: $scope.repository.name, - revision: $scope.revision, - expression: convertExpressionsIntoArray($scope.expressions) - }); - }; - - var converted = convertExpressionsIntoArray($scope.expressions); - if (converted.length == 0) { - RepositoryService.getFile($scope.project.name, $scope.repository.name, $scope.revision, - { - path: $scope.path, - type: 'IDENTITY' - }).then( - function (file) { - $scope.file = file; - $scope.queryResult = JSON.stringify(JSON.parse(file.content), null, 2) + '\n'; - }); - } else { - RepositoryService.getFile($scope.project.name, $scope.repository.name, $scope.revision, - { - path: $scope.path, - type: $scope.queryType, - expressions: converted - }).then( - function (file) { - $scope.file = file; - $scope.queryResult = JSON.stringify(JSON.parse(file.content), null, 2) + '\n'; - }); - } - }); diff --git a/server/src/main/resources/webapp/scripts/app/entities/repositories/repository.query.html b/server/src/main/resources/webapp/scripts/app/entities/repositories/repository.query.html deleted file mode 100644 index 5789c94c20..0000000000 --- a/server/src/main/resources/webapp/scripts/app/entities/repositories/repository.query.html +++ /dev/null @@ -1,68 +0,0 @@ -
-

- -

- -
- -
- -
-

- -

-
-
- -
- -

- - - {{repository.name}} - - - - / - - {{parsedPath.name}} - - - / {{file.name}} -

- -
- -
-
-
-
- {{queryType}}[{{$index}}] - - - - - -
-
-
- -
-
-
- - -
diff --git a/server/src/main/resources/webapp/scripts/app/entities/repositories/repository.search.controller.js b/server/src/main/resources/webapp/scripts/app/entities/repositories/repository.search.controller.js deleted file mode 100644 index ea05882345..0000000000 --- a/server/src/main/resources/webapp/scripts/app/entities/repositories/repository.search.controller.js +++ /dev/null @@ -1,46 +0,0 @@ -'use strict'; - -angular.module('CentralDogmaAdmin') - .controller('RepositorySearchController', - function ($scope, $state, $stateParams, $location, $window, - CentralDogmaConstant, RepositoryService, StringUtil) { - $scope.project = { - name: $stateParams.projectName - }; - $scope.repository = { - name: $stateParams.repositoryName - }; - $scope.revision = StringUtil.isEmpty($stateParams.revision) ? - CentralDogmaConstant.HEAD : $stateParams.revision; - - $scope.term = !angular.isString($stateParams.term) ? '' : $stateParams.term; - if ($scope.term === 'true') { - $scope.term = ''; - } - - $scope.files = []; - - $scope.setRevision = function (revision) { - console.log($scope.term); - $location.path('/projects/' + $scope.project.name + '/repos/' + $scope.repository.name + - '/search/' + revision); - }; - - $scope.search = function () { - $state.go('repositorySearch', { - projectName: $scope.project.name, - repositoryName: $scope.repository.name, - revision: $scope.revision, - term: $scope.term - }); - }; - - if (StringUtil.isNotEmpty($scope.term)) { - RepositoryService.search($scope.project.name, $scope.repository.name, $scope.revision, - $scope.term).then( - function (files) { - $scope.files = files; - } - ); - } - }); diff --git a/server/src/main/resources/webapp/scripts/app/entities/repositories/repository.search.html b/server/src/main/resources/webapp/scripts/app/entities/repositories/repository.search.html deleted file mode 100644 index ab8d89a8ea..0000000000 --- a/server/src/main/resources/webapp/scripts/app/entities/repositories/repository.search.html +++ /dev/null @@ -1,49 +0,0 @@ -
-

- -

- -
- -
- -
-

- -

-
-
- -
- - - - - - - - - - - - -
entities.entries_not_found
- - - - - {{file.path}} - - - {{file.path}} - -
-
diff --git a/server/src/main/resources/webapp/scripts/app/entities/repositories/repository.tree.controller.js b/server/src/main/resources/webapp/scripts/app/entities/repositories/repository.tree.controller.js deleted file mode 100644 index 7424925c33..0000000000 --- a/server/src/main/resources/webapp/scripts/app/entities/repositories/repository.tree.controller.js +++ /dev/null @@ -1,74 +0,0 @@ -'use strict'; - -angular.module('CentralDogmaAdmin') - .controller('RepositoryTreeController', - function ($scope, $stateParams, $location, $uibModal, Principal, CentralDogmaConstant, RepositoryService, - NotificationUtil, StringUtil) { - $scope.project = { - name: $stateParams.projectName - }; - $scope.repository = { - name: $stateParams.repositoryName - }; - $scope.revision = StringUtil.isEmpty($stateParams.revision) ? - CentralDogmaConstant.HEAD : $stateParams.revision; - - $scope.path = StringUtil.normalizePath($stateParams.path); - $scope.parsedPaths = RepositoryService.parsePath($scope.path); - $scope.files = []; - $scope.selectedFile = null; - - $scope.setRevision = function (revision) { - $location.path('/projects/' + $scope.project.name + '/repos/' + $scope.repository.name + - '/list/' + revision + $scope.path); - }; - - $scope.selectFile = function (file) { - $scope.selectedFile = file === $scope.selectedFile ? null : file; - }; - - $scope.deleteFile = function () { - var modalInstance = $uibModal.open({ - templateUrl: 'scripts/app/entities/repositories/repository.file.delete.html', - controller: 'RepositoryFileDeleteController', - resolve: { - project: function () { - return $scope.project; - }, - repository: function () { - return $scope.repository; - }, - revision: function () { - return $scope.revision; - }, - file: function () { - return $scope.selectedFile; - } - } - }); - - modalInstance.result.then( - function (message) { - $scope.selectedFile = null; - NotificationUtil.success(message); - getTree(); - }); - }; - - var getTree = function () { - RepositoryService.getTree( - $scope.project.name, $scope.repository.name, $scope.revision, $scope.path).then( - function (files) { - if (angular.isArray(files)) { - $scope.files = files; - $scope.files.forEach(function (file) { - const components = file.path.split('/'); - file.name = components[components.length - 1]; - }); - } else { - $scope.files = []; - } - }); - }; - getTree(); - }); diff --git a/server/src/main/resources/webapp/scripts/app/entities/repositories/repository.tree.html b/server/src/main/resources/webapp/scripts/app/entities/repositories/repository.tree.html deleted file mode 100644 index c3ac83f95b..0000000000 --- a/server/src/main/resources/webapp/scripts/app/entities/repositories/repository.tree.html +++ /dev/null @@ -1,89 +0,0 @@ -
-

- -

- -
- -
- -
-

- -

-
-
- -
- -

- - - {{repository.name}} - - - - / - - {{parsedPath.name}} - - -

- - - - - - - - - - - - - - - - -
- .. -
entities.empty_directory
- - - - {{file.name}} - {{file.name}} -
- -
- -
- - -
-
- - {{ 'entities.button_create' | translate }} - - -
-
-
-
diff --git a/server/src/main/resources/webapp/scripts/app/settings/setting.js b/server/src/main/resources/webapp/scripts/app/settings/setting.js deleted file mode 100644 index e8f53470b0..0000000000 --- a/server/src/main/resources/webapp/scripts/app/settings/setting.js +++ /dev/null @@ -1,9 +0,0 @@ -'use strict'; - -angular.module('CentralDogmaAdmin').config(function ($stateProvider) { - $stateProvider.state('setting', { - abstract: true, - parent: 'site', - url: "/settings" - }); -}); diff --git a/server/src/main/resources/webapp/scripts/app/settings/tokens/token.generated.controller.js b/server/src/main/resources/webapp/scripts/app/settings/tokens/token.generated.controller.js deleted file mode 100644 index a1c9fd6647..0000000000 --- a/server/src/main/resources/webapp/scripts/app/settings/tokens/token.generated.controller.js +++ /dev/null @@ -1,9 +0,0 @@ -'use strict'; - -angular.module('CentralDogmaAdmin').controller('TokenGeneratedController', - function ($scope, $timeout, $uibModalInstance, newToken) { - $scope.newToken = newToken; - $scope.close = function () { - $uibModalInstance.close(); - }; - }); diff --git a/server/src/main/resources/webapp/scripts/app/settings/tokens/token.generated.html b/server/src/main/resources/webapp/scripts/app/settings/tokens/token.generated.html deleted file mode 100644 index a49b02bb49..0000000000 --- a/server/src/main/resources/webapp/scripts/app/settings/tokens/token.generated.html +++ /dev/null @@ -1,41 +0,0 @@ - diff --git a/server/src/main/resources/webapp/scripts/app/settings/tokens/token.new.controller.js b/server/src/main/resources/webapp/scripts/app/settings/tokens/token.new.controller.js deleted file mode 100644 index 7f6cf968c2..0000000000 --- a/server/src/main/resources/webapp/scripts/app/settings/tokens/token.new.controller.js +++ /dev/null @@ -1,27 +0,0 @@ -'use strict'; - -angular.module('CentralDogmaAdmin').controller('TokenNewController', - function ($scope, $timeout, $uibModal, $uibModalInstance, $filter, SettingsService, NotificationUtil) { - - $scope.isAdmin = false; - - $scope.generateToken = function (isAdmin) { - var data = 'appId=' + encodeURIComponent($scope.appId) + '&isAdmin=' + isAdmin; - - SettingsService.createToken(data).then(function (token) { - $scope.newToken = token; - $scope.newToken.creation.timestamp = moment(token.creationTime).fromNow(); - $uibModalInstance.close($scope.newToken); - }, function (error) { - if (typeof error.status !== 'undefined' && error.status === 409) { - NotificationUtil.error('settings.token_application_id.exist', {appId: $scope.appId}); - } else { - NotificationUtil.error(error); - } - }); - }; - - $scope.close = function () { - $uibModalInstance.close(); - }; - }); diff --git a/server/src/main/resources/webapp/scripts/app/settings/tokens/token.new.html b/server/src/main/resources/webapp/scripts/app/settings/tokens/token.new.html deleted file mode 100644 index 09ad25490f..0000000000 --- a/server/src/main/resources/webapp/scripts/app/settings/tokens/token.new.html +++ /dev/null @@ -1,23 +0,0 @@ -
- - - -
diff --git a/server/src/main/resources/webapp/scripts/app/settings/tokens/tokens.controller.js b/server/src/main/resources/webapp/scripts/app/settings/tokens/tokens.controller.js deleted file mode 100644 index 36f57b1e1a..0000000000 --- a/server/src/main/resources/webapp/scripts/app/settings/tokens/tokens.controller.js +++ /dev/null @@ -1,101 +0,0 @@ -'use strict'; - -angular.module('CentralDogmaAdmin').controller('TokensController', - function ($scope, $uibModal, SettingsService, ConfirmationDialog, NotificationUtil, EntitiesUtil, - $timeout, CentralDogmaConstant) { - $scope.sanitizeEmail = EntitiesUtil.sanitizeEmail; - - var refreshNow = function () { - $scope.selectedToken = null; - SettingsService.listTokens().then( - function (tokens) { - $scope.tokens = tokens; - } - ); - }; - - var refresh = function () { - $timeout(function () { - refreshNow(); - }, CentralDogmaConstant.REFRESH_DELAY_MSEC); - }; - - $scope.selectToken = function (token) { - if (token === $scope.selectedToken) { - $scope.selectedToken = null; - } else { - $scope.selectedToken = token; - } - }; - - $scope.showGenerateTokenDialog = function () { - var modalInstance = $uibModal.open({ - templateUrl: 'scripts/app/settings/tokens/token.new.html', - controller: 'TokenNewController', - backdrop: 'static' - }); - modalInstance.result.then( - function (newToken) { - if (angular.isDefined(newToken)) { - $scope.newToken = newToken; - $scope.showTokenGeneratedDialog(); - } - }); - }; - $scope.showTokenGeneratedDialog = function () { - var modalInstance = $uibModal.open({ - templateUrl: 'scripts/app/settings/tokens/token.generated.html', - controller: 'TokenGeneratedController', - backdrop: 'static', - resolve: { - newToken: function () { - return $scope.newToken; - } - } - }); - modalInstance.result.then( - function () { - $scope.selectedToken = null; - refresh(); - } - ) - }; - - $scope.activateToken = function () { - ConfirmationDialog.openModal('settings.title_activate_token', { - token: $scope.selectedToken.appId - }).then(function () { - SettingsService.activateToken($scope.selectedToken.appId).then(function () { - refresh(); - }, function (error) { - NotificationUtil.error(error); - }); - }); - }; - - $scope.deactivateToken = function () { - ConfirmationDialog.openModal('settings.title_deactivate_token', { - token: $scope.selectedToken.appId - }).then(function () { - SettingsService.deactivateToken($scope.selectedToken.appId).then(function () { - refresh(); - }, function (error) { - NotificationUtil.error(error); - }); - }); - }; - - $scope.deleteToken = function () { - ConfirmationDialog.openModal('settings.title_delete_token', { - token: $scope.selectedToken.appId - }).then(function () { - SettingsService.deleteToken($scope.selectedToken.appId).then(function () { - refresh(); - }, function (error) { - NotificationUtil.error(error); - }); - }); - }; - - refreshNow(); - }); diff --git a/server/src/main/resources/webapp/scripts/app/settings/tokens/tokens.html b/server/src/main/resources/webapp/scripts/app/settings/tokens/tokens.html deleted file mode 100644 index 59314664b5..0000000000 --- a/server/src/main/resources/webapp/scripts/app/settings/tokens/tokens.html +++ /dev/null @@ -1,70 +0,0 @@ -
-

Application Tokens

- - - - - - - - - - - - - - - - - - - - -
settings.token_application_idsettings.token_levelsettings.token_creatorsettings.token_creation_timesettings.token_status
- {{token.appId}} - - -

{{token.secret}}

-
-
-
Admin
-
User
-
-
{{sanitizeEmail(token.creation.user)}}{{token.creationTimeStr}} -
-
-
-
Scheduled for deletion
-
Inactive
-
-
-
Active
-
-
- -
- -
-
- - - - -
-
- -
diff --git a/server/src/main/resources/webapp/scripts/app/settings/tokens/tokens.js b/server/src/main/resources/webapp/scripts/app/settings/tokens/tokens.js deleted file mode 100644 index ab18e8386f..0000000000 --- a/server/src/main/resources/webapp/scripts/app/settings/tokens/tokens.js +++ /dev/null @@ -1,15 +0,0 @@ -'use strict'; - -angular.module('CentralDogmaAdmin').config(function ($stateProvider) { - $stateProvider.state('tokens', { - parent: 'setting', - url: '/tokens', - data: {}, - views: { - 'content@': { - templateUrl: 'scripts/app/settings/tokens/tokens.html', - controller: 'TokensController' - } - } - }); -}); diff --git a/server/src/main/resources/webapp/scripts/app/user/user.js b/server/src/main/resources/webapp/scripts/app/user/user.js deleted file mode 100644 index b48929d290..0000000000 --- a/server/src/main/resources/webapp/scripts/app/user/user.js +++ /dev/null @@ -1,10 +0,0 @@ -'use strict'; - -angular.module('CentralDogmaAdmin') - .config(function ($stateProvider) { - $stateProvider - .state('user', { - abstract: true, - parent: 'site' - }); - }); diff --git a/server/src/main/resources/webapp/scripts/components/auth/authority.directive.js b/server/src/main/resources/webapp/scripts/components/auth/authority.directive.js deleted file mode 100644 index 49fcdf8cc6..0000000000 --- a/server/src/main/resources/webapp/scripts/components/auth/authority.directive.js +++ /dev/null @@ -1,81 +0,0 @@ -'use strict'; - -angular.module('CentralDogmaAdmin') - .directive('hasAnyRole', ['Principal', function (Principal) { - return { - restrict: 'A', - link: function (scope, element, attrs) { - var setVisible = function () { - element.removeClass('hidden'); - }, - setHidden = function () { - element.addClass('hidden'); - }, - defineVisibility = function (reset) { - var result; - if (reset) { - setVisible(); - } - - result = Principal.isInAnyRole(roles); - if (result) { - setVisible(); - } else { - setHidden(); - } - }, - roles = attrs.hasAnyRole.replace(/\s+/g, '').split(','); - - if (roles.length > 0) { - defineVisibility(true); - } - - scope.$on('user:logged_in', function (event, data) { - defineVisibility(true); - }); - - scope.$on('user:logged_out', function (event, data) { - defineVisibility(true); - }); - } - }; - }]) - .directive('hasRole', ['Principal', function (Principal) { - return { - restrict: 'A', - link: function (scope, element, attrs) { - var setVisible = function () { - element.removeClass('hidden'); - }, - setHidden = function () { - element.addClass('hidden'); - }, - defineVisibility = function (reset) { - var result; - if (reset) { - setVisible(); - } - - result = Principal.isInRole(role); - if (result) { - setVisible(); - } else { - setHidden(); - } - }, - role = attrs.hasRole.replace(/\s+/g, ''); - - if (role.length > 0) { - defineVisibility(true); - } - - scope.$on('user:logged_in', function (event, data) { - defineVisibility(false); - }); - - scope.$on('user:logged_out', function (event, data) { - defineVisibility(false); - }); - } - }; - }]); diff --git a/server/src/main/resources/webapp/scripts/components/auth/principal.service.js b/server/src/main/resources/webapp/scripts/components/auth/principal.service.js deleted file mode 100644 index 90262a2ef8..0000000000 --- a/server/src/main/resources/webapp/scripts/components/auth/principal.service.js +++ /dev/null @@ -1,104 +0,0 @@ -'use strict'; - -angular.module('CentralDogmaAdmin') - .factory('Principal', - function Principal($rootScope, $q, $window, User, CentralDogmaConstant) { - var _identity, _authenticated = false; - - return { - isAuthenticated: function () { - return _authenticated; - }, - - projectRole: function (metadata) { - var me = null; - if (!_authenticated || - angular.isUndefined(metadata) || - angular.isUndefined(metadata.members) || - metadata.members === null) { - return CentralDogmaConstant.PROJECT_ROLE_GUEST; - } - // We deal 'admin' as an owner of the project. - if (_identity.roles.indexOf(CentralDogmaConstant.LEVEL_ADMIN) !== -1) { - return CentralDogmaConstant.PROJECT_ROLE_OWNER; - } - Object.keys(metadata.members).forEach(function (value) { - if (angular.equals(value, _identity.email)) { - me = metadata.members[value]; - } - }); - if (me === null) { - return CentralDogmaConstant.PROJECT_ROLE_GUEST; - } - return me.role; - }, - - isInRole: function (role) { - if (!_authenticated || !_identity || !_identity.roles) { - return false; - } - - return _identity.roles.indexOf(role) !== -1; - }, - - isUser: function () { - return this.isInRole(CentralDogmaConstant.LEVEL_USER); - }, - - isInAnyRole: function (roles) { - if (!_authenticated || !_identity.roles) { - return false; - } - - for (var i = 0; i < roles.length; i++) { - if (this.isInRole(roles[i])) { - return true; - } - } - - return false; - }, - - set: function (identity) { - if (typeof identity !== 'object') { - return; - } - - $rootScope.user = _identity = identity; - if (identity !== null) { - _authenticated = true; - $rootScope.$broadcast('user:logged_in', identity); - } - }, - - clear: function () { - if (!_authenticated || !_identity) { - return false; - } - - var oldIdentity = _identity; - _authenticated = false; - $rootScope.user = _identity = null; - $rootScope.$broadcast('user:logged_out', oldIdentity); - return true; - }, - - refresh: function () { - var deferred = $q.defer(); - - // retrieve the identity data from the server, update the identity object, and then resolve. - var $this = this; - User.get() - .then(function (account) { - $this.set(account); - deferred.resolve(_identity); - }, function () { - $this.clear(); - deferred.resolve(null); - $window.localStorage.clear(); - }); - - return deferred.promise; - } - }; - }); diff --git a/server/src/main/resources/webapp/scripts/components/auth/security.service.js b/server/src/main/resources/webapp/scripts/components/auth/security.service.js deleted file mode 100644 index 82a2900918..0000000000 --- a/server/src/main/resources/webapp/scripts/components/auth/security.service.js +++ /dev/null @@ -1,31 +0,0 @@ -'use strict'; - -angular.module('CentralDogmaAdmin') - .factory('Security', - function ($rootScope, $http, $q, NotificationUtil) { - return { - resolve: function () { - var defer = $q.defer(); - if (this.isResolved()) { - defer.resolve($rootScope.isSecurityEnabled); - } else { - $http.get('/security_enabled').then(function () { - $rootScope.isSecurityEnabled = true; - defer.resolve(true); - }, function (error) { - if (error.status === 404) { - defer.resolve(false); - } else { - NotificationUtil.error(error); - defer.reject(error); - } - }); - } - return defer.promise; - }, - - isResolved: function () { - return angular.isDefined($rootScope.isSecurityEnabled); - } - }; - }); diff --git a/server/src/main/resources/webapp/scripts/components/entities/entities.util.js b/server/src/main/resources/webapp/scripts/components/entities/entities.util.js deleted file mode 100644 index d90355e773..0000000000 --- a/server/src/main/resources/webapp/scripts/components/entities/entities.util.js +++ /dev/null @@ -1,45 +0,0 @@ -'use strict'; - -angular.module('CentralDogmaAdmin') - .factory('EntitiesUtil', - function (StringUtil) { - return { - toKeySet: function (map) { - if (angular.isUndefined(map) || map === null) { - return []; - } - return Object.keys(map); - }, - - toUniqueSet: function (sourceSet, filterSet) { - if (angular.isUndefined(sourceSet) || sourceSet === null) { - return []; - } - if (angular.isUndefined(filterSet) || filterSet === null || filterSet.length === 0) { - return sourceSet; - } - return sourceSet.filter(function (value) { - return filterSet.indexOf(value) === -1; // not exist - }); - }, - - toDateTimeStr: function (timestamp) { - return moment(timestamp).fromNow(); - }, - - toReplaceJsonPatch: function (path, value) { - return [{ - op: 'replace', - path: path, - value: value - }] - }, - - sanitizeEmail: function (email) { - if (StringUtil.endsWith(email, '@localhost.localdomain')) { - return email.split('@')[0]; - } - return email; - } - }; - }); diff --git a/server/src/main/resources/webapp/scripts/components/entities/identifier.with.role.js b/server/src/main/resources/webapp/scripts/components/entities/identifier.with.role.js deleted file mode 100644 index 75a4453b23..0000000000 --- a/server/src/main/resources/webapp/scripts/components/entities/identifier.with.role.js +++ /dev/null @@ -1,24 +0,0 @@ -'use strict'; - -angular.module('CentralDogmaAdmin') - .factory('IdentifierWithRole', function () { - function IdentifierWithRole() { - this.elements = []; - } - - IdentifierWithRole.prototype = { - pushNew: function () { - this.elements.push({ - id: null, - role: null - }); - }, - remove: function (elm) { - this.elements = this.elements.filter(function (value) { - return value !== elm; - }); - } - }; - - return (IdentifierWithRole); -}); diff --git a/server/src/main/resources/webapp/scripts/components/entities/permission.js b/server/src/main/resources/webapp/scripts/components/entities/permission.js deleted file mode 100644 index 645b5b53a7..0000000000 --- a/server/src/main/resources/webapp/scripts/components/entities/permission.js +++ /dev/null @@ -1,61 +0,0 @@ -'use strict'; - -angular.module('CentralDogmaAdmin') - .factory('Permission', function () { - function Permission() { - this.elements = []; - } - - Permission.prototype = { - pushNew: function () { - this.elements.push({ - name: null, - read: false, - write: false - }); - }, - remove: function (perm) { - this.elements = this.elements.filter(function (value) { - return value !== perm; - }); - }, - validate: function (perm) { - // If 'write' is permitted, 'read' should also be permitted. - if (perm.write === true) { - perm.read = true; - } - } - }; - - Permission.toSet = function (perm) { - var set = []; - if (perm.read === true) { - set.push('READ'); - } - if (perm.write === true) { - set.push('WRITE'); - } - return set; - }; - - Permission.toRequest = function (name, perm) { - return { - id: name, - permissions: Permission.toSet(perm) - }; - }; - - Permission.makePermissionTable = function (permissionMap) { - var permTable = {}; - Object.entries(permissionMap).forEach(function (entry) { - const permSet = new Set(entry[1]); - permTable[entry[0]] = { - read: permSet.has('READ'), - write: permSet.has('WRITE') - }; - }); - return permTable; - }; - - return (Permission); -}); diff --git a/server/src/main/resources/webapp/scripts/components/entities/project.service.js b/server/src/main/resources/webapp/scripts/components/entities/project.service.js deleted file mode 100644 index 20895226ee..0000000000 --- a/server/src/main/resources/webapp/scripts/components/entities/project.service.js +++ /dev/null @@ -1,36 +0,0 @@ -'use strict'; - -angular.module('CentralDogmaAdmin') - .factory('ProjectService', - function (ApiV1Service, StringUtil, EntitiesUtil) { - return { - createProject: function (projectName) { - name = StringUtil.requireNotEmpty(projectName, 'projectName'); - return ApiV1Service.post('projects', {'name': name}); - }, - - listProjects: function () { - return ApiV1Service.get('projects'); - }, - - listRemovedProjects: function () { - return ApiV1Service.get('projects?status=removed'); - }, - - checkPermission: function (projectName) { - return ApiV1Service.get(StringUtil.encodeUri(['projects', projectName]) + - '?checkPermissionOnly=true'); - }, - - removeProject: function (projectName) { - name = StringUtil.requireNotEmpty(projectName, 'projectName'); - return ApiV1Service.delete(StringUtil.encodeUri(['projects', name])); - }, - - restoreProject: function (projectName) { - name = StringUtil.requireNotEmpty(projectName, 'projectName'); - return ApiV1Service.jsonPatch(StringUtil.encodeUri(['projects', name]), - EntitiesUtil.toReplaceJsonPatch('/status', 'active')); - } - }; - }); diff --git a/server/src/main/resources/webapp/scripts/components/entities/repository.service.js b/server/src/main/resources/webapp/scripts/components/entities/repository.service.js deleted file mode 100644 index f3438bfebd..0000000000 --- a/server/src/main/resources/webapp/scripts/components/entities/repository.service.js +++ /dev/null @@ -1,248 +0,0 @@ -'use strict'; - -angular.module('CentralDogmaAdmin') - .factory('RepositoryService', - function (ApiService, ApiV1Service, StringUtil, EntitiesUtil) { - return { - createRepository: function (projectName, repositoryName) { - projectName = StringUtil.requireNotEmpty(projectName, 'projectName'); - repositoryName = StringUtil.requireNotEmpty(repositoryName, 'repositoryName'); - - // NOTE: API v1 uses 'repos' instead of 'repositories'. - return ApiV1Service.post(StringUtil.encodeUri(['projects', projectName, 'repos']), - {name: repositoryName} - ); - }, - - removeRepository: function (projectName, repositoryName) { - projectName = StringUtil.requireNotEmpty(projectName, 'projectName'); - repositoryName = StringUtil.requireNotEmpty(repositoryName, 'repositoryName'); - - // NOTE: API v1 uses 'repos' instead of 'repositories'. - return ApiV1Service.delete(StringUtil.encodeUri(['projects', projectName, - 'repos', repositoryName])); - }, - - restoreRepository: function (projectName, repositoryName) { - projectName = StringUtil.requireNotEmpty(projectName, 'projectName'); - repositoryName = StringUtil.requireNotEmpty(repositoryName, 'repositoryName'); - - // NOTE: API v1 uses 'repos' instead of 'repositories'. - return ApiV1Service.jsonPatch(StringUtil.encodeUri(['projects', projectName, - 'repos', repositoryName]), - EntitiesUtil.toReplaceJsonPatch('/status', 'active')); - }, - - listRepositories: function (projectName) { - projectName = StringUtil.requireNotEmpty(projectName, 'projectName'); - - // NOTE: API v1 uses 'repos' instead of 'repositories'. - return ApiV1Service.get(StringUtil.encodeUri(['projects', projectName, 'repos'])); - }, - - normalizeRevision: function (projectName, repositoryName, revision) { - projectName = StringUtil.requireNotEmpty(projectName, 'projectName'); - repositoryName = StringUtil.requireNotEmpty(repositoryName, 'repositoryName'); - if (!angular.isNumber(revision)) { - revision = StringUtil.requireNotEmpty(revision, 'revision'); - } - - var sb = []; - sb.push('projects/'); - sb.push(StringUtil.encodeParam(projectName)); - sb.push('/repositories/'); - sb.push(StringUtil.encodeParam(repositoryName)); - sb.push('/revision/'); - sb.push(revision); - - return ApiService.get(sb.join('')); - }, - - getTree: function (projectName, repositoryName, revision, path) { - projectName = StringUtil.requireNotEmpty(projectName, 'projectName'); - repositoryName = StringUtil.requireNotEmpty(repositoryName, 'repositoryName'); - revision = StringUtil.requireNotEmpty(revision, 'revision'); - path = StringUtil.requireNotEmpty(path, 'path'); - - return ApiV1Service.get(StringUtil.encodeUri(['projects', projectName, - 'repos', repositoryName, - 'list', path]) + - "?revision=" + revision); - }, - - getFile: function (projectName, repositoryName, revision, query) { - projectName = StringUtil.requireNotEmpty(projectName, 'projectName'); - repositoryName = StringUtil.requireNotEmpty(repositoryName, 'repositoryName'); - revision = StringUtil.requireNotEmpty(revision, 'revision'); - - var path = StringUtil.requireNotEmpty(query.path, 'path'); - var queryType = StringUtil.defaultString(query.type, 'IDENTITY'); - var queryExpressions = angular.isArray(query.expressions) ? query.expressions : []; - - var sb = []; - sb.push('projects/'); - sb.push(StringUtil.encodeParam(projectName)); - sb.push('/repositories/'); - sb.push(StringUtil.encodeParam(repositoryName)); - sb.push('/files/revisions/'); - sb.push(revision); - sb.push(StringUtil.encodePath(path)); // path starts with '/' - - var params = ['queryType=' + queryType]; - if (angular.isArray(queryExpressions)) { - for (var idx in queryExpressions) { - params.push('&expression='); - params.push(StringUtil.encodeParam(queryExpressions[idx])); - } - } - - if (params.length > 0) { - sb.push('?'); - sb.push(params.join('')); - } - - return ApiService.get(sb.join('')); - }, - - addFile: function (projectName, repositoryName, revision, commitMessage, file) { - return this.saveFile(projectName, repositoryName, revision, commitMessage, file, 'ADD'); - }, - - editFile: function (projectName, repositoryName, revision, commitMessage, file) { - return this.saveFile(projectName, repositoryName, revision, commitMessage, file, 'EDIT'); - }, - - saveFile: function (projectName, repositoryName, revision, commitMessage, file, saveMode) { - projectName = StringUtil.requireNotEmpty(projectName, 'projectName'); - repositoryName = StringUtil.requireNotEmpty(repositoryName, 'repositoryName'); - revision = StringUtil.requireNotEmpty(revision, 'revision'); - - if (angular.isUndefined(file)) { - throw new Error('undefined file'); - } - if (angular.isUndefined(commitMessage)) { - throw new Error('undefined commitMessage'); - } - - var sb = []; - sb.push('projects/'); - sb.push(StringUtil.encodeParam(projectName)); - sb.push('/repositories/'); - sb.push(StringUtil.encodeParam(repositoryName)); - sb.push('/files/revisions/'); - sb.push(revision); - - switch (saveMode) { - case 'ADD': - return ApiService.post(sb.join(''), { - file: file, - commitMessage: commitMessage - }); - break; - case 'EDIT': - return ApiService.put(sb.join(''), { - file: file, - commitMessage: commitMessage - }); - break; - default: - throw new Error('unsupported saveMode' + saveMode); - } - }, - - deleteFile: function (projectName, repositoryName, revision, commitMessage, path) { - projectName = StringUtil.requireNotEmpty(projectName, 'projectName'); - repositoryName = StringUtil.requireNotEmpty(repositoryName, 'repositoryName'); - revision = StringUtil.requireNotEmpty(revision, 'revision'); - path = StringUtil.requireNotEmpty(path, 'path'); - - if (angular.isUndefined(commitMessage)) { - throw new Error('undefined commitMessage'); - } - - var sb = []; - sb.push('projects/'); - sb.push(StringUtil.encodeParam(projectName)); - sb.push('/repositories/'); - sb.push(StringUtil.encodeParam(repositoryName)); - sb.push('/delete/revisions/'); - sb.push(revision); - sb.push(StringUtil.encodePath(path)); // path starts with '/' - - return ApiService.post(sb.join(''), { - commitMessage: commitMessage - }); - }, - - getHistory: function (projectName, repositoryName, path, fromRevision, toRevision) { - projectName = StringUtil.requireNotEmpty(projectName, 'projectName'); - repositoryName = StringUtil.requireNotEmpty(repositoryName, 'repositoryName'); - path = StringUtil.requireNotEmpty(path, 'path'); - - if (!angular.isNumber(fromRevision)) { - fromRevision = StringUtil.requireNotEmpty(fromRevision, 'fromRevision'); - } - if (!angular.isNumber(toRevision)) { - toRevision = StringUtil.requireNotEmpty(toRevision, 'toRevision'); - } - - var sb = []; - sb.push('projects/'); - sb.push(StringUtil.encodeParam(projectName)); - sb.push('/repositories/'); - sb.push(StringUtil.encodeParam(repositoryName)); - sb.push('/history'); - sb.push(StringUtil.encodePath(path)); // path starts with '/' - sb.push("?from="); - sb.push(fromRevision); - sb.push("&to="); - sb.push(toRevision); - - return ApiService.get(sb.join('')); - }, - - search: function (projectName, repositoryName, revision, term) { - projectName = StringUtil.requireNotEmpty(projectName, 'projectName'); - repositoryName = StringUtil.requireNotEmpty(repositoryName, 'repositoryName'); - revision = StringUtil.requireNotEmpty(revision, 'revision'); - term = StringUtil.requireNotEmpty(term, 'term'); - - var sb = []; - sb.push('projects/'); - sb.push(StringUtil.encodeParam(projectName)); - sb.push('/repositories/'); - sb.push(StringUtil.encodeParam(repositoryName)); - sb.push('/search/revisions/'); - sb.push(revision); - sb.push('?term='); - sb.push(StringUtil.encodeParam(term)); - - return ApiService.get(sb.join('')); - }, - - parsePath: function (path) { - path = StringUtil.requireNotEmpty(path, 'path'); - - var ret = [{name: 'root', path: '/'}]; - - var split = path.split('/'); - for (var i = 0; i < split.length; i++) { - if (split[i] === '') { - continue; - } - - var temp = []; - for (var j = 0; j <= i; j++) { - temp.push(split[j]); - } - - ret.push({ - 'name': split[i], - 'path': temp.join('/') - }); - } - - return ret; - } - }; - }); diff --git a/server/src/main/resources/webapp/scripts/components/entities/settings.service.js b/server/src/main/resources/webapp/scripts/components/entities/settings.service.js deleted file mode 100644 index e940f1d9c5..0000000000 --- a/server/src/main/resources/webapp/scripts/components/entities/settings.service.js +++ /dev/null @@ -1,49 +0,0 @@ -'use strict'; - -angular.module('CentralDogmaAdmin') - .factory('SettingsService', - function (ApiV1Service, EntitiesUtil, $q) { - return { - listTokens: function () { - var defer = $q.defer(); - ApiV1Service.get("tokens").then(function (tokens) { - var i; - if (angular.isArray(tokens)) { - for (i in tokens) { - tokens[i].creationTimeStr = moment(tokens[i].creation.timestamp).fromNow(); - tokens[i].isActive = !angular.isDefined(tokens[i].deactivation); - tokens[i].isDeleted = angular.isDefined(tokens[i].deletion); - } - defer.resolve(tokens); - } else { - defer.resolve([]); - } - }, function (error) { - defer.reject(error); - }); - return defer.promise; - }, - - createToken: function (data) { - return ApiV1Service.post('tokens', data, { - headers: { - 'Content-Type': 'application/x-www-form-urlencoded' - } - }); - }, - - activateToken: function (id) { - return ApiV1Service.jsonPatch('tokens/' + id, - EntitiesUtil.toReplaceJsonPatch('/status', 'active')); - }, - - deactivateToken: function (id) { - return ApiV1Service.jsonPatch('tokens/' + id, - EntitiesUtil.toReplaceJsonPatch('/status', 'inactive')); - }, - - deleteToken: function (id) { - return ApiV1Service.delete('tokens/' + id); - } - }; - }); diff --git a/server/src/main/resources/webapp/scripts/components/language/language.controller.js b/server/src/main/resources/webapp/scripts/components/language/language.controller.js deleted file mode 100644 index e80ad1d98a..0000000000 --- a/server/src/main/resources/webapp/scripts/components/language/language.controller.js +++ /dev/null @@ -1,13 +0,0 @@ -'use strict'; - -angular.module('CentralDogmaAdmin') - .controller('LanguageController', - function ($scope, $translate, Language) { - $scope.changeLanguage = function (languageKey) { - $translate.use(languageKey); - }; - - Language.getAll().then(function (languages) { - $scope.languages = languages; - }); - }); diff --git a/server/src/main/resources/webapp/scripts/components/language/language.service.js b/server/src/main/resources/webapp/scripts/components/language/language.service.js deleted file mode 100644 index 995b7686fe..0000000000 --- a/server/src/main/resources/webapp/scripts/components/language/language.service.js +++ /dev/null @@ -1,32 +0,0 @@ -'use strict'; - -angular.module('CentralDogmaAdmin') - .factory('Language', - function ($q, $http, $translate, LANGUAGES) { - return { - getCurrent: function () { - var deferred = $q.defer(); - var language = $translate.storage().get('NG_TRANSLATE_LANG_KEY'); - - if (angular.isUndefined(language)) { - language = 'en'; - } - - deferred.resolve(language); - return deferred.promise; - }, - getAll: function () { - var deferred = $q.defer(); - deferred.resolve(LANGUAGES); - return deferred.promise; - } - }; - }) - /* - Languages codes are ISO_639-1 codes, see http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes - They are written in English to avoid character encoding issues (not a perfect solution) - */ - .constant('LANGUAGES', [ - 'en' - ] -); diff --git a/server/src/main/resources/webapp/scripts/components/navbar/navbar.controller.js b/server/src/main/resources/webapp/scripts/components/navbar/navbar.controller.js deleted file mode 100644 index b43d2f7b19..0000000000 --- a/server/src/main/resources/webapp/scripts/components/navbar/navbar.controller.js +++ /dev/null @@ -1,14 +0,0 @@ -'use strict'; - -angular.module('CentralDogmaAdmin') - .controller('NavbarController', - function ($scope, $rootScope, $state, $q, $uibModal, $window, - Title, Principal) { - - $scope.isAuthenticated = Principal.isAuthenticated; - - Title.get().then(function (data) { - $scope.title = data.title; - $scope.hostname = data.hostname; - }); - }); diff --git a/server/src/main/resources/webapp/scripts/components/navbar/navbar.directive.js b/server/src/main/resources/webapp/scripts/components/navbar/navbar.directive.js deleted file mode 100644 index 8cd68d9ae5..0000000000 --- a/server/src/main/resources/webapp/scripts/components/navbar/navbar.directive.js +++ /dev/null @@ -1,40 +0,0 @@ -'use strict'; - -angular.module('CentralDogmaAdmin') - .directive('activeMenu', function ($translate, $locale, tmhDynamicLocale) { - return { - restrict: 'A', - link: function (scope, element, attrs) { - var language = attrs.activeMenu; - - scope.$watch(function () { - return $translate.use(); - }, function (selectedLanguage) { - if (language === selectedLanguage) { - tmhDynamicLocale.set(language); - element.addClass('active'); - } else { - element.removeClass('active'); - } - }); - } - }; - }) - .directive('activeLink', function (location) { - return { - restrict: 'A', - link: function (scope, element, attrs) { - var clazz = attrs.activeLink; - var path = attrs.href; - path = path.substring(1); //hack because path does bot return including hashbang - scope.location = location; - scope.$watch('location.path()', function (newPath) { - if (path === newPath) { - element.addClass(clazz); - } else { - element.removeClass(clazz); - } - }); - } - }; - }); diff --git a/server/src/main/resources/webapp/scripts/components/navbar/navbar.html b/server/src/main/resources/webapp/scripts/components/navbar/navbar.html deleted file mode 100644 index 5ffd9b6d54..0000000000 --- a/server/src/main/resources/webapp/scripts/components/navbar/navbar.html +++ /dev/null @@ -1,46 +0,0 @@ - diff --git a/server/src/main/resources/webapp/scripts/components/title/title.service.js b/server/src/main/resources/webapp/scripts/components/title/title.service.js deleted file mode 100644 index d53c2753fe..0000000000 --- a/server/src/main/resources/webapp/scripts/components/title/title.service.js +++ /dev/null @@ -1,17 +0,0 @@ -'use strict'; - -angular.module('CentralDogmaAdmin') - .factory('Title', - function ($http, $q) { - return { - get: function() { - var deferred = $q.defer(); - $http.get('/title').then(function (response) { - deferred.resolve(response.data); - }, function (response) { - deferred.reject(response.status); - }); - return deferred.promise; - } - }; - }); diff --git a/server/src/main/resources/webapp/scripts/components/user/user.service.js b/server/src/main/resources/webapp/scripts/components/user/user.service.js deleted file mode 100644 index 083ab6612d..0000000000 --- a/server/src/main/resources/webapp/scripts/components/user/user.service.js +++ /dev/null @@ -1,11 +0,0 @@ -'use strict'; - -angular.module('CentralDogmaAdmin') - .factory('User', - function (ApiService) { - return { - get: function () { - return ApiService.get('users/me'); - } - }; - }); diff --git a/server/src/main/resources/webapp/scripts/components/util/ace-editor.directive.js b/server/src/main/resources/webapp/scripts/components/util/ace-editor.directive.js deleted file mode 100644 index b3a13ce3f4..0000000000 --- a/server/src/main/resources/webapp/scripts/components/util/ace-editor.directive.js +++ /dev/null @@ -1,211 +0,0 @@ -'use strict'; - -angular.module('CentralDogmaAdmin') - .directive('aceEditor', - function () { - return { - template: '
' + - '
' + - ' ' + - ' ' + - '
', - restrict: 'E', - scope: { - 'editorClass': '@class', - 'path': '=pathNgModel', - 'content': '=contentNgModel', - 'readonly': '=', - 'callback': '&' - }, - controller: function ($scope, $timeout, $translate, localStorageService) { - - // Load the theme list. - $scope.availableThemes = angular.copy(window.ace.require('ace/ext/themelist').themes); - $scope.defaultTheme = 'ace/theme/eclipse'; - - // Localize the theme type caption: - $translate('entities.light_themes').then(function (translated) { - for (var i in $scope.availableThemes) { - var t = $scope.availableThemes[i]; - if (!t.isDark) { - t.type = translated; - } - } - }); - $translate('entities.dark_themes').then(function (translated) { - for (var i in $scope.availableThemes) { - var t = $scope.availableThemes[i]; - if (t.isDark) { - t.type = translated; - } - } - }); - - // Define the keyboard handler list. - $scope.availableKeyboardHandlers = [ - { 'name': 'Ace', - 'value': 'default' }, - { 'name': 'Vim', - 'value': 'ace/keyboard/vim' }, - { 'name': 'Emacs', - 'value': 'ace/keyboard/emacs' } - ]; - $scope.defaultKeyboardHandler = $scope.availableKeyboardHandlers[0].value; - - // Add '(Default)' to the theme and keyboard handler captions. - $translate('entities.default_theme').then(function (translated) { - for (var i in $scope.availableThemes) { - var t = $scope.availableThemes[i]; - if (t.theme === $scope.defaultTheme) { - t.caption = t.caption + " (" + translated + ')'; - } - } - - for (var i in $scope.availableKeyboardHandlers) { - var h = $scope.availableKeyboardHandlers[i]; - if (h.value === $scope.defaultKeyboardHandler) { - h.name = h.name + " (" + translated + ')'; - break; - } - } - }); - - var KEY_ACE_PREFS = 'acePrefs'; - - // Configure the editor with the preferred theme and keyboard handler. - $scope.aceLoaded = function (editor) { - $scope.editor = editor; - - editor.$blockScrolling = Infinity; - editor.setShowInvisibles(true); - editor.setAnimatedScroll(true); - editor.setShowFoldWidgets(true); - editor.setShowPrintMargin(true); - editor.setPrintMarginColumn(112); - - $scope.loadPrefs(editor); - - var options = { - showGutter: true, - showLineNumbers: true - }; - - if ($scope.readonly) { - editor.setReadOnly(true); - } else { - options.enableBasicAutocompletion = true; - options.enableLiveAutocompletion = true; - } - - editor.setOptions(options); - - var session = editor.getSession(); - session.setUseWrapMode(true); - session.setUseSoftTabs(true); - session.setNewLineMode('unix'); - - var callback = $scope.callback; - if (typeof callback === 'function') { - callback = callback(); - if (typeof callback === 'function') { - callback(editor); - } - } - }; - - // Auto-detect the edit mode and tab size from the file path. - $scope.$watch('path', function (value) { - if (typeof $scope.editor === 'undefined' || typeof value !== 'string') { - return; - } - - var session = $scope.editor.getSession(); - var modelist = window.ace.require('ace/ext/modelist'); - var mode = modelist.getModeForPath(value).mode; - session.setMode(mode); - if (mode === 'ace/mode/json') { - session.setTabSize(2); - } else { - session.setTabSize(4); - } - }); - - // Loads the preferred theme and keyboard handler. - $scope.loadPrefs = function (editor) { - var prefs = localStorageService.get(KEY_ACE_PREFS); - - if (typeof prefs !== 'object' || prefs === null || - typeof prefs.theme !== 'string' || - typeof prefs.keyboardHandler !== 'string') { - prefs = { - theme: $scope.defaultTheme, - keyboardHandler: $scope.defaultKeyboardHandler - }; - } - - var themeSet = false; - for (var i in $scope.availableThemes) { - var t = $scope.availableThemes[i]; - if (prefs.theme === t.theme) { - editor.setTheme(prefs.theme); - $scope.theme = prefs.theme; - themeSet = true; - break; - } - } - - if (!themeSet) { - editor.setTheme($scope.defaultTheme); - $scope.theme = $scope.defaultTheme; - } - - var keyboardHandlerSet = false; - if (prefs.keyboardHandler !== 'default') { - for (var i in $scope.availableKeyboardHandlers) { - var h = $scope.availableKeyboardHandlers[i]; - if (prefs.keyboardHandler === h.value) { - editor.setKeyboardHandler(prefs.keyboardHandler); - $scope.keyboardHandler = prefs.keyboardHandler; - keyboardHandlerSet = true; - break; - } - } - } - - if (!keyboardHandlerSet) { - editor.setKeyboardHandler(editor.commands); - $scope.keyboardHandler = $scope.defaultKeyboardHandler; - } - }; - - // Update and save the preferred theme and keyboard handler. - $scope.updatePrefs = function () { - if (typeof $scope.editor === 'undefined') { - return; - } - - var editor = $scope.editor; - var theme = $scope.theme; - editor.setTheme(theme); - - var keyboardHandler = $scope.keyboardHandler; - if (keyboardHandler === $scope.defaultKeyboardHandler) { - editor.setKeyboardHandler(editor.commands); - } else { - editor.setKeyboardHandler(keyboardHandler); - } - - localStorageService.set(KEY_ACE_PREFS, - { theme: theme, keyboardHandler: keyboardHandler }); - }; - } - }; - }); diff --git a/server/src/main/resources/webapp/scripts/components/util/api.service.js b/server/src/main/resources/webapp/scripts/components/util/api.service.js deleted file mode 100644 index 7970bf714e..0000000000 --- a/server/src/main/resources/webapp/scripts/components/util/api.service.js +++ /dev/null @@ -1,102 +0,0 @@ -'use strict'; - -angular.module('CentralDogmaAdmin') - .factory('ApiService', function ($rootScope, $http, $q, $window, StringUtil, NotificationUtil, CentralDogmaConstant, Security) { - function makeRequest0(verb, uri, config, data) { - var sessionId; - var defer = $q.defer(); - - if (angular.isUndefined(config)) { - config = {} - } - - config.method = verb; - config.url = rewriteUri(uri); - - if ($rootScope.isSecurityEnabled) { - sessionId = $window.localStorage.getItem('sessionId'); - } else { - sessionId = "anonymous"; - } - if (sessionId !== null) { - if (angular.isUndefined(config.headers)) { - config.headers = {}; - } - config.headers.authorization = 'bearer ' + sessionId; - } - - if (angular.isDefined(data) && verb.match(/post|put|patch/)) { - config.data = data; - } - - $http(config).then(function (data) { - defer.resolve(data.data); - }, - function (error) { - var rejected = { - status: error.status, - statusText: error.statusText, - message: angular.isDefined(error.data.message) ? error.data.message : '', - exception: angular.isDefined(error.data.exception) ? error.data.exception : '' - }; - - var callback = defer.promise.$$state.pending; - if (callback && callback.length && typeof callback[0][2] !== 'function') { - NotificationUtil.error(rejected); - } - - defer.reject(rejected); - }); - - return defer.promise; - } - - function makeRequest(verb, uri, config, data) { - var defer; - - if (Security.isResolved()) { - return makeRequest0(verb, uri, config, data); - } - - defer = $q.defer(); - Security.resolve().then(function () { - makeRequest0(verb, uri, config, data).then(function (data) { - defer.resolve(data); - }, function (error) { - defer.reject(error); - } - ); - }); - return defer.promise; - } - - function rewriteUri(uri) { - if (uri.startsWith('/')) { - return uri; - } else { - return CentralDogmaConstant.API_PREFIX + uri; - } - } - - return { - get: function (uri, config) { - return makeRequest('get', uri, config); - }, - - post: function (uri, data, config) { - return makeRequest('post', uri, config, data); - }, - - put: function (uri, data, config) { - return makeRequest('put', uri, config, data); - }, - - patch: function (uri, data, config) { - return makeRequest('patch', uri, config, data); - }, - - delete: function (uri, config) { - return makeRequest('delete', uri, config); - } - }; - }); diff --git a/server/src/main/resources/webapp/scripts/components/util/api.v1.service.js b/server/src/main/resources/webapp/scripts/components/util/api.v1.service.js deleted file mode 100644 index 030fb491a0..0000000000 --- a/server/src/main/resources/webapp/scripts/components/util/api.v1.service.js +++ /dev/null @@ -1,91 +0,0 @@ -'use strict'; - -angular.module('CentralDogmaAdmin') - .factory('ApiV1Service', function ($rootScope, $http, $q, $window, StringUtil, NotificationUtil, - CentralDogmaConstant) { - function makeRequest(verb, uri, config, data) { - var sessionId; - var defer = $q.defer(); - - if (angular.isUndefined(config)) { - config = {} - } - - config.method = verb; - config.url = rewriteUri(uri); - - if ($rootScope.isSecurityEnabled) { - sessionId = $window.localStorage.getItem('sessionId'); - } else { - sessionId = "anonymous"; - } - if (sessionId !== null) { - if (angular.isUndefined(config.headers)) { - config.headers = {}; - } - config.headers.authorization = 'bearer ' + sessionId; - } - - if (angular.isDefined(data) && verb.match(/post|put|patch/)) { - config.data = data; - } - - $http(config).then(function (data) { - defer.resolve(data.data); - }, - function (error) { - var rejected = { - status: error.status, - statusText: error.statusText, - message: error.data.message - }; - - var callback = defer.promise.$$state.pending; - if (callback && callback.length && typeof callback[0][2] !== 'function') { - NotificationUtil.error(rejected); - } - - defer.reject(rejected); - }); - - return defer.promise; - } - - function rewriteUri(uri) { - if (uri.startsWith('/')) { - return uri; - } else { - return CentralDogmaConstant.API_V1_PREFIX + uri; - } - } - - return { - get: function (uri, config) { - return makeRequest('get', uri, config); - }, - - post: function (uri, data, config) { - return makeRequest('post', uri, config, data); - }, - - put: function (uri, data, config) { - return makeRequest('put', uri, config, data); - }, - - patch: function (uri, data, config) { - return makeRequest('patch', uri, config, data); - }, - - jsonPatch: function (uri, data) { - return makeRequest('patch', uri, { - headers: { - 'Content-Type': 'application/json-patch+json' - } - }, data); - }, - - delete: function (uri, config) { - return makeRequest('delete', uri, config); - } - }; - }); diff --git a/server/src/main/resources/webapp/scripts/components/util/confirmation-dialog.html b/server/src/main/resources/webapp/scripts/components/util/confirmation-dialog.html deleted file mode 100644 index 57bc0142fe..0000000000 --- a/server/src/main/resources/webapp/scripts/components/util/confirmation-dialog.html +++ /dev/null @@ -1,11 +0,0 @@ - - diff --git a/server/src/main/resources/webapp/scripts/components/util/confirmation-dialog.js b/server/src/main/resources/webapp/scripts/components/util/confirmation-dialog.js deleted file mode 100644 index 58e1bcb93a..0000000000 --- a/server/src/main/resources/webapp/scripts/components/util/confirmation-dialog.js +++ /dev/null @@ -1,68 +0,0 @@ -'use strict'; - -angular.module('CentralDogmaAdmin') - .factory('ConfirmationDialog', function ($uibModal, $translate, $q) { - return { - open: function (customModalDefaults, customModalOptions) { - const modalDefaults = { - backdrop: true, - keyboard: true, - modalFade: true, - templateUrl: 'scripts/components/util/confirmation-dialog.html' - }; - const modalOptions = { - text: 'Perform this action?' - }; - - //Create temp objects to work with since we're in a singleton service - var tempModalDefaults = {}; - var tempModalOptions = {}; - - //Map angular-ui modal custom defaults to modal defaults defined in service - angular.extend(tempModalDefaults, modalDefaults, customModalDefaults); - - //Map modal.html $scope custom properties to defaults defined in service - angular.extend(tempModalOptions, modalOptions, customModalOptions); - - if (!tempModalDefaults.controller) { - tempModalDefaults.controller = function ($scope, $uibModalInstance) { - $scope.modalOptions = tempModalOptions; - $scope.modalOptions.ok = function () { - $uibModalInstance.close(true); - }; - $scope.modalOptions.close = function () { - $uibModalInstance.close(false); - }; - } - } - return $uibModal.open(tempModalDefaults).result; - }, - - openModal: function (translateId, interpolateParams) { - const defer = $q.defer(); - const open = this.open; - $translate(translateId, interpolateParams).then(function (translated) { - return open({ - backdrop: 'static' - }, { - text: translated - }).then(function (result) { - if (result) { - defer.resolve(); - } - }); - }, function () { - return open({ - backdrop: 'static' - }, { - text: translateId - }).then(function (result) { - if (result) { - defer.resolve(); - } - }); - }); - return defer.promise; - } - } -}); diff --git a/server/src/main/resources/webapp/scripts/components/util/notification-util.service.js b/server/src/main/resources/webapp/scripts/components/util/notification-util.service.js deleted file mode 100644 index 6147ed7b4c..0000000000 --- a/server/src/main/resources/webapp/scripts/components/util/notification-util.service.js +++ /dev/null @@ -1,77 +0,0 @@ -'use strict'; - -angular.module('CentralDogmaAdmin') - .factory('NotificationUtil', - function ($translate, StringUtil, Notification) { - return { - success: function () { - if (arguments.length <= 0 || arguments.length > 2) { - return; - } - - var decoded = this.decodeArgs(arguments); - var translationId = decoded[0]; - var interpolateParams = decoded[1]; - - $translate(translationId, interpolateParams).then(function (translated) { - Notification.success(translated); - }, function () { - Notification.success(translationId); - }); - }, - error: function () { - if (arguments.length <= 0 || arguments.length > 2) { - return; - } - - var arg = arguments[0]; - if (typeof arg === 'object' && - typeof arg.status === 'number' && typeof arg.statusText === 'string') { - if (StringUtil.isNotEmpty(arg.message)) { - Notification.error(StringUtil.escapeHtml(arg.message)); - } else { - var message = arg.status + ' ' + arg.statusText; - if (arg.status === 401) { - // Ignore 401 status code. - } else if (arg.status === 403) { - // TODO(hyangtack) Refine the error message. - Notification.error('Permission denied'); - } else { - Notification.error(message); - } - } - return; - } - - var decoded = this.decodeArgs(arguments); - var translationId = decoded[0]; - var interpolateParams = decoded[1]; - - $translate(translationId, interpolateParams).then(function (translated) { - Notification.error(translated); - }, function () { - Notification.error(translationId); - }); - }, - decodeArgs: function (args) { - var translationId; - var interpolateParams; - if (args.length == 1) { - var arg = args[0]; - if (typeof arg === 'object' && - typeof arg.translationId === 'string' && typeof arg.interpolateParams === 'object') { - translationId = arg.translationId; - interpolateParams = arg.interpolateParams; - } else { - translationId = arg; - interpolateParams = {}; - } - } else { - translationId = args[0]; - interpolateParams = args[1]; - } - - return [ translationId, interpolateParams ]; - } - }; - }); diff --git a/server/src/main/resources/webapp/scripts/components/util/revision.directive.js b/server/src/main/resources/webapp/scripts/components/util/revision.directive.js deleted file mode 100644 index b091fbd2ef..0000000000 --- a/server/src/main/resources/webapp/scripts/components/util/revision.directive.js +++ /dev/null @@ -1,148 +0,0 @@ -'use strict'; - -angular.module('CentralDogmaAdmin') - .directive('revision', - function () { - return { - template: '' + - '', - restrict: 'E', - scope: { - project: '<', - repository: '<', - path: '<', - revision: '<', - showInitialCommit: '<', - callback: '&' - }, - controller: function ($scope, $timeout, RepositoryService) { - var maxCommits = 15; // The maximum number of adjacent commits to show. - - $scope.templateUrl = 'revisionPopoverTemplate.html'; - $scope.history = []; - - $scope.keyUp = function (event) { - if (event.keyCode === 13) { // return - $scope.callCallback($('#target-revision').val()); - } - }; - - $scope.callCallback = function (revision) { - if (angular.isNumber(revision)) { - if (revision === -1) { - $scope.callback()('head'); - } else { - $scope.callback()(parseInt(revision).toString()); - } - return; - } - - revision = revision.toString().toLowerCase(); - if (revision === 'head') { - $scope.callback()('head'); - return; - } - - var revisionAsInt = parseInt(revision); - if (Number.isNaN(revisionAsInt)) { - return; - } - - if (revisionAsInt === -1) { - $scope.callback()('head'); - return; - } - - $scope.callback()(revisionAsInt.toString()); - }; - - $scope.hasHistory = function () { - return $scope.history.length > 0; - }; - - var fetchHistory = function (fromRev) { - if (!angular.isDefined($scope.path)) { - return; - } - - var toRev = Math.max(1, fromRev - maxCommits + 1); - RepositoryService.getHistory($scope.project, $scope.repository, $scope.path, fromRev, - toRev).then(function (result) { - - if (!$scope.showInitialCommit && - result.length > 0 && result[result.length - 1].revision.major === 1) { - $scope.history = result.slice(0, result.length - 1); - } else { - $scope.history = result; - } - }); - }; - - // Focus the target-revision input field when it goes visible. - $scope.$watch(function() { - return angular.element('#target-revision').is(':visible'); - }, function () { - $timeout(function() { angular.element('#target-revision').focus(); }); - }); - - // Fetch the adjacent commits. - RepositoryService.normalizeRevision($scope.project, $scope.repository, -1).then(function (head) { - - var headRev = head.major; - var fromRev; - var revisionAsInt = parseInt($scope.revision); - if (Number.isNaN(revisionAsInt)) { - revisionAsInt = -1; - } - - if (revisionAsInt < 0) { - RepositoryService.normalizeRevision($scope.project, $scope.repository, revisionAsInt).then(function (normalized) { - var normalizedRev = normalized.major; - if (revisionAsInt !== -1) { - $scope.specifiedRevision = revisionAsInt; - } else { - $scope.specifiedRevision = 'HEAD'; - } - $scope.normalizedRevision = normalizedRev; - fetchHistory(Math.min(headRev, normalizedRev + (maxCommits >> 1))); - }); - } else { - $scope.specifiedRevision = revisionAsInt; - if (revisionAsInt === headRev) { - $scope.normalizedRevision = 'HEAD'; - } - fromRev = Math.min(headRev, revisionAsInt + (maxCommits >> 1)); - fetchHistory(fromRev); - } - }); - } - }; - }); diff --git a/server/src/main/resources/webapp/scripts/components/util/search.directive.js b/server/src/main/resources/webapp/scripts/components/util/search.directive.js deleted file mode 100644 index 9ab3feb116..0000000000 --- a/server/src/main/resources/webapp/scripts/components/util/search.directive.js +++ /dev/null @@ -1,37 +0,0 @@ -'use strict'; - -angular.module('CentralDogmaAdmin') - .directive('search', - function () { - return { - template: '
' + - '
' + - '
' + - '' + - '
', - restrict: 'E', - scope: { - project: '=', - repository: '=', - revision: '=', - term: '=' - }, - controller: function ($scope, $state) { - $scope.keyUp = function (event) { - if (event.keyCode === 13) { // return - $scope.search(); - } - }; - - $scope.search = function () { - $state.go('repositorySearch', { - projectName: $scope.project, - repositoryName: $scope.repository, - revision: $scope.revision, - term: $scope.term - }); - }; - } - }; - }); diff --git a/server/src/main/resources/webapp/scripts/components/util/string-util.service.js b/server/src/main/resources/webapp/scripts/components/util/string-util.service.js deleted file mode 100644 index be68cac7ed..0000000000 --- a/server/src/main/resources/webapp/scripts/components/util/string-util.service.js +++ /dev/null @@ -1,104 +0,0 @@ -'use strict'; - -angular.module('CentralDogmaAdmin') - .factory('StringUtil', - function () { - return { - isEmpty: function (value) { - if (value == null || value === 'undefined') { - return true; - } - - if (!angular.isString(value)) { - throw new Error('given value is not a string: ' + value); - } - - return value.length == 0; - }, - - isNotEmpty: function (value) { - return !this.isEmpty(value); - }, - - requireNotEmpty: function (value, message) { - if (this.isEmpty(value)) { - throw new Error(message); - } - return value; - }, - - defaultString: function (value, defaultValue) { - return this.isEmpty(value) ? defaultValue : value; - }, - - normalizePath: function (value) { - if (this.isEmpty(value)) { - return '/'; - } - - var temp = value.replace(/\/\/+/, '/'); - if (temp === '/') { - return temp; - } - - if (!this.startsWith(temp, '/')) { - temp = '/' + temp; - } - if (this.endsWith(temp, '/')) { - temp = temp.slice(0, -1); - } - - return temp; - }, - - startsWith: function (str, prefix) { - return str.indexOf(prefix) === 0; - }, - - endsWith: function (str, suffix) { - return str.match(suffix + '$') == suffix; - }, - - encodePath: function (str) { - var split = str.split('/'); - for (var index in split) { - split[index] = this.encodeParam(split[index]); - } - return split.join('/'); - }, - - encodeParam: function (str) { - return encodeURIComponent(str); - }, - - encodeUri: function (uriComponents) { - var uri = []; - uriComponents.forEach(function (uriComponent) { - uriComponent.split('/').filter(function (value) { - // This would replace '//' with '/' in the result URI. - return value.length > 0; - }).forEach(function (value) { - uri.push(encodeURIComponent(value)); - }) - }); - // Allow the first '/' and the last '/' of the string array. - var result = ''; - if (this.startsWith(uriComponents[0], '/')) { - result += '/'; - } - result += uri.join('/'); - if (this.endsWith(uriComponents[uriComponents.length - 1], '/')) { - result += '/'; - } - return result; - }, - escapeHtml: function(unsafe) { - return unsafe - .replace(/&/g, "&") - .replace(//g, ">") - .replace(/"/g, """) - .replace(/'/g, "'"); - } - }; - }); diff --git a/server/src/main/resources/webapp/scripts/components/util/truncate.filter.js b/server/src/main/resources/webapp/scripts/components/util/truncate.filter.js deleted file mode 100644 index 19965501e5..0000000000 --- a/server/src/main/resources/webapp/scripts/components/util/truncate.filter.js +++ /dev/null @@ -1,48 +0,0 @@ -'use strict'; - -angular.module('CentralDogmaAdmin') - .filter('characters', - function () { - return function (input, chars, breakOnWord) { - if (isNaN(chars)) { - return input; - } - if (chars <= 0) { - return ''; - } - if (input && input.length > chars) { - input = input.substring(0, chars); - - if (!breakOnWord) { - var lastspace = input.lastIndexOf(' '); - // Get last space - if (lastspace !== -1) { - input = input.substr(0, lastspace); - } - } else { - while (input.charAt(input.length - 1) === ' ') { - input = input.substr(0, input.length - 1); - } - } - return input + '...'; - } - return input; - }; - }) - .filter('words', function () { - return function (input, words) { - if (isNaN(words)) { - return input; - } - if (words <= 0) { - return ''; - } - if (input) { - var inputWords = input.split(/\s+/); - if (inputWords.length > words) { - input = inputWords.slice(0, words).join(' ') + '...'; - } - } - return input; - }; - }); diff --git a/server/src/main/resources/webapp/styles/main.css b/server/src/main/resources/webapp/styles/main.css deleted file mode 100644 index eacadb73bc..0000000000 --- a/server/src/main/resources/webapp/styles/main.css +++ /dev/null @@ -1,254 +0,0 @@ -body { - background: #FAFAFA; - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - color: #333; -} - -/* ========================================================================== -Hide ng-cloak on page load, https://docs.angularjs.org/api/ng/directive/ngCloak -========================================================================== */ -[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak { - display: none !important; -} - -/* ========================================================================== -Development Ribbon -========================================================================== */ -.development { - position: absolute; - width: 149px; - height: 149px; - top: 0; - left: 0; - border: 0; - z-index: 1000; - background-image: url("../images/development_ribbon.png"); - background-position: center center; - background-repeat: no-repeat; -} - -/* ========================================================================== -Version number in navbar -========================================================================== */ -.navbar-version { - font-size: 10px; - color: #CCC -} - -/* ========================================================================== -Browser Upgrade Prompt -========================================================================== */ -.browserupgrade { - margin: 0.2em 0; - background: #CCC; - color: #000; - padding: 0.2em 0; -} - -.hero-unit { - margin: 50px auto 0 auto; - width: 300px; - font-size: 18px; - font-weight: 200; - line-height: 30px; - background-color: #EEE; - border-radius: 6px; - padding: 60px; -} - -.hero-unit h1 { - font-size: 60px; - line-height: 1; - letter-spacing: -1px; -} - -.error { - color: white; - background-color: red; -} - -.hand { - cursor: pointer; -} - -#threadDump .popover, #healthCheck .popover { - top: inherit; - display: block; - font-size: 10px; - max-width: 1024px; -} - -#healthCheck .popover { - margin-left: -50px; -} - -.health-details { - min-width: 400px; -} - -.alert .popover pre { - font-size: 10px; -} - -.voffset { - margin-top: 2px; -} - -.voffset1 { - margin-top: 5px; -} - -.voffset2 { - margin-top: 10px; -} - -.voffset3 { - margin-top: 15px; -} - -.voffset4 { - margin-top: 30px; -} - -.voffset5 { - margin-top: 40px; -} - -.voffset6 { - margin-top: 60px; -} - -.voffset7 { - margin-top: 80px; -} - -.voffset8 { - margin-top: 100px; -} - -.voffset9 { - margin-top: 150px; -} - -/* start Password strength bar style */ -ul#strength { - display: inline; - list-style: none; - margin: 0; - margin-left: 15px; - padding: 0; - vertical-align: 2px; -} - -.point:last { - margin: 0 !important; -} - -.point { - background: #DDD; - border-radius: 2px; - display: inline-block; - height: 5px; - margin-right: 1px; - width: 20px; -} - -/* end Password strength bar style */ - -.gridStyle { - border: 1px solid rgb(212, 212, 212); - width: 100%; - height: 100% -} - -.ngCell { - display: table-cell; - height: auto !important; - overflow-y: visible; - position: static; -} - -.ngRow { - display: table-row; - height: auto !important; - position: static; -} - -.ngCellText { - height: auto !important; - white-space: normal; - overflow-y: visible; -} - -.ngViewport.ng-scope { - height: auto !important; -} - -.pointer { - cursor: pointer; -} - -.diffDeletedLine { - background-color: #FDD; -} - -.diffAddedLine { - background-color: #DFD; -} - -[ng-click], -[data-ng-click], -[x-ng-click] { - cursor: pointer; -} - -.top-buffer { - margin-top: 10px; -} - -.file-area { - width: 100%; - height: 500px; -} - -.ace-prefs { - float: right; - margin-top: -40px; - padding-right: 24px; - position: relative; - z-index: 10; -} - -/* Increase the maximum width of the angular-ui-bootstrap popover */ -.popover { - max-width: 320px; /* optional max width */ - width: intrinsic; /* Safari/WebKit uses a non-standard name */ - width: -moz-max-content; /* Firefox/Gecko */ - width: -webkit-max-content; /* Chrome */ -} - -/* Increase the maximum width of the angular-ui-bootstrap tooltip */ -.tooltip-inner { - max-width: 320px; /* optional max width */ - width: intrinsic; /* Safari/WebKit uses a non-standard name */ - width: -moz-max-content; /* Firefox/Gecko */ - width: -webkit-max-content; /* Chrome */ - - /* And left-align the tooltip text */ - text-align: left; - /* And allow multiline tooltip text */ - white-space: pre-wrap; -} - -/* Do not display bullets for the commit list in the revision popover. */ -.commits ul { - list-style-type: none; - padding-left: 0; -} - -/* Ensure the commit list in the revision popover form is single-lined. */ -.commits li { - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -}