Merge branch 'main' into Issue/3989

# Conflicts:
#	src/app/community-list-page/community-list/community-list.component.html
This commit is contained in:
Oscar Chacón
2025-05-02 16:59:10 -06:00
76 changed files with 256 additions and 225 deletions

157
package-lock.json generated
View File

@@ -20,7 +20,7 @@
"@angular/platform-browser-dynamic": "^18.2.12", "@angular/platform-browser-dynamic": "^18.2.12",
"@angular/platform-server": "^18.2.12", "@angular/platform-server": "^18.2.12",
"@angular/router": "^18.2.12", "@angular/router": "^18.2.12",
"@angular/ssr": "^18.2.18", "@angular/ssr": "^18.2.19",
"@babel/runtime": "7.27.0", "@babel/runtime": "7.27.0",
"@kolkov/ngx-gallery": "^2.0.1", "@kolkov/ngx-gallery": "^2.0.1",
"@ng-bootstrap/ng-bootstrap": "^12.0.0", "@ng-bootstrap/ng-bootstrap": "^12.0.0",
@@ -35,7 +35,7 @@
"@terraformer/wkt": "^2.2.1", "@terraformer/wkt": "^2.2.1",
"altcha": "^0.9.0", "altcha": "^0.9.0",
"angulartics2": "^12.2.0", "angulartics2": "^12.2.0",
"axios": "^1.8.4", "axios": "^1.9.0",
"bootstrap": "^5.3", "bootstrap": "^5.3",
"cerialize": "0.1.18", "cerialize": "0.1.18",
"cli-progress": "^3.12.0", "cli-progress": "^3.12.0",
@@ -86,7 +86,7 @@
}, },
"devDependencies": { "devDependencies": {
"@angular-builders/custom-webpack": "~18.0.0", "@angular-builders/custom-webpack": "~18.0.0",
"@angular-devkit/build-angular": "^18.2.18", "@angular-devkit/build-angular": "^18.2.19",
"@angular-eslint/builder": "^18.4.1", "@angular-eslint/builder": "^18.4.1",
"@angular-eslint/bundled-angular-compiler": "^18.4.1", "@angular-eslint/bundled-angular-compiler": "^18.4.1",
"@angular-eslint/eslint-plugin": "^18.4.1", "@angular-eslint/eslint-plugin": "^18.4.1",
@@ -94,7 +94,7 @@
"@angular-eslint/schematics": "^18.4.1", "@angular-eslint/schematics": "^18.4.1",
"@angular-eslint/template-parser": "^18.4.1", "@angular-eslint/template-parser": "^18.4.1",
"@angular-eslint/utils": "^18.4.1", "@angular-eslint/utils": "^18.4.1",
"@angular/cli": "^18.2.18", "@angular/cli": "^18.2.19",
"@angular/compiler-cli": "^18.2.12", "@angular/compiler-cli": "^18.2.12",
"@angular/language-service": "^18.2.12", "@angular/language-service": "^18.2.12",
"@cypress/schematic": "^1.5.0", "@cypress/schematic": "^1.5.0",
@@ -150,7 +150,7 @@
"postcss-loader": "^4.0.3", "postcss-loader": "^4.0.3",
"postcss-preset-env": "^7.4.2", "postcss-preset-env": "^7.4.2",
"rimraf": "^3.0.2", "rimraf": "^3.0.2",
"sass": "~1.86.3", "sass": "~1.87.0",
"sass-loader": "^12.6.0", "sass-loader": "^12.6.0",
"sass-resources-loader": "^2.2.5", "sass-resources-loader": "^2.2.5",
"ts-node": "^8.10.2", "ts-node": "^8.10.2",
@@ -266,13 +266,13 @@
} }
}, },
"node_modules/@angular-devkit/architect": { "node_modules/@angular-devkit/architect": {
"version": "0.1802.18", "version": "0.1802.19",
"resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1802.18.tgz", "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1802.19.tgz",
"integrity": "sha512-3OitvTddHp7bSqEGOJlH7Zqv07DdmZHktU2jsekjcbUxmoC1WIpWSYy+Bqyu7HjidJc0xVP7wyE/NPYkrwT5SA==", "integrity": "sha512-M4B1tzxGX1nWCZr9GMM8OO0yBJO2HFSdK8M8P74vEFQfKIeq3y16IQ5zlEveJrkCOFVtmlIy2C9foMCdNyBRMA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@angular-devkit/core": "18.2.18", "@angular-devkit/core": "18.2.19",
"rxjs": "7.8.1" "rxjs": "7.8.1"
}, },
"engines": { "engines": {
@@ -291,17 +291,17 @@
} }
}, },
"node_modules/@angular-devkit/build-angular": { "node_modules/@angular-devkit/build-angular": {
"version": "18.2.18", "version": "18.2.19",
"resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-18.2.18.tgz", "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-18.2.19.tgz",
"integrity": "sha512-yNw5b46BB27YW2lgP9pAt15xtfTS8F1JdWR79bLci0MYL7VPmRBrRtZk+sozRCziit1+oNAVpOUT8QyvDmvAZA==", "integrity": "sha512-xwY7v+nGE7TXOc4pgY6u57bLzIPSHuecosYr3TiWHAl9iEcKHzkCCFKsLZyunohHmq/i1uA6g3cC6iwp2xNYyg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@ampproject/remapping": "2.3.0", "@ampproject/remapping": "2.3.0",
"@angular-devkit/architect": "0.1802.18", "@angular-devkit/architect": "0.1802.19",
"@angular-devkit/build-webpack": "0.1802.18", "@angular-devkit/build-webpack": "0.1802.19",
"@angular-devkit/core": "18.2.18", "@angular-devkit/core": "18.2.19",
"@angular/build": "18.2.18", "@angular/build": "18.2.19",
"@babel/core": "7.26.10", "@babel/core": "7.26.10",
"@babel/generator": "7.26.10", "@babel/generator": "7.26.10",
"@babel/helper-annotate-as-pure": "7.25.9", "@babel/helper-annotate-as-pure": "7.25.9",
@@ -312,7 +312,7 @@
"@babel/preset-env": "7.26.9", "@babel/preset-env": "7.26.9",
"@babel/runtime": "7.26.10", "@babel/runtime": "7.26.10",
"@discoveryjs/json-ext": "0.6.1", "@discoveryjs/json-ext": "0.6.1",
"@ngtools/webpack": "18.2.18", "@ngtools/webpack": "18.2.19",
"ansi-colors": "4.1.3", "ansi-colors": "4.1.3",
"autoprefixer": "10.4.20", "autoprefixer": "10.4.20",
"babel-loader": "9.1.3", "babel-loader": "9.1.3",
@@ -322,7 +322,7 @@
"css-loader": "7.1.2", "css-loader": "7.1.2",
"esbuild-wasm": "0.23.0", "esbuild-wasm": "0.23.0",
"fast-glob": "3.3.2", "fast-glob": "3.3.2",
"http-proxy-middleware": "3.0.3", "http-proxy-middleware": "3.0.5",
"https-proxy-agent": "7.0.5", "https-proxy-agent": "7.0.5",
"istanbul-lib-instrument": "6.0.3", "istanbul-lib-instrument": "6.0.3",
"jsonc-parser": "3.3.1", "jsonc-parser": "3.3.1",
@@ -418,13 +418,13 @@
} }
}, },
"node_modules/@angular-devkit/build-angular/node_modules/@angular-devkit/build-webpack": { "node_modules/@angular-devkit/build-angular/node_modules/@angular-devkit/build-webpack": {
"version": "0.1802.18", "version": "0.1802.19",
"resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1802.18.tgz", "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1802.19.tgz",
"integrity": "sha512-xSiUC2EeELKgs70aceet/iK57y2nk6VobgeeQzGzTtE5HXWX0n5/g9FIOVM1rznv/tj+9VFZpQKCdLqiP7JmCQ==", "integrity": "sha512-axz1Sasn+c+GJpJexBL+B3Rh1w3wJrQq8k8gkniodjJ594p4ti2qGk7i9Tj8A4cXx5fGY+EpuZvKfI/9Tr7QwA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@angular-devkit/architect": "0.1802.18", "@angular-devkit/architect": "0.1802.19",
"rxjs": "7.8.1" "rxjs": "7.8.1"
}, },
"engines": { "engines": {
@@ -491,23 +491,6 @@
"node": ">=6.9.0" "node": ">=6.9.0"
} }
}, },
"node_modules/@angular-devkit/build-angular/node_modules/@ngtools/webpack": {
"version": "18.2.18",
"resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-18.2.18.tgz",
"integrity": "sha512-rFTf3zrAMp7KJF8F/sOn0SNits+HhRaNKw4g20Pxk4QG5XZsXChsQIKrrzAnmlCfMb3nQmBnElAhr1rvBmzZWQ==",
"dev": true,
"license": "MIT",
"engines": {
"node": "^18.19.1 || ^20.11.1 || >=22.0.0",
"npm": "^6.11.0 || ^7.5.6 || >=8.0.0",
"yarn": ">= 1.13.0"
},
"peerDependencies": {
"@angular/compiler-cli": "^18.0.0",
"typescript": ">=5.4 <5.6",
"webpack": "^5.54.0"
}
},
"node_modules/@angular-devkit/build-angular/node_modules/@types/retry": { "node_modules/@angular-devkit/build-angular/node_modules/@types/retry": {
"version": "0.12.2", "version": "0.12.2",
"resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.2.tgz", "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.2.tgz",
@@ -711,10 +694,11 @@
} }
}, },
"node_modules/@angular-devkit/build-angular/node_modules/http-proxy-middleware": { "node_modules/@angular-devkit/build-angular/node_modules/http-proxy-middleware": {
"version": "3.0.3", "version": "3.0.5",
"resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-3.0.3.tgz", "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-3.0.5.tgz",
"integrity": "sha512-usY0HG5nyDUwtqpiZdETNbmKtw3QQ1jwYFZ9wi5iHzX2BcILwQKtYDJPo7XHTsu5Z0B2Hj3W9NNnbd+AjFWjqg==", "integrity": "sha512-GLZZm1X38BPY4lkXA01jhwxvDoOkkXqjgVyUzVxiEK4iuRu03PZoYHhHRwxnfhQMDuaxi3vVri0YgSro/1oWqg==",
"dev": true, "dev": true,
"license": "MIT",
"dependencies": { "dependencies": {
"@types/http-proxy": "^1.17.15", "@types/http-proxy": "^1.17.15",
"debug": "^4.3.6", "debug": "^4.3.6",
@@ -757,6 +741,7 @@
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz",
"integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==",
"dev": true, "dev": true,
"license": "MIT",
"engines": { "engines": {
"node": ">=0.10.0" "node": ">=0.10.0"
} }
@@ -1100,9 +1085,9 @@
} }
}, },
"node_modules/@angular-devkit/build-angular/node_modules/webpack-dev-server/node_modules/http-proxy-middleware": { "node_modules/@angular-devkit/build-angular/node_modules/webpack-dev-server/node_modules/http-proxy-middleware": {
"version": "2.0.8", "version": "2.0.9",
"resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.8.tgz", "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.9.tgz",
"integrity": "sha512-/iazaeFPmL8KLA6QB7DFAU4O5j+9y/TA0D019MbLtPuFI56VK4BXFzM6j6QS9oGpScy8IIDH4S2LHv3zg/63Bw==", "integrity": "sha512-c1IyJYLYppU574+YI7R4QyX2ystMtVXZwIdzazUIPIJsHuWNd+mho2j+bKoHftndicGj9yh+xjd+l0yj7VeT1Q==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@@ -1166,9 +1151,9 @@
} }
}, },
"node_modules/@angular-devkit/core": { "node_modules/@angular-devkit/core": {
"version": "18.2.18", "version": "18.2.19",
"resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-18.2.18.tgz", "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-18.2.19.tgz",
"integrity": "sha512-gncn8QN73mi4in7oAfoWnJglLx5iI8d87796h1LTuAxULSkfzhW3E03NZU764FBiIAWFxuty4PWmrHxMlmbtbw==", "integrity": "sha512-Ptf92Zomc6FCr7GWmHKdgOUbA1GpctZwH/hRcpYpU3tM56MG2t5FOFpufnE595GgolOCktabkFEoODMG8PBVDQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@@ -1203,13 +1188,13 @@
} }
}, },
"node_modules/@angular-devkit/schematics": { "node_modules/@angular-devkit/schematics": {
"version": "18.2.18", "version": "18.2.19",
"resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-18.2.18.tgz", "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-18.2.19.tgz",
"integrity": "sha512-i7dy3x32Z8+lmVMKlKHdrSuCya5hUP24BOUn5lXKFAFGcJC0JT30OJrDPqQMA2RzNQiiyacPhxaCdLloEFVh3Q==", "integrity": "sha512-P/0KjkzOf2ZShuShx3cBbjLI7XlcS6B/yCRBo1MQfCC4cZfmzPQoUEOSQeYZgy5pnC24f+dKh/+TWc5uYL/Lvg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@angular-devkit/core": "18.2.18", "@angular-devkit/core": "18.2.19",
"jsonc-parser": "3.3.1", "jsonc-parser": "3.3.1",
"magic-string": "0.30.11", "magic-string": "0.30.11",
"ora": "5.4.1", "ora": "5.4.1",
@@ -1341,14 +1326,14 @@
} }
}, },
"node_modules/@angular/build": { "node_modules/@angular/build": {
"version": "18.2.18", "version": "18.2.19",
"resolved": "https://registry.npmjs.org/@angular/build/-/build-18.2.18.tgz", "resolved": "https://registry.npmjs.org/@angular/build/-/build-18.2.19.tgz",
"integrity": "sha512-8PEhrkS1t9xpvBLaLVgi0OWt/0B72ENKKVc6BAKEZ5gg+SD7uf47sJcT1d23r7d/V6FaOJnWim6BrqgFs4rW9A==", "integrity": "sha512-dTqR+mhcZWtCRyOafvzHNVpYxMQnt8HHHqNM0kyEMzcztXL2L9zDlKr0H9d+AgGGq/v4qwCh+1gFDxsHByZwMQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@ampproject/remapping": "2.3.0", "@ampproject/remapping": "2.3.0",
"@angular-devkit/architect": "0.1802.18", "@angular-devkit/architect": "0.1802.19",
"@babel/core": "7.25.2", "@babel/core": "7.25.2",
"@babel/helper-annotate-as-pure": "7.24.7", "@babel/helper-annotate-as-pure": "7.24.7",
"@babel/helper-split-export-declaration": "7.24.7", "@babel/helper-split-export-declaration": "7.24.7",
@@ -1814,9 +1799,9 @@
} }
}, },
"node_modules/@angular/build/node_modules/@types/node": { "node_modules/@angular/build/node_modules/@types/node": {
"version": "22.14.0", "version": "22.15.3",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.14.0.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.3.tgz",
"integrity": "sha512-Kmpl+z84ILoG+3T/zQFyAJsU6EPTmOCj8/2+83fSN6djd6I4o7uOuGIH6vq3PrjY5BGitSbFuMN18j3iknubbA==", "integrity": "sha512-lX7HFZeHf4QG/J7tBZqrCAXwz9J5RD56Y6MpP0eJkka8p+K0RY/yBTW7CYFJ4VGCclxqOLKmiGP5juQc6MKgcw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
@@ -1873,9 +1858,9 @@
"peer": true "peer": true
}, },
"node_modules/@angular/build/node_modules/vite": { "node_modules/@angular/build/node_modules/vite": {
"version": "5.4.17", "version": "5.4.18",
"resolved": "https://registry.npmjs.org/vite/-/vite-5.4.17.tgz", "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.18.tgz",
"integrity": "sha512-5+VqZryDj4wgCs55o9Lp+p8GE78TLVg0lasCH5xFZ4jacZjtqZa6JUw9/p0WeAojaOfncSM6v77InkFPGnvPvg==", "integrity": "sha512-1oDcnEp3lVyHCuQ2YFelM4Alm2o91xNoMncRm1U7S+JdYfYOvbiGZ3/CxGttrOu2M/KcGz7cRC2DoNUA6urmMA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@@ -1988,18 +1973,18 @@
} }
}, },
"node_modules/@angular/cli": { "node_modules/@angular/cli": {
"version": "18.2.18", "version": "18.2.19",
"resolved": "https://registry.npmjs.org/@angular/cli/-/cli-18.2.18.tgz", "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-18.2.19.tgz",
"integrity": "sha512-UwwI03FVvTHbb9kgR9D0HdLajxsVm1jYkcWMfbSMnQGYM1qy1EWj9HvGnfIoQxAEzA8aeQbmsn9+h3w6MQmyCg==", "integrity": "sha512-LGVMTc36JQuw8QX8Sclxyei306EQW3KslopXbf7cfqt6D5/fHS+FqqA0O7V8ob/vOGMca+l6hQD27nW5Y3W6pA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@angular-devkit/architect": "0.1802.18", "@angular-devkit/architect": "0.1802.19",
"@angular-devkit/core": "18.2.18", "@angular-devkit/core": "18.2.19",
"@angular-devkit/schematics": "18.2.18", "@angular-devkit/schematics": "18.2.19",
"@inquirer/prompts": "5.3.8", "@inquirer/prompts": "5.3.8",
"@listr2/prompt-adapter-inquirer": "2.0.15", "@listr2/prompt-adapter-inquirer": "2.0.15",
"@schematics/angular": "18.2.18", "@schematics/angular": "18.2.19",
"@yarnpkg/lockfile": "1.1.0", "@yarnpkg/lockfile": "1.1.0",
"ini": "4.1.3", "ini": "4.1.3",
"jsonc-parser": "3.3.1", "jsonc-parser": "3.3.1",
@@ -2247,9 +2232,9 @@
} }
}, },
"node_modules/@angular/ssr": { "node_modules/@angular/ssr": {
"version": "18.2.18", "version": "18.2.19",
"resolved": "https://registry.npmjs.org/@angular/ssr/-/ssr-18.2.18.tgz", "resolved": "https://registry.npmjs.org/@angular/ssr/-/ssr-18.2.19.tgz",
"integrity": "sha512-WJ56mpiRGp18vcSH4jFHWR6dylBtUk3QOz+RQhuqYFPAfKk2YXEH5BiBXcjNicW5tIxaU8NlHfZVwWHQyEjpiA==", "integrity": "sha512-kMNPWZiLGhtrXFwQpDn1laKXxwMpaiXVajpDT7m/yQkyKMH5EbyZASFcyDHK6EsRV2LQsPaXeKzeQof/C1zNcw==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"critters": "0.0.24", "critters": "0.0.24",
@@ -6975,14 +6960,14 @@
"dev": true "dev": true
}, },
"node_modules/@schematics/angular": { "node_modules/@schematics/angular": {
"version": "18.2.18", "version": "18.2.19",
"resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-18.2.18.tgz", "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-18.2.19.tgz",
"integrity": "sha512-ko5KmtCZz8SqZLKrNeqMauS2LPHBKf7mT01waoOD1uN2gQkSIiLzDEYuXOaIarG6VnxAy5pL6NjkD+EmPsH6eg==", "integrity": "sha512-s9aynH/fwB/LT94miVfsaL2C4Qd5BLgjMzWFx7iJ8Hyv7FjOBGYO6eGVovjCt2c6/abG+GQAk4EBOCfg3AUtCA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@angular-devkit/core": "18.2.18", "@angular-devkit/core": "18.2.19",
"@angular-devkit/schematics": "18.2.18", "@angular-devkit/schematics": "18.2.19",
"jsonc-parser": "3.3.1" "jsonc-parser": "3.3.1"
}, },
"engines": { "engines": {
@@ -8847,9 +8832,9 @@
} }
}, },
"node_modules/axios": { "node_modules/axios": {
"version": "1.8.4", "version": "1.9.0",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.8.4.tgz", "resolved": "https://registry.npmjs.org/axios/-/axios-1.9.0.tgz",
"integrity": "sha512-eBSYY4Y68NNlHbHBMdeDmKNtDgXWhQsJcGqzO3iLUM0GraQFSS9cVgPX5I9b3lbdFKyYoAEGAZF1DwhTaljNAw==", "integrity": "sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"follow-redirects": "^1.15.6", "follow-redirects": "^1.15.6",
@@ -11077,9 +11062,9 @@
} }
}, },
"node_modules/detect-libc": { "node_modules/detect-libc": {
"version": "2.0.3", "version": "2.0.4",
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz",
"integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", "integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==",
"dev": true, "dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"engines": { "engines": {
@@ -20694,9 +20679,9 @@
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
}, },
"node_modules/sass": { "node_modules/sass": {
"version": "1.86.3", "version": "1.87.0",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.86.3.tgz", "resolved": "https://registry.npmjs.org/sass/-/sass-1.87.0.tgz",
"integrity": "sha512-iGtg8kus4GrsGLRDLRBRHY9dNVA78ZaS7xr01cWnS7PEMQyFtTqBiyCrfpTYTZXRWM94akzckYjh8oADfFNTzw==", "integrity": "sha512-d0NoFH4v6SjEK7BoX810Jsrhj7IQSYHAHLi/iSpgqKc7LaIDshFRlSg5LOymf9FqQhxEHs2W5ZQXlvy0KD45Uw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {

View File

@@ -102,7 +102,7 @@
"@angular/platform-browser-dynamic": "^18.2.12", "@angular/platform-browser-dynamic": "^18.2.12",
"@angular/platform-server": "^18.2.12", "@angular/platform-server": "^18.2.12",
"@angular/router": "^18.2.12", "@angular/router": "^18.2.12",
"@angular/ssr": "^18.2.18", "@angular/ssr": "^18.2.19",
"@babel/runtime": "7.27.0", "@babel/runtime": "7.27.0",
"@kolkov/ngx-gallery": "^2.0.1", "@kolkov/ngx-gallery": "^2.0.1",
"@ng-bootstrap/ng-bootstrap": "^12.0.0", "@ng-bootstrap/ng-bootstrap": "^12.0.0",
@@ -117,7 +117,7 @@
"@terraformer/wkt": "^2.2.1", "@terraformer/wkt": "^2.2.1",
"altcha": "^0.9.0", "altcha": "^0.9.0",
"angulartics2": "^12.2.0", "angulartics2": "^12.2.0",
"axios": "^1.8.4", "axios": "^1.9.0",
"bootstrap": "^5.3", "bootstrap": "^5.3",
"cerialize": "0.1.18", "cerialize": "0.1.18",
"cli-progress": "^3.12.0", "cli-progress": "^3.12.0",
@@ -168,7 +168,7 @@
}, },
"devDependencies": { "devDependencies": {
"@angular-builders/custom-webpack": "~18.0.0", "@angular-builders/custom-webpack": "~18.0.0",
"@angular-devkit/build-angular": "^18.2.18", "@angular-devkit/build-angular": "^18.2.19",
"@angular-eslint/builder": "^18.4.1", "@angular-eslint/builder": "^18.4.1",
"@angular-eslint/bundled-angular-compiler": "^18.4.1", "@angular-eslint/bundled-angular-compiler": "^18.4.1",
"@angular-eslint/eslint-plugin": "^18.4.1", "@angular-eslint/eslint-plugin": "^18.4.1",
@@ -176,7 +176,7 @@
"@angular-eslint/schematics": "^18.4.1", "@angular-eslint/schematics": "^18.4.1",
"@angular-eslint/template-parser": "^18.4.1", "@angular-eslint/template-parser": "^18.4.1",
"@angular-eslint/utils": "^18.4.1", "@angular-eslint/utils": "^18.4.1",
"@angular/cli": "^18.2.18", "@angular/cli": "^18.2.19",
"@angular/compiler-cli": "^18.2.12", "@angular/compiler-cli": "^18.2.12",
"@angular/language-service": "^18.2.12", "@angular/language-service": "^18.2.12",
"@cypress/schematic": "^1.5.0", "@cypress/schematic": "^1.5.0",
@@ -232,7 +232,7 @@
"postcss-loader": "^4.0.3", "postcss-loader": "^4.0.3",
"postcss-preset-env": "^7.4.2", "postcss-preset-env": "^7.4.2",
"rimraf": "^3.0.2", "rimraf": "^3.0.2",
"sass": "~1.86.3", "sass": "~1.87.0",
"sass-loader": "^12.6.0", "sass-loader": "^12.6.0",
"sass-resources-loader": "^2.2.5", "sass-resources-loader": "^2.2.5",
"ts-node": "^8.10.2", "ts-node": "^8.10.2",

View File

@@ -12,7 +12,7 @@
} }
<ng-template #breadcrumb let-text="text" let-url="url"> <ng-template #breadcrumb let-text="text" let-url="url">
<li class="breadcrumb-item"><div class="breadcrumb-item-limiter"><a [routerLink]="url" class="text-truncate" [ngbTooltip]="text | translate" placement="bottom" >{{text | translate}}</a></div></li> <li class="breadcrumb-item"><div class="breadcrumb-item-limiter"><a [routerLink]="url" class="text-truncate" [ngbTooltip]="text | translate" placement="bottom" role="link" tabindex="0">{{text | translate}}</a></div></li>
</ng-template> </ng-template>
<ng-template #activeBreadcrumb let-text="text"> <ng-template #activeBreadcrumb let-text="text">

View File

@@ -20,6 +20,8 @@
<a class="btn btn-primary" <a class="btn btn-primary"
[routerLink]="['/search']" [routerLink]="['/search']"
[queryParams]="queryParams" [queryParams]="queryParams"
[queryParamsHandling]="'merge'"> [queryParamsHandling]="'merge'"
role="link"
tabindex="0">
{{ 'browse.taxonomy.button' | translate }}</a> {{ 'browse.taxonomy.button' | translate }}</a>
</section> </section>

View File

@@ -12,7 +12,7 @@
<div class="align-middle my-auto"> <div class="align-middle my-auto">
@if ((dataSource.loading$ | async) !== true) { @if ((dataSource.loading$ | async) !== true) {
<button (click)="getNextPage(node)" <button (click)="getNextPage(node)"
class="btn btn-outline-primary btn-sm" role="button" data-test="show-more-button"> class="btn btn-outline-primary btn-sm" role="button" tabindex="0" data-test="show-more-button">
<i class="fas fa-angle-down"></i> {{ 'communityList.showMore' | translate }} <i class="fas fa-angle-down"></i> {{ 'communityList.showMore' | translate }}
</button> </button>
} }
@@ -34,7 +34,11 @@
<button type="button" class="btn btn-default btn-transparent" cdkTreeNodeToggle <button type="button" class="btn btn-default btn-transparent" cdkTreeNodeToggle
[attr.aria-label]="(node.isExpanded ? 'communityList.collapse' : 'communityList.expand') | translate:{ name: dsoNameService.getName(node.payload) }" [attr.aria-label]="(node.isExpanded ? 'communityList.collapse' : 'communityList.expand') | translate:{ name: dsoNameService.getName(node.payload) }"
(click)="toggleExpanded(node)" (click)="toggleExpanded(node)"
data-test="expand-button"> (keyup.enter)="toggleExpanded(node)"
(keyup.space)="toggleExpanded(node)"
data-test="expand-button"
role="button"
tabindex="0">
<span class="{{node.isExpanded ? 'fa fa-chevron-down' : 'fa fa-chevron-right'}}" <span class="{{node.isExpanded ? 'fa fa-chevron-down' : 'fa fa-chevron-right'}}"
aria-hidden="true"></span> aria-hidden="true"></span>
<span class="sr-only">{{ (node.isExpanded ? 'communityList.collapse' : 'communityList.expand') | translate:{ name: dsoNameService.getName(node.payload) } }}</span> <span class="sr-only">{{ (node.isExpanded ? 'communityList.collapse' : 'communityList.expand') | translate:{ name: dsoNameService.getName(node.payload) } }}</span>
@@ -48,7 +52,7 @@
} }
<div class="d-flex flex-row"> <div class="d-flex flex-row">
<span class="d-flex align-middle my-auto"> <span class="d-flex align-middle my-auto">
<a [routerLink]="node.route" class="lead">{{ dsoNameService.getName(node.payload) }}</a> <a [routerLink]="node.route" class="lead" role="link" tabindex="0">{{ dsoNameService.getName(node.payload) }}</a>
<span class="pe-2">&nbsp;</span> <span class="pe-2">&nbsp;</span>
@if (node.payload.archivedItemsCount >= 0) { @if (node.payload.archivedItemsCount >= 0) {
<span class="badge rounded-pill bg-secondary align-top archived-items-lead my-auto ps-2 pe-2">{{node.payload.archivedItemsCount}}</span> <span class="badge rounded-pill bg-secondary align-top archived-items-lead my-auto ps-2 pe-2">{{node.payload.archivedItemsCount}}</span>
@@ -88,7 +92,7 @@
<span class="fa fa-chevron-right"></span> <span class="fa fa-chevron-right"></span>
</span> </span>
<h6 class="align-middle my-auto"> <h6 class="align-middle my-auto">
<a [routerLink]="node.route" class="lead">{{ dsoNameService.getName(node.payload) }}</a> <a [routerLink]="node.route" class="lead" role="link" tabindex="0">{{ dsoNameService.getName(node.payload) }}</a>
</h6> </h6>
</div> </div>
<ds-truncatable [id]="node.id"> <ds-truncatable [id]="node.id">

View File

@@ -7,7 +7,7 @@
<a <a
[target]="(linkType === linkTypes.ExternalLink) ? '_blank' : '_self'" [target]="(linkType === linkTypes.ExternalLink) ? '_blank' : '_self'"
[attr.rel]="(linkType === linkTypes.ExternalLink) ? 'noopener noreferrer' : null" [routerLink]="[itemPageRoute]" [attr.rel]="(linkType === linkTypes.ExternalLink) ? 'noopener noreferrer' : null" [routerLink]="[itemPageRoute]"
class="card-img-top full-width" [attr.title]="'search.results.view-result' | translate"> class="card-img-top full-width" [attr.title]="'search.results.view-result' | translate" role="link" tabindex="0">
<div> <div>
<ds-thumbnail [thumbnail]="dso?.thumbnail | async" [limitWidth]="false"> <ds-thumbnail [thumbnail]="dso?.thumbnail | async" [limitWidth]="false">
</ds-thumbnail> </ds-thumbnail>
@@ -48,7 +48,7 @@
<div class="text-center"> <div class="text-center">
<a [target]="(linkType === linkTypes.ExternalLink) ? '_blank' : '_self'" <a [target]="(linkType === linkTypes.ExternalLink) ? '_blank' : '_self'"
[attr.rel]="(linkType === linkTypes.ExternalLink) ? 'noopener noreferrer' : null" [routerLink]="[itemPageRoute]" [attr.rel]="(linkType === linkTypes.ExternalLink) ? 'noopener noreferrer' : null" [routerLink]="[itemPageRoute]"
class="lead btn btn-primary viewButton">{{ 'search.results.view-result' | translate}}</a> class="lead btn btn-primary viewButton" role="link" tabindex="0">{{ 'search.results.view-result' | translate}}</a>
</div> </div>
} }
</div> </div>

View File

@@ -7,7 +7,7 @@
<a <a
[target]="(linkType === linkTypes.ExternalLink) ? '_blank' : '_self'" [target]="(linkType === linkTypes.ExternalLink) ? '_blank' : '_self'"
[attr.rel]="(linkType === linkTypes.ExternalLink) ? 'noopener noreferrer' : null" [routerLink]="[itemPageRoute]" [attr.rel]="(linkType === linkTypes.ExternalLink) ? 'noopener noreferrer' : null" [routerLink]="[itemPageRoute]"
class="card-img-top full-width" [attr.title]="'search.results.view-result' | translate"> class="card-img-top full-width" [attr.title]="'search.results.view-result' | translate" role="link" tabindex="0">
<div> <div>
<ds-thumbnail [thumbnail]="dso?.thumbnail | async" [limitWidth]="false"> <ds-thumbnail [thumbnail]="dso?.thumbnail | async" [limitWidth]="false">
</ds-thumbnail> </ds-thumbnail>
@@ -48,7 +48,7 @@
<div class="text-center"> <div class="text-center">
<a [target]="(linkType === linkTypes.ExternalLink) ? '_blank' : '_self'" <a [target]="(linkType === linkTypes.ExternalLink) ? '_blank' : '_self'"
[attr.rel]="(linkType === linkTypes.ExternalLink) ? 'noopener noreferrer' : null" [routerLink]="[itemPageRoute]" [attr.rel]="(linkType === linkTypes.ExternalLink) ? 'noopener noreferrer' : null" [routerLink]="[itemPageRoute]"
class="lead btn btn-primary viewButton">{{ 'search.results.view-result' | translate}}</a> class="lead btn btn-primary viewButton" role="link" tabindex="0">{{ 'search.results.view-result' | translate}}</a>
</div> </div>
} }
</div> </div>

View File

@@ -7,7 +7,7 @@
<a <a
[target]="(linkType === linkTypes.ExternalLink) ? '_blank' : '_self'" [target]="(linkType === linkTypes.ExternalLink) ? '_blank' : '_self'"
[attr.rel]="(linkType === linkTypes.ExternalLink) ? 'noopener noreferrer' : null" [routerLink]="[itemPageRoute]" [attr.rel]="(linkType === linkTypes.ExternalLink) ? 'noopener noreferrer' : null" [routerLink]="[itemPageRoute]"
class="card-img-top full-width" [attr.title]="'search.results.view-result' | translate"> class="card-img-top full-width" [attr.title]="'search.results.view-result' | translate" role="link" tabindex="0">
<div> <div>
<ds-thumbnail [thumbnail]="dso?.thumbnail | async" [limitWidth]="false"> <ds-thumbnail [thumbnail]="dso?.thumbnail | async" [limitWidth]="false">
</ds-thumbnail> </ds-thumbnail>
@@ -54,7 +54,7 @@
<div class="text-center"> <div class="text-center">
<a [target]="(linkType === linkTypes.ExternalLink) ? '_blank' : '_self'" <a [target]="(linkType === linkTypes.ExternalLink) ? '_blank' : '_self'"
[attr.rel]="(linkType === linkTypes.ExternalLink) ? 'noopener noreferrer' : null" [routerLink]="[itemPageRoute]" [attr.rel]="(linkType === linkTypes.ExternalLink) ? 'noopener noreferrer' : null" [routerLink]="[itemPageRoute]"
class="lead btn btn-primary viewButton">{{ 'search.results.view-result' | translate}}</a> class="lead btn btn-primary viewButton" role="link" tabindex="0">{{ 'search.results.view-result' | translate}}</a>
</div> </div>
} }
</div> </div>

View File

@@ -4,7 +4,7 @@
@if (linkType !== linkTypes.None) { @if (linkType !== linkTypes.None) {
<a [target]="(linkType === linkTypes.ExternalLink) ? '_blank' : '_self'" <a [target]="(linkType === linkTypes.ExternalLink) ? '_blank' : '_self'"
[attr.rel]="(linkType === linkTypes.ExternalLink) ? 'noopener noreferrer' : null" [attr.rel]="(linkType === linkTypes.ExternalLink) ? 'noopener noreferrer' : null"
[routerLink]="[itemPageRoute]" class="lead item-list-title dont-break-out"> [routerLink]="[itemPageRoute]" class="lead item-list-title dont-break-out" role="link" tabindex="0">
<ds-thumbnail [thumbnail]="dso?.thumbnail | async" [limitWidth]="true"> <ds-thumbnail [thumbnail]="dso?.thumbnail | async" [limitWidth]="true">
</ds-thumbnail> </ds-thumbnail>
</a> </a>
@@ -26,7 +26,7 @@
<a [target]="(linkType === linkTypes.ExternalLink) ? '_blank' : '_self'" <a [target]="(linkType === linkTypes.ExternalLink) ? '_blank' : '_self'"
[attr.rel]="(linkType === linkTypes.ExternalLink) ? 'noopener noreferrer' : null" [attr.rel]="(linkType === linkTypes.ExternalLink) ? 'noopener noreferrer' : null"
[routerLink]="[itemPageRoute]" class="lead item-list-title dont-break-out" [routerLink]="[itemPageRoute]" class="lead item-list-title dont-break-out"
[innerHTML]="dsoTitle"></a> [innerHTML]="dsoTitle" role="link" tabindex="0"></a>
} }
@if (linkType === linkTypes.None) { @if (linkType === linkTypes.None) {
<span <span

View File

@@ -4,7 +4,7 @@
@if (linkType !== linkTypes.None) { @if (linkType !== linkTypes.None) {
<a [target]="(linkType === linkTypes.ExternalLink) ? '_blank' : '_self'" <a [target]="(linkType === linkTypes.ExternalLink) ? '_blank' : '_self'"
[attr.rel]="(linkType === linkTypes.ExternalLink) ? 'noopener noreferrer' : null" [attr.rel]="(linkType === linkTypes.ExternalLink) ? 'noopener noreferrer' : null"
[routerLink]="[itemPageRoute]" class="lead item-list-title dont-break-out"> [routerLink]="[itemPageRoute]" class="lead item-list-title dont-break-out" role="link" tabindex="0">
<ds-thumbnail [thumbnail]="dso?.thumbnail | async" [limitWidth]="true"> <ds-thumbnail [thumbnail]="dso?.thumbnail | async" [limitWidth]="true">
</ds-thumbnail> </ds-thumbnail>
</a> </a>
@@ -26,7 +26,7 @@
<a [target]="(linkType === linkTypes.ExternalLink) ? '_blank' : '_self'" <a [target]="(linkType === linkTypes.ExternalLink) ? '_blank' : '_self'"
[attr.rel]="(linkType === linkTypes.ExternalLink) ? 'noopener noreferrer' : null" [attr.rel]="(linkType === linkTypes.ExternalLink) ? 'noopener noreferrer' : null"
[routerLink]="[itemPageRoute]" class="lead item-list-title dont-break-out" [routerLink]="[itemPageRoute]" class="lead item-list-title dont-break-out"
[innerHTML]="dsoTitle"></a> [innerHTML]="dsoTitle" role="link" tabindex="0"></a>
} }
@if (linkType === linkTypes.None) { @if (linkType === linkTypes.None) {
<span <span

View File

@@ -3,7 +3,7 @@
<div class="col-3 col-md-2"> <div class="col-3 col-md-2">
@if (linkType !== linkTypes.None) { @if (linkType !== linkTypes.None) {
<a [target]="(linkType === linkTypes.ExternalLink) ? '_blank' : '_self'" [attr.rel]="(linkType === linkTypes.ExternalLink) ? 'noopener noreferrer' : null" <a [target]="(linkType === linkTypes.ExternalLink) ? '_blank' : '_self'" [attr.rel]="(linkType === linkTypes.ExternalLink) ? 'noopener noreferrer' : null"
[routerLink]="[itemPageRoute]" class="lead item-list-title dont-break-out"> [routerLink]="[itemPageRoute]" class="lead item-list-title dont-break-out" role="link" tabindex="0">
<ds-thumbnail [thumbnail]="dso?.thumbnail | async" [limitWidth]="true"> <ds-thumbnail [thumbnail]="dso?.thumbnail | async" [limitWidth]="true">
</ds-thumbnail> </ds-thumbnail>
</a> </a>
@@ -24,7 +24,7 @@
@if (linkType !== linkTypes.None) { @if (linkType !== linkTypes.None) {
<a [target]="(linkType === linkTypes.ExternalLink) ? '_blank' : '_self'" [attr.rel]="(linkType === linkTypes.ExternalLink) ? 'noopener noreferrer' : null" <a [target]="(linkType === linkTypes.ExternalLink) ? '_blank' : '_self'" [attr.rel]="(linkType === linkTypes.ExternalLink) ? 'noopener noreferrer' : null"
[routerLink]="[itemPageRoute]" class="lead item-list-title dont-break-out" [routerLink]="[itemPageRoute]" class="lead item-list-title dont-break-out"
[innerHTML]="dsoTitle"></a> [innerHTML]="dsoTitle" role="link" tabindex="0"></a>
} }
@if (linkType === linkTypes.None) { @if (linkType === linkTypes.None) {
<span <span

View File

@@ -53,7 +53,7 @@
[label]="'journalissue.page.keyword'"> [label]="'journalissue.page.keyword'">
</ds-generic-item-page-field> </ds-generic-item-page-field>
<div> <div>
<a class="btn btn-outline-primary" [routerLink]="[itemPageRoute + '/full']"> <a class="btn btn-outline-primary" [routerLink]="[itemPageRoute + '/full']" role="button" tabindex="0">
{{"item.page.link.full" | translate}} {{"item.page.link.full" | translate}}
</a> </a>
</div> </div>

View File

@@ -36,7 +36,7 @@
[label]="'journalvolume.page.description'"> [label]="'journalvolume.page.description'">
</ds-generic-item-page-field> </ds-generic-item-page-field>
<div> <div>
<a class="btn btn-outline-primary" [routerLink]="[itemPageRoute + '/full']"> <a class="btn btn-outline-primary" [routerLink]="[itemPageRoute + '/full']" role="button" tabindex="0">
{{"item.page.link.full" | translate}} {{"item.page.link.full" | translate}}
</a> </a>
</div> </div>

View File

@@ -35,7 +35,7 @@
[label]="'journal.page.description'"> [label]="'journal.page.description'">
</ds-generic-item-page-field> </ds-generic-item-page-field>
<div> <div>
<a class="btn btn-outline-primary" [routerLink]="[itemPageRoute + '/full']"> <a class="btn btn-outline-primary" [routerLink]="[itemPageRoute + '/full']" role="button" tabindex="0">
{{"item.page.link.full" | translate}} {{"item.page.link.full" | translate}}
</a> </a>
</div> </div>

View File

@@ -7,7 +7,7 @@
<a <a
[target]="(linkType === linkTypes.ExternalLink) ? '_blank' : '_self'" [target]="(linkType === linkTypes.ExternalLink) ? '_blank' : '_self'"
[attr.rel]="(linkType === linkTypes.ExternalLink) ? 'noopener noreferrer' : null" [routerLink]="[itemPageRoute]" [attr.rel]="(linkType === linkTypes.ExternalLink) ? 'noopener noreferrer' : null" [routerLink]="[itemPageRoute]"
class="card-img-top full-width" [attr.title]="'search.results.view-result' | translate"> class="card-img-top full-width" [attr.title]="'search.results.view-result' | translate" role="link" tabindex="0">
<div> <div>
<ds-thumbnail [thumbnail]="dso?.thumbnail | async" [limitWidth]="false"> <ds-thumbnail [thumbnail]="dso?.thumbnail | async" [limitWidth]="false">
</ds-thumbnail> </ds-thumbnail>
@@ -56,7 +56,7 @@
<div class="text-center"> <div class="text-center">
<a [target]="(linkType === linkTypes.ExternalLink) ? '_blank' : '_self'" <a [target]="(linkType === linkTypes.ExternalLink) ? '_blank' : '_self'"
[attr.rel]="(linkType === linkTypes.ExternalLink) ? 'noopener noreferrer' : null" [routerLink]="[itemPageRoute]" [attr.rel]="(linkType === linkTypes.ExternalLink) ? 'noopener noreferrer' : null" [routerLink]="[itemPageRoute]"
class="lead btn btn-primary viewButton">{{ 'search.results.view-result' | translate}}</a> class="lead btn btn-primary viewButton" role="link" tabindex="0">{{ 'search.results.view-result' | translate}}</a>
</div> </div>
} }
</div> </div>

View File

@@ -7,7 +7,7 @@
<a <a
[target]="(linkType === linkTypes.ExternalLink) ? '_blank' : '_self'" [target]="(linkType === linkTypes.ExternalLink) ? '_blank' : '_self'"
[attr.rel]="(linkType === linkTypes.ExternalLink) ? 'noopener noreferrer' : null" [routerLink]="[itemPageRoute]" [attr.rel]="(linkType === linkTypes.ExternalLink) ? 'noopener noreferrer' : null" [routerLink]="[itemPageRoute]"
class="card-img-top full-width" [attr.title]="'search.results.view-result' | translate"> class="card-img-top full-width" [attr.title]="'search.results.view-result' | translate" role="link" tabindex="0">
<div> <div>
<ds-thumbnail [thumbnail]="dso?.thumbnail | async" [limitWidth]="false"> <ds-thumbnail [thumbnail]="dso?.thumbnail | async" [limitWidth]="false">
</ds-thumbnail> </ds-thumbnail>
@@ -47,7 +47,7 @@
<div class="text-center"> <div class="text-center">
<a [target]="(linkType === linkTypes.ExternalLink) ? '_blank' : '_self'" <a [target]="(linkType === linkTypes.ExternalLink) ? '_blank' : '_self'"
[attr.rel]="(linkType === linkTypes.ExternalLink) ? 'noopener noreferrer' : null" [routerLink]="[itemPageRoute]" [attr.rel]="(linkType === linkTypes.ExternalLink) ? 'noopener noreferrer' : null" [routerLink]="[itemPageRoute]"
class="lead btn btn-primary viewButton">{{ 'search.results.view-result' | translate}}</a> class="lead btn btn-primary viewButton" role="link" tabindex="0">{{ 'search.results.view-result' | translate}}</a>
</div> </div>
} }
</div> </div>

View File

@@ -7,7 +7,7 @@
<a <a
[target]="(linkType === linkTypes.ExternalLink) ? '_blank' : '_self'" [target]="(linkType === linkTypes.ExternalLink) ? '_blank' : '_self'"
[attr.rel]="(linkType === linkTypes.ExternalLink) ? 'noopener noreferrer' : null" [routerLink]="[itemPageRoute]" [attr.rel]="(linkType === linkTypes.ExternalLink) ? 'noopener noreferrer' : null" [routerLink]="[itemPageRoute]"
class="card-img-top full-width" [attr.title]="'search.results.view-result' | translate"> class="card-img-top full-width" [attr.title]="'search.results.view-result' | translate" role="link" tabindex="0">
<div> <div>
<ds-thumbnail [thumbnail]="dso?.thumbnail | async" [limitWidth]="false"> <ds-thumbnail [thumbnail]="dso?.thumbnail | async" [limitWidth]="false">
</ds-thumbnail> </ds-thumbnail>
@@ -40,7 +40,7 @@
<div class="text-center"> <div class="text-center">
<a [target]="(linkType === linkTypes.ExternalLink) ? '_blank' : '_self'" <a [target]="(linkType === linkTypes.ExternalLink) ? '_blank' : '_self'"
[attr.rel]="(linkType === linkTypes.ExternalLink) ? 'noopener noreferrer' : null" [routerLink]="[itemPageRoute]" [attr.rel]="(linkType === linkTypes.ExternalLink) ? 'noopener noreferrer' : null" [routerLink]="[itemPageRoute]"
class="lead btn btn-primary viewButton">{{ 'search.results.view-result' | translate}}</a> class="lead btn btn-primary viewButton" role="link" tabindex="0">{{ 'search.results.view-result' | translate}}</a>
</div> </div>
} }
</div> </div>

View File

@@ -4,7 +4,7 @@
@if (linkType !== linkTypes.None) { @if (linkType !== linkTypes.None) {
<a [target]="(linkType === linkTypes.ExternalLink) ? '_blank' : '_self'" <a [target]="(linkType === linkTypes.ExternalLink) ? '_blank' : '_self'"
[attr.rel]="(linkType === linkTypes.ExternalLink) ? 'noopener noreferrer' : null" [attr.rel]="(linkType === linkTypes.ExternalLink) ? 'noopener noreferrer' : null"
[routerLink]="[itemPageRoute]" class="dont-break-out"> [routerLink]="[itemPageRoute]" class="dont-break-out" role="link" tabindex="0">
<ds-thumbnail [thumbnail]="dso?.thumbnail | async" <ds-thumbnail [thumbnail]="dso?.thumbnail | async"
[defaultImage]="'assets/images/orgunit-placeholder.svg'" [defaultImage]="'assets/images/orgunit-placeholder.svg'"
[alt]="'thumbnail.orgunit.alt'" [alt]="'thumbnail.orgunit.alt'"
@@ -32,7 +32,7 @@
<a [target]="(linkType === linkTypes.ExternalLink) ? '_blank' : '_self'" <a [target]="(linkType === linkTypes.ExternalLink) ? '_blank' : '_self'"
[attr.rel]="(linkType === linkTypes.ExternalLink) ? 'noopener noreferrer' : null" [attr.rel]="(linkType === linkTypes.ExternalLink) ? 'noopener noreferrer' : null"
[routerLink]="[itemPageRoute]" class="lead" [routerLink]="[itemPageRoute]" class="lead"
[innerHTML]="dsoTitle || ('orgunit.listelement.no-title' | translate)"></a> [innerHTML]="dsoTitle || ('orgunit.listelement.no-title' | translate)" role="link" tabindex="0"></a>
} }
@if (linkType === linkTypes.None) { @if (linkType === linkTypes.None) {
<span <span

View File

@@ -4,7 +4,7 @@
@if (linkType !== linkTypes.None) { @if (linkType !== linkTypes.None) {
<a [target]="(linkType === linkTypes.ExternalLink) ? '_blank' : '_self'" <a [target]="(linkType === linkTypes.ExternalLink) ? '_blank' : '_self'"
[attr.rel]="(linkType === linkTypes.ExternalLink) ? 'noopener noreferrer' : null" [attr.rel]="(linkType === linkTypes.ExternalLink) ? 'noopener noreferrer' : null"
[routerLink]="[itemPageRoute]" class="dont-break-out"> [routerLink]="[itemPageRoute]" class="dont-break-out" role="link" tabindex="0">
<ds-thumbnail [thumbnail]="dso?.thumbnail | async" <ds-thumbnail [thumbnail]="dso?.thumbnail | async"
[defaultImage]="'assets/images/person-placeholder.svg'" [defaultImage]="'assets/images/person-placeholder.svg'"
[alt]="'thumbnail.person.alt'" [alt]="'thumbnail.person.alt'"
@@ -32,7 +32,7 @@
<a [target]="(linkType === linkTypes.ExternalLink) ? '_blank' : '_self'" <a [target]="(linkType === linkTypes.ExternalLink) ? '_blank' : '_self'"
[attr.rel]="(linkType === linkTypes.ExternalLink) ? 'noopener noreferrer' : null" [attr.rel]="(linkType === linkTypes.ExternalLink) ? 'noopener noreferrer' : null"
[routerLink]="[itemPageRoute]" class="lead" [routerLink]="[itemPageRoute]" class="lead"
[innerHTML]="dsoTitle || ('person.listelement.no-title' | translate)"></a> [innerHTML]="dsoTitle || ('person.listelement.no-title' | translate)" role="link" tabindex="0"></a>
} }
@if (linkType === linkTypes.None) { @if (linkType === linkTypes.None) {
<span <span

View File

@@ -4,7 +4,7 @@
@if (linkType !== linkTypes.None) { @if (linkType !== linkTypes.None) {
<a [target]="(linkType === linkTypes.ExternalLink) ? '_blank' : '_self'" <a [target]="(linkType === linkTypes.ExternalLink) ? '_blank' : '_self'"
[attr.rel]="(linkType === linkTypes.ExternalLink) ? 'noopener noreferrer' : null" [attr.rel]="(linkType === linkTypes.ExternalLink) ? 'noopener noreferrer' : null"
[routerLink]="[itemPageRoute]" class="dont-break-out"> [routerLink]="[itemPageRoute]" class="dont-break-out" role="link" tabindex="0">
<ds-thumbnail [thumbnail]="dso?.thumbnail | async" <ds-thumbnail [thumbnail]="dso?.thumbnail | async"
[defaultImage]="'assets/images/project-placeholder.svg'" [defaultImage]="'assets/images/project-placeholder.svg'"
[alt]="'thumbnail.project.alt'" [alt]="'thumbnail.project.alt'"
@@ -32,7 +32,7 @@
<a [target]="(linkType === linkTypes.ExternalLink) ? '_blank' : '_self'" <a [target]="(linkType === linkTypes.ExternalLink) ? '_blank' : '_self'"
[attr.rel]="(linkType === linkTypes.ExternalLink) ? 'noopener noreferrer' : null" [attr.rel]="(linkType === linkTypes.ExternalLink) ? 'noopener noreferrer' : null"
[routerLink]="[itemPageRoute]" class="lead item-list-title dont-break-out" [routerLink]="[itemPageRoute]" class="lead item-list-title dont-break-out"
[innerHTML]="dsoTitle"></a> [innerHTML]="dsoTitle" role="link" tabindex="0"></a>
} }
@if (linkType === linkTypes.None) { @if (linkType === linkTypes.None) {
<span <span

View File

@@ -56,7 +56,7 @@
[label]="'orgunit.page.description'"> [label]="'orgunit.page.description'">
</ds-generic-item-page-field> </ds-generic-item-page-field>
<div> <div>
<a class="btn btn-outline-primary" [routerLink]="[itemPageRoute + '/full']"> <a class="btn btn-outline-primary" [routerLink]="[itemPageRoute + '/full']" role="button" tabindex="0">
{{"item.page.link.full" | translate}} {{"item.page.link.full" | translate}}
</a> </a>
</div> </div>

View File

@@ -52,7 +52,7 @@
[label]="'person.page.name'"> [label]="'person.page.name'">
</ds-generic-item-page-field> </ds-generic-item-page-field>
<div> <div>
<a class="btn btn-outline-primary" [routerLink]="[itemPageRoute + '/full']"> <a class="btn btn-outline-primary" [routerLink]="[itemPageRoute + '/full']" role="button" tabindex="0">
{{"item.page.link.full" | translate}} {{"item.page.link.full" | translate}}
</a> </a>
</div> </div>

View File

@@ -64,7 +64,7 @@
[label]="'project.page.keyword'"> [label]="'project.page.keyword'">
</ds-generic-item-page-field> </ds-generic-item-page-field>
<div> <div>
<a class="btn btn-outline-primary" [routerLink]="[itemPageRoute + '/full']"> <a class="btn btn-outline-primary" [routerLink]="[itemPageRoute + '/full']" role="button" tabindex="0">
{{"item.page.link.full" | translate}} {{"item.page.link.full" | translate}}
</a> </a>
</div> </div>

View File

@@ -26,7 +26,7 @@
<h5 class="text-uppercase">Footer Content</h5> <h5 class="text-uppercase">Footer Content</h5>
<ul class="list-unstyled mb-0"> <ul class="list-unstyled mb-0">
<li> <li>
<a routerLink="./" class="">Suspendisse potenti</a> <a routerLink="./" class="" role="link" tabindex="0">Suspendisse potenti</a>
</li> </li>
</ul> </ul>
</div> </div>
@@ -53,40 +53,40 @@
<div class="content-container"> <div class="content-container">
<p class="m-0"> <p class="m-0">
<a class="text-white" <a class="text-white"
href="http://www.dspace.org/">{{ 'footer.link.dspace' | translate}}</a> href="http://www.dspace.org/" role="link" tabindex="0">{{ 'footer.link.dspace' | translate}}</a>
{{ 'footer.copyright' | translate:{year: dateObj | date:'y'} }} {{ 'footer.copyright' | translate:{year: dateObj | date:'y'} }}
<a class="text-white" <a class="text-white"
href="https://www.lyrasis.org/">{{ 'footer.link.lyrasis' | translate}}</a> href="https://www.lyrasis.org/" role="link" tabindex="0">{{ 'footer.link.lyrasis' | translate}}</a>
</p> </p>
<ul class="footer-info list-unstyled d-flex justify-content-center mb-0"> <ul class="footer-info list-unstyled d-flex justify-content-center mb-0">
<li> <li>
<button class="btn btn-link text-white" type="button" (click)="showCookieSettings()"> <button class="btn btn-link text-white" type="button" (click)="showCookieSettings()" role="button" tabindex="0">
{{ 'footer.link.cookies' | translate}} {{ 'footer.link.cookies' | translate}}
</button> </button>
</li> </li>
@if (showPrivacyPolicy) { @if (showPrivacyPolicy) {
<li> <li>
<a class="btn text-white" <a class="btn text-white"
routerLink="info/privacy">{{ 'footer.link.privacy-policy' | translate}}</a> routerLink="info/privacy" role="link" tabindex="0">{{ 'footer.link.privacy-policy' | translate}}</a>
</li> </li>
} }
@if (showEndUserAgreement) { @if (showEndUserAgreement) {
<li> <li>
<a class="btn text-white" <a class="btn text-white"
routerLink="info/end-user-agreement">{{ 'footer.link.end-user-agreement' | translate}}</a> routerLink="info/end-user-agreement" role="link" tabindex="0">{{ 'footer.link.end-user-agreement' | translate}}</a>
</li> </li>
} }
@if (showSendFeedback$ | async) { @if (showSendFeedback$ | async) {
<li> <li>
<a class="btn text-white" <a class="btn text-white"
routerLink="info/feedback">{{ 'footer.link.feedback' | translate}}</a> routerLink="info/feedback" role="link" tabindex="0">{{ 'footer.link.feedback' | translate}}</a>
</li> </li>
} }
</ul> </ul>
</div> </div>
@if (coarLdnEnabled$ | async) { @if (coarLdnEnabled$ | async) {
<div class="notify-enabled text-white"> <div class="notify-enabled text-white">
<a class="coar-notify-support-route" routerLink="info/coar-notify-support"> <a class="coar-notify-support-route" routerLink="info/coar-notify-support" role="link" tabindex="0">
<img class="n-coar" src="assets/images/n-coar.svg" [attr.alt]="'menu.header.image.logo' | translate" /> <img class="n-coar" src="assets/images/n-coar.svg" [attr.alt]="'menu.header.image.logo' | translate" />
{{ 'footer.link.coar-notify-support' | translate }} {{ 'footer.link.coar-notify-support' | translate }}
</a> </a>

View File

@@ -1,7 +1,7 @@
<header> <header>
<div class="container"> <div class="container">
<div class="d-flex flex-row justify-content-between"> <div class="d-flex flex-row justify-content-between">
<a class="navbar-brand my-2" routerLink="/home"> <a class="navbar-brand my-2" routerLink="/home" role="button" tabindex="0">
<img src="assets/images/dspace-logo.svg" [attr.alt]="'menu.header.image.logo' | translate"/> <img src="assets/images/dspace-logo.svg" [attr.alt]="'menu.header.image.logo' | translate"/>
</a> </a>

View File

@@ -14,7 +14,7 @@
<li>issue permanent urls and trustworthy identifiers, including optional integrations with handle.net and DataCite DOI</li> <li>issue permanent urls and trustworthy identifiers, including optional integrations with handle.net and DataCite DOI</li>
</ul> </ul>
<p>Join an international community of <a href="https://wiki.lyrasis.org/display/DSPACE/DSpace+Positioning" <p>Join an international community of <a href="https://wiki.lyrasis.org/display/DSPACE/DSpace+Positioning"
target="_blank">leading institutions using DSpace</a>. target="_blank" role="link" tabindex="0">leading institutions using DSpace</a>.
</p> </p>
</div> </div>
</div> </div>

View File

@@ -9,7 +9,7 @@
</ds-listable-object-component-loader> </ds-listable-object-component-loader>
</div> </div>
} }
<button (click)="onLoadMore()" class="btn btn-primary search-button mt-4 float-start ng-tns-c290-40"> {{'vocabulary-treeview.load-more' | translate }} ...</button> <button (click)="onLoadMore()" class="btn btn-primary search-button mt-4 float-start ng-tns-c290-40" role="button" tabindex="0"> {{'vocabulary-treeview.load-more' | translate }} ...</button>
</div> </div>
} }
@if (itemRD?.hasFailed) { @if (itemRD?.hasFailed) {

View File

@@ -10,7 +10,7 @@
<div class="d-flex justify-content-between flex-wrap"> <div class="d-flex justify-content-between flex-wrap">
<span class="align-self-center">{{'item.alerts.withdrawn' | translate}}</span> <span class="align-self-center">{{'item.alerts.withdrawn' | translate}}</span>
<div class="gap-2 d-flex"> <div class="gap-2 d-flex">
<a routerLink="/home" class="btn btn-primary btn-sm">{{"404.link.home-page" | translate}}</a> <a routerLink="/home" class="btn btn-primary btn-sm" role="button" tabindex="0">{{"404.link.home-page" | translate}}</a>
@if (showReinstateButton$ | async) { @if (showReinstateButton$ | async) {
<a class="btn btn-primary btn-sm" (click)="openReinstateModal()">{{ 'item.alerts.reinstate-request' | translate}}</a> <a class="btn btn-primary btn-sm" (click)="openReinstateModal()">{{ 'item.alerts.reinstate-request' | translate}}</a>
} }

View File

@@ -1,7 +1,7 @@
<ds-metadata-field-wrapper [label]="label | translate"> <ds-metadata-field-wrapper [label]="label | translate">
<div class="collections"> <div class="collections">
@for (collection of (this.collections$ | async); track collection; let last = $last) { @for (collection of (this.collections$ | async); track collection; let last = $last) {
<a [routerLink]="['/collections', collection.id]"> <a [routerLink]="['/collections', collection.id]" role="button" tabindex="0">
<span>{{ dsoNameService.getName(collection) }}</span>@if (!last) { <span>{{ dsoNameService.getName(collection) }}</span>@if (!last) {
<span [innerHTML]="separator"></span> <span [innerHTML]="separator"></span>
} }
@@ -21,6 +21,8 @@
class="load-more-btn btn btn-sm btn-outline-secondary" class="load-more-btn btn btn-sm btn-outline-secondary"
role="button" role="button"
href="javascript:void(0);" href="javascript:void(0);"
role="button"
tabindex="0"
> >
{{'item.page.collections.load-more' | translate}} {{'item.page.collections.load-more' | translate}}
</a> </a>

View File

@@ -1,6 +1,6 @@
<ds-metadata-field-wrapper [label]="label | translate"> <ds-metadata-field-wrapper [label]="label | translate">
@for (mdValue of mdValues; track mdValue; let last = $last) { @for (mdValue of mdValues; track mdValue; let last = $last) {
<a class="dont-break-out" [href]="mdValue.value" [target]="hasInternalLink(mdValue.value) ? '_self' : '_blank'"> <a class="dont-break-out" [href]="mdValue.value" [target]="hasInternalLink(mdValue.value) ? '_self' : '_blank'" role="link" tabindex="0">
{{ linktext || mdValue.value }}@if (!last) { {{ linktext || mdValue.value }}@if (!last) {
<span [innerHTML]="separator"></span> <span [innerHTML]="separator"></span>
} }

View File

@@ -23,14 +23,14 @@
<a class="dont-break-out ds-simple-metadata-link" <a class="dont-break-out ds-simple-metadata-link"
[href]="value" [href]="value"
[attr.target]="getLinkAttributes(value).target" [attr.target]="getLinkAttributes(value).target"
[attr.rel]="getLinkAttributes(value).rel"> [attr.rel]="getLinkAttributes(value).rel" role="link" tabindex="0">
{{value}} {{value}}
</a> </a>
</ng-template> </ng-template>
<!-- Render value as a link with icon --> <!-- Render value as a link with icon -->
<ng-template #linkImg let-img="img" let-value="value"> <ng-template #linkImg let-img="img" let-value="value">
<a [href]="value" class="link-anchor dont-break-out ds-simple-metadata-link" target="_blank"> <a [href]="value" class="link-anchor dont-break-out ds-simple-metadata-link" target="_blank" role="link" tabindex="0">
<img class="link-logo" <img class="link-logo"
[alt]="img.alt | translate" [alt]="img.alt | translate"
[style.height]="'var(' + img.heightVar + ', --ds-item-page-img-field-default-inline-height)'" [style.height]="'var(' + img.heightVar + ', --ds-item-page-img-field-default-inline-height)'"
@@ -48,5 +48,5 @@
<ng-template #browselink let-value="value"> <ng-template #browselink let-value="value">
<a class="dont-break-out preserve-line-breaks ds-browse-link" <a class="dont-break-out preserve-line-breaks ds-browse-link"
[routerLink]="['/browse', browseDefinition.id]" [routerLink]="['/browse', browseDefinition.id]"
[queryParams]="getQueryParams(value)">{{value}}</a> [queryParams]="getQueryParams(value)" role="link" tabindex="0">{{value}}</a>
</ng-template> </ng-template>

View File

@@ -116,7 +116,7 @@
</ds-geospatial-item-page-field> </ds-geospatial-item-page-field>
} }
<div> <div>
<a class="btn btn-outline-primary" role="button" [routerLink]="[itemPageRoute + '/full']"> <a class="btn btn-outline-primary" role="button" [routerLink]="[itemPageRoute + '/full']" role="button" tabindex="0">
<i class="fas fa-info-circle"></i> {{"item.page.link.full" | translate}} <i class="fas fa-info-circle"></i> {{"item.page.link.full" | translate}}
</a> </a>
</div> </div>

View File

@@ -104,7 +104,7 @@
<ds-item-page-cc-license-field [item]="object" [variant]="'full'"> <ds-item-page-cc-license-field [item]="object" [variant]="'full'">
</ds-item-page-cc-license-field> </ds-item-page-cc-license-field>
<div> <div>
<a class="btn btn-outline-primary" [routerLink]="[itemPageRoute + '/full']" role="button"> <a class="btn btn-outline-primary" [routerLink]="[itemPageRoute + '/full']" role="button" role="button" tabindex="0">
<i class="fas fa-info-circle"></i> {{"item.page.link.full" | translate}} <i class="fas fa-info-circle"></i> {{"item.page.link.full" | translate}}
</a> </a>
</div> </div>

View File

@@ -3,6 +3,6 @@
<h2><small><em>{{missingItem}}</em></small></h2> <h2><small><em>{{missingItem}}</em></small></h2>
<br /> <br />
<p class="text-center"> <p class="text-center">
<a routerLink="/home" class="btn btn-primary">{{"404.link.home-page" | translate}}</a> <a routerLink="/home" class="btn btn-primary" role="button" tabindex="0">{{"404.link.home-page" | translate}}</a>
</p> </p>
</div> </div>

View File

@@ -5,6 +5,6 @@
<p>{{"error-page." + code | translate}}</p> <p>{{"error-page." + code | translate}}</p>
<br/> <br/>
<p class="text-center"> <p class="text-center">
<a href="/home" class="btn btn-primary">{{ status + ".link.home-page" | translate}}</a> <a href="/home" class="btn btn-primary" role="link" tabindex="0">{{ status + ".link.home-page" | translate}}</a>
</p> </p>
</div> </div>

View File

@@ -5,6 +5,6 @@
<p>{{"404.help" | translate}}</p> <p>{{"404.help" | translate}}</p>
<br/> <br/>
<p class="text-center"> <p class="text-center">
<a routerLink="/home" class="btn btn-primary">{{"404.link.home-page" | translate}}</a> <a routerLink="/home" class="btn btn-primary" role="button" tabindex="0">{{"404.link.home-page" | translate}}</a>
</p> </p>
</div> </div>

View File

@@ -42,7 +42,7 @@
<div class="processed-message"> <div class="processed-message">
<p>{{ 'grant-deny-request-copy.processed' | translate }}</p> <p>{{ 'grant-deny-request-copy.processed' | translate }}</p>
<p class="text-center"> <p class="text-center">
<a routerLink="/home" class="btn btn-primary">{{ 'grant-deny-request-copy.home-page' | translate }}</a> <a routerLink="/home" class="btn btn-primary" role="button" tabindex="0">{{ 'grant-deny-request-copy.home-page' | translate }}</a>
</p> </p>
</div> </div>
} }

View File

@@ -7,7 +7,7 @@
[class.display]="searchExpanded ? 'inline-block' : 'none'" [class.display]="searchExpanded ? 'inline-block' : 'none'"
[tabIndex]="searchExpanded ? 0 : -1" [tabIndex]="searchExpanded ? 0 : -1"
[attr.data-test]="'header-search-box' | dsBrowserOnly"> [attr.data-test]="'header-search-box' | dsBrowserOnly">
<button class="submit-icon btn btn-link btn-link-inline" [attr.aria-label]="'nav.search.button' | translate" type="button" (click)="searchExpanded ? onSubmit(searchForm.value) : expand()" [attr.data-test]="'header-search-icon' | dsBrowserOnly"> <button class="submit-icon btn btn-link btn-link-inline" [attr.aria-label]="'nav.search.button' | translate" type="button" (click)="searchExpanded ? onSubmit(searchForm.value) : expand()" [attr.data-test]="'header-search-icon' | dsBrowserOnly" tabindex="0" role="button">
<em class="fas fa-search fa-lg fa-fw"></em> <em class="fas fa-search fa-lg fa-fw"></em>
</button> </button>
</form> </form>

View File

@@ -8,6 +8,7 @@
<a href="javascript:void(0);" class="dropdownLogin px-0.5" [attr.aria-label]="'nav.login' |translate" <a href="javascript:void(0);" class="dropdownLogin px-0.5" [attr.aria-label]="'nav.login' |translate"
(click)="$event.preventDefault()" [attr.data-test]="'login-menu' | dsBrowserOnly" (click)="$event.preventDefault()" [attr.data-test]="'login-menu' | dsBrowserOnly"
role="menuitem" role="menuitem"
tabindex="0"
aria-haspopup="menu" aria-haspopup="menu"
aria-controls="loginDropdownMenu" aria-controls="loginDropdownMenu"
[attr.aria-expanded]="loginDrop.isOpen()" [attr.aria-expanded]="loginDrop.isOpen()"
@@ -26,6 +27,7 @@
<div ngbDropdown #loggedInDrop="ngbDropdown" display="dynamic" placement="bottom-right" class="d-inline-block" @fadeInOut> <div ngbDropdown #loggedInDrop="ngbDropdown" display="dynamic" placement="bottom-right" class="d-inline-block" @fadeInOut>
<a href="javascript:void(0);" <a href="javascript:void(0);"
role="menuitem" role="menuitem"
tabindex="0"
[attr.aria-label]="'nav.user-profile-menu-and-logout' | translate" [attr.aria-label]="'nav.user-profile-menu-and-logout' | translate"
aria-controls="user-menu-dropdown" aria-controls="user-menu-dropdown"
(click)="$event.preventDefault()" [title]="'nav.user-profile-menu-and-logout' | translate" (click)="$event.preventDefault()" [title]="'nav.user-profile-menu-and-logout' | translate"
@@ -43,12 +45,12 @@
} @else { } @else {
<div data-test="auth-nav"> <div data-test="auth-nav">
@if ((isAuthenticated | async) !== true) { @if ((isAuthenticated | async) !== true) {
<a routerLink="/login" routerLinkActive="active" class="loginLink px-0.5" role="button"> <a routerLink="/login" routerLinkActive="active" class="loginLink px-0.5" role="button" tabindex="0">
{{ 'nav.login' | translate }}<span class="sr-only">(current)</span> {{ 'nav.login' | translate }}<span class="sr-only">(current)</span>
</a> </a>
} }
@if ((isAuthenticated | async)) { @if ((isAuthenticated | async)) {
<a role="button" [attr.aria-label]="'nav.logout' |translate" [title]="'nav.logout' | translate" routerLink="/logout" routerLinkActive="active" class="logoutLink px-1"> <a role="button" [attr.aria-label]="'nav.logout' |translate" [title]="'nav.logout' | translate" routerLink="/logout" routerLinkActive="active" class="logoutLink px-1" role="button" tabindex="0">
<i class="fas fa-sign-out-alt fa-lg fa-fw"></i> <i class="fas fa-sign-out-alt fa-lg fa-fw"></i>
<span class="sr-only">(current)</span> <span class="sr-only">(current)</span>
</a> </a>

View File

@@ -10,7 +10,9 @@
role="tab" role="tab"
[routerLink]="option.routerLink" [routerLink]="option.routerLink"
[queryParams]="option.params" [queryParams]="option.params"
[class.active]="(currentOption$ | async)?.id === option.id"> [class.active]="(currentOption$ | async)?.id === option.id"
role="tab"
tabindex="0">
{{ option.label | translate }} {{ option.label | translate }}
</a> </a>
} }

View File

@@ -3,6 +3,6 @@
@if (title) { @if (title) {
<span class="mb-0">{{ title | translate }}</span> <span class="mb-0">{{ title | translate }}</span>
} }
<a [href]="getHandle()">{{getHandle()}}</a> <a [href]="getHandle()" role="link" tabindex="0">{{getHandle()}}</a>
</p> </p>
} }

View File

@@ -5,7 +5,9 @@
[queryParams]="(bitstreamPath$| async)?.queryParams" [queryParams]="(bitstreamPath$| async)?.queryParams"
[target]="isBlank ? '_blank': '_self'" [target]="isBlank ? '_blank': '_self'"
[ngClass]="cssClasses" [ngClass]="cssClasses"
[attr.aria-label]="('file-download-link.download' | translate) + dsoNameService.getName(bitstream)"> [attr.aria-label]="('file-download-link.download' | translate) + dsoNameService.getName(bitstream)"
role="link"
tabindex="0">
@if ((canDownload$ | async) === false && (canDownloadWithToken$ | async) === false) { @if ((canDownload$ | async) === false && (canDownloadWithToken$ | async) === false) {
<!-- If the user cannot download the file by auth or token, show a lock icon --> <!-- If the user cannot download the file by auth or token, show a lock icon -->
<span role="img" [attr.aria-label]="'file-download-link.restricted' | translate" class="pr-1"><i class="fas fa-lock"></i></span> <span role="img" [attr.aria-label]="'file-download-link.restricted' | translate" class="pr-1"><i class="fas fa-lock"></i></span>

View File

@@ -40,5 +40,9 @@
.col-form-label { .col-form-label {
padding-top: 0; padding-top: 0;
padding-bottom: 0; padding-bottom: 0;
margin-bottom: 0.5rem; margin-bottom: 0.25rem;
}
label {
margin-bottom: 0.25rem;
} }

View File

@@ -7,10 +7,10 @@
[formGroupName]="model.id" [formGroupName]="model.id"
[ngClass]="model.layout.element?.control"> [ngClass]="model.layout.element?.control">
@for (columnItems of items; track columnItems) { @for (columnItems of items; track columnItems) {
<div class="col-sm ms-3"> <div class="col-sm">
@for (item of columnItems; track item) { @for (item of columnItems; track item) {
<div class="custom-control custom-checkbox"> <div class="form-check">
<input type="checkbox" class="custom-control-input" <input type="checkbox" class="form-check-input"
[attr.aria-labelledby]="'label_' + model.id" [attr.aria-labelledby]="'label_' + model.id"
[attr.tabindex]="item.index" [attr.tabindex]="item.index"
[checked]="item.value" [checked]="item.value"
@@ -21,7 +21,7 @@
(blur)="onBlur($event)" (blur)="onBlur($event)"
(change)="onChange($event)" (change)="onChange($event)"
(focus)="onFocus($event)"/> (focus)="onFocus($event)"/>
<label class="custom-control-label" <label class="form-check-label"
[class.disabled]="model.disabled" [class.disabled]="model.disabled"
[ngClass]="model.layout.element?.control" [ngClass]="model.layout.element?.control"
[for]="item.id"> [for]="item.id">
@@ -43,10 +43,10 @@
[ngClass]="model.layout.element?.control" [ngClass]="model.layout.element?.control"
(change)="onChange($event)"> (change)="onChange($event)">
@for (columnItems of items; track columnItems) { @for (columnItems of items; track columnItems) {
<div class="col-sm ms-3"> <div class="col-sm">
@for (item of columnItems; track item) { @for (item of columnItems; track item) {
<div class="custom-control custom-radio"> <div class="form-check">
<input type="radio" class="custom-control-input" <input type="radio" class="form-check-input"
[checked]="item.value" [checked]="item.value"
[id]="item.id" [id]="item.id"
[name]="model.id" [name]="model.id"
@@ -54,7 +54,7 @@
[value]="item.index" [value]="item.index"
(blur)="onBlur($event)" (blur)="onBlur($event)"
(focus)="onFocus($event)"/> (focus)="onFocus($event)"/>
<label class="custom-control-label" <label class="form-check-label"
[class.disabled]="model.disabled" [class.disabled]="model.disabled"
[ngClass]="model.layout.element?.control" [ngClass]="model.layout.element?.control"
[for]="item.id"> [for]="item.id">

View File

@@ -179,8 +179,8 @@ describe('DsDynamicListComponent test suite', () => {
}); });
it('should set model value properly when a checkbox option is selected', () => { it('should set model value properly when a checkbox option is selected', () => {
const de = listFixture.debugElement.queryAll(By.css('div.custom-checkbox')); const de = listFixture.debugElement.queryAll(By.css('div.form-check'));
const items = de[0].queryAll(By.css('input.custom-control-input')); const items = de[0].queryAll(By.css('input.form-check-input'));
const item = items[0]; const item = items[0];
modelValue = [Object.assign(new VocabularyEntry(), { authority: 1, display: 'one', value: 1 })]; modelValue = [Object.assign(new VocabularyEntry(), { authority: 1, display: 'one', value: 1 })];
@@ -229,8 +229,8 @@ describe('DsDynamicListComponent test suite', () => {
}); });
it('should set model value properly when a checkbox option is deselected', () => { it('should set model value properly when a checkbox option is deselected', () => {
const de = listFixture.debugElement.queryAll(By.css('div.custom-checkbox')); const de = listFixture.debugElement.queryAll(By.css('div.form-check'));
const items = de[0].queryAll(By.css('input.custom-control-input')); const items = de[0].queryAll(By.css('input.form-check-input'));
const item = items[0]; const item = items[0];
modelValue = []; modelValue = [];
@@ -267,8 +267,8 @@ describe('DsDynamicListComponent test suite', () => {
}); });
it('should set model value when a radio option is selected', () => { it('should set model value when a radio option is selected', () => {
const de = listFixture.debugElement.queryAll(By.css('div.custom-radio')); const de = listFixture.debugElement.queryAll(By.css('div.form-check'));
const items = de[0].queryAll(By.css('input.custom-control-input')); const items = de[0].queryAll(By.css('input.form-check-input'));
const item = items[0]; const item = items[0];
modelValue = Object.assign(new VocabularyEntry(), { authority: 1, display: 'one', value: 1 }); modelValue = Object.assign(new VocabularyEntry(), { authority: 1, display: 'one', value: 1 });

View File

@@ -3,6 +3,7 @@ import {
DynamicSelectModelConfig, DynamicSelectModelConfig,
} from '@ng-dynamic-forms/core'; } from '@ng-dynamic-forms/core';
import { environment } from '../../../../../environments/environment';
import { isNotEmpty } from '../../../empty.util'; import { isNotEmpty } from '../../../empty.util';
import { import {
DsDynamicInputModel, DsDynamicInputModel,
@@ -90,6 +91,7 @@ export class OneboxFieldParser extends FieldParser {
return new DynamicOneboxModel(oneboxModelConfig); return new DynamicOneboxModel(oneboxModelConfig);
} else { } else {
const inputModelConfig: DsDynamicInputModelConfig = this.initModel(null, label); const inputModelConfig: DsDynamicInputModelConfig = this.initModel(null, label);
inputModelConfig.spellCheck = environment.form.spellCheck;
this.setValues(inputModelConfig, fieldValue); this.setValues(inputModelConfig, fieldValue);
return new DsDynamicInputModel(inputModelConfig); return new DsDynamicInputModel(inputModelConfig);

View File

@@ -9,21 +9,21 @@
[placeholder]="'vocabulary-treeview.search.form.search-placeholder' | translate"> [placeholder]="'vocabulary-treeview.search.form.search-placeholder' | translate">
<div class="input-group-append" id="button-addon4"> <div class="input-group-append" id="button-addon4">
<button class="btn btn-outline-primary" type="button" (click)="search()" [dsBtnDisabled]="!isSearchEnabled()" <button class="btn btn-outline-primary" type="button" (click)="search()" [dsBtnDisabled]="!isSearchEnabled()"
[attr.aria-label]="'vocabulary-treeview.search.form.search' | translate"> [attr.aria-label]="'vocabulary-treeview.search.form.search' | translate" role="button" tabindex="0">
{{'vocabulary-treeview.search.form.search' | translate}} {{'vocabulary-treeview.search.form.search' | translate}}
</button> </button>
<button class="btn btn-outline-secondary" type="button" (click)="reset()" <button class="btn btn-outline-secondary" type="button" (click)="reset()"
[attr.aria-label]="'vocabulary-treeview.search.form.reset' | translate"> [attr.aria-label]="'vocabulary-treeview.search.form.reset' | translate" role="button" tabindex="0">
{{'vocabulary-treeview.search.form.reset' | translate}} {{'vocabulary-treeview.search.form.reset' | translate}}
</button> </button>
@if (showAdd && this.vocabularyOptions.closed) { @if (showAdd && this.vocabularyOptions.closed) {
<button class="btn btn-outline-primary" type="button" (click)="add()" <button class="btn btn-outline-primary" type="button" (click)="add()"
[attr.aria-label]="'vocabulary-treeview.search.form.add' | translate"> [attr.aria-label]="'vocabulary-treeview.search.form.add' | translate" role="button" tabindex="0">
{{'vocabulary-treeview.search.form.add' | translate}} {{'vocabulary-treeview.search.form.add' | translate}}
</button> </button>
} }
<button class="btn btn-outline-primary" type="button" (click)="add()" [dsBtnDisabled]="this.vocabularyOptions.closed" <button class="btn btn-outline-primary" type="button" (click)="add()" [dsBtnDisabled]="this.vocabularyOptions.closed"
[attr.aria-label]="'vocabulary-treeview.search.form.add' | translate"> [attr.aria-label]="'vocabulary-treeview.search.form.add' | translate" role="button" tabindex="0">
{{'vocabulary-treeview.search.form.add' | translate}} {{'vocabulary-treeview.search.form.add' | translate}}
</button> </button>
</div> </div>
@@ -59,6 +59,8 @@
[(ngModel)]="node.isSelected" [(ngModel)]="node.isSelected"
[checked]="node.isSelected" [checked]="node.isSelected"
(change)="onSelect(node.item)" (change)="onSelect(node.item)"
role="checkbox"
tabindex="0"
> >
<span>{{node.item.display}}</span> <span>{{node.item.display}}</span>
</label> </label>
@@ -70,7 +72,9 @@
[ngbTooltip]="node.item?.otherInformation?.note" [ngbTooltip]="node.item?.otherInformation?.note"
[openDelay]="500" [openDelay]="500"
container="body" container="body"
(click)="onSelect(node.item)"> (click)="onSelect(node.item)"
role="button"
tabindex="0">
<span>{{node.item.display}}</span> <span>{{node.item.display}}</span>
</button> </button>
} }
@@ -80,7 +84,11 @@
<cdk-tree-node *cdkTreeNodeDef="let node; when: hasChildren" cdkTreeNodePadding class="d-flex"> <cdk-tree-node *cdkTreeNodeDef="let node; when: hasChildren" cdkTreeNodePadding class="d-flex">
<button type="button" class="btn btn-default px-2 me-1 btn-transparent" cdkTreeNodeToggle <button type="button" class="btn btn-default px-2 me-1 btn-transparent" cdkTreeNodeToggle
[attr.aria-label]="'toggle ' + node.name" [attr.aria-label]="'toggle ' + node.name"
(click)="loadChildren(node)"> (click)="loadChildren(node)"
(keydown.enter)="loadChildren(node)"
(keydown.space)="loadChildren(node)"
role="button"
tabindex="0">
<i class="fas fa-fw {{treeControl.isExpanded(node) ? 'fa-angle-down' : 'fa-angle-right'}}"></i> <i class="fas fa-fw {{treeControl.isExpanded(node) ? 'fa-angle-down' : 'fa-angle-right'}}"></i>
</button> </button>
@@ -95,6 +103,8 @@
[(ngModel)]="node.isSelected" [(ngModel)]="node.isSelected"
[checked]="node.isSelected" [checked]="node.isSelected"
(change)="onSelect(node.item)" (change)="onSelect(node.item)"
role="checkbox"
tabindex="0"
> >
<span>{{node.item.display}}</span> <span>{{node.item.display}}</span>
</label> </label>
@@ -106,7 +116,9 @@
[ngbTooltip]="node.item?.otherInformation?.note" [ngbTooltip]="node.item?.otherInformation?.note"
[openDelay]="500" [openDelay]="500"
container="body" container="body"
(click)="onSelect(node.item)"> (click)="onSelect(node.item)"
role="button"
tabindex="0">
<span>{{node.item.display}}</span> <span>{{node.item.display}}</span>
</button> </button>
} }
@@ -114,14 +126,14 @@
<cdk-tree-node *cdkTreeNodeDef="let node; when: isLoadMore" cdkTreeNodePadding> <cdk-tree-node *cdkTreeNodeDef="let node; when: isLoadMore" cdkTreeNodePadding>
<button class="btn btn-outline-secondary btn-sm" (click)="loadMore(node.loadMoreParentItem)" <button class="btn btn-outline-secondary btn-sm" (click)="loadMore(node.loadMoreParentItem)"
[attr.aria-label]="'vocabulary-treeview.load-more' | translate"> [attr.aria-label]="'vocabulary-treeview.load-more' | translate" role="button" tabindex="0">
{{'vocabulary-treeview.load-more' | translate}}... {{'vocabulary-treeview.load-more' | translate}}...
</button> </button>
</cdk-tree-node> </cdk-tree-node>
<cdk-tree-node *cdkTreeNodeDef="let node; when: isLoadMoreRoot"> <cdk-tree-node *cdkTreeNodeDef="let node; when: isLoadMoreRoot">
<button class="btn btn-outline-secondary btn-sm" (click)="loadMoreRoot(node)" <button class="btn btn-outline-secondary btn-sm" (click)="loadMoreRoot(node)"
[attr.aria-label]="'vocabulary-treeview.load-more' | translate"> [attr.aria-label]="'vocabulary-treeview.load-more' | translate" role="button" tabindex="0">
{{'vocabulary-treeview.load-more' | translate}}... {{'vocabulary-treeview.load-more' | translate}}...
</button> </button>
</cdk-tree-node> </cdk-tree-node>

View File

@@ -1,3 +1,3 @@
<button class="btn btn-lg btn-primary w-100 text-white" (click)="redirectToExternalProvider()"> <button class="btn btn-lg btn-primary w-100 text-white" (click)="redirectToExternalProvider()" role="button" tabindex="0">
<i class="fas fa-sign-in-alt"></i> {{getButtonLabel() | translate}} <i class="fas fa-sign-in-alt"></i> {{getButtonLabel() | translate}}
</button> </button>

View File

@@ -28,18 +28,18 @@
} }
<button class="btn btn-lg btn-primary w-100" type="submit" [attr.data-test]="'login-button' | dsBrowserOnly" <button class="btn btn-lg btn-primary w-100" type="submit" [attr.data-test]="'login-button' | dsBrowserOnly"
[dsBtnDisabled]="!form.valid"><i class="fas fa-sign-in-alt"></i> {{"login.form.submit" | translate}}</button> [dsBtnDisabled]="!form.valid" role="button" tabindex="0"><i class="fas fa-sign-in-alt"></i> {{"login.form.submit" | translate}}</button>
</form> </form>
@if (canShowDivider$ | async) { @if (canShowDivider$ | async) {
<div class="mt-2"> <div class="mt-2">
@if (canRegister$ | async) { @if (canRegister$ | async) {
<a class="dropdown-item" [routerLink]="[getRegisterRoute()]" <a class="dropdown-item" [routerLink]="[getRegisterRoute()]"
[attr.data-test]="'register' | dsBrowserOnly" role="menuitem">{{"login.form.new-user" | translate}}</a> [attr.data-test]="'register' | dsBrowserOnly" role="menuitem" tabindex="0">{{"login.form.new-user" | translate}}</a>
} }
@if (canForgot$ | async) { @if (canForgot$ | async) {
<a class="dropdown-item" [routerLink]="[getForgotRoute()]" <a class="dropdown-item" [routerLink]="[getForgotRoute()]"
[attr.data-test]="'forgot' | dsBrowserOnly" role="menuitem">{{"login.form.forgot-password" | translate}}</a> [attr.data-test]="'forgot' | dsBrowserOnly" role="menuitem" tabindex="0">{{"login.form.forgot-password" | translate}}</a>
} }
</div> </div>
} }

View File

@@ -8,4 +8,5 @@
(keyup.space)="navigate($event)" (keyup.space)="navigate($event)"
(keydown.enter)="navigate($event)" (keydown.enter)="navigate($event)"
href="javascript:void(0);" href="javascript:void(0);"
tabindex="0"
>{{item.text | translate}}</a> >{{item.text | translate}}</a>

View File

@@ -1 +1 @@
<span class="ds-menu-item" [class.disabled]="item.disabled">{{item.text | translate}}</span> <span class="ds-menu-item" [class.disabled]="item.disabled" tabindex="0" role="button">{{item.text | translate}}</span>

View File

@@ -1,6 +1,6 @@
<div class="d-flex flex-row"> <div class="d-flex flex-row">
@if (linkType !== linkTypes.None) { @if (linkType !== linkTypes.None) {
<a [target]="(linkType === linkTypes.ExternalLink) ? '_blank' : '_self'" [attr.rel]="(linkType === linkTypes.ExternalLink) ? 'noopener noreferrer' : null" [routerLink]="[]" [queryParams]="queryParams$ | async" [queryParamsHandling]="'merge'" class="lead"> <a [target]="(linkType === linkTypes.ExternalLink) ? '_blank' : '_self'" [attr.rel]="(linkType === linkTypes.ExternalLink) ? 'noopener noreferrer' : null" [routerLink]="[]" [queryParams]="queryParams$ | async" [queryParamsHandling]="'merge'" class="lead" role="link" tabindex="0">
{{object.value}} {{object.value}}
</a> </a>
} }

View File

@@ -1,6 +1,6 @@
<div class="d-flex flex-row"> <div class="d-flex flex-row">
@if (linkType !== linkTypes.None) { @if (linkType !== linkTypes.None) {
<a [target]="(linkType === linkTypes.ExternalLink) ? '_blank' : '_self'" [attr.rel]="(linkType === linkTypes.ExternalLink) ? 'noopener noreferrer' : null" [routerLink]="['/collections/' + object.id]" class="lead"> <a [target]="(linkType === linkTypes.ExternalLink) ? '_blank' : '_self'" [attr.rel]="(linkType === linkTypes.ExternalLink) ? 'noopener noreferrer' : null" [routerLink]="['/collections/' + object.id]" class="lead" role="link" tabindex="0">
{{ dsoNameService.getName(object) }} {{ dsoNameService.getName(object) }}
</a> </a>
} }

View File

@@ -1,6 +1,6 @@
<div class="d-flex flex-row"> <div class="d-flex flex-row">
@if (linkType !== linkTypes.None) { @if (linkType !== linkTypes.None) {
<a [target]="(linkType === linkTypes.ExternalLink) ? '_blank' : '_self'" [attr.rel]="(linkType === linkTypes.ExternalLink) ? 'noopener noreferrer' : null" [routerLink]="['/communities/' + object.id]" class="lead"> <a [target]="(linkType === linkTypes.ExternalLink) ? '_blank' : '_self'" [attr.rel]="(linkType === linkTypes.ExternalLink) ? 'noopener noreferrer' : null" [routerLink]="['/communities/' + object.id]" class="lead" role="link" tabindex="0">
{{ dsoNameService.getName(object) }} {{ dsoNameService.getName(object) }}
</a> </a>
} }

View File

@@ -7,7 +7,7 @@
} }
@if ((mdRepresentation.representationType==='plain_text') && isLink()) { @if ((mdRepresentation.representationType==='plain_text') && isLink()) {
<a class="dont-break-out" <a class="dont-break-out"
target="_blank" [href]="mdRepresentation.getValue()"> target="_blank" [href]="mdRepresentation.getValue()" role="link" tabindex="0">
{{mdRepresentation.getValue()}} {{mdRepresentation.getValue()}}
</a> </a>
} }
@@ -18,7 +18,9 @@
<a <a
class="dont-break-out ds-browse-link" class="dont-break-out ds-browse-link"
[routerLink]="['/browse/', mdRepresentation.browseDefinition.id]" [routerLink]="['/browse/', mdRepresentation.browseDefinition.id]"
[queryParams]="getQueryParams()"> [queryParams]="getQueryParams()"
role="link"
tabindex="0">
{{mdRepresentation.getValue()}} {{mdRepresentation.getValue()}}
</a> </a>
} }

View File

@@ -3,7 +3,7 @@
<div class="col-3 col-md-2"> <div class="col-3 col-md-2">
@if (linkType !== linkTypes.None) { @if (linkType !== linkTypes.None) {
<a [target]="(linkType === linkTypes.ExternalLink) ? '_blank' : '_self'" [attr.rel]="(linkType === linkTypes.ExternalLink) ? 'noopener noreferrer' : null" <a [target]="(linkType === linkTypes.ExternalLink) ? '_blank' : '_self'" [attr.rel]="(linkType === linkTypes.ExternalLink) ? 'noopener noreferrer' : null"
[routerLink]="[itemPageRoute]" class="dont-break-out"> [routerLink]="[itemPageRoute]" class="dont-break-out" role="button" tabindex="0">
<ds-thumbnail [thumbnail]="dso?.thumbnail | async" [limitWidth]="true"> <ds-thumbnail [thumbnail]="dso?.thumbnail | async" [limitWidth]="true">
</ds-thumbnail> </ds-thumbnail>
</a> </a>
@@ -28,7 +28,7 @@
@if (linkType !== linkTypes.None) { @if (linkType !== linkTypes.None) {
<a [target]="(linkType === linkTypes.ExternalLink) ? '_blank' : '_self'" [attr.rel]="(linkType === linkTypes.ExternalLink) ? 'noopener noreferrer' : null" <a [target]="(linkType === linkTypes.ExternalLink) ? '_blank' : '_self'" [attr.rel]="(linkType === linkTypes.ExternalLink) ? 'noopener noreferrer' : null"
[routerLink]="[itemPageRoute]" class="lead item-list-title dont-break-out" [routerLink]="[itemPageRoute]" class="lead item-list-title dont-break-out"
[innerHTML]="dsoTitle"></a> [innerHTML]="dsoTitle" role="link" tabindex="0"></a>
} }
@if (linkType === linkTypes.None) { @if (linkType === linkTypes.None) {
<span class="lead item-list-title dont-break-out" <span class="lead item-list-title dont-break-out"

View File

@@ -12,14 +12,14 @@
<div class="col"> <div class="col">
@if (!hideGear) { @if (!hideGear) {
<div ngbDropdown #paginationControls="ngbDropdown" placement="bottom-right" class="d-inline-block float-end"> <div ngbDropdown #paginationControls="ngbDropdown" placement="bottom-right" class="d-inline-block float-end">
<button class="btn btn-secondary" id="paginationControls" ngbDropdownToggle [title]="'pagination.options.description' | translate" [attr.aria-label]="'pagination.options.description' | translate" aria-haspopup="true" aria-expanded="false"><i class="fas fa-cog" aria-hidden="true"></i></button> <button class="btn btn-secondary" id="paginationControls" ngbDropdownToggle [title]="'pagination.options.description' | translate" [attr.aria-label]="'pagination.options.description' | translate" aria-haspopup="true" aria-expanded="false" role="button" tabindex="0"><i class="fas fa-cog" aria-hidden="true"></i></button>
<ul id="paginationControlsDropdownMenu" aria-labelledby="paginationControls" role="menu" ngbDropdownMenu> <ul id="paginationControlsDropdownMenu" aria-labelledby="paginationControls" role="menu" ngbDropdownMenu>
<li role="menuitem"> <li role="menuitem">
<span class="dropdown-header" id="pagination-control_results-per-page" role="heading">{{ 'pagination.results-per-page' | translate}}</span> <span class="dropdown-header" id="pagination-control_results-per-page" role="heading">{{ 'pagination.results-per-page' | translate}}</span>
<ul aria-labelledby="pagination-control_results-per-page" class="list-unstyled" role="listbox"> <ul aria-labelledby="pagination-control_results-per-page" class="list-unstyled" role="listbox">
@for (item of pageSizeOptions; track item) { @for (item of pageSizeOptions; track item) {
<li role="option" [attr.aria-selected]="item === (pageSize$ | async)"> <li role="option" [attr.aria-selected]="item === (pageSize$ | async)">
<button (click)="doPageSizeChange(item)" class="dropdown-item"> <button (click)="doPageSizeChange(item)" class="dropdown-item" role="button" tabindex="0">
<i [ngClass]="{'invisible': item !== (pageSize$ | async) }" class="fas fa-check" aria-hidden="true"></i> {{item}} <i [ngClass]="{'invisible': item !== (pageSize$ | async) }" class="fas fa-check" aria-hidden="true"></i> {{item}}
</button> </button>
</li> </li>
@@ -32,7 +32,7 @@
<ul aria-labelledby="pagination-control_sort-direction" class="list-unstyled" role="listbox"> <ul aria-labelledby="pagination-control_sort-direction" class="list-unstyled" role="listbox">
@for (direction of (sortDirections | dsKeys); track direction) { @for (direction of (sortDirections | dsKeys); track direction) {
<li [attr.aria-selected]="direction.value === (sortDirection$ | async)" role="option"> <li [attr.aria-selected]="direction.value === (sortDirection$ | async)" role="option">
<button class="dropdown-item" (click)="doSortDirectionChange(direction.value)"> <button class="dropdown-item" (click)="doSortDirectionChange(direction.value)" role="button" tabindex="0">
<i [ngClass]="{'invisible': direction.value !== (sortDirection$ |async)}" class="fas fa-check" aria-hidden="true"></i> {{'sorting.' + direction.key | translate}} <i [ngClass]="{'invisible': direction.value !== (sortDirection$ |async)}" class="fas fa-check" aria-hidden="true"></i> {{'sorting.' + direction.key | translate}}
</button> </button>
</li> </li>
@@ -73,12 +73,12 @@
<div class="d-flex justify-content-between"> <div class="d-flex justify-content-between">
<button id="nav-prev" type="button" class="btn btn-outline-primary float-start" <button id="nav-prev" type="button" class="btn btn-outline-primary float-start"
(click)="goPrev()" (click)="goPrev()"
[dsBtnDisabled]="(objects?.payload?.currentPage <= 1) && (paginationOptions?.currentPage <= 1)"> [dsBtnDisabled]="(objects?.payload?.currentPage <= 1) && (paginationOptions?.currentPage <= 1)" role="button" tabindex="0">
<i class="fas fa-angle-left"></i> {{'pagination.previous.button' |translate}} <i class="fas fa-angle-left"></i> {{'pagination.previous.button' |translate}}
</button> </button>
<button id="nav-next" type="button" class="btn btn-outline-primary float-end" <button id="nav-next" type="button" class="btn btn-outline-primary float-end"
(click)="goNext()" (click)="goNext()"
[dsBtnDisabled]="(objects?.payload?.currentPage >= objects?.payload?.totalPages) || (paginationOptions?.currentPage >= objects?.payload?.totalPages)"> [dsBtnDisabled]="(objects?.payload?.currentPage >= objects?.payload?.totalPages) || (paginationOptions?.currentPage >= objects?.payload?.totalPages)" role="button" tabindex="0">
<span [ngbTooltip]="objects?.payload?.currentPage >= objects?.payload?.totalPages ? ('pagination.next.button.disabled.tooltip' |translate) : null"> <span [ngbTooltip]="objects?.payload?.currentPage >= objects?.payload?.totalPages ? ('pagination.next.button.disabled.tooltip' |translate) : null">
<i class="fas fa-angle-right"></i> {{'pagination.next.button' |translate}} <i class="fas fa-angle-right"></i> {{'pagination.next.button' |translate}}
</span> </span>

View File

@@ -1,4 +1,4 @@
<button class="btn btn-secondary btn-sm mb-2 ng-tns-c242-28" (click)="back()"> <button class="btn btn-secondary btn-sm mb-2 ng-tns-c242-28" (click)="back()" role="button" tabindex="0">
<i _ngcontent-dspace-angular-c242="" class="fas fa-arrow-left ng-tns-c242-3"></i> <i _ngcontent-dspace-angular-c242="" class="fas fa-arrow-left ng-tns-c242-3"></i>
{{this.buttonLabel | async}} {{this.buttonLabel | async}}
</button> </button>

View File

@@ -2,7 +2,7 @@
@if (route$ | async; as route) { @if (route$ | async; as route) {
<div class="d-inline-block float-end margin-right"> <div class="d-inline-block float-end margin-right">
<a target="_blank" rel="noopener noreferrer" [href]="route" class="btn btn-secondary" <a target="_blank" rel="noopener noreferrer" [href]="route" class="btn btn-secondary"
[title]="'feed.description' | translate" [attr.aria-label]="'feed.description' | translate"> [title]="'feed.description' | translate" [attr.aria-label]="'feed.description' | translate" role="button" tabindex="0">
<i class="fas fa-rss-square"></i> <i class="fas fa-rss-square"></i>
</a> </a>
</div> </div>

View File

@@ -4,14 +4,14 @@
@if (showScopeSelector) { @if (showScopeSelector) {
<button class="scope-button btn btn-outline-secondary text-truncate" <button class="scope-button btn btn-outline-secondary text-truncate"
[ngbTooltip]="dsoNameService.getName(selectedScope | async)" type="button" [ngbTooltip]="dsoNameService.getName(selectedScope | async)" type="button"
(click)="openScopeModal()"> (click)="openScopeModal()" role="button" tabindex="0">
{{dsoNameService.getName(selectedScope | async) || ('search.form.scope.all' | translate)}} {{dsoNameService.getName(selectedScope | async) || ('search.form.scope.all' | translate)}}
</button> </button>
} }
<input type="text" [(ngModel)]="query" name="query" class="form-control" <input type="text" [(ngModel)]="query" name="query" class="form-control"
[attr.aria-label]="searchPlaceholder" [attr.data-test]="'search-box' | dsBrowserOnly" [attr.aria-label]="searchPlaceholder" [attr.data-test]="'search-box' | dsBrowserOnly"
[placeholder]="searchPlaceholder"> [placeholder]="searchPlaceholder" tabindex="0">
<button type="submit" class="search-button btn btn-{{brandColor}}" [attr.data-test]="'search-button' | dsBrowserOnly"><i class="fas fa-search"></i> {{ ('search.form.search' | translate) }}</button> <button type="submit" class="search-button btn btn-{{brandColor}}" [attr.data-test]="'search-button' | dsBrowserOnly" role="button" tabindex="0"><i class="fas fa-search"></i> {{ ('search.form.search' | translate) }}</button>
</div> </div>
</div> </div>
</form> </form>

View File

@@ -13,13 +13,13 @@
<div class="clearfix toggle-more-filters"> <div class="clearfix toggle-more-filters">
@if ((isLastPage$ | async) !== true) { @if ((isLastPage$ | async) !== true) {
<a class="float-start" <a class="float-start"
(click)="showMore()" href="javascript:void(0);"> (click)="showMore()" href="javascript:void(0);" role="button" tabindex="0">
{{"search.filters.filter.show-more" | translate}} {{"search.filters.filter.show-more" | translate}}
</a> </a>
} }
@if ((currentPage | async) > 1) { @if ((currentPage | async) > 1) {
<a class="float-end" <a class="float-end"
(click)="showFirstPageOnly()" href="javascript:void(0);"> (click)="showFirstPageOnly()" href="javascript:void(0);" role="button" tabindex="0">
{{"search.filters.filter.show-less" | translate}} {{"search.filters.filter.show-less" | translate}}
</a> </a>
} }

View File

@@ -13,13 +13,13 @@
<div class="clearfix toggle-more-filters"> <div class="clearfix toggle-more-filters">
@if ((isLastPage$ | async) !== true) { @if ((isLastPage$ | async) !== true) {
<a class="float-start" <a class="float-start"
(click)="showMore()" href="javascript:void(0);"> (click)="showMore()" href="javascript:void(0);" role="button" tabindex="0">
{{"search.filters.filter.show-more" | translate}} {{"search.filters.filter.show-more" | translate}}
</a> </a>
} }
@if ((currentPage | async) > 1) { @if ((currentPage | async) > 1) {
<a class="float-end" <a class="float-end"
(click)="showFirstPageOnly()" href="javascript:void(0);"> (click)="showFirstPageOnly()" href="javascript:void(0);" role="button" tabindex="0">
{{"search.filters.filter.show-less" | translate}} {{"search.filters.filter.show-less" | translate}}
</a> </a>
} }

View File

@@ -5,7 +5,7 @@
[queryParams]="addQueryParams$ | async" [queryParams]="addQueryParams$ | async"
(click)="announceFilter(); filterService.minimizeAll()"> (click)="announceFilter(); filterService.minimizeAll()">
<label class="mb-0 d-flex w-100"> <label class="mb-0 d-flex w-100">
<input type="checkbox" [checked]="false" class="my-1 align-self-stretch filter-checkbox"/> <input type="checkbox" [checked]="false" class="my-1 align-self-stretch filter-checkbox" role="checkbox" tabindex="0"/>
<span class="w-100 ps-1 break-facet"> <span class="w-100 ps-1 break-facet">
<span class="float-end badge bg-secondary rounded-pill mt-1 ms-1">{{filterValue.count | dsShortNumber}}</span> <span class="float-end badge bg-secondary rounded-pill mt-1 ms-1">{{filterValue.count | dsShortNumber}}</span>
{{ 'search.filters.' + filterConfig.name + '.' + filterValue.value | translate: {default: filterValue.value} }} {{ 'search.filters.' + filterConfig.name + '.' + filterValue.value | translate: {default: filterValue.value} }}

View File

@@ -2,7 +2,8 @@
<a class="d-flex flex-row" <a class="d-flex flex-row"
(click)="filterService.minimizeAll()" (click)="filterService.minimizeAll()"
[routerLink]="[searchLink]" [routerLink]="[searchLink]"
[queryParams]="changeQueryParams" queryParamsHandling="merge"> [queryParams]="changeQueryParams" queryParamsHandling="merge"
role="button" tabindex="0">
<span class="filter-value px-1">{{filterValue.label}}</span> <span class="filter-value px-1">{{filterValue.label}}</span>
<span class="float-end filter-value-count ms-auto"> <span class="float-end filter-value-count ms-auto">
<span class="badge bg-secondary rounded-pill">{{filterValue.count | dsShortNumber}}</span> <span class="badge bg-secondary rounded-pill">{{filterValue.count | dsShortNumber}}</span>

View File

@@ -4,7 +4,7 @@
[queryParams]="removeQueryParams | async" [queryParams]="removeQueryParams | async"
(click)="searchFilterService.minimizeAll()"> (click)="searchFilterService.minimizeAll()">
<label class="mb-0 d-flex w-100"> <label class="mb-0 d-flex w-100">
<input type="checkbox" [checked]="true" class="my-1 align-self-stretch filter-checkbox"/> <input type="checkbox" [checked]="true" class="my-1 align-self-stretch filter-checkbox" role="checkbox" tabindex="0"/>
<span class="filter-value ps-1 break-facet"> <span class="filter-value ps-1 break-facet">
{{ 'search.filters.' + filterConfig.name + '.' + selectedValue.value | translate: {default: selectedValue.label} }} {{ 'search.filters.' + filterConfig.name + '.' + selectedValue.value | translate: {default: selectedValue.label} }}
</span> </span>

View File

@@ -6,6 +6,8 @@
[attr.aria-expanded]="(collapsed$ | async) !== true" [attr.aria-expanded]="(collapsed$ | async) !== true"
[attr.aria-label]="(((collapsed$ | async) ? 'search.filters.filter.expand' : 'search.filters.filter.collapse') | translate) + ' ' + (('search.filters.filter.' + filter.name + '.head') | translate | lowercase)" [attr.aria-label]="(((collapsed$ | async) ? 'search.filters.filter.expand' : 'search.filters.filter.collapse') | translate) + ' ' + (('search.filters.filter.' + filter.name + '.head') | translate | lowercase)"
[attr.data-test]="'filter-toggle' | dsBrowserOnly" [attr.data-test]="'filter-toggle' | dsBrowserOnly"
role="button"
tabindex="0"
> >
<span class="h4 d-inline-block text-left mt-auto mb-auto dark:text-white text-dark"> <span class="h4 d-inline-block text-left mt-auto mb-auto dark:text-white text-dark">
{{'search.filters.filter.' + filter.name + '.head'| translate}} {{'search.filters.filter.' + filter.name + '.head'| translate}}

View File

@@ -13,13 +13,13 @@
<div class="clearfix toggle-more-filters"> <div class="clearfix toggle-more-filters">
@if ((isLastPage$ | async) !== true) { @if ((isLastPage$ | async) !== true) {
<a class="float-start" <a class="float-start"
(click)="showMore()" href="javascript:void(0);"> (click)="showMore()" href="javascript:void(0);" role="button" tabindex="0">
{{"search.filters.filter.show-more" | translate}} {{"search.filters.filter.show-more" | translate}}
</a> </a>
} }
@if ((currentPage | async) > 1) { @if ((currentPage | async) > 1) {
<a class="float-end" <a class="float-end"
(click)="showFirstPageOnly()" href="javascript:void(0);"> (click)="showFirstPageOnly()" href="javascript:void(0);" role="button" tabindex="0">
{{"search.filters.filter.show-less" | translate}} {{"search.filters.filter.show-less" | translate}}
</a> </a>
} }
@@ -44,7 +44,7 @@
<a <a
href="javascript:void(0);" href="javascript:void(0);"
id="show-{{filterConfig.name}}-tree" id="show-{{filterConfig.name}}-tree"
(click)="showVocabularyTree()"> (click)="showVocabularyTree()" role="button" tabindex="0">
{{'search.filters.filter.show-tree' | translate: {name: ('search.filters.filter.' + filterConfig.name + '.head' | translate | lowercase )} }} {{'search.filters.filter.show-tree' | translate: {name: ('search.filters.filter.' + filterConfig.name + '.head' | translate | lowercase )} }}
</a> </a>
} }

View File

@@ -26,7 +26,7 @@
/> />
</label> </label>
</div> </div>
<button class="sr-only" type="submit"> <button class="sr-only" type="submit" role="button" tabindex="0">
{{'search.filters.search.submit' | translate}} {{'search.filters.search.submit' | translate}}
</button> </button>
</form> </form>
@@ -46,7 +46,7 @@
} }
</div> </div>
} }
<button (click)="onSubmit()" class="btn btn-primary"> <button (click)="onSubmit()" class="btn btn-primary" role="button" tabindex="0">
{{'search.filters.search.submit' | translate}} {{'search.filters.search.submit' | translate}}
</button> </button>
</div> </div>

View File

@@ -13,13 +13,13 @@
<div class="clearfix toggle-more-filters"> <div class="clearfix toggle-more-filters">
@if ((isLastPage$ | async) !== true) { @if ((isLastPage$ | async) !== true) {
<a class="float-start" <a class="float-start"
(click)="showMore()" href="javascript:void(0);"> (click)="showMore()" href="javascript:void(0);" role="button" tabindex="0">
{{"search.filters.filter.show-more" | translate}} {{"search.filters.filter.show-more" | translate}}
</a> </a>
} }
@if ((currentPage | async) > 1) { @if ((currentPage | async) > 1) {
<a class="float-end" <a class="float-end"
(click)="showFirstPageOnly()" href="javascript:void(0);"> (click)="showFirstPageOnly()" href="javascript:void(0);" role="button" tabindex="0">
{{"search.filters.filter.show-less" | translate}} {{"search.filters.filter.show-less" | translate}}
</a> </a>
} }

View File

@@ -55,7 +55,7 @@
{{ 'search.results.no-results' | translate }} {{ 'search.results.no-results' | translate }}
<a [routerLink]="['/search']" <a [routerLink]="['/search']"
[queryParams]="{ query: surroundStringWithQuotes(searchConfig?.query) }" [queryParams]="{ query: surroundStringWithQuotes(searchConfig?.query) }"
queryParamsHandling="merge"> queryParamsHandling="merge" role="link" tabindex="0">
{{"search.results.no-results-link" | translate}} {{"search.results.no-results-link" | translate}}
</a> </a>
</div> </div>

View File

@@ -32,7 +32,7 @@
<div class="mb-3 input-group pt-1 pt-md-0"> <div class="mb-3 input-group pt-1 pt-md-0">
<input class="form-control" placeholder="{{'browse.startsWith.type_date' | translate}}" [attr.aria-label]="'browse.startsWith.type_date.label' |translate" type="text" name="startsWith" <input class="form-control" placeholder="{{'browse.startsWith.type_date' | translate}}" [attr.aria-label]="'browse.startsWith.type_date.label' |translate" type="text" name="startsWith"
formControlName="startsWith" [value]="getStartsWith() ? getStartsWith() : ''"/> formControlName="startsWith" [value]="getStartsWith() ? getStartsWith() : ''"/>
<button class="btn btn-primary" type="submit"><i class="fas fa-book-open"></i> {{ 'browse.startsWith.submit' | translate }}</button> <button class="btn btn-primary" type="submit" role="button" tabindex="0"><i class="fas fa-book-open"></i> {{ 'browse.startsWith.submit' | translate }}</button>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -3,7 +3,7 @@
<div class="row"> <div class="row">
<div class="mb-3 input-group col-sm-12 col-md-6 col-auto"> <div class="mb-3 input-group col-sm-12 col-md-6 col-auto">
<input class="form-control" [attr.aria-label]="'browse.startsWith.input' | translate" placeholder="{{'browse.search-form.placeholder' | translate}}" type="text" name="startsWith" formControlName="startsWith" [value]="getStartsWith()" /> <input class="form-control" [attr.aria-label]="'browse.startsWith.input' | translate" placeholder="{{'browse.search-form.placeholder' | translate}}" type="text" name="startsWith" formControlName="startsWith" [value]="getStartsWith()" />
<button class="btn btn-primary" type="submit"><i class="fas fa-book-open"></i> {{'browse.startsWith.submit' | translate}}</button> <button class="btn btn-primary" type="submit" role="button" tabindex="0"><i class="fas fa-book-open"></i> {{'browse.startsWith.submit' | translate}}</button>
</div> </div>
</div> </div>
<small class="text-muted">{{'browse.startsWith.type_text' | translate}}</small> <small class="text-muted">{{'browse.startsWith.type_text' | translate}}</small>

View File

@@ -10,6 +10,7 @@
(keyup.Space)="toggle()" (keyup.Space)="toggle()"
role="button" role="button"
[attr.aria-expanded]="isExpanded" [attr.aria-expanded]="isExpanded"
tabindex="0"
> >
<i class="fas {{isExpanded ? 'fa-angle-up' : 'fa-angle-down'}}"></i> <i class="fas {{isExpanded ? 'fa-angle-up' : 'fa-angle-down'}}"></i>
<span class="ms-1">{{ 'item.truncatable-part.show-' + (isExpanded ? 'less' : 'more') | translate }}</span> <span class="ms-1">{{ 'item.truncatable-part.show-' + (isExpanded ? 'less' : 'more') | translate }}</span>

View File

@@ -1,5 +1,4 @@
{ {
"401.help": "You're not authorized to access this page. You can use the button below to get back to the home page.", "401.help": "You're not authorized to access this page. You can use the button below to get back to the home page.",
"401.link.home-page": "Take me to the home page", "401.link.home-page": "Take me to the home page",
@@ -640,7 +639,6 @@
"admin.reports.items.title": "Title", "admin.reports.items.title": "Title",
"admin.reports.commons.filters": "Filters", "admin.reports.commons.filters": "Filters",
"admin.reports.commons.additional-data": "Additional data to return", "admin.reports.commons.additional-data": "Additional data to return",
@@ -661,7 +659,6 @@
"admin.reports.commons.filters.matches_all": "Matches all specified filters", "admin.reports.commons.filters.matches_all": "Matches all specified filters",
"admin.reports.commons.filters.property": "Item Property Filters", "admin.reports.commons.filters.property": "Item Property Filters",
"admin.reports.commons.filters.property.is_item": "Is Item - always true", "admin.reports.commons.filters.property.is_item": "Is Item - always true",
@@ -2910,6 +2907,14 @@
"item.preview.oaire.citation.endPage": "Citation end page", "item.preview.oaire.citation.endPage": "Citation end page",
"item.preview.dc.relation.hasversion": "Has version",
"item.preview.dc.relation.ispartofseries": "Is part of series",
"item.preview.dc.rights": "Rights",
"item.preview.dc.identifier.other": "Other Identifier",
"item.preview.dc.relation.issn": "ISSN", "item.preview.dc.relation.issn": "ISSN",
"item.preview.dc.identifier.isbn": "ISBN", "item.preview.dc.identifier.isbn": "ISBN",
@@ -5697,6 +5702,8 @@
"subscriptions.tooltip": "Subscribe", "subscriptions.tooltip": "Subscribe",
"subscriptions.unsubscribe": "Unsubscribe",
"subscriptions.modal.title": "Subscriptions", "subscriptions.modal.title": "Subscriptions",
"subscriptions.modal.type-frequency": "Type and frequency", "subscriptions.modal.type-frequency": "Type and frequency",

View File

@@ -5,7 +5,7 @@
[attr.role]="(isMobile$ | async) ? 'navigation' : 'presentation'" [attr.role]="(isMobile$ | async) ? 'navigation' : 'presentation'"
[attr.aria-label]="(isMobile$ | async) ? ('nav.main.description' | translate) : null" [attr.aria-label]="(isMobile$ | async) ? ('nav.main.description' | translate) : null"
class="h-100 flex-fill d-flex flex-row flex-nowrap justify-content-start align-items-center gapx-3"> class="h-100 flex-fill d-flex flex-row flex-nowrap justify-content-start align-items-center gapx-3">
<a class="d-block my-2 my-md-0" routerLink="/home" [attr.aria-label]="'home.title' | translate"> <a class="d-block my-2 my-md-0" routerLink="/home" [attr.aria-label]="'home.title' | translate" role="button" tabindex="0">
<img id="header-logo" src="assets/images/dspace-logo.svg" [attr.alt]="'menu.header.image.logo' | translate"/> <img id="header-logo" src="assets/images/dspace-logo.svg" [attr.alt]="'menu.header.image.logo' | translate"/>
</a> </a>
@if ((isMobile$ | async) !== true) { @if ((isMobile$ | async) !== true) {

View File

@@ -4,7 +4,7 @@
<div class="d-flex flex-wrap"> <div class="d-flex flex-wrap">
<div> <div>
<h1 class="display-2">DSpace 9</h1> <h1 class="display-2">DSpace 9</h1>
<p><i class="fas fa-circle-info"></i> This site is running DSpace 9. For more information, see the <a href="https://wiki.lyrasis.org/display/DSDOC9x/Release+Notes">DSpace 9 Release Notes</a>.</p> <p><i class="fas fa-circle-info"></i> This site is running DSpace 9. For more information, see the <a href="https://wiki.lyrasis.org/display/DSDOC9x/Release+Notes" role="link" tabindex="0">DSpace 9 Release Notes</a>.</p>
<p class="lead">DSpace is the world leading open source repository platform that enables <p class="lead">DSpace is the world leading open source repository platform that enables
organisations to:</p> organisations to:</p>
</div> </div>
@@ -20,7 +20,7 @@
handle.net and DataCite DOI handle.net and DataCite DOI
</li> </li>
</ul> </ul>
<p>Join an international community of <a href="https://wiki.lyrasis.org/display/DSPACE/DSpace+Positioning" target="_blank">leading institutions using DSpace</a>.</p> <p>Join an international community of <a href="https://wiki.lyrasis.org/display/DSPACE/DSpace+Positioning" target="_blank" role="link" tabindex="0">leading institutions using DSpace</a>.</p>
<p>The test user accounts below have their password set to the name of this <p>The test user accounts below have their password set to the name of this
software in lowercase.</p> software in lowercase.</p>
<ul> <ul>