Merge branch 'feat/rfc' into related_no_alias
This commit is contained in:
commit
cf3a270cd2
1
.github/workflows/ci-run-tests.yml
vendored
1
.github/workflows/ci-run-tests.yml
vendored
|
@ -4,6 +4,7 @@ on:
|
|||
pull_request:
|
||||
branches:
|
||||
- 'main'
|
||||
- 'feat/rfc'
|
||||
paths:
|
||||
- 'client/**'
|
||||
- 'ietf/**'
|
||||
|
|
22
.pnp.cjs
generated
22
.pnp.cjs
generated
|
@ -65,7 +65,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
|
|||
["eslint-plugin-promise", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:6.1.1"],\
|
||||
["eslint-plugin-vue", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:9.14.1"],\
|
||||
["file-saver", "npm:2.0.5"],\
|
||||
["highcharts", "npm:11.0.1"],\
|
||||
["highcharts", "npm:11.1.0"],\
|
||||
["html-validate", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:7.18.1"],\
|
||||
["ical.js", "npm:1.5.0"],\
|
||||
["jquery", "npm:3.7.0"],\
|
||||
|
@ -84,7 +84,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
|
|||
["pinia", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:2.1.3"],\
|
||||
["pinia-plugin-persist", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:1.0.0"],\
|
||||
["pug", "npm:3.0.2"],\
|
||||
["sass", "npm:1.62.1"],\
|
||||
["sass", "npm:1.63.4"],\
|
||||
["seedrandom", "npm:3.0.5"],\
|
||||
["select2", "npm:4.1.0-rc.0"],\
|
||||
["select2-bootstrap-5-theme", "npm:1.3.0"],\
|
||||
|
@ -5487,10 +5487,10 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
|
|||
}]\
|
||||
]],\
|
||||
["highcharts", [\
|
||||
["npm:11.0.1", {\
|
||||
"packageLocation": "./.yarn/cache/highcharts-npm-11.0.1-05a14e3887-773a7b8765.zip/node_modules/highcharts/",\
|
||||
["npm:11.1.0", {\
|
||||
"packageLocation": "./.yarn/cache/highcharts-npm-11.1.0-0d42a04430-f9b8cdc38b.zip/node_modules/highcharts/",\
|
||||
"packageDependencies": [\
|
||||
["highcharts", "npm:11.0.1"]\
|
||||
["highcharts", "npm:11.1.0"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}]\
|
||||
|
@ -7895,7 +7895,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
|
|||
["eslint-plugin-promise", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:6.1.1"],\
|
||||
["eslint-plugin-vue", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:9.14.1"],\
|
||||
["file-saver", "npm:2.0.5"],\
|
||||
["highcharts", "npm:11.0.1"],\
|
||||
["highcharts", "npm:11.1.0"],\
|
||||
["html-validate", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:7.18.1"],\
|
||||
["ical.js", "npm:1.5.0"],\
|
||||
["jquery", "npm:3.7.0"],\
|
||||
|
@ -7914,7 +7914,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
|
|||
["pinia", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:2.1.3"],\
|
||||
["pinia-plugin-persist", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:1.0.0"],\
|
||||
["pug", "npm:3.0.2"],\
|
||||
["sass", "npm:1.62.1"],\
|
||||
["sass", "npm:1.63.4"],\
|
||||
["seedrandom", "npm:3.0.5"],\
|
||||
["select2", "npm:4.1.0-rc.0"],\
|
||||
["select2-bootstrap-5-theme", "npm:1.3.0"],\
|
||||
|
@ -7998,10 +7998,10 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
|
|||
],\
|
||||
"linkType": "HARD"\
|
||||
}],\
|
||||
["npm:1.62.1", {\
|
||||
"packageLocation": "./.yarn/cache/sass-npm-1.62.1-c16d65fd28-1b1b3584b3.zip/node_modules/sass/",\
|
||||
["npm:1.63.4", {\
|
||||
"packageLocation": "./.yarn/cache/sass-npm-1.63.4-bf5f3496c2-12bde5beff.zip/node_modules/sass/",\
|
||||
"packageDependencies": [\
|
||||
["sass", "npm:1.62.1"],\
|
||||
["sass", "npm:1.63.4"],\
|
||||
["chokidar", "npm:3.5.3"],\
|
||||
["immutable", "npm:4.0.0"],\
|
||||
["source-map-js", "npm:1.0.2"]\
|
||||
|
@ -8716,7 +8716,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
|
|||
["less", null],\
|
||||
["postcss", "npm:8.4.23"],\
|
||||
["rollup", "npm:3.21.6"],\
|
||||
["sass", "npm:1.62.1"],\
|
||||
["sass", "npm:1.63.4"],\
|
||||
["stylus", null],\
|
||||
["sugarss", null],\
|
||||
["terser", null]\
|
||||
|
|
Binary file not shown.
Binary file not shown.
BIN
.yarn/cache/sass-npm-1.63.4-bf5f3496c2-12bde5beff.zip
vendored
Normal file
BIN
.yarn/cache/sass-npm-1.63.4-bf5f3496c2-12bde5beff.zip
vendored
Normal file
Binary file not shown.
|
@ -140,10 +140,10 @@ This will create packages under `ietf/static/dist-neue`, which are then served b
|
|||
|
||||
#### Parcel *(Legacy/jQuery)*
|
||||
|
||||
The Datatracker includes these packages from the various Javascript and CSS files in `ietf/static/js` and `ietf/static/css`, respectively.
|
||||
The Datatracker includes these packages from the various Javascript and CSS files in `ietf/static/js` and `ietf/static/css` respectively, bundled using Parcel.
|
||||
Static images are likewise in `ietf/static/images`.
|
||||
|
||||
Whenever changes are made to the files under `ietf/static`, you must re-run `parcel` to package them:
|
||||
Whenever changes are made to the files under `ietf/static`, you must re-run the build command to package them:
|
||||
|
||||
``` shell
|
||||
yarn legacy:build
|
||||
|
|
65
dev/coverage-action/package-lock.json
generated
65
dev/coverage-action/package-lock.json
generated
|
@ -17,8 +17,8 @@
|
|||
"luxon": "3.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint": "8.41.0",
|
||||
"eslint-config-standard": "17.0.0",
|
||||
"eslint": "8.42.0",
|
||||
"eslint-config-standard": "17.1.0",
|
||||
"eslint-plugin-import": "2.27.5",
|
||||
"eslint-plugin-node": "11.1.0",
|
||||
"eslint-plugin-promise": "6.1.1",
|
||||
|
@ -111,9 +111,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@eslint/js": {
|
||||
"version": "8.41.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.41.0.tgz",
|
||||
"integrity": "sha512-LxcyMGxwmTh2lY9FwHPGWOHmYFCZvbrFCBZL4FzSSsxsRPuhrYUg/49/0KDfW8tnIEaEHtfmn6+NPN+1DqaNmA==",
|
||||
"version": "8.42.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.42.0.tgz",
|
||||
"integrity": "sha512-6SWlXpWU5AvId8Ac7zjzmIOqMOba/JWY8XZ4A7q7Gn1Vlfg/SFFIlrtHXt9nPn4op9ZPAkl91Jao+QQv3r/ukw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||
|
@ -126,9 +126,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"node_modules/@humanwhocodes/config-array": {
|
||||
"version": "0.11.8",
|
||||
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz",
|
||||
"integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==",
|
||||
"version": "0.11.10",
|
||||
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz",
|
||||
"integrity": "sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@humanwhocodes/object-schema": "^1.2.1",
|
||||
|
@ -1718,16 +1718,16 @@
|
|||
}
|
||||
},
|
||||
"node_modules/eslint": {
|
||||
"version": "8.41.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.41.0.tgz",
|
||||
"integrity": "sha512-WQDQpzGBOP5IrXPo4Hc0814r4/v2rrIsB0rhT7jtunIalgg6gYXWhRMOejVO8yH21T/FGaxjmFjBMNqcIlmH1Q==",
|
||||
"version": "8.42.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.42.0.tgz",
|
||||
"integrity": "sha512-ulg9Ms6E1WPf67PHaEY4/6E2tEn5/f7FXGzr3t9cBMugOmf1INYvuUwwh1aXQN4MfJ6a5K2iNwP3w4AColvI9A==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@eslint-community/eslint-utils": "^4.2.0",
|
||||
"@eslint-community/regexpp": "^4.4.0",
|
||||
"@eslint/eslintrc": "^2.0.3",
|
||||
"@eslint/js": "8.41.0",
|
||||
"@humanwhocodes/config-array": "^0.11.8",
|
||||
"@eslint/js": "8.42.0",
|
||||
"@humanwhocodes/config-array": "^0.11.10",
|
||||
"@humanwhocodes/module-importer": "^1.0.1",
|
||||
"@nodelib/fs.walk": "^1.2.8",
|
||||
"ajv": "^6.10.0",
|
||||
|
@ -1774,9 +1774,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/eslint-config-standard": {
|
||||
"version": "17.0.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-17.0.0.tgz",
|
||||
"integrity": "sha512-/2ks1GKyqSOkH7JFvXJicu0iMpoojkwB+f5Du/1SC0PtBL+s8v30k9njRZ21pm2drKYm2342jFnGWzttxPmZVg==",
|
||||
"version": "17.1.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-17.1.0.tgz",
|
||||
"integrity": "sha512-IwHwmaBNtDK4zDHQukFDW5u/aTb8+meQWZvNFWkiGmbWjD6bqyuSSBxxXKkCftCUzc1zwCH2m/baCNDLGmuO5Q==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
|
@ -1792,10 +1792,13 @@
|
|||
"url": "https://feross.org/support"
|
||||
}
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"eslint": "^8.0.1",
|
||||
"eslint-plugin-import": "^2.25.2",
|
||||
"eslint-plugin-n": "^15.0.0",
|
||||
"eslint-plugin-n": "^15.0.0 || ^16.0.0 ",
|
||||
"eslint-plugin-promise": "^6.0.0"
|
||||
}
|
||||
},
|
||||
|
@ -6326,9 +6329,9 @@
|
|||
}
|
||||
},
|
||||
"@eslint/js": {
|
||||
"version": "8.41.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.41.0.tgz",
|
||||
"integrity": "sha512-LxcyMGxwmTh2lY9FwHPGWOHmYFCZvbrFCBZL4FzSSsxsRPuhrYUg/49/0KDfW8tnIEaEHtfmn6+NPN+1DqaNmA==",
|
||||
"version": "8.42.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.42.0.tgz",
|
||||
"integrity": "sha512-6SWlXpWU5AvId8Ac7zjzmIOqMOba/JWY8XZ4A7q7Gn1Vlfg/SFFIlrtHXt9nPn4op9ZPAkl91Jao+QQv3r/ukw==",
|
||||
"dev": true
|
||||
},
|
||||
"@gar/promisify": {
|
||||
|
@ -6338,9 +6341,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"@humanwhocodes/config-array": {
|
||||
"version": "0.11.8",
|
||||
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz",
|
||||
"integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==",
|
||||
"version": "0.11.10",
|
||||
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz",
|
||||
"integrity": "sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@humanwhocodes/object-schema": "^1.2.1",
|
||||
|
@ -7531,16 +7534,16 @@
|
|||
"dev": true
|
||||
},
|
||||
"eslint": {
|
||||
"version": "8.41.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.41.0.tgz",
|
||||
"integrity": "sha512-WQDQpzGBOP5IrXPo4Hc0814r4/v2rrIsB0rhT7jtunIalgg6gYXWhRMOejVO8yH21T/FGaxjmFjBMNqcIlmH1Q==",
|
||||
"version": "8.42.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.42.0.tgz",
|
||||
"integrity": "sha512-ulg9Ms6E1WPf67PHaEY4/6E2tEn5/f7FXGzr3t9cBMugOmf1INYvuUwwh1aXQN4MfJ6a5K2iNwP3w4AColvI9A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@eslint-community/eslint-utils": "^4.2.0",
|
||||
"@eslint-community/regexpp": "^4.4.0",
|
||||
"@eslint/eslintrc": "^2.0.3",
|
||||
"@eslint/js": "8.41.0",
|
||||
"@humanwhocodes/config-array": "^0.11.8",
|
||||
"@eslint/js": "8.42.0",
|
||||
"@humanwhocodes/config-array": "^0.11.10",
|
||||
"@humanwhocodes/module-importer": "^1.0.1",
|
||||
"@nodelib/fs.walk": "^1.2.8",
|
||||
"ajv": "^6.10.0",
|
||||
|
@ -7589,9 +7592,9 @@
|
|||
}
|
||||
},
|
||||
"eslint-config-standard": {
|
||||
"version": "17.0.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-17.0.0.tgz",
|
||||
"integrity": "sha512-/2ks1GKyqSOkH7JFvXJicu0iMpoojkwB+f5Du/1SC0PtBL+s8v30k9njRZ21pm2drKYm2342jFnGWzttxPmZVg==",
|
||||
"version": "17.1.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-17.1.0.tgz",
|
||||
"integrity": "sha512-IwHwmaBNtDK4zDHQukFDW5u/aTb8+meQWZvNFWkiGmbWjD6bqyuSSBxxXKkCftCUzc1zwCH2m/baCNDLGmuO5Q==",
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
|
|
|
@ -14,8 +14,8 @@
|
|||
"luxon": "3.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint": "8.41.0",
|
||||
"eslint-config-standard": "17.0.0",
|
||||
"eslint": "8.42.0",
|
||||
"eslint-config-standard": "17.1.0",
|
||||
"eslint-plugin-import": "2.27.5",
|
||||
"eslint-plugin-node": "11.1.0",
|
||||
"eslint-plugin-promise": "6.1.1",
|
||||
|
|
14
dev/del-old-packages/package-lock.json
generated
14
dev/del-old-packages/package-lock.json
generated
|
@ -9,7 +9,7 @@
|
|||
"version": "1.0.0",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@octokit/core": "^4.2.1",
|
||||
"@octokit/core": "^4.2.4",
|
||||
"luxon": "^3.3.0"
|
||||
}
|
||||
},
|
||||
|
@ -25,9 +25,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@octokit/core": {
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/core/-/core-4.2.1.tgz",
|
||||
"integrity": "sha512-tEDxFx8E38zF3gT7sSMDrT1tGumDgsw5yPG6BBh/X+5ClIQfMH/Yqocxz1PnHx6CHyF6pxmovUTOfZAUvQ0Lvw==",
|
||||
"version": "4.2.4",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/core/-/core-4.2.4.tgz",
|
||||
"integrity": "sha512-rYKilwgzQ7/imScn3M9/pFfUf4I1AZEH3KhyJmtPdE2zfaXAn2mFfUy4FbKewzc2We5y/LlKLj36fWJLKC2SIQ==",
|
||||
"dependencies": {
|
||||
"@octokit/auth-token": "^3.0.0",
|
||||
"@octokit/graphql": "^5.0.0",
|
||||
|
@ -215,9 +215,9 @@
|
|||
}
|
||||
},
|
||||
"@octokit/core": {
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/core/-/core-4.2.1.tgz",
|
||||
"integrity": "sha512-tEDxFx8E38zF3gT7sSMDrT1tGumDgsw5yPG6BBh/X+5ClIQfMH/Yqocxz1PnHx6CHyF6pxmovUTOfZAUvQ0Lvw==",
|
||||
"version": "4.2.4",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/core/-/core-4.2.4.tgz",
|
||||
"integrity": "sha512-rYKilwgzQ7/imScn3M9/pFfUf4I1AZEH3KhyJmtPdE2zfaXAn2mFfUy4FbKewzc2We5y/LlKLj36fWJLKC2SIQ==",
|
||||
"requires": {
|
||||
"@octokit/auth-token": "^3.0.0",
|
||||
"@octokit/graphql": "^5.0.0",
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@octokit/core": "^4.2.1",
|
||||
"@octokit/core": "^4.2.4",
|
||||
"luxon": "^3.3.0"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
server {
|
||||
listen 8000 default_server;
|
||||
listen [::]:8000 default_server;
|
||||
|
||||
proxy_read_timeout 1d;
|
||||
proxy_send_timeout 1d;
|
||||
|
||||
root /var/www/html;
|
||||
index index.html index.htm index.nginx-debian.html;
|
||||
|
|
|
@ -22,7 +22,6 @@ echo "Fix chromedriver /dev/shm permissions..."
|
|||
sudo chmod 1777 /dev/shm
|
||||
|
||||
# Run nginx
|
||||
|
||||
echo "Starting nginx..."
|
||||
sudo nginx
|
||||
|
||||
|
@ -30,6 +29,9 @@ sudo nginx
|
|||
echo "Compiling native node packages..."
|
||||
yarn rebuild
|
||||
|
||||
# Silence Browserlist warnings
|
||||
export BROWSERSLIST_IGNORE_OLD_DATA=1
|
||||
|
||||
# Generate static assets
|
||||
echo "Building static assets... (this could take a minute or two)"
|
||||
yarn build
|
||||
|
|
|
@ -12,12 +12,11 @@ from django.core.exceptions import ObjectDoesNotExist
|
|||
|
||||
import debug # pyflakes:ignore
|
||||
|
||||
import tastypie
|
||||
import tastypie.resources
|
||||
import tastypie.serializers
|
||||
from tastypie.api import Api
|
||||
from tastypie.bundle import Bundle
|
||||
from tastypie.exceptions import ApiFieldError
|
||||
from tastypie.serializers import Serializer # pyflakes:ignore (we're re-exporting this)
|
||||
from tastypie.fields import ApiField
|
||||
|
||||
_api_list = []
|
||||
|
@ -152,3 +151,8 @@ class ToOneField(tastypie.fields.ToOneField):
|
|||
dehydrated = self.dehydrate_related(fk_bundle, fk_resource, for_list=for_list)
|
||||
fk_resource._meta.cache.set(cache_key, dehydrated)
|
||||
return dehydrated
|
||||
|
||||
|
||||
class Serializer(tastypie.serializers.Serializer):
|
||||
def format_datetime(self, data):
|
||||
return data.astimezone(datetime.timezone.utc).replace(tzinfo=None).isoformat(timespec="seconds") + "Z"
|
||||
|
|
|
@ -964,11 +964,11 @@ class RfcdiffSupportTests(TestCase):
|
|||
|
||||
def do_rfc_test(self, draft_name):
|
||||
draft = WgDraftFactory(name=draft_name, create_revisions=range(0,2))
|
||||
draft.docalias.create(name=f'rfc{self.next_rfc_number():04}')
|
||||
rfc = WgRfcFactory(group=draft.group, rfc_number=self.next_rfc_number())
|
||||
draft.relateddocument_set.create(relationship_id="became_rfc", target=rfc.docalias.first())
|
||||
draft.set_state(State.objects.get(type_id='draft',slug='rfc'))
|
||||
draft.set_state(State.objects.get(type_id='draft-iesg', slug='pub'))
|
||||
draft = reload_db_objects(draft)
|
||||
rfc = WgRfcFactory(group=draft.group) # todo link this with its pre-publication draft
|
||||
draft, rfc = reload_db_objects(draft, rfc)
|
||||
|
||||
number = rfc.rfc_number
|
||||
received = self.getJson(dict(name=number))
|
||||
|
@ -976,7 +976,7 @@ class RfcdiffSupportTests(TestCase):
|
|||
received,
|
||||
dict(
|
||||
content_url=rfc.get_href(),
|
||||
name=rfc.canonical_name(),
|
||||
name=rfc.name,
|
||||
previous=f'{draft.name}-{draft.rev}',
|
||||
previous_url= draft.history_set.get(rev=draft.rev).get_href(),
|
||||
),
|
||||
|
@ -1016,11 +1016,11 @@ class RfcdiffSupportTests(TestCase):
|
|||
|
||||
def test_rfc_with_tombstone(self):
|
||||
draft = WgDraftFactory(create_revisions=range(0,2))
|
||||
draft.docalias.create(name='rfc3261') # See views_doc.HAS_TOMBSTONE
|
||||
rfc = WgRfcFactory(rfc_number=3261,group=draft.group)# See views_doc.HAS_TOMBSTONE
|
||||
draft.relateddocument_set.create(relationship_id="became_rfc", target=rfc.docalias.first())
|
||||
draft.set_state(State.objects.get(type_id='draft',slug='rfc'))
|
||||
draft.set_state(State.objects.get(type_id='draft-iesg', slug='pub'))
|
||||
draft = reload_db_objects(draft)
|
||||
rfc = draft
|
||||
|
||||
# Some old rfcs had tombstones that shouldn't be used for comparisons
|
||||
received = self.getJson(dict(name=rfc.canonical_name()))
|
||||
|
@ -1028,11 +1028,11 @@ class RfcdiffSupportTests(TestCase):
|
|||
|
||||
def do_rfc_with_broken_history_test(self, draft_name):
|
||||
draft = WgDraftFactory(rev='10', name=draft_name)
|
||||
draft.docalias.create(name=f'rfc{self.next_rfc_number():04}')
|
||||
rfc = WgRfcFactory(group=draft.group, rfc_number=self.next_rfc_number())
|
||||
draft.relateddocument_set.create(relationship_id="became_rfc", target=rfc.docalias.first())
|
||||
draft.set_state(State.objects.get(type_id='draft',slug='rfc'))
|
||||
draft.set_state(State.objects.get(type_id='draft-iesg', slug='pub'))
|
||||
draft = reload_db_objects(draft)
|
||||
rfc = draft
|
||||
|
||||
received = self.getJson(dict(name=draft.name))
|
||||
self.assertEqual(
|
||||
|
|
|
@ -317,12 +317,9 @@ def get_previous_url(name, rev=None):
|
|||
previous_url = ''
|
||||
if condition in ('historic version', 'current version'):
|
||||
doc = history if history else document
|
||||
if found_rev:
|
||||
doc.is_rfc = lambda: False
|
||||
previous_url = doc.get_href()
|
||||
elif condition == 'version dochistory not found':
|
||||
document.rev = found_rev
|
||||
document.is_rfc = lambda: False
|
||||
previous_url = document.get_href()
|
||||
return previous_url
|
||||
|
||||
|
@ -330,22 +327,32 @@ def get_previous_url(name, rev=None):
|
|||
def rfcdiff_latest_json(request, name, rev=None):
|
||||
response = dict()
|
||||
condition, document, history, found_rev = find_doc_for_rfcdiff(name, rev)
|
||||
|
||||
if document.type_id == "rfc":
|
||||
draft_alias = next(iter(document.related_that('became_rfc')), None)
|
||||
if condition == 'no such document':
|
||||
raise Http404
|
||||
elif condition in ('historic version', 'current version'):
|
||||
doc = history if history else document
|
||||
if not found_rev and doc.is_rfc():
|
||||
response['content_url'] = doc.get_href()
|
||||
response['name']=doc.canonical_name()
|
||||
if doc.name != doc.canonical_name():
|
||||
if doc.type_id == "rfc":
|
||||
response['content_url'] = doc.get_href()
|
||||
response['name']=doc.name
|
||||
if draft_alias:
|
||||
draft = draft_alias.document
|
||||
prev_rev = draft.rev
|
||||
if doc.rfc_number in HAS_TOMBSTONE and prev_rev != '00':
|
||||
prev_rev = f'{(int(draft.rev)-1):02d}'
|
||||
response['previous'] = f'{draft.name}-{prev_rev}'
|
||||
response['previous_url'] = get_previous_url(draft.name, prev_rev)
|
||||
elif doc.type_id == "draft" and not found_rev and doc.relateddocument_set.filter(relationship_id="became_rfc").exists():
|
||||
rfc = doc.related_that_doc("became_rfc")[0].document
|
||||
response['content_url'] = rfc.get_href()
|
||||
response['name']=rfc.name
|
||||
prev_rev = doc.rev
|
||||
if doc.rfc_number in HAS_TOMBSTONE and prev_rev != '00':
|
||||
if rfc.rfc_number in HAS_TOMBSTONE and prev_rev != '00':
|
||||
prev_rev = f'{(int(doc.rev)-1):02d}'
|
||||
response['previous'] = f'{doc.name}-{prev_rev}'
|
||||
response['previous_url'] = get_previous_url(doc.name, prev_rev)
|
||||
else:
|
||||
doc.is_rfc = lambda: False
|
||||
response['content_url'] = doc.get_href()
|
||||
response['rev'] = doc.rev
|
||||
response['name'] = doc.name
|
||||
|
@ -371,7 +378,6 @@ def rfcdiff_latest_json(request, name, rev=None):
|
|||
response['name'] = document.name
|
||||
response['rev'] = found_rev
|
||||
document.rev = found_rev
|
||||
document.is_rfc = lambda: False
|
||||
response['content_url'] = document.get_href()
|
||||
# not sure what to do if non-numeric values come back, so at least log it
|
||||
log.assertion('found_rev.isdigit()')
|
||||
|
|
|
@ -116,7 +116,7 @@ class DocumentFactory(BaseDocumentFactory):
|
|||
class RfcFactory(BaseDocumentFactory):
|
||||
type_id = "rfc"
|
||||
rfc_number = factory.Sequence(lambda n: n + 1000)
|
||||
name = factory.LazyAttribute(lambda o: f"rfc{o.rfc_number:04d}")
|
||||
name = factory.LazyAttribute(lambda o: f"rfc{o.rfc_number:d}")
|
||||
expires = None
|
||||
|
||||
@factory.post_generation
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
# Copyright The IETF Trust 2007-2020, All Rights Reserved
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import debug # pyflakes:ignore
|
||||
|
||||
import datetime
|
||||
import unicodedata
|
||||
|
@ -8,8 +9,12 @@ import unicodedata
|
|||
from django.contrib.syndication.views import Feed, FeedDoesNotExist
|
||||
from django.utils.feedgenerator import Atom1Feed, Rss201rev2Feed
|
||||
from django.urls import reverse as urlreverse
|
||||
from django.template.defaultfilters import truncatewords, truncatewords_html, date as datefilter
|
||||
from django.template.defaultfilters import linebreaks # type: ignore
|
||||
from django.template.defaultfilters import (
|
||||
truncatewords,
|
||||
truncatewords_html,
|
||||
date as datefilter,
|
||||
)
|
||||
from django.template.defaultfilters import linebreaks # type: ignore
|
||||
from django.utils import timezone
|
||||
from django.utils.html import strip_tags
|
||||
|
||||
|
@ -21,12 +26,12 @@ from ietf.utils.timezone import RPC_TZINFO
|
|||
|
||||
def strip_control_characters(s):
|
||||
"""Remove Unicode control / non-printing characters from a string"""
|
||||
replacement_char = unicodedata.lookup('REPLACEMENT CHARACTER')
|
||||
return ''.join(
|
||||
replacement_char if unicodedata.category(c)[0] == 'C' else c
|
||||
for c in s
|
||||
replacement_char = unicodedata.lookup("REPLACEMENT CHARACTER")
|
||||
return "".join(
|
||||
replacement_char if unicodedata.category(c)[0] == "C" else c for c in s
|
||||
)
|
||||
|
||||
|
||||
class DocumentChangesFeed(Feed):
|
||||
feed_type = Atom1Feed
|
||||
|
||||
|
@ -39,25 +44,37 @@ class DocumentChangesFeed(Feed):
|
|||
def link(self, obj):
|
||||
if obj is None:
|
||||
raise FeedDoesNotExist
|
||||
return urlreverse('ietf.doc.views_doc.document_history', kwargs=dict(name=obj.canonical_name()))
|
||||
return urlreverse(
|
||||
"ietf.doc.views_doc.document_history",
|
||||
kwargs=dict(name=obj.canonical_name()),
|
||||
)
|
||||
|
||||
def subtitle(self, obj):
|
||||
return "History of change entries for %s." % obj.display_name()
|
||||
|
||||
def items(self, obj):
|
||||
events = obj.docevent_set.all().order_by("-time","-id").select_related("by", "newrevisiondocevent", "submissiondocevent")
|
||||
events = (
|
||||
obj.docevent_set.all()
|
||||
.order_by("-time", "-id")
|
||||
.select_related("by", "newrevisiondocevent", "submissiondocevent")
|
||||
)
|
||||
augment_events_with_revision(obj, events)
|
||||
return events
|
||||
|
||||
def item_title(self, item):
|
||||
return strip_control_characters("[%s] %s [rev. %s]" % (
|
||||
item.by,
|
||||
truncatewords(strip_tags(item.desc), 15),
|
||||
item.rev,
|
||||
))
|
||||
return strip_control_characters(
|
||||
"[%s] %s [rev. %s]"
|
||||
% (
|
||||
item.by,
|
||||
truncatewords(strip_tags(item.desc), 15),
|
||||
item.rev,
|
||||
)
|
||||
)
|
||||
|
||||
def item_description(self, item):
|
||||
return strip_control_characters(truncatewords_html(format_textarea(item.desc), 20))
|
||||
return strip_control_characters(
|
||||
truncatewords_html(format_textarea(item.desc), 20)
|
||||
)
|
||||
|
||||
def item_pubdate(self, item):
|
||||
return item.time
|
||||
|
@ -66,17 +83,28 @@ class DocumentChangesFeed(Feed):
|
|||
return str(item.by)
|
||||
|
||||
def item_link(self, item):
|
||||
return urlreverse('ietf.doc.views_doc.document_history', kwargs=dict(name=item.doc.canonical_name())) + "#history-%s" % item.pk
|
||||
return (
|
||||
urlreverse(
|
||||
"ietf.doc.views_doc.document_history",
|
||||
kwargs=dict(name=item.doc.canonical_name()),
|
||||
)
|
||||
+ "#history-%s" % item.pk
|
||||
)
|
||||
|
||||
|
||||
class InLastCallFeed(Feed):
|
||||
title = "Documents in Last Call"
|
||||
subtitle = "Announcements for documents in last call."
|
||||
feed_type = Atom1Feed
|
||||
author_name = 'IESG Secretary'
|
||||
author_name = "IESG Secretary"
|
||||
link = "/doc/iesg/last-call/"
|
||||
|
||||
def items(self):
|
||||
docs = list(Document.objects.filter(type="draft", states=State.objects.get(type="draft-iesg", slug="lc")))
|
||||
docs = list(
|
||||
Document.objects.filter(
|
||||
type="draft", states=State.objects.get(type="draft-iesg", slug="lc")
|
||||
)
|
||||
)
|
||||
for d in docs:
|
||||
d.lc_event = d.latest_event(LastCallDocEvent, type="sent_last_call")
|
||||
|
||||
|
@ -86,9 +114,11 @@ class InLastCallFeed(Feed):
|
|||
return docs
|
||||
|
||||
def item_title(self, item):
|
||||
return "%s (%s - %s)" % (item.name,
|
||||
datefilter(item.lc_event.time, "F j"),
|
||||
datefilter(item.lc_event.expires, "F j, Y"))
|
||||
return "%s (%s - %s)" % (
|
||||
item.name,
|
||||
datefilter(item.lc_event.time, "F j"),
|
||||
datefilter(item.lc_event.expires, "F j, Y"),
|
||||
)
|
||||
|
||||
def item_description(self, item):
|
||||
return strip_control_characters(linebreaks(item.lc_event.desc))
|
||||
|
@ -96,33 +126,55 @@ class InLastCallFeed(Feed):
|
|||
def item_pubdate(self, item):
|
||||
return item.lc_event.time
|
||||
|
||||
|
||||
class Rss201WithNamespacesFeed(Rss201rev2Feed):
|
||||
def root_attributes(self):
|
||||
attrs = super(Rss201WithNamespacesFeed, self).root_attributes()
|
||||
attrs['xmlns:dcterms'] = 'http://purl.org/dc/terms/'
|
||||
attrs['xmlns:media'] = 'http://search.yahoo.com/mrss/'
|
||||
attrs['xmlns:xsi'] = 'http://www.w3.org/2001/XMLSchema-instance'
|
||||
attrs["xmlns:dcterms"] = "http://purl.org/dc/terms/"
|
||||
attrs["xmlns:media"] = "http://search.yahoo.com/mrss/"
|
||||
attrs["xmlns:xsi"] = "http://www.w3.org/2001/XMLSchema-instance"
|
||||
return attrs
|
||||
|
||||
def add_item_elements(self, handler, item):
|
||||
super(Rss201WithNamespacesFeed, self).add_item_elements(handler, item)
|
||||
|
||||
for element_name in ['abstract','accessRights', 'format', 'publisher',]:
|
||||
dc_item_name = 'dcterms_%s' % element_name
|
||||
dc_element_name = 'dcterms:%s' % element_name
|
||||
attrs= {'xsi:type':'dcterms:local'} if element_name == 'publisher' else {}
|
||||
for element_name in [
|
||||
"abstract",
|
||||
"accessRights",
|
||||
"format",
|
||||
"publisher",
|
||||
]:
|
||||
dc_item_name = "dcterms_%s" % element_name
|
||||
dc_element_name = "dcterms:%s" % element_name
|
||||
attrs = {"xsi:type": "dcterms:local"} if element_name == "publisher" else {}
|
||||
if dc_item_name in item and item[dc_item_name] is not None:
|
||||
handler.addQuickElement(dc_element_name,item[dc_item_name],attrs)
|
||||
handler.addQuickElement(dc_element_name, item[dc_item_name], attrs)
|
||||
|
||||
if 'doi' in item and item['doi'] is not None:
|
||||
handler.addQuickElement('dcterms:identifier',item['doi'],{'xsi:type':'dcterms:doi'})
|
||||
if 'doiuri' in item and item['doiuri'] is not None:
|
||||
handler.addQuickElement('dcterms:identifier',item['doiuri'],{'xsi:type':'dcterms:uri'})
|
||||
if "doi" in item and item["doi"] is not None:
|
||||
handler.addQuickElement(
|
||||
"dcterms:identifier", item["doi"], {"xsi:type": "dcterms:doi"}
|
||||
)
|
||||
if "doiuri" in item and item["doiuri"] is not None:
|
||||
handler.addQuickElement(
|
||||
"dcterms:identifier", item["doiuri"], {"xsi:type": "dcterms:uri"}
|
||||
)
|
||||
|
||||
# TODO: consider using media:group
|
||||
if "media_contents" in item and item["media_contents"] is not None:
|
||||
for media_content in item["media_contents"]:
|
||||
handler.startElement(
|
||||
"media:content",
|
||||
{
|
||||
"url": media_content["url"],
|
||||
"type": media_content["media_type"],
|
||||
},
|
||||
)
|
||||
if "is_format_of" in media_content:
|
||||
handler.addQuickElement(
|
||||
"dcterms:isFormatOf", media_content["is_format_of"]
|
||||
)
|
||||
handler.endElement("media:content")
|
||||
|
||||
if 'media_content' in item and item['media_content'] is not None:
|
||||
handler.startElement('media:content',{'url':item['media_content']['url'],'type':'text/plain'})
|
||||
handler.addQuickElement('dcterms:isFormatOf',item['media_content']['link_url'])
|
||||
handler.endElement('media:content')
|
||||
|
||||
class RfcFeed(Feed):
|
||||
feed_type = Rss201WithNamespacesFeed
|
||||
|
@ -130,55 +182,96 @@ class RfcFeed(Feed):
|
|||
author_name = "RFC Editor"
|
||||
link = "https://www.rfc-editor.org/rfc-index2.html"
|
||||
|
||||
def get_object(self,request,year=None):
|
||||
def get_object(self, request, year=None):
|
||||
self.year = year
|
||||
|
||||
|
||||
def items(self):
|
||||
if self.year:
|
||||
# Find published RFCs based on their official publication year
|
||||
start_of_year = datetime.datetime(int(self.year), 1, 1, tzinfo=RPC_TZINFO)
|
||||
start_of_next_year = datetime.datetime(int(self.year) + 1, 1, 1, tzinfo=RPC_TZINFO)
|
||||
start_of_next_year = datetime.datetime(
|
||||
int(self.year) + 1, 1, 1, tzinfo=RPC_TZINFO
|
||||
)
|
||||
rfc_events = DocEvent.objects.filter(
|
||||
type='published_rfc',
|
||||
type="published_rfc",
|
||||
time__gte=start_of_year,
|
||||
time__lt=start_of_next_year,
|
||||
).order_by('-time')
|
||||
).order_by("-time")
|
||||
else:
|
||||
cutoff = timezone.now() - datetime.timedelta(days=8)
|
||||
rfc_events = DocEvent.objects.filter(type='published_rfc',time__gte=cutoff).order_by('-time')
|
||||
rfc_events = DocEvent.objects.filter(
|
||||
type="published_rfc", time__gte=cutoff
|
||||
).order_by("-time")
|
||||
results = [(e.doc, e.time) for e in rfc_events]
|
||||
for doc,time in results:
|
||||
for doc, time in results:
|
||||
doc.publication_time = time
|
||||
return [doc for doc,time in results]
|
||||
|
||||
return [doc for doc, time in results]
|
||||
|
||||
def item_title(self, item):
|
||||
return "%s : %s" % (item.canonical_name(),item.title)
|
||||
return "%s : %s" % (item.canonical_name(), item.title)
|
||||
|
||||
def item_description(self, item):
|
||||
return item.abstract
|
||||
|
||||
def item_link(self, item):
|
||||
return "https://rfc-editor.org/info/%s"%item.canonical_name()
|
||||
return "https://rfc-editor.org/info/%s" % item.canonical_name()
|
||||
|
||||
def item_pubdate(self, item):
|
||||
return item.publication_time
|
||||
|
||||
def item_extra_kwargs(self, item):
|
||||
extra = super(RfcFeed, self).item_extra_kwargs(item)
|
||||
extra.update({'dcterms_accessRights': 'gratis'})
|
||||
extra.update({'dcterms_format': 'text/html'})
|
||||
extra.update({'media_content': {'url': 'https://rfc-editor.org/rfc/%s.txt' % item.canonical_name(),
|
||||
'link_url': self.item_link(item)
|
||||
}
|
||||
})
|
||||
extra.update({'doi':'10.17487/%s' % item.canonical_name().upper()})
|
||||
extra.update({'doiuri':'http://dx.doi.org/10.17487/%s' % item.canonical_name().upper()})
|
||||
extra.update({"dcterms_accessRights": "gratis"})
|
||||
extra.update({"dcterms_format": "text/html"})
|
||||
media_contents = []
|
||||
if item.rfc_number < 8650:
|
||||
if item.rfc_number not in [8, 9, 51, 418, 500, 530, 589]:
|
||||
for fmt, media_type in [("txt", "text/plain"), ("html", "text/html")]:
|
||||
media_contents.append(
|
||||
{
|
||||
"url": f"https://rfc-editor.org/rfc/{item.canonical_name()}.{fmt}",
|
||||
"media_type": media_type,
|
||||
"is_format_of": self.item_link(item),
|
||||
}
|
||||
)
|
||||
if item.rfc_number not in [571, 587]:
|
||||
media_contents.append(
|
||||
{
|
||||
"url": f"https://www.rfc-editor.org/rfc/pdfrfc/{item.canonical_name()}.txt.pdf",
|
||||
"media_type": "application/pdf",
|
||||
"is_format_of": self.item_link(item),
|
||||
}
|
||||
)
|
||||
else:
|
||||
media_contents.append(
|
||||
{
|
||||
"url": f"https://www.rfc-editor.org/rfc/{item.canonical_name()}.xml",
|
||||
"media_type": "application/rfc+xml",
|
||||
}
|
||||
)
|
||||
for fmt, media_type in [
|
||||
("txt", "text/plain"),
|
||||
("html", "text/html"),
|
||||
("pdf", "application/pdf"),
|
||||
]:
|
||||
media_contents.append(
|
||||
{
|
||||
"url": f"https://rfc-editor.org/rfc/{item.canonical_name()}.{fmt}",
|
||||
"media_type": media_type,
|
||||
"is_format_of": f"https://www.rfc-editor.org/rfc/{item.canonical_name()}.xml",
|
||||
}
|
||||
)
|
||||
extra.update({"media_contents": media_contents})
|
||||
|
||||
extra.update({"doi": "10.17487/%s" % item.canonical_name().upper()})
|
||||
extra.update(
|
||||
{"doiuri": "http://dx.doi.org/10.17487/%s" % item.canonical_name().upper()}
|
||||
)
|
||||
|
||||
#TODO
|
||||
# R104 Publisher (Mandatory - but we need a string from them first)
|
||||
extra.update({'dcterms_publisher':'rfc-editor.org'})
|
||||
extra.update({"dcterms_publisher": "rfc-editor.org"})
|
||||
|
||||
#TODO MAYBE (Optional stuff)
|
||||
# TODO MAYBE (Optional stuff)
|
||||
# R108 License
|
||||
# R115 Creator/Contributor (which would we use?)
|
||||
# F305 Checksum (do they use it?) (or should we put the our digital signature in here somewhere?)
|
||||
|
@ -188,4 +281,3 @@ class RfcFeed(Feed):
|
|||
# R118 Keyword
|
||||
|
||||
return extra
|
||||
|
||||
|
|
|
@ -148,7 +148,7 @@ class AddDownrefForm(forms.Form):
|
|||
raise forms.ValidationError("Please provide a referenced RFC and a referencing Internet-Draft")
|
||||
|
||||
rfc = self.cleaned_data['rfc']
|
||||
if not rfc.is_rfc():
|
||||
if rfc.document.type_id != "rfc":
|
||||
raise forms.ValidationError("Cannot find the RFC: " + rfc.name)
|
||||
return rfc
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ from ietf.doc.models import Document
|
|||
from ietf.group.utils import get_group_role_emails, get_group_ad_emails
|
||||
from ietf.utils.aliases import dump_sublist
|
||||
from utils.mail import parseaddr
|
||||
from ietf.utils import log
|
||||
|
||||
DEFAULT_YEARS = 2
|
||||
|
||||
|
@ -120,16 +121,19 @@ class Command(BaseCommand):
|
|||
vfile.write("%s anything\n" % settings.DRAFT_VIRTUAL_DOMAIN)
|
||||
|
||||
# Internet-Drafts with active status or expired within DEFAULT_YEARS
|
||||
drafts = Document.objects.filter(name__startswith='draft-')
|
||||
drafts = Document.objects.filter(type_id="draft")
|
||||
active_drafts = drafts.filter(states__slug='active')
|
||||
inactive_recent_drafts = drafts.exclude(states__slug='active').filter(expires__gte=show_since)
|
||||
interesting_drafts = active_drafts | inactive_recent_drafts
|
||||
|
||||
alias_domains = ['ietf.org', ]
|
||||
for draft in interesting_drafts.distinct().iterator():
|
||||
# Omit RFCs, unless they were published in the last DEFAULT_YEARS
|
||||
if draft.docalias.filter(name__startswith='rfc'):
|
||||
if draft.latest_event(type='published_rfc').time < show_since:
|
||||
# Omit drafts that became RFCs, unless they were published in the last DEFAULT_YEARS
|
||||
if draft.get_state_slug()=="rfc":
|
||||
rfc_alias = next(iter(draft.related_that_doc("became_rfc")), None)
|
||||
log.assertion("rfc_alias is not None")
|
||||
rfc = rfc_alias.document
|
||||
if rfc.latest_event(type='published_rfc').time < show_since:
|
||||
continue
|
||||
|
||||
alias = draft.name
|
||||
|
|
|
@ -24,7 +24,7 @@ def forward(apps, schema_editor):
|
|||
assert set(found_by_name) == set(found_by_state), "mismatch between rfcs identified by state and docalias"
|
||||
|
||||
# As of 2023-06-15, there is one Document with two rfc aliases: rfc6312 and rfc6342 are the same Document. This
|
||||
# was due to a publication error. We'll handle that specially.
|
||||
# was due to a publication error. Because we go alias-by-alias, no special handling is needed in this migration.
|
||||
|
||||
for rfc_alias in rfc_docaliases.order_by("name"):
|
||||
assert rfc_alias.docs.count() == 1, f"DocAlias {rfc_alias} is linked to more than 1 Document"
|
||||
|
@ -40,11 +40,15 @@ def forward(apps, schema_editor):
|
|||
type=rfc_doctype,
|
||||
name=rfc_alias.name,
|
||||
rfc_number=int(rfc_alias.name[3:]),
|
||||
time=draft.time,
|
||||
title=draft.title,
|
||||
stream=draft.stream,
|
||||
group=draft.group,
|
||||
abstract=draft.abstract,
|
||||
pages=draft.pages,
|
||||
words=draft.words,
|
||||
std_level=draft.std_level,
|
||||
ad=draft.ad,
|
||||
external_url=draft.external_url,
|
||||
uploaded_filename=draft.uploaded_filename,
|
||||
note=draft.note,
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
# Generated by Django 4.2.2 on 2023-06-20 18:36
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
def forward(apps, schema_editor):
|
||||
"""Point "rfc..." DocAliases at the rfc-type Document"""
|
||||
DocAlias = apps.get_model("doc", "DocAlias")
|
||||
Document = apps.get_model("doc", "Document")
|
||||
for rfc_alias in DocAlias.objects.filter(name__startswith="rfc"):
|
||||
rfc = Document.objects.get(name=rfc_alias.name)
|
||||
rfc_alias.docs.set([rfc])
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("doc", "0008_move_rfc_docevents"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(forward),
|
||||
]
|
45
ietf/doc/migrations/0009_rfc_relateddocuments.py
Normal file
45
ietf/doc/migrations/0009_rfc_relateddocuments.py
Normal file
|
@ -0,0 +1,45 @@
|
|||
# Generated by Django 4.2.3 on 2023-07-05 22:40
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
def forward(apps, schema_editor):
|
||||
DocAlias = apps.get_model("doc", "DocAlias")
|
||||
Document = apps.get_model("doc", "Document")
|
||||
RelatedDocument = apps.get_model("doc", "RelatedDocument")
|
||||
for rfc_alias in DocAlias.objects.filter(name__startswith="rfc").exclude(
|
||||
docs__type__slug="rfc"
|
||||
):
|
||||
# Move these over to the RFC
|
||||
RelatedDocument.objects.filter(
|
||||
relationship__slug__in=(
|
||||
"tobcp",
|
||||
"toexp",
|
||||
"tohist",
|
||||
"toinf",
|
||||
"tois",
|
||||
"tops",
|
||||
"obs",
|
||||
"updates",
|
||||
),
|
||||
source__docalias=rfc_alias,
|
||||
).update(source=Document.objects.get(name=rfc_alias.name))
|
||||
# Duplicate references on the RFC but keep the ones on the draft as well
|
||||
originals = list(
|
||||
RelatedDocument.objects.filter(
|
||||
relationship__slug__in=("refinfo", "refnorm", "refold", "refunk"),
|
||||
source__docalias=rfc_alias,
|
||||
)
|
||||
)
|
||||
for o in originals:
|
||||
o.pk = None
|
||||
o.source = Document.objects.get(name=rfc_alias.name)
|
||||
RelatedDocument.objects.bulk_create(originals)
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("doc", "0008_move_rfc_docevents"),
|
||||
]
|
||||
|
||||
operations = [migrations.RunPython(forward)]
|
38
ietf/doc/migrations/0010_move_rfc_docaliases.py
Normal file
38
ietf/doc/migrations/0010_move_rfc_docaliases.py
Normal file
|
@ -0,0 +1,38 @@
|
|||
# Generated by Django 4.2.2 on 2023-06-20 18:36
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
def forward(apps, schema_editor):
|
||||
"""Point "rfc..." DocAliases at the rfc-type Document
|
||||
|
||||
Creates a became_rfc RelatedDocument to preserve the connection between the draft and the rfc.
|
||||
"""
|
||||
DocAlias = apps.get_model("doc", "DocAlias")
|
||||
Document = apps.get_model("doc", "Document")
|
||||
RelatedDocument = apps.get_model("doc", "RelatedDocument")
|
||||
|
||||
for rfc_alias in DocAlias.objects.filter(name__startswith="rfc"):
|
||||
rfc = Document.objects.get(name=rfc_alias.name)
|
||||
aliased_doc = rfc_alias.docs.get() # implicitly confirms only one value in rfc_alias.docs
|
||||
if aliased_doc != rfc:
|
||||
# If the DocAlias was not already pointing at the rfc, it was pointing at the draft
|
||||
# it came from. Create the relationship between draft and rfc Documents.
|
||||
assert aliased_doc.type_id == "draft", f"Alias for {rfc.name} should be pointing at a draft"
|
||||
RelatedDocument.objects.create(
|
||||
source=aliased_doc,
|
||||
target=rfc_alias,
|
||||
relationship_id="became_rfc",
|
||||
)
|
||||
# Now move the alias from the draft to the rfc
|
||||
rfc_alias.docs.set([rfc])
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("doc", "0009_rfc_relateddocuments"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(forward),
|
||||
]
|
|
@ -137,18 +137,17 @@ class DocumentInfo(models.Model):
|
|||
|
||||
def get_file_path(self):
|
||||
if not hasattr(self, '_cached_file_path'):
|
||||
if self.type_id == "draft":
|
||||
if self.type_id == "rfc":
|
||||
self._cached_file_path = settings.RFC_PATH
|
||||
elif self.type_id == "draft":
|
||||
if self.is_dochistory():
|
||||
self._cached_file_path = settings.INTERNET_ALL_DRAFTS_ARCHIVE_DIR
|
||||
else:
|
||||
if self.get_state_slug() == "rfc":
|
||||
self._cached_file_path = settings.RFC_PATH
|
||||
draft_state = self.get_state('draft')
|
||||
if draft_state and draft_state.slug == 'active':
|
||||
self._cached_file_path = settings.INTERNET_DRAFT_PATH
|
||||
else:
|
||||
draft_state = self.get_state('draft')
|
||||
if draft_state and draft_state.slug == 'active':
|
||||
self._cached_file_path = settings.INTERNET_DRAFT_PATH
|
||||
else:
|
||||
self._cached_file_path = settings.INTERNET_ALL_DRAFTS_ARCHIVE_DIR
|
||||
self._cached_file_path = settings.INTERNET_ALL_DRAFTS_ARCHIVE_DIR
|
||||
elif self.meeting_related() and self.type_id in (
|
||||
"agenda", "minutes", "slides", "bluesheets", "procmaterials", "chatlog", "polls"
|
||||
):
|
||||
|
@ -173,14 +172,13 @@ class DocumentInfo(models.Model):
|
|||
if not hasattr(self, '_cached_base_name'):
|
||||
if self.uploaded_filename:
|
||||
self._cached_base_name = self.uploaded_filename
|
||||
elif self.type_id == 'rfc':
|
||||
self._cached_base_name = "%s.txt" % self.canonical_name()
|
||||
elif self.type_id == 'draft':
|
||||
if self.is_dochistory():
|
||||
self._cached_base_name = "%s-%s.txt" % (self.doc.name, self.rev)
|
||||
else:
|
||||
if self.get_state_slug() == 'rfc':
|
||||
self._cached_base_name = "%s.txt" % self.canonical_name()
|
||||
else:
|
||||
self._cached_base_name = "%s-%s.txt" % (self.name, self.rev)
|
||||
self._cached_base_name = "%s-%s.txt" % (self.name, self.rev)
|
||||
elif self.type_id in ["slides", "agenda", "minutes", "bluesheets", "procmaterials", ] and self.meeting_related():
|
||||
ext = 'pdf' if self.type_id == 'procmaterials' else 'txt'
|
||||
self._cached_base_name = f'{self.canonical_name()}-{self.rev}.{ext}'
|
||||
|
@ -245,7 +243,7 @@ class DocumentInfo(models.Model):
|
|||
format = settings.DOC_HREFS[self.type_id]
|
||||
elif self.type_id in settings.DOC_HREFS:
|
||||
self.is_meeting_related = False
|
||||
if self.is_rfc():
|
||||
if self.type_id == "rfc":
|
||||
format = settings.DOC_HREFS['rfc']
|
||||
else:
|
||||
format = settings.DOC_HREFS[self.type_id]
|
||||
|
@ -348,10 +346,9 @@ class DocumentInfo(models.Model):
|
|||
iesg_state_summary = iesg_state_summary + "::"+"::".join(tag.name for tag in iesg_substate)
|
||||
|
||||
if state.slug == "rfc":
|
||||
# todo check this once became-rfc relationships are actually created
|
||||
rfcs = self.related_that("became-rfc") # should be only one
|
||||
rfcs = self.related_that_doc("became_rfc") # should be only one
|
||||
if len(rfcs) > 0:
|
||||
rfc = rfcs[0]
|
||||
rfc = rfcs[0].document
|
||||
return f"Became RFC {rfc.rfc_number} ({rfc.std_level})"
|
||||
else:
|
||||
return "Became RFC"
|
||||
|
@ -384,9 +381,6 @@ class DocumentInfo(models.Model):
|
|||
else:
|
||||
return state.name
|
||||
|
||||
def is_rfc(self):
|
||||
return self.type_id == "rfc"
|
||||
|
||||
def author_list(self):
|
||||
best_addresses = []
|
||||
for author in self.documentauthor_set.all():
|
||||
|
@ -646,10 +640,20 @@ class DocumentInfo(models.Model):
|
|||
return self.relations_that_doc(('refnorm','refinfo','refunk','refold'))
|
||||
|
||||
def referenced_by(self):
|
||||
return self.relations_that(('refnorm','refinfo','refunk','refold')).filter(source__states__type__slug='draft',source__states__slug__in=['rfc','active'])
|
||||
|
||||
return self.relations_that(("refnorm", "refinfo", "refunk", "refold")).filter(
|
||||
models.Q(
|
||||
source__type__slug="draft",
|
||||
source__states__type__slug="draft",
|
||||
source__states__slug="active",
|
||||
)
|
||||
| models.Q(source__type__slug="rfc")
|
||||
)
|
||||
|
||||
|
||||
def referenced_by_rfcs(self):
|
||||
return self.relations_that(('refnorm','refinfo','refunk','refold')).filter(source__states__type__slug='draft',source__states__slug='rfc')
|
||||
return self.relations_that(("refnorm", "refinfo", "refunk", "refold")).filter(
|
||||
source__type__slug="rfc"
|
||||
)
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
@ -681,7 +685,7 @@ class RelatedDocument(models.Model):
|
|||
if source_lvl not in ['bcp','ps','ds','std']:
|
||||
return None
|
||||
|
||||
if self.target.get_state().slug == 'rfc':
|
||||
if self.target.type_id == 'rfc':
|
||||
if not self.target.std_level:
|
||||
target_lvl = 'unkn'
|
||||
else:
|
||||
|
@ -704,8 +708,8 @@ class RelatedDocument(models.Model):
|
|||
|
||||
def is_approved_downref(self):
|
||||
|
||||
if self.target.get_state().slug == 'rfc':
|
||||
if RelatedDocument.objects.filter(relationship_id='downref-approval', target=self.target):
|
||||
if self.target.type_id == 'rfc':
|
||||
if RelatedDocument.objects.filter(relationship_id='downref-approval', target=self.target).exists():
|
||||
return "Approved Downref"
|
||||
|
||||
return False
|
||||
|
@ -1002,7 +1006,7 @@ class Document(DocumentInfo):
|
|||
|
||||
This is the rfc publication date for RFCs, and the new-revision date for other documents.
|
||||
"""
|
||||
if self.get_state_slug() == "rfc":
|
||||
if self.type_id == "rfc":
|
||||
# As of Sept 2022, in ietf.sync.rfceditor.update_docs_from_rfc_index() `published_rfc` events are
|
||||
# created with a timestamp whose date *in the PST8PDT timezone* is the official publication date
|
||||
# assigned by the RFC editor.
|
||||
|
|
|
@ -556,7 +556,7 @@ def consensus(doc):
|
|||
@register.filter
|
||||
def std_level_to_label_format(doc):
|
||||
"""Returns valid Bootstrap classes to label a status level badge."""
|
||||
if doc.is_rfc():
|
||||
if doc.type_id == "rfc":
|
||||
if doc.related_that("obs"):
|
||||
return "obs"
|
||||
else:
|
||||
|
|
|
@ -619,7 +619,6 @@ Man Expires September 22, 2015 [Page 3]
|
|||
def test_document_draft(self):
|
||||
draft = WgDraftFactory(name='draft-ietf-mars-test',rev='01', create_revisions=range(0,2))
|
||||
|
||||
|
||||
HolderIprDisclosureFactory(docs=[draft])
|
||||
|
||||
# Docs for testing relationships. Does not test 'possibly-replaces'. The 'replaced_by' direction
|
||||
|
@ -635,7 +634,7 @@ Man Expires September 22, 2015 [Page 3]
|
|||
updated_by = IndividualDraftFactory()
|
||||
updated_by.relateddocument_set.create(relationship_id='updates',source=obsoleted_by,target=draft)
|
||||
|
||||
external_resource = DocExtResourceFactory(doc=draft)
|
||||
DocExtResourceFactory(doc=draft)
|
||||
|
||||
# these tests aren't testing all attributes yet, feel free to
|
||||
# expand them
|
||||
|
@ -648,16 +647,6 @@ Man Expires September 22, 2015 [Page 3]
|
|||
self.assertNotContains(r, "Deimos street")
|
||||
self.assertContains(r, replaced.canonical_name())
|
||||
self.assertContains(r, replaced.title)
|
||||
# obs/updates not included until draft is RFC
|
||||
self.assertNotContains(r, obsoleted.canonical_name())
|
||||
self.assertNotContains(r, obsoleted.title)
|
||||
self.assertNotContains(r, obsoleted_by.canonical_name())
|
||||
self.assertNotContains(r, obsoleted_by.title)
|
||||
self.assertNotContains(r, updated.canonical_name())
|
||||
self.assertNotContains(r, updated.title)
|
||||
self.assertNotContains(r, updated_by.canonical_name())
|
||||
self.assertNotContains(r, updated_by.title)
|
||||
self.assertContains(r, external_resource.value)
|
||||
|
||||
r = self.client.get(urlreverse("ietf.doc.views_doc.document_main", kwargs=dict(name=draft.name)) + "?include_text=0")
|
||||
self.assertEqual(r.status_code, 200)
|
||||
|
@ -666,15 +655,6 @@ Man Expires September 22, 2015 [Page 3]
|
|||
self.assertNotContains(r, "Deimos street")
|
||||
self.assertContains(r, replaced.canonical_name())
|
||||
self.assertContains(r, replaced.title)
|
||||
# obs/updates not included until draft is RFC
|
||||
self.assertNotContains(r, obsoleted.canonical_name())
|
||||
self.assertNotContains(r, obsoleted.title)
|
||||
self.assertNotContains(r, obsoleted_by.canonical_name())
|
||||
self.assertNotContains(r, obsoleted_by.title)
|
||||
self.assertNotContains(r, updated.canonical_name())
|
||||
self.assertNotContains(r, updated.title)
|
||||
self.assertNotContains(r, updated_by.canonical_name())
|
||||
self.assertNotContains(r, updated_by.title)
|
||||
|
||||
r = self.client.get(urlreverse("ietf.doc.views_doc.document_main", kwargs=dict(name=draft.name)) + "?include_text=foo")
|
||||
self.assertEqual(r.status_code, 200)
|
||||
|
@ -683,15 +663,6 @@ Man Expires September 22, 2015 [Page 3]
|
|||
self.assertContains(r, "Deimos street")
|
||||
self.assertContains(r, replaced.canonical_name())
|
||||
self.assertContains(r, replaced.title)
|
||||
# obs/updates not included until draft is RFC
|
||||
self.assertNotContains(r, obsoleted.canonical_name())
|
||||
self.assertNotContains(r, obsoleted.title)
|
||||
self.assertNotContains(r, obsoleted_by.canonical_name())
|
||||
self.assertNotContains(r, obsoleted_by.title)
|
||||
self.assertNotContains(r, updated.canonical_name())
|
||||
self.assertNotContains(r, updated.title)
|
||||
self.assertNotContains(r, updated_by.canonical_name())
|
||||
self.assertNotContains(r, updated_by.title)
|
||||
|
||||
r = self.client.get(urlreverse("ietf.doc.views_doc.document_main", kwargs=dict(name=draft.name)) + "?include_text=1")
|
||||
self.assertEqual(r.status_code, 200)
|
||||
|
@ -700,15 +671,6 @@ Man Expires September 22, 2015 [Page 3]
|
|||
self.assertContains(r, "Deimos street")
|
||||
self.assertContains(r, replaced.canonical_name())
|
||||
self.assertContains(r, replaced.title)
|
||||
# obs/updates not included until draft is RFC
|
||||
self.assertNotContains(r, obsoleted.canonical_name())
|
||||
self.assertNotContains(r, obsoleted.title)
|
||||
self.assertNotContains(r, obsoleted_by.canonical_name())
|
||||
self.assertNotContains(r, obsoleted_by.title)
|
||||
self.assertNotContains(r, updated.canonical_name())
|
||||
self.assertNotContains(r, updated.title)
|
||||
self.assertNotContains(r, updated_by.canonical_name())
|
||||
self.assertNotContains(r, updated_by.title)
|
||||
|
||||
self.client.cookies = SimpleCookie({str('full_draft'): str('on')})
|
||||
r = self.client.get(urlreverse("ietf.doc.views_doc.document_main", kwargs=dict(name=draft.name)))
|
||||
|
@ -718,15 +680,6 @@ Man Expires September 22, 2015 [Page 3]
|
|||
self.assertContains(r, "Deimos street")
|
||||
self.assertContains(r, replaced.canonical_name())
|
||||
self.assertContains(r, replaced.title)
|
||||
# obs/updates not included until draft is RFC
|
||||
self.assertNotContains(r, obsoleted.canonical_name())
|
||||
self.assertNotContains(r, obsoleted.title)
|
||||
self.assertNotContains(r, obsoleted_by.canonical_name())
|
||||
self.assertNotContains(r, obsoleted_by.title)
|
||||
self.assertNotContains(r, updated.canonical_name())
|
||||
self.assertNotContains(r, updated.title)
|
||||
self.assertNotContains(r, updated_by.canonical_name())
|
||||
self.assertNotContains(r, updated_by.title)
|
||||
|
||||
self.client.cookies = SimpleCookie({str('full_draft'): str('off')})
|
||||
r = self.client.get(urlreverse("ietf.doc.views_doc.document_main", kwargs=dict(name=draft.name)))
|
||||
|
@ -736,15 +689,6 @@ Man Expires September 22, 2015 [Page 3]
|
|||
self.assertNotContains(r, "Deimos street")
|
||||
self.assertContains(r, replaced.canonical_name())
|
||||
self.assertContains(r, replaced.title)
|
||||
# obs/updates not included until draft is RFC
|
||||
self.assertNotContains(r, obsoleted.canonical_name())
|
||||
self.assertNotContains(r, obsoleted.title)
|
||||
self.assertNotContains(r, obsoleted_by.canonical_name())
|
||||
self.assertNotContains(r, obsoleted_by.title)
|
||||
self.assertNotContains(r, updated.canonical_name())
|
||||
self.assertNotContains(r, updated.title)
|
||||
self.assertNotContains(r, updated_by.canonical_name())
|
||||
self.assertNotContains(r, updated_by.title)
|
||||
|
||||
self.client.cookies = SimpleCookie({str('full_draft'): str('foo')})
|
||||
r = self.client.get(urlreverse("ietf.doc.views_doc.document_main", kwargs=dict(name=draft.name)))
|
||||
|
@ -755,15 +699,6 @@ Man Expires September 22, 2015 [Page 3]
|
|||
self.assertNotContains(r, "Deimos street")
|
||||
self.assertContains(r, replaced.canonical_name())
|
||||
self.assertContains(r, replaced.title)
|
||||
# obs/updates not included until draft is RFC
|
||||
self.assertNotContains(r, obsoleted.canonical_name())
|
||||
self.assertNotContains(r, obsoleted.title)
|
||||
self.assertNotContains(r, obsoleted_by.canonical_name())
|
||||
self.assertNotContains(r, obsoleted_by.title)
|
||||
self.assertNotContains(r, updated.canonical_name())
|
||||
self.assertNotContains(r, updated.title)
|
||||
self.assertNotContains(r, updated_by.canonical_name())
|
||||
self.assertNotContains(r, updated_by.title)
|
||||
|
||||
r = self.client.get(urlreverse("ietf.doc.views_doc.document_html", kwargs=dict(name=draft.name)))
|
||||
self.assertEqual(r.status_code, 200)
|
||||
|
@ -831,26 +766,29 @@ Man Expires September 22, 2015 [Page 3]
|
|||
|
||||
# draft published as RFC
|
||||
draft.set_state(State.objects.get(type="draft", slug="rfc"))
|
||||
draft.std_level_id = "bcp"
|
||||
draft.save_with_history([DocEvent.objects.create(doc=draft, rev=draft.rev, type="published_rfc", by=Person.objects.get(name="(System)"))])
|
||||
draft.std_level_id = "ps"
|
||||
|
||||
rfc = WgRfcFactory(group=draft.group, name="rfc123456")
|
||||
rfc.save_with_history([DocEvent.objects.create(doc=rfc, rev=None, type="published_rfc", by=Person.objects.get(name="(System)"))])
|
||||
|
||||
rfc_alias = DocAlias.objects.create(name="rfc123456")
|
||||
rfc_alias.docs.add(draft)
|
||||
bcp_alias = DocAlias.objects.create(name="bcp123456")
|
||||
bcp_alias.docs.add(draft)
|
||||
draft.relateddocument_set.create(relationship_id="became_rfc", target=rfc.docalias.first())
|
||||
|
||||
obsoleted = IndividualRfcFactory()
|
||||
rfc.relateddocument_set.create(relationship_id='obs',target=obsoleted.docalias.first())
|
||||
obsoleted_by = IndividualRfcFactory()
|
||||
obsoleted_by.relateddocument_set.create(relationship_id='obs',target=rfc.docalias.first())
|
||||
updated = IndividualRfcFactory()
|
||||
rfc.relateddocument_set.create(relationship_id='updates',target=updated.docalias.first())
|
||||
updated_by = IndividualRfcFactory()
|
||||
updated_by.relateddocument_set.create(relationship_id='updates',target=rfc.docalias.first())
|
||||
|
||||
r = self.client.get(urlreverse("ietf.doc.views_doc.document_main", kwargs=dict(name=draft.name)))
|
||||
self.assertEqual(r.status_code, 302)
|
||||
r = self.client.get(urlreverse("ietf.doc.views_doc.document_main", kwargs=dict(name=bcp_alias.name)))
|
||||
self.assertEqual(r.status_code, 302)
|
||||
|
||||
r = self.client.get(urlreverse("ietf.doc.views_doc.document_main", kwargs=dict(name=rfc_alias.name)))
|
||||
r = self.client.get(urlreverse("ietf.doc.views_doc.document_main", kwargs=dict(name=rfc.name)))
|
||||
self.assertEqual(r.status_code, 200)
|
||||
self.assertContains(r, "RFC 123456")
|
||||
self.assertContains(r, draft.name)
|
||||
self.assertContains(r, replaced.canonical_name())
|
||||
self.assertContains(r, replaced.title)
|
||||
# obs/updates included with RFC
|
||||
self.assertContains(r, obsoleted.canonical_name())
|
||||
self.assertContains(r, obsoleted.title)
|
||||
|
@ -1490,11 +1428,11 @@ Man Expires September 22, 2015 [Page 3]
|
|||
self.assertEqual(r.status_code, 200)
|
||||
self.assert_correct_wg_group_link(r, group)
|
||||
|
||||
rfc = WgRfcFactory(name='draft-rfc-document-%s' % group_type_id, group=group)
|
||||
rfc = WgRfcFactory(group=group)
|
||||
draft = WgDraftFactory(group=group)
|
||||
draft.relateddocument_set.create(relationship_id="became_rfc", target=rfc.docalias.first())
|
||||
DocEventFactory.create(doc=rfc, type='published_rfc', time=event_datetime)
|
||||
# get the rfc name to avoid a redirect
|
||||
rfc_name = rfc.docalias.filter(name__startswith='rfc').first().name
|
||||
r = self.client.get(urlreverse("ietf.doc.views_doc.document_main", kwargs=dict(name=rfc_name)))
|
||||
r = self.client.get(urlreverse("ietf.doc.views_doc.document_main", kwargs=dict(name=rfc.name)))
|
||||
self.assertEqual(r.status_code, 200)
|
||||
self.assert_correct_wg_group_link(r, group)
|
||||
|
||||
|
@ -1505,11 +1443,11 @@ Man Expires September 22, 2015 [Page 3]
|
|||
self.assertEqual(r.status_code, 200)
|
||||
self.assert_correct_non_wg_group_link(r, group)
|
||||
|
||||
rfc = WgRfcFactory(name='draft-rfc-document-%s' % group_type_id, group=group)
|
||||
rfc = WgRfcFactory(group=group)
|
||||
draft = WgDraftFactory(name='draft-rfc-document-%s'% group_type_id, group=group)
|
||||
draft.relateddocument_set.create(relationship_id="became_rfc", target=rfc.docalias.first())
|
||||
DocEventFactory.create(doc=rfc, type='published_rfc', time=event_datetime)
|
||||
# get the rfc name to avoid a redirect
|
||||
rfc_name = rfc.docalias.filter(name__startswith='rfc').first().name
|
||||
r = self.client.get(urlreverse("ietf.doc.views_doc.document_main", kwargs=dict(name=rfc_name)))
|
||||
r = self.client.get(urlreverse("ietf.doc.views_doc.document_main", kwargs=dict(name=rfc.name)))
|
||||
self.assertEqual(r.status_code, 200)
|
||||
self.assert_correct_non_wg_group_link(r, group)
|
||||
|
||||
|
@ -1611,7 +1549,7 @@ class DocTestCase(TestCase):
|
|||
r = self.client.get(urlreverse("ietf.doc.views_doc.document_main", kwargs=dict(name=statchg.name)))
|
||||
self.assertEqual(r.status_code, 200)
|
||||
r = self.client.get(urlreverse("ietf.doc.views_doc.document_main", kwargs=dict(name=statchg.relateddocument_set.first().target)))
|
||||
self.assertEqual(r.status_code, 302)
|
||||
self.assertEqual(r.status_code, 200)
|
||||
|
||||
def test_document_charter(self):
|
||||
CharterFactory(name='charter-ietf-mars')
|
||||
|
@ -1853,15 +1791,14 @@ class DocTestCase(TestCase):
|
|||
self.assertContains(r, e.desc)
|
||||
|
||||
def test_history_bis_00(self):
|
||||
rfcname='rfc9090'
|
||||
rfc = WgRfcFactory(alias2=rfcname)
|
||||
bis_draft = WgDraftFactory(name='draft-ietf-{}-{}bis'.format(rfc.group.acronym,rfcname))
|
||||
rfc = WgRfcFactory(rfc_number=9090)
|
||||
bis_draft = WgDraftFactory(name='draft-ietf-{}-{}bis'.format(rfc.group.acronym,rfc.name))
|
||||
|
||||
url = urlreverse('ietf.doc.views_doc.document_history', kwargs=dict(name=bis_draft.name))
|
||||
r = self.client.get(url)
|
||||
self.assertEqual(r.status_code, 200)
|
||||
q = PyQuery(unicontent(r))
|
||||
attr1='value="{}"'.format(rfcname)
|
||||
attr1='value="{}"'.format(rfc.name)
|
||||
self.assertEqual(len(q('option['+attr1+'][selected="selected"]')), 1)
|
||||
|
||||
|
||||
|
@ -1911,11 +1848,31 @@ class DocTestCase(TestCase):
|
|||
self.assertContains(r, doc.name)
|
||||
|
||||
def test_rfc_feed(self):
|
||||
WgRfcFactory()
|
||||
rfc = WgRfcFactory(rfc_number=9000)
|
||||
DocEventFactory(doc=rfc, type="published_rfc")
|
||||
r = self.client.get("/feed/rfc/")
|
||||
self.assertTrue(r.status_code, 200)
|
||||
q = PyQuery(r.content[39:]) # Strip off the xml declaration
|
||||
self.assertEqual(len(q("item")), 1)
|
||||
item = q("item")[0]
|
||||
media_content = item.findall("{http://search.yahoo.com/mrss/}content")
|
||||
self.assertEqual(len(media_content),4)
|
||||
types = set([m.attrib["type"] for m in media_content])
|
||||
self.assertEqual(types, set(["application/rfc+xml", "text/plain", "text/html", "application/pdf"]))
|
||||
rfcs_2016 = WgRfcFactory.create_batch(3) # rfc numbers will be well below v3
|
||||
for rfc in rfcs_2016:
|
||||
e = DocEventFactory(doc=rfc, type="published_rfc")
|
||||
e.time = e.time.replace(year=2016)
|
||||
e.save()
|
||||
r = self.client.get("/feed/rfc/2016")
|
||||
self.assertTrue(r.status_code, 200)
|
||||
q = PyQuery(r.content[39:])
|
||||
self.assertEqual(len(q("item")), 3)
|
||||
item = q("item")[0]
|
||||
media_content = item.findall("{http://search.yahoo.com/mrss/}content")
|
||||
self.assertEqual(len(media_content), 3)
|
||||
types = set([m.attrib["type"] for m in media_content])
|
||||
self.assertEqual(types, set(["text/plain", "text/html", "application/pdf"]))
|
||||
|
||||
def test_state_help(self):
|
||||
url = urlreverse('ietf.doc.views_help.state_help', kwargs=dict(type="draft-iesg"))
|
||||
|
@ -1965,7 +1922,7 @@ class DocTestCase(TestCase):
|
|||
r = self.client.get(url)
|
||||
entry = self._parse_bibtex_response(r)["rfc%s"%num]
|
||||
self.assertEqual(entry['series'], 'Request for Comments')
|
||||
self.assertEqual(entry['number'], num)
|
||||
self.assertEqual(int(entry['number']), num)
|
||||
self.assertEqual(entry['doi'], '10.17487/RFC%s'%num)
|
||||
self.assertEqual(entry['year'], '2010')
|
||||
self.assertEqual(entry['month'].lower()[0:3], 'oct')
|
||||
|
@ -1979,7 +1936,7 @@ class DocTestCase(TestCase):
|
|||
std_level_id = 'inf',
|
||||
time = datetime.datetime(1990, 4, 1, tzinfo=ZoneInfo(settings.TIME_ZONE)),
|
||||
)
|
||||
num = april1.rfc_number()
|
||||
num = april1.rfc_number
|
||||
DocEventFactory.create(
|
||||
doc=april1,
|
||||
type='published_rfc',
|
||||
|
@ -1991,7 +1948,7 @@ class DocTestCase(TestCase):
|
|||
self.assertEqual(r.get('Content-Type'), 'text/plain; charset=utf-8')
|
||||
entry = self._parse_bibtex_response(r)["rfc%s"%num]
|
||||
self.assertEqual(entry['series'], 'Request for Comments')
|
||||
self.assertEqual(entry['number'], num)
|
||||
self.assertEqual(int(entry['number']), num)
|
||||
self.assertEqual(entry['doi'], '10.17487/RFC%s'%num)
|
||||
self.assertEqual(entry['year'], '1990')
|
||||
self.assertEqual(entry['month'].lower()[0:3], 'apr')
|
||||
|
@ -2100,124 +2057,168 @@ class ReferencesTest(TestCase):
|
|||
self.assertContains(r, doc1.name)
|
||||
|
||||
class GenerateDraftAliasesTests(TestCase):
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.doc_aliases_file = NamedTemporaryFile(delete=False, mode='w+')
|
||||
self.doc_aliases_file.close()
|
||||
self.doc_virtual_file = NamedTemporaryFile(delete=False, mode='w+')
|
||||
self.doc_virtual_file.close()
|
||||
self.saved_draft_aliases_path = settings.DRAFT_ALIASES_PATH
|
||||
self.saved_draft_virtual_path = settings.DRAFT_VIRTUAL_PATH
|
||||
settings.DRAFT_ALIASES_PATH = self.doc_aliases_file.name
|
||||
settings.DRAFT_VIRTUAL_PATH = self.doc_virtual_file.name
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.doc_aliases_file = NamedTemporaryFile(delete=False, mode="w+")
|
||||
self.doc_aliases_file.close()
|
||||
self.doc_virtual_file = NamedTemporaryFile(delete=False, mode="w+")
|
||||
self.doc_virtual_file.close()
|
||||
self.saved_draft_aliases_path = settings.DRAFT_ALIASES_PATH
|
||||
self.saved_draft_virtual_path = settings.DRAFT_VIRTUAL_PATH
|
||||
settings.DRAFT_ALIASES_PATH = self.doc_aliases_file.name
|
||||
settings.DRAFT_VIRTUAL_PATH = self.doc_virtual_file.name
|
||||
|
||||
def tearDown(self):
|
||||
settings.DRAFT_ALIASES_PATH = self.saved_draft_aliases_path
|
||||
settings.DRAFT_VIRTUAL_PATH = self.saved_draft_virtual_path
|
||||
os.unlink(self.doc_aliases_file.name)
|
||||
os.unlink(self.doc_virtual_file.name)
|
||||
super().tearDown()
|
||||
def tearDown(self):
|
||||
settings.DRAFT_ALIASES_PATH = self.saved_draft_aliases_path
|
||||
settings.DRAFT_VIRTUAL_PATH = self.saved_draft_virtual_path
|
||||
os.unlink(self.doc_aliases_file.name)
|
||||
os.unlink(self.doc_virtual_file.name)
|
||||
super().tearDown()
|
||||
|
||||
def testManagementCommand(self):
|
||||
a_month_ago = (timezone.now() - datetime.timedelta(30)).astimezone(RPC_TZINFO)
|
||||
a_month_ago = a_month_ago.replace(hour=0, minute=0, second=0, microsecond=0)
|
||||
ad = RoleFactory(name_id='ad', group__type_id='area', group__state_id='active').person
|
||||
shepherd = PersonFactory()
|
||||
author1 = PersonFactory()
|
||||
author2 = PersonFactory()
|
||||
author3 = PersonFactory()
|
||||
author4 = PersonFactory()
|
||||
author5 = PersonFactory()
|
||||
author6 = PersonFactory()
|
||||
mars = GroupFactory(type_id='wg', acronym='mars')
|
||||
marschairman = PersonFactory(user__username='marschairman')
|
||||
mars.role_set.create(name_id='chair', person=marschairman, email=marschairman.email())
|
||||
doc1 = IndividualDraftFactory(authors=[author1], shepherd=shepherd.email(), ad=ad)
|
||||
doc2 = WgDraftFactory(name='draft-ietf-mars-test', group__acronym='mars', authors=[author2], ad=ad)
|
||||
doc3 = WgRfcFactory.create(name='draft-ietf-mars-finished', group__acronym='mars', authors=[author3], ad=ad, std_level_id='ps', states=[('draft','rfc'),('draft-iesg','pub')], time=a_month_ago)
|
||||
DocEventFactory.create(doc=doc3, type='published_rfc', time=a_month_ago)
|
||||
doc4 = WgRfcFactory.create(authors=[author4,author5], ad=ad, std_level_id='ps', states=[('draft','rfc'),('draft-iesg','pub')], time=datetime.datetime(2010,10,10, tzinfo=ZoneInfo(settings.TIME_ZONE)))
|
||||
DocEventFactory.create(doc=doc4, type='published_rfc', time=datetime.datetime(2010, 10, 10, tzinfo=RPC_TZINFO))
|
||||
doc5 = IndividualDraftFactory(authors=[author6])
|
||||
def testManagementCommand(self):
|
||||
a_month_ago = (timezone.now() - datetime.timedelta(30)).astimezone(RPC_TZINFO)
|
||||
a_month_ago = a_month_ago.replace(hour=0, minute=0, second=0, microsecond=0)
|
||||
ad = RoleFactory(
|
||||
name_id="ad", group__type_id="area", group__state_id="active"
|
||||
).person
|
||||
shepherd = PersonFactory()
|
||||
author1 = PersonFactory()
|
||||
author2 = PersonFactory()
|
||||
author3 = PersonFactory()
|
||||
author4 = PersonFactory()
|
||||
author5 = PersonFactory()
|
||||
author6 = PersonFactory()
|
||||
mars = GroupFactory(type_id="wg", acronym="mars")
|
||||
marschairman = PersonFactory(user__username="marschairman")
|
||||
mars.role_set.create(
|
||||
name_id="chair", person=marschairman, email=marschairman.email()
|
||||
)
|
||||
doc1 = IndividualDraftFactory(
|
||||
authors=[author1], shepherd=shepherd.email(), ad=ad
|
||||
)
|
||||
doc2 = WgDraftFactory(
|
||||
name="draft-ietf-mars-test", group__acronym="mars", authors=[author2], ad=ad
|
||||
)
|
||||
doc3 = WgDraftFactory.create(
|
||||
name="draft-ietf-mars-finished",
|
||||
group__acronym="mars",
|
||||
authors=[author3],
|
||||
ad=ad,
|
||||
std_level_id="ps",
|
||||
states=[("draft", "rfc"), ("draft-iesg", "pub")],
|
||||
time=a_month_ago,
|
||||
)
|
||||
rfc3 = WgRfcFactory()
|
||||
DocEventFactory.create(doc=rfc3, type="published_rfc", time=a_month_ago)
|
||||
doc3.relateddocument_set.create(
|
||||
relationship_id="became_rfc", target=rfc3.docalias.first()
|
||||
)
|
||||
doc4 = WgDraftFactory.create(
|
||||
authors=[author4, author5],
|
||||
ad=ad,
|
||||
std_level_id="ps",
|
||||
states=[("draft", "rfc"), ("draft-iesg", "pub")],
|
||||
time=datetime.datetime(2010, 10, 10, tzinfo=ZoneInfo(settings.TIME_ZONE)),
|
||||
)
|
||||
rfc4 = WgRfcFactory()
|
||||
DocEventFactory.create(
|
||||
doc=rfc4,
|
||||
type="published_rfc",
|
||||
time=datetime.datetime(2010, 10, 10, tzinfo=RPC_TZINFO),
|
||||
)
|
||||
doc4.relateddocument_set.create(
|
||||
relationship_id="became_rfc", target=rfc4.docalias.first()
|
||||
)
|
||||
doc5 = IndividualDraftFactory(authors=[author6])
|
||||
|
||||
args = [ ]
|
||||
kwargs = { }
|
||||
out = io.StringIO()
|
||||
call_command("generate_draft_aliases", *args, **kwargs, stdout=out, stderr=out)
|
||||
self.assertFalse(out.getvalue())
|
||||
args = []
|
||||
kwargs = {}
|
||||
out = io.StringIO()
|
||||
call_command("generate_draft_aliases", *args, **kwargs, stdout=out, stderr=out)
|
||||
self.assertFalse(out.getvalue())
|
||||
|
||||
with open(settings.DRAFT_ALIASES_PATH) as afile:
|
||||
acontent = afile.read()
|
||||
self.assertTrue(all([x in acontent for x in [
|
||||
'xfilter-' + doc1.name,
|
||||
'xfilter-' + doc1.name + '.ad',
|
||||
'xfilter-' + doc1.name + '.authors',
|
||||
'xfilter-' + doc1.name + '.shepherd',
|
||||
'xfilter-' + doc1.name + '.all',
|
||||
'xfilter-' + doc2.name,
|
||||
'xfilter-' + doc2.name + '.ad',
|
||||
'xfilter-' + doc2.name + '.authors',
|
||||
'xfilter-' + doc2.name + '.chairs',
|
||||
'xfilter-' + doc2.name + '.all',
|
||||
'xfilter-' + doc3.name,
|
||||
'xfilter-' + doc3.name + '.ad',
|
||||
'xfilter-' + doc3.name + '.authors',
|
||||
'xfilter-' + doc3.name + '.chairs',
|
||||
'xfilter-' + doc5.name,
|
||||
'xfilter-' + doc5.name + '.authors',
|
||||
'xfilter-' + doc5.name + '.all',
|
||||
]]))
|
||||
self.assertFalse(all([x in acontent for x in [
|
||||
'xfilter-' + doc1.name + '.chairs',
|
||||
'xfilter-' + doc2.name + '.shepherd',
|
||||
'xfilter-' + doc3.name + '.shepherd',
|
||||
'xfilter-' + doc4.name,
|
||||
'xfilter-' + doc5.name + '.shepherd',
|
||||
'xfilter-' + doc5.name + '.ad',
|
||||
]]))
|
||||
with open(settings.DRAFT_ALIASES_PATH) as afile:
|
||||
acontent = afile.read()
|
||||
for x in [
|
||||
"xfilter-" + doc1.name,
|
||||
"xfilter-" + doc1.name + ".ad",
|
||||
"xfilter-" + doc1.name + ".authors",
|
||||
"xfilter-" + doc1.name + ".shepherd",
|
||||
"xfilter-" + doc1.name + ".all",
|
||||
"xfilter-" + doc2.name,
|
||||
"xfilter-" + doc2.name + ".ad",
|
||||
"xfilter-" + doc2.name + ".authors",
|
||||
"xfilter-" + doc2.name + ".chairs",
|
||||
"xfilter-" + doc2.name + ".all",
|
||||
"xfilter-" + doc3.name,
|
||||
"xfilter-" + doc3.name + ".ad",
|
||||
"xfilter-" + doc3.name + ".authors",
|
||||
"xfilter-" + doc3.name + ".chairs",
|
||||
"xfilter-" + doc5.name,
|
||||
"xfilter-" + doc5.name + ".authors",
|
||||
"xfilter-" + doc5.name + ".all",
|
||||
]:
|
||||
self.assertIn(x, acontent)
|
||||
|
||||
with open(settings.DRAFT_VIRTUAL_PATH) as vfile:
|
||||
vcontent = vfile.read()
|
||||
self.assertTrue(all([x in vcontent for x in [
|
||||
ad.email_address(),
|
||||
shepherd.email_address(),
|
||||
marschairman.email_address(),
|
||||
author1.email_address(),
|
||||
author2.email_address(),
|
||||
author3.email_address(),
|
||||
author6.email_address(),
|
||||
]]))
|
||||
self.assertFalse(all([x in vcontent for x in [
|
||||
author4.email_address(),
|
||||
author5.email_address(),
|
||||
]]))
|
||||
self.assertTrue(all([x in vcontent for x in [
|
||||
'xfilter-' + doc1.name,
|
||||
'xfilter-' + doc1.name + '.ad',
|
||||
'xfilter-' + doc1.name + '.authors',
|
||||
'xfilter-' + doc1.name + '.shepherd',
|
||||
'xfilter-' + doc1.name + '.all',
|
||||
'xfilter-' + doc2.name,
|
||||
'xfilter-' + doc2.name + '.ad',
|
||||
'xfilter-' + doc2.name + '.authors',
|
||||
'xfilter-' + doc2.name + '.chairs',
|
||||
'xfilter-' + doc2.name + '.all',
|
||||
'xfilter-' + doc3.name,
|
||||
'xfilter-' + doc3.name + '.ad',
|
||||
'xfilter-' + doc3.name + '.authors',
|
||||
'xfilter-' + doc3.name + '.chairs',
|
||||
'xfilter-' + doc5.name,
|
||||
'xfilter-' + doc5.name + '.authors',
|
||||
'xfilter-' + doc5.name + '.all',
|
||||
]]))
|
||||
self.assertFalse(all([x in vcontent for x in [
|
||||
'xfilter-' + doc1.name + '.chairs',
|
||||
'xfilter-' + doc2.name + '.shepherd',
|
||||
'xfilter-' + doc3.name + '.shepherd',
|
||||
'xfilter-' + doc4.name,
|
||||
'xfilter-' + doc5.name + '.shepherd',
|
||||
'xfilter-' + doc5.name + '.ad',
|
||||
]]))
|
||||
for x in [
|
||||
"xfilter-" + doc1.name + ".chairs",
|
||||
"xfilter-" + doc2.name + ".shepherd",
|
||||
"xfilter-" + doc3.name + ".shepherd",
|
||||
"xfilter-" + doc4.name,
|
||||
"xfilter-" + doc5.name + ".shepherd",
|
||||
"xfilter-" + doc5.name + ".ad",
|
||||
]:
|
||||
self.assertNotIn(x, acontent)
|
||||
|
||||
with open(settings.DRAFT_VIRTUAL_PATH) as vfile:
|
||||
vcontent = vfile.read()
|
||||
for x in [
|
||||
ad.email_address(),
|
||||
shepherd.email_address(),
|
||||
marschairman.email_address(),
|
||||
author1.email_address(),
|
||||
author2.email_address(),
|
||||
author3.email_address(),
|
||||
author6.email_address(),
|
||||
]:
|
||||
self.assertIn(x, vcontent)
|
||||
|
||||
for x in [
|
||||
author4.email_address(),
|
||||
author5.email_address(),
|
||||
]:
|
||||
self.assertNotIn(x, vcontent)
|
||||
|
||||
for x in [
|
||||
"xfilter-" + doc1.name,
|
||||
"xfilter-" + doc1.name + ".ad",
|
||||
"xfilter-" + doc1.name + ".authors",
|
||||
"xfilter-" + doc1.name + ".shepherd",
|
||||
"xfilter-" + doc1.name + ".all",
|
||||
"xfilter-" + doc2.name,
|
||||
"xfilter-" + doc2.name + ".ad",
|
||||
"xfilter-" + doc2.name + ".authors",
|
||||
"xfilter-" + doc2.name + ".chairs",
|
||||
"xfilter-" + doc2.name + ".all",
|
||||
"xfilter-" + doc3.name,
|
||||
"xfilter-" + doc3.name + ".ad",
|
||||
"xfilter-" + doc3.name + ".authors",
|
||||
"xfilter-" + doc3.name + ".chairs",
|
||||
"xfilter-" + doc5.name,
|
||||
"xfilter-" + doc5.name + ".authors",
|
||||
"xfilter-" + doc5.name + ".all",
|
||||
]:
|
||||
self.assertIn(x, vcontent)
|
||||
|
||||
for x in [
|
||||
"xfilter-" + doc1.name + ".chairs",
|
||||
"xfilter-" + doc2.name + ".shepherd",
|
||||
"xfilter-" + doc3.name + ".shepherd",
|
||||
"xfilter-" + doc4.name,
|
||||
"xfilter-" + doc5.name + ".shepherd",
|
||||
"xfilter-" + doc5.name + ".ad",
|
||||
]:
|
||||
self.assertNotIn(x, vcontent)
|
||||
|
||||
class EmailAliasesTests(TestCase):
|
||||
|
||||
|
@ -2650,10 +2651,10 @@ class Idnits2SupportTests(TestCase):
|
|||
settings_temp_path_overrides = TestCase.settings_temp_path_overrides + ['DERIVED_DIR']
|
||||
|
||||
def test_obsoleted(self):
|
||||
rfc = WgRfcFactory(alias2__name='rfc1001')
|
||||
WgRfcFactory(alias2__name='rfc1003',relations=[('obs',rfc)])
|
||||
rfc = WgRfcFactory(alias2__name='rfc1005')
|
||||
WgRfcFactory(alias2__name='rfc1007',relations=[('obs',rfc)])
|
||||
rfc = WgRfcFactory(rfc_number=1001)
|
||||
WgRfcFactory(rfc_number=1003,relations=[('obs',rfc)])
|
||||
rfc = WgRfcFactory(rfc_number=1005)
|
||||
WgRfcFactory(rfc_number=1007,relations=[('obs',rfc)])
|
||||
|
||||
url = urlreverse('ietf.doc.views_doc.idnits2_rfcs_obsoleted')
|
||||
r = self.client.get(url)
|
||||
|
@ -2678,6 +2679,8 @@ class Idnits2SupportTests(TestCase):
|
|||
|
||||
def test_idnits2_state(self):
|
||||
rfc = WgRfcFactory()
|
||||
draft = WgDraftFactory()
|
||||
draft.relateddocument_set.create(relationship_id="became_rfc", target=rfc.docalias.first())
|
||||
url = urlreverse('ietf.doc.views_doc.idnits2_state', kwargs=dict(name=rfc.canonical_name()))
|
||||
r = self.client.get(url)
|
||||
self.assertEqual(r.status_code, 200)
|
||||
|
@ -2736,16 +2739,12 @@ class RawIdTests(TestCase):
|
|||
self.should_succeed(dict(name=draft.name, rev='00',ext='txt'))
|
||||
self.should_404(dict(name=draft.name, rev='00',ext='html'))
|
||||
|
||||
def test_raw_id_rfc(self):
|
||||
rfc = WgRfcFactory()
|
||||
dir = settings.INTERNET_ALL_DRAFTS_ARCHIVE_DIR
|
||||
(Path(dir) / f'{rfc.name}-{rfc.rev}.txt').touch()
|
||||
self.should_succeed(dict(name=rfc.name))
|
||||
self.should_404(dict(name=rfc.canonical_name()))
|
||||
# test_raw_id_rfc intentionally removed
|
||||
# an rfc is no longer a pseudo-version of a draft.
|
||||
|
||||
def test_non_draft(self):
|
||||
charter = CharterFactory()
|
||||
self.should_404(dict(name=charter.name))
|
||||
for doc in [CharterFactory(), WgRfcFactory()]:
|
||||
self.should_404(dict(name=doc.name))
|
||||
|
||||
class PdfizedTests(TestCase):
|
||||
|
||||
|
@ -2764,24 +2763,27 @@ class PdfizedTests(TestCase):
|
|||
r = self.client.get(url)
|
||||
self.assertEqual(r.status_code, 404)
|
||||
|
||||
# This takes a _long_ time (32s on a 2022 m1 macbook pro) - is it worth what it covers?
|
||||
def test_pdfized(self):
|
||||
rfc = WgRfcFactory(create_revisions=range(0,2))
|
||||
rfc = WgRfcFactory()
|
||||
draft = WgDraftFactory(create_revisions=range(0,2))
|
||||
draft.relateddocument_set.create(relationship_id="became_rfc", target=rfc.docalias.first())
|
||||
|
||||
dir = settings.RFC_PATH
|
||||
with (Path(dir) / f'{rfc.canonical_name()}.txt').open('w') as f:
|
||||
with (Path(dir) / f'{rfc.name}.txt').open('w') as f:
|
||||
f.write('text content')
|
||||
dir = settings.INTERNET_ALL_DRAFTS_ARCHIVE_DIR
|
||||
for r in range(0,2):
|
||||
with (Path(dir) / f'{rfc.name}-{r:02d}.txt').open('w') as f:
|
||||
with (Path(dir) / f'{draft.name}-{r:02d}.txt').open('w') as f:
|
||||
f.write('text content')
|
||||
|
||||
self.should_succeed(dict(name=rfc.canonical_name()))
|
||||
self.should_succeed(dict(name=rfc.name))
|
||||
self.should_succeed(dict(name=draft.name))
|
||||
for r in range(0,2):
|
||||
self.should_succeed(dict(name=rfc.name,rev=f'{r:02d}'))
|
||||
self.should_succeed(dict(name=draft.name,rev=f'{r:02d}'))
|
||||
for ext in ('pdf','txt','html','anythingatall'):
|
||||
self.should_succeed(dict(name=rfc.name,rev=f'{r:02d}',ext=ext))
|
||||
self.should_404(dict(name=rfc.name,rev='02'))
|
||||
self.should_succeed(dict(name=draft.name,rev=f'{r:02d}',ext=ext))
|
||||
self.should_404(dict(name=draft.name,rev='02'))
|
||||
|
||||
class NotifyValidationTests(TestCase):
|
||||
def test_notify_validation(self):
|
||||
|
|
|
@ -1121,8 +1121,8 @@ class RegenerateLastCallTestCase(TestCase):
|
|||
self.assertFalse("contains these normative down" in lc_text)
|
||||
|
||||
rfc = IndividualRfcFactory.create(
|
||||
rfc_number=6666,
|
||||
stream_id='ise',
|
||||
name='rfc6666',
|
||||
states=[('draft','rfc'),('draft-iesg','pub')],
|
||||
std_level_id='inf',
|
||||
)
|
||||
|
|
|
@ -22,7 +22,7 @@ class Downref(TestCase):
|
|||
self.draftalias = self.draft.docalias.get(name='draft-ietf-mars-test')
|
||||
self.doc = WgDraftFactory(name='draft-ietf-mars-approved-document',states=[('draft-iesg','rfcqueue')])
|
||||
self.docalias = self.doc.docalias.get(name='draft-ietf-mars-approved-document')
|
||||
self.rfc = WgRfcFactory(name='rfc9998')
|
||||
self.rfc = WgRfcFactory(rfc_number=9998)
|
||||
self.rfcalias = self.rfc.docalias.get(name='rfc9998')
|
||||
RelatedDocument.objects.create(source=self.doc, target=self.rfc, relationship_id='downref-approval')
|
||||
|
||||
|
@ -100,7 +100,7 @@ class Downref(TestCase):
|
|||
def test_downref_last_call(self):
|
||||
draft = WgDraftFactory(name='draft-ietf-mars-ready-for-lc-document',intended_std_level_id='ps',states=[('draft-iesg','iesg-eva')])
|
||||
WgDraftFactory(name='draft-ietf-mars-another-approved-document',states=[('draft-iesg','rfcqueue')])
|
||||
rfc9999 = WgRfcFactory(name='rfc9999', std_level_id=None)
|
||||
rfc9999 = WgRfcFactory(alias2__name='rfc9999', std_level_id=None)
|
||||
RelatedDocument.objects.create(source=draft, target=rfc9999, relationship_id='refnorm')
|
||||
url = urlreverse('ietf.doc.views_ballot.lastcalltext', kwargs=dict(name=draft.name))
|
||||
login_testing_unauthorized(self, "secretary", url)
|
||||
|
|
|
@ -137,10 +137,18 @@ class ReviewTests(TestCase):
|
|||
url = urlreverse('ietf.doc.views_review.request_review', kwargs={ "name": doc.name })
|
||||
login_testing_unauthorized(self, "ad", url)
|
||||
|
||||
# get should fail
|
||||
# get should fail - all non draft types 404
|
||||
r = self.client.get(url)
|
||||
self.assertEqual(r.status_code, 404)
|
||||
|
||||
# Can only request reviews on active draft documents
|
||||
doc = WgDraftFactory(states=[("draft","rfc")])
|
||||
url = urlreverse('ietf.doc.views_review.request_review', kwargs={ "name": doc.name })
|
||||
r = self.client.get(url)
|
||||
self.assertEqual(r.status_code, 403)
|
||||
|
||||
|
||||
|
||||
def test_doc_page(self):
|
||||
|
||||
doc = WgDraftFactory(group__acronym='mars',rev='01')
|
||||
|
|
|
@ -14,7 +14,7 @@ from textwrap import wrap
|
|||
from django.conf import settings
|
||||
from django.urls import reverse as urlreverse
|
||||
|
||||
from ietf.doc.factories import DocumentFactory, IndividualRfcFactory, WgRfcFactory
|
||||
from ietf.doc.factories import DocumentFactory, IndividualRfcFactory, WgRfcFactory, WgDraftFactory
|
||||
from ietf.doc.models import ( Document, State, DocEvent,
|
||||
BallotPositionDocEvent, NewRevisionDocEvent, TelechatDocEvent, WriteupDocEvent )
|
||||
from ietf.doc.utils import create_ballot_if_not_open
|
||||
|
@ -449,9 +449,16 @@ class StatusChangeTests(TestCase):
|
|||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
IndividualRfcFactory(name='rfc14',std_level_id='unkn')
|
||||
WgRfcFactory(name='rfc9999',std_level_id='ps')
|
||||
WgRfcFactory(name='rfc9998',std_level_id='inf')
|
||||
IndividualRfcFactory(rfc_number=14,std_level_id='unkn') # draft was never issued
|
||||
|
||||
rfc = WgRfcFactory(rfc_number=9999,std_level_id='ps')
|
||||
draft = WgDraftFactory(name='draft-ietf-random-thing')
|
||||
draft.relateddocument_set.create(relationship_id="became_rfc", target=rfc)
|
||||
|
||||
rfc = WgRfcFactory(rfc_number=9998,std_level_id='inf')
|
||||
draft = WgDraftFactory(name='draft-ietf-random-other-thing')
|
||||
draft.relateddocument_set.create(relationship_id="became_rfc", target=rfc)
|
||||
|
||||
DocumentFactory(type_id='statchg',name='status-change-imaginary-mid-review',notify='notify@example.org')
|
||||
|
||||
class StatusChangeSubmitTests(TestCase):
|
||||
|
|
|
@ -11,10 +11,10 @@ from django.utils import timezone
|
|||
from ietf.group.factories import GroupFactory, RoleFactory
|
||||
from ietf.name.models import DocTagName
|
||||
from ietf.person.factories import PersonFactory
|
||||
from ietf.utils.test_utils import TestCase, name_of_file_containing
|
||||
from ietf.utils.test_utils import TestCase, name_of_file_containing, reload_db_objects
|
||||
from ietf.person.models import Person
|
||||
from ietf.doc.factories import DocumentFactory, WgRfcFactory, WgDraftFactory
|
||||
from ietf.doc.models import State, DocumentActionHolder, DocumentAuthor, Document
|
||||
from ietf.doc.models import State, DocumentActionHolder, DocumentAuthor
|
||||
from ietf.doc.utils import (update_action_holders, add_state_change_event, update_documentauthors,
|
||||
fuzzy_find_documents, rebuild_reference_relations, build_file_urls)
|
||||
from ietf.utils.draft import Draft, PlaintextDraft
|
||||
|
@ -251,40 +251,42 @@ class MiscTests(TestCase):
|
|||
self.assertEqual(docauth.country, '')
|
||||
|
||||
def do_fuzzy_find_documents_rfc_test(self, name):
|
||||
rfc = WgRfcFactory(name=name, create_revisions=(0, 1, 2))
|
||||
rfc = Document.objects.get(pk=rfc.pk) # clear out any cached values
|
||||
draft = WgDraftFactory(name=name, create_revisions=(0, 1, 2))
|
||||
rfc = WgRfcFactory()
|
||||
draft.relateddocument_set.create(relationship_id="became_rfc", target=rfc.docalias.first())
|
||||
draft, rfc = reload_db_objects(draft, rfc)
|
||||
|
||||
# by canonical name
|
||||
found = fuzzy_find_documents(rfc.canonical_name(), None)
|
||||
self.assertCountEqual(found.documents, [rfc])
|
||||
self.assertEqual(found.matched_rev, None)
|
||||
self.assertEqual(found.matched_name, rfc.canonical_name())
|
||||
|
||||
# by draft name, no rev
|
||||
found = fuzzy_find_documents(rfc.name, None)
|
||||
self.assertCountEqual(found.documents, [rfc])
|
||||
self.assertEqual(found.matched_rev, None)
|
||||
self.assertEqual(found.matched_name, rfc.name)
|
||||
|
||||
# by draft name, no rev
|
||||
found = fuzzy_find_documents(draft.name, None)
|
||||
self.assertCountEqual(found.documents, [draft])
|
||||
self.assertEqual(found.matched_rev, None)
|
||||
self.assertEqual(found.matched_name, draft.name)
|
||||
|
||||
# by draft name, latest rev
|
||||
found = fuzzy_find_documents(rfc.name, '02')
|
||||
self.assertCountEqual(found.documents, [rfc])
|
||||
found = fuzzy_find_documents(draft.name, '02')
|
||||
self.assertCountEqual(found.documents, [draft])
|
||||
self.assertEqual(found.matched_rev, '02')
|
||||
self.assertEqual(found.matched_name, rfc.name)
|
||||
self.assertEqual(found.matched_name, draft.name)
|
||||
|
||||
# by draft name, earlier rev
|
||||
found = fuzzy_find_documents(rfc.name, '01')
|
||||
self.assertCountEqual(found.documents, [rfc])
|
||||
found = fuzzy_find_documents(draft.name, '01')
|
||||
self.assertCountEqual(found.documents, [draft])
|
||||
self.assertEqual(found.matched_rev, '01')
|
||||
self.assertEqual(found.matched_name, rfc.name)
|
||||
self.assertEqual(found.matched_name, draft.name)
|
||||
|
||||
# wrong name or revision
|
||||
found = fuzzy_find_documents(rfc.name + '-incorrect')
|
||||
found = fuzzy_find_documents(draft.name + '-incorrect')
|
||||
self.assertCountEqual(found.documents, [], 'Should not find document that does not match')
|
||||
found = fuzzy_find_documents(rfc.name + '-incorrect', '02')
|
||||
found = fuzzy_find_documents(draft.name + '-incorrect', '02')
|
||||
self.assertCountEqual(found.documents, [], 'Still should not find document, even with a version')
|
||||
found = fuzzy_find_documents(rfc.name, '22')
|
||||
self.assertCountEqual(found.documents, [rfc],
|
||||
found = fuzzy_find_documents(draft.name, '22')
|
||||
self.assertCountEqual(found.documents, [draft],
|
||||
'Should find document even if rev does not exist')
|
||||
|
||||
|
||||
|
|
|
@ -998,14 +998,11 @@ def get_search_cache_key(params):
|
|||
kwargs = dict([ (k,v) for (k,v) in list(params.items()) if k in fields ])
|
||||
key = "doc:document:search:" + hashlib.sha512(json.dumps(kwargs, sort_keys=True).encode('utf-8')).hexdigest()
|
||||
return key
|
||||
|
||||
def build_file_urls(doc: Union[Document, DocHistory]):
|
||||
if doc.type_id != 'draft':
|
||||
return [], []
|
||||
|
||||
if doc.is_rfc():
|
||||
name = doc.canonical_name()
|
||||
base_path = os.path.join(settings.RFC_PATH, name + ".")
|
||||
|
||||
def build_file_urls(doc: Union[Document, DocHistory]):
|
||||
if doc.type_id == "rfc":
|
||||
base_path = os.path.join(settings.RFC_PATH, doc.name + ".")
|
||||
possible_types = settings.RFC_FILE_TYPES
|
||||
found_types = [t for t in possible_types if os.path.exists(base_path + t)]
|
||||
|
||||
|
@ -1014,17 +1011,17 @@ def build_file_urls(doc: Union[Document, DocHistory]):
|
|||
file_urls = []
|
||||
for t in found_types:
|
||||
label = "plain text" if t == "txt" else t
|
||||
file_urls.append((label, base + name + "." + t))
|
||||
file_urls.append((label, base + doc.name + "." + t))
|
||||
|
||||
if "pdf" not in found_types and "txt" in found_types:
|
||||
file_urls.append(("pdf", base + "pdfrfc/" + name + ".txt.pdf"))
|
||||
file_urls.append(("pdf", base + "pdfrfc/" + doc.name + ".txt.pdf"))
|
||||
|
||||
if "txt" in found_types:
|
||||
file_urls.append(("htmlized", urlreverse('ietf.doc.views_doc.document_html', kwargs=dict(name=name))))
|
||||
file_urls.append(("htmlized", urlreverse('ietf.doc.views_doc.document_html', kwargs=dict(name=doc.name))))
|
||||
if doc.tags.filter(slug="verified-errata").exists():
|
||||
file_urls.append(("with errata", settings.RFC_EDITOR_INLINE_ERRATA_URL.format(rfc_number=doc.rfc_number)))
|
||||
file_urls.append(("bibtex", urlreverse('ietf.doc.views_doc.document_bibtex',kwargs=dict(name=name))))
|
||||
elif doc.rev:
|
||||
file_urls.append(("bibtex", urlreverse('ietf.doc.views_doc.document_bibtex',kwargs=dict(name=doc.name))))
|
||||
elif doc.type_id == "draft" and doc.rev != "":
|
||||
base_path = os.path.join(settings.INTERNET_ALL_DRAFTS_ARCHIVE_DIR, doc.name + "-" + doc.rev + ".")
|
||||
possible_types = settings.IDSUBMIT_FILE_TYPES
|
||||
found_types = [t for t in possible_types if os.path.exists(base_path + t)]
|
||||
|
@ -1039,12 +1036,14 @@ def build_file_urls(doc: Union[Document, DocHistory]):
|
|||
file_urls.append(("pdfized", urlreverse('ietf.doc.views_doc.document_pdfized', kwargs=dict(name=doc.name, rev=doc.rev))))
|
||||
file_urls.append(("bibtex", urlreverse('ietf.doc.views_doc.document_bibtex',kwargs=dict(name=doc.name,rev=doc.rev))))
|
||||
else:
|
||||
# As of 2022-12-14, there are 1463 Document and 3136 DocHistory records with type='draft' and rev=''.
|
||||
# All of these are in the rfc state and are covered by the above cases.
|
||||
log.unreachable('2022-12-14')
|
||||
if doc.type_id == "draft":
|
||||
# TODO: look at the state of the database post migration and update this comment, or remove the block
|
||||
# As of 2022-12-14, there are 1463 Document and 3136 DocHistory records with type='draft' and rev=''.
|
||||
# All of these are in the rfc state and are covered by the above cases.
|
||||
log.unreachable('2022-12-14')
|
||||
file_urls = []
|
||||
found_types = []
|
||||
|
||||
|
||||
return file_urls, found_types
|
||||
|
||||
def augment_docs_and_user_with_user_info(docs, user):
|
||||
|
@ -1111,7 +1110,7 @@ def generate_idnits2_rfc_status():
|
|||
'unkn': 'U',
|
||||
}
|
||||
|
||||
rfcs = Document.objects.filter(type_id='rfc',states__slug='published',states__type='rfc')
|
||||
rfcs = Document.objects.filter(type_id='rfc')
|
||||
for rfc in rfcs:
|
||||
offset = int(rfc.rfc_number)-1
|
||||
blob[offset] = symbols[rfc.std_level_id]
|
||||
|
@ -1170,8 +1169,14 @@ def fuzzy_find_documents(name, rev=None):
|
|||
if re.match("^[0-9]+$", name):
|
||||
name = f'rfc{name}'
|
||||
|
||||
if name.startswith("rfc"):
|
||||
sought_type = "rfc"
|
||||
log.assertion("rev is None")
|
||||
else:
|
||||
sought_type = "draft"
|
||||
|
||||
# see if we can find a document using this name
|
||||
docs = Document.objects.filter(docalias__name=name, type_id='draft')
|
||||
docs = Document.objects.filter(docalias__name=name, type_id=sought_type)
|
||||
if rev and not docs.exists():
|
||||
# No document found, see if the name/rev split has been misidentified.
|
||||
# Handles some special cases, like draft-ietf-tsvwg-ieee-802-11.
|
||||
|
|
|
@ -93,7 +93,7 @@ def fill_in_document_table_attributes(docs, have_telechat_date=False):
|
|||
# emulate canonical name which is used by a lot of the utils
|
||||
# d.canonical_name = wrap_value(rfc_aliases[d.pk] if d.pk in rfc_aliases else d.name)
|
||||
|
||||
if d.is_rfc() and d.latest_event_cache["published_rfc"]:
|
||||
if d.type_id == "rfc" and d.latest_event_cache["published_rfc"]:
|
||||
d.latest_revision_date = d.latest_event_cache["published_rfc"].time
|
||||
elif d.latest_event_cache["new_revision"]:
|
||||
d.latest_revision_date = d.latest_event_cache["new_revision"].time
|
||||
|
@ -140,17 +140,35 @@ def fill_in_document_table_attributes(docs, have_telechat_date=False):
|
|||
d.obsoleted_by_list = []
|
||||
d.updated_by_list = []
|
||||
|
||||
xed_by = RelatedDocument.objects.filter(target__name__in=list(rfc_aliases.values()),
|
||||
relationship__in=("obs", "updates")).select_related('target')
|
||||
rel_rfc_aliases = dict([ (a.document.id, re.sub(r"rfc(\d+)", r"RFC \1", a.name, flags=re.IGNORECASE)) for a in DocAlias.objects.filter(name__startswith="rfc", docs__id__in=[rel.source_id for rel in xed_by]) ])
|
||||
# Revisit this block after RFCs become first-class Document objects
|
||||
xed_by = list(
|
||||
RelatedDocument.objects.filter(
|
||||
target__name__in=list(rfc_aliases.values()),
|
||||
relationship__in=("obs", "updates"),
|
||||
).select_related("target")
|
||||
)
|
||||
rel_rfc_aliases = {
|
||||
a.document.id: re.sub(r"rfc(\d+)", r"RFC \1", a.name, flags=re.IGNORECASE)
|
||||
for a in DocAlias.objects.filter(
|
||||
name__startswith="rfc", docs__id__in=[rel.source_id for rel in xed_by]
|
||||
)
|
||||
}
|
||||
xed_by.sort(
|
||||
key=lambda rel: int(
|
||||
re.sub(
|
||||
r"rfc\s*(\d+)",
|
||||
r"\1",
|
||||
rel_rfc_aliases[rel.source_id],
|
||||
flags=re.IGNORECASE,
|
||||
)
|
||||
)
|
||||
)
|
||||
for rel in xed_by:
|
||||
d = doc_dict[rel.target.id]
|
||||
if rel.relationship_id == "obs":
|
||||
l = d.obsoleted_by_list
|
||||
d.obsoleted_by_list.append(s)
|
||||
elif rel.relationship_id == "updates":
|
||||
l = d.updated_by_list
|
||||
l.append(rel_rfc_aliases[rel.source_id])
|
||||
l.sort()
|
||||
d.updated_by_list.append(s)
|
||||
|
||||
def augment_docs_with_related_docs_info(docs):
|
||||
"""Augment all documents with related documents information.
|
||||
|
|
|
@ -953,7 +953,13 @@ def approve_downrefs(request, name):
|
|||
|
||||
login = request.user.person
|
||||
|
||||
downrefs_to_rfc = [rel for rel in doc.relateddocument_set.all() if rel.is_downref() and not rel.is_approved_downref() and rel.target.is_rfc()]
|
||||
downrefs_to_rfc = [
|
||||
rel
|
||||
for rel in doc.relateddocument_set.all()
|
||||
if rel.is_downref()
|
||||
and not rel.is_approved_downref()
|
||||
and rel.target.type_id == "rfc"
|
||||
]
|
||||
|
||||
downrefs_to_rfc_qs = RelatedDocument.objects.filter(pk__in=[r.pk for r in downrefs_to_rfc])
|
||||
|
||||
|
|
|
@ -54,13 +54,13 @@ from django.contrib.staticfiles import finders
|
|||
|
||||
import debug # pyflakes:ignore
|
||||
|
||||
from ietf.doc.models import ( Document, DocAlias, DocHistory, DocEvent, BallotDocEvent, BallotType,
|
||||
from ietf.doc.models import ( Document, DocHistory, DocEvent, BallotDocEvent, BallotType,
|
||||
ConsensusDocEvent, NewRevisionDocEvent, TelechatDocEvent, WriteupDocEvent, IanaExpertDocEvent,
|
||||
IESG_BALLOT_ACTIVE_STATES, STATUSCHANGE_RELATIONS, DocumentActionHolder, DocumentAuthor,
|
||||
RelatedDocument, RelatedDocHistory)
|
||||
from ietf.doc.utils import (augment_events_with_revision,
|
||||
can_adopt_draft, can_unadopt_draft, get_chartering_type, get_tags_for_stream_id,
|
||||
needed_ballot_positions, nice_consensus, prettify_std_name, update_telechat, has_same_ballot,
|
||||
needed_ballot_positions, nice_consensus, update_telechat, has_same_ballot,
|
||||
get_initial_notify, make_notify_changed_event, make_rev_history, default_consensus,
|
||||
add_events_message_info, get_unicode_document_content,
|
||||
augment_docs_and_user_with_user_info, irsg_needed_ballot_positions, add_action_holder_change_event,
|
||||
|
@ -114,13 +114,46 @@ def render_document_top(request, doc, tab, name):
|
|||
rsab_ballot,
|
||||
None if rsab_ballot else "RSAB Evaluation Ballot has not been created yet"
|
||||
))
|
||||
if doc.type_id in ("draft","conflrev", "statchg"):
|
||||
tabs.append(("IESG Evaluation Record", "ballot", urlreverse("ietf.doc.views_doc.document_ballot", kwargs=dict(name=name)), iesg_ballot, None if iesg_ballot else "IESG Evaluation Ballot has not been created yet"))
|
||||
elif doc.type_id == "charter" and doc.group.type_id == "wg":
|
||||
tabs.append(("IESG Review", "ballot", urlreverse("ietf.doc.views_doc.document_ballot", kwargs=dict(name=name)), iesg_ballot, None if iesg_ballot else "IESG Review Ballot has not been created yet"))
|
||||
|
||||
if doc.type_id == "draft" or (doc.type_id == "charter" and doc.group.type_id == "wg"):
|
||||
tabs.append(("IESG Writeups", "writeup", urlreverse('ietf.doc.views_doc.document_writeup', kwargs=dict(name=name)), True, None))
|
||||
|
||||
if iesg_ballot or (doc.group and doc.group.type_id == "wg"):
|
||||
if doc.type_id in ("draft", "conflrev", "statchg"):
|
||||
tabs.append(
|
||||
(
|
||||
"IESG Evaluation Record",
|
||||
"ballot",
|
||||
urlreverse(
|
||||
"ietf.doc.views_doc.document_ballot", kwargs=dict(name=name)
|
||||
),
|
||||
iesg_ballot,
|
||||
None,
|
||||
)
|
||||
)
|
||||
elif doc.type_id == "charter" and doc.group and doc.group.type_id == "wg":
|
||||
tabs.append(
|
||||
(
|
||||
"IESG Review",
|
||||
"ballot",
|
||||
urlreverse(
|
||||
"ietf.doc.views_doc.document_ballot", kwargs=dict(name=name)
|
||||
),
|
||||
iesg_ballot,
|
||||
None,
|
||||
)
|
||||
)
|
||||
if doc.type_id == "draft" or (
|
||||
doc.type_id == "charter" and doc.group and doc.group.type_id == "wg"
|
||||
):
|
||||
tabs.append(
|
||||
(
|
||||
"IESG Writeups",
|
||||
"writeup",
|
||||
urlreverse(
|
||||
"ietf.doc.views_doc.document_writeup", kwargs=dict(name=name)
|
||||
),
|
||||
True,
|
||||
None,
|
||||
)
|
||||
)
|
||||
|
||||
tabs.append(("Email expansions","email",urlreverse('ietf.doc.views_doc.document_email', kwargs=dict(name=name)), True, None))
|
||||
tabs.append(("History", "history", urlreverse('ietf.doc.views_doc.document_history', kwargs=dict(name=name)), True, None))
|
||||
|
@ -147,9 +180,9 @@ def interesting_doc_relations(doc):
|
|||
else:
|
||||
raise TypeError("Expected this method to be called with a Document or DocHistory object")
|
||||
|
||||
that_relationships = STATUSCHANGE_RELATIONS + ('conflrev', 'replaces', 'possibly_replaces', 'updates', 'obs')
|
||||
that_relationships = STATUSCHANGE_RELATIONS + ('conflrev', 'replaces', 'possibly_replaces', 'updates', 'obs', 'became_rfc')
|
||||
|
||||
that_doc_relationships = ('replaces', 'possibly_replaces', 'updates', 'obs')
|
||||
that_doc_relationships = ('replaces', 'possibly_replaces', 'updates', 'obs', 'became_rfc')
|
||||
|
||||
interesting_relations_that = cls.objects.filter(target=target, relationship__in=that_relationships).select_related('source')
|
||||
interesting_relations_that_doc = cls.objects.filter(source=doc, relationship__in=that_doc_relationships).prefetch_related('target')
|
||||
|
@ -160,11 +193,10 @@ def document_main(request, name, rev=None, document_html=False):
|
|||
doc = get_object_or_404(Document.objects.select_related(), docalias__name=name)
|
||||
|
||||
# take care of possible redirections
|
||||
aliases = DocAlias.objects.filter(docs=doc).values_list("name", flat=True)
|
||||
if document_html is False and rev==None and doc.type_id == "draft" and not name.startswith("rfc"):
|
||||
for a in aliases:
|
||||
if a.startswith("rfc"):
|
||||
return redirect("ietf.doc.views_doc.document_main", name=a)
|
||||
if document_html is False and rev is None:
|
||||
became_rfc = next(iter(doc.related_that_doc("became_rfc")), None)
|
||||
if became_rfc:
|
||||
return redirect("ietf.doc.views_doc.document_main", name=became_rfc.name)
|
||||
|
||||
revisions = []
|
||||
for h in doc.history_set.order_by("time", "id"):
|
||||
|
@ -206,7 +238,163 @@ def document_main(request, name, rev=None, document_html=False):
|
|||
|
||||
|
||||
# specific document types
|
||||
if doc.type_id == "draft":
|
||||
if doc.type_id == "rfc":
|
||||
split_content = request.COOKIES.get("full_draft", settings.USER_PREFERENCE_DEFAULTS["full_draft"]) == "off"
|
||||
if request.GET.get('include_text') == "0":
|
||||
split_content = True
|
||||
elif request.GET.get('include_text') == "1":
|
||||
split_content = False
|
||||
else:
|
||||
pass
|
||||
|
||||
interesting_relations_that, interesting_relations_that_doc = interesting_doc_relations(doc)
|
||||
|
||||
can_edit = has_role(request.user, ("Area Director", "Secretariat"))
|
||||
can_edit_authors = has_role(request.user, ("Secretariat"))
|
||||
|
||||
stream_slugs = StreamName.objects.values_list("slug", flat=True)
|
||||
# For some reason, AnonymousUser has __iter__, but is not iterable,
|
||||
# which causes problems in the filter() below. Work around this:
|
||||
if request.user.is_authenticated:
|
||||
roles = Role.objects.filter(group__acronym__in=stream_slugs, person__user=request.user)
|
||||
roles = group_features_role_filter(roles, request.user.person, 'docman_roles')
|
||||
else:
|
||||
roles = []
|
||||
|
||||
can_change_stream = bool(can_edit or roles)
|
||||
|
||||
file_urls, found_types = build_file_urls(doc)
|
||||
content = doc.text_or_error() # pyflakes:ignore
|
||||
content = markup_txt.markup(maybe_split(content, split=split_content))
|
||||
|
||||
if not found_types:
|
||||
content = "This RFC is not currently available online."
|
||||
split_content = False
|
||||
elif "txt" not in found_types:
|
||||
content = "This RFC is not available in plain text format."
|
||||
split_content = False
|
||||
|
||||
# mailing list search archive
|
||||
search_archive = "www.ietf.org/mail-archive/web/"
|
||||
if doc.stream_id == "ietf" and group.type_id == "wg" and group.list_archive:
|
||||
search_archive = group.list_archive
|
||||
|
||||
search_archive = quote(search_archive, safe="~")
|
||||
|
||||
# status changes
|
||||
status_changes = []
|
||||
proposed_status_changes = []
|
||||
for r in interesting_relations_that.filter(relationship__in=STATUSCHANGE_RELATIONS):
|
||||
state_slug = r.source.get_state_slug()
|
||||
if state_slug in ('appr-sent', 'appr-pend'):
|
||||
status_changes.append(r)
|
||||
elif state_slug in ('needshep','adrev','iesgeval','defer','appr-pr'):
|
||||
proposed_status_changes.append(r)
|
||||
else:
|
||||
pass
|
||||
|
||||
presentations = doc.future_presentations()
|
||||
|
||||
augment_docs_and_user_with_user_info([doc], request.user)
|
||||
|
||||
exp_comment = doc.latest_event(IanaExpertDocEvent,type="comment")
|
||||
iana_experts_comment = exp_comment and exp_comment.desc
|
||||
|
||||
# Do not show the Auth48 URL in the "Additional URLs" section
|
||||
additional_urls = doc.documenturl_set.exclude(tag_id='auth48')
|
||||
|
||||
html = None
|
||||
js = None
|
||||
css = None
|
||||
diff_revisions = None
|
||||
simple_diff_revisions = None
|
||||
if document_html:
|
||||
diff_revisions=get_diff_revisions(request, name, doc if isinstance(doc,Document) else doc.doc)
|
||||
simple_diff_revisions = [t[1] for t in diff_revisions if t[0] == doc.name]
|
||||
simple_diff_revisions.reverse()
|
||||
if rev and rev != doc.rev:
|
||||
# No DocHistory was found matching rev - snapshot will be false
|
||||
# and doc will be a Document object, not a DocHistory
|
||||
snapshot = True
|
||||
doc = doc.fake_history_obj(rev)
|
||||
else:
|
||||
html = doc.html_body()
|
||||
if request.COOKIES.get("pagedeps") == "inline":
|
||||
js = Path(finders.find("ietf/js/document_html.js")).read_text()
|
||||
css = Path(finders.find("ietf/css/document_html_inline.css")).read_text()
|
||||
if html:
|
||||
css += Path(finders.find("ietf/css/document_html_txt.css")).read_text()
|
||||
draft_that_became_rfc = None
|
||||
became_rfc_alias = next(iter(doc.related_that("became_rfc")), None)
|
||||
if became_rfc_alias:
|
||||
draft_that_became_rfc = became_rfc_alias.document
|
||||
# submission
|
||||
submission = ""
|
||||
if group is None:
|
||||
submission = "unknown"
|
||||
elif group.type_id == "individ":
|
||||
submission = "individual"
|
||||
elif group.type_id == "area" and doc.stream_id == "ietf":
|
||||
submission = "individual in %s area" % group.acronym
|
||||
else:
|
||||
if group.features.acts_like_wg and not group.type_id == "edwg":
|
||||
submission = "%s %s" % (group.acronym, group.type)
|
||||
else:
|
||||
submission = group.acronym
|
||||
submission = '<a href="%s">%s</a>' % (group.about_url(), submission)
|
||||
# Should be unreachable?
|
||||
if (
|
||||
draft_that_became_rfc
|
||||
and draft_that_became_rfc.stream_id
|
||||
and draft_that_became_rfc.get_state_slug(
|
||||
"draft-stream-%s" % draft_that_became_rfc.stream_id
|
||||
)
|
||||
== "c-adopt"
|
||||
):
|
||||
submission = "candidate for %s" % submission
|
||||
|
||||
|
||||
# todo replace document_html?
|
||||
return render(request, "doc/document_rfc.html" if document_html is False else "doc/document_html.html",
|
||||
dict(doc=doc,
|
||||
document_html=document_html,
|
||||
css=css,
|
||||
js=js,
|
||||
html=html,
|
||||
group=group,
|
||||
top=top,
|
||||
name=doc.name,
|
||||
content=content,
|
||||
split_content=split_content,
|
||||
revisions=simple_diff_revisions if document_html else revisions,
|
||||
snapshot=snapshot,
|
||||
latest_rev=latest_rev,
|
||||
can_edit=can_edit,
|
||||
can_edit_authors=can_edit_authors,
|
||||
can_change_stream=can_change_stream,
|
||||
rfc_number=doc.rfc_number,
|
||||
draft_name=draft_that_became_rfc and draft_that_became_rfc.name,
|
||||
updates=interesting_relations_that_doc.filter(relationship="updates"),
|
||||
updated_by=interesting_relations_that.filter(relationship="updates"),
|
||||
obsoletes=interesting_relations_that_doc.filter(relationship="obs"),
|
||||
obsoleted_by=interesting_relations_that.filter(relationship="obs"),
|
||||
status_changes=status_changes,
|
||||
proposed_status_changes=proposed_status_changes,
|
||||
has_errata=doc.pk and doc.tags.filter(slug="errata"), # doc.pk == None if using a fake_history_obj
|
||||
file_urls=file_urls,
|
||||
additional_urls=additional_urls,
|
||||
rfc_editor_state=doc.get_state("draft-rfceditor"),
|
||||
iana_review_state=doc.get_state("draft-iana-review"),
|
||||
iana_action_state=doc.get_state("draft-iana-action"),
|
||||
iana_experts_state=doc.get_state("draft-iana-experts"),
|
||||
iana_experts_comment=iana_experts_comment,
|
||||
search_archive=search_archive,
|
||||
presentations=presentations,
|
||||
diff_revisions=diff_revisions,
|
||||
submission=submission
|
||||
))
|
||||
|
||||
elif doc.type_id == "draft":
|
||||
split_content = request.COOKIES.get("full_draft", settings.USER_PREFERENCE_DEFAULTS["full_draft"]) == "off"
|
||||
if request.GET.get('include_text') == "0":
|
||||
split_content = True
|
||||
|
@ -244,43 +432,13 @@ def document_main(request, name, rev=None, document_html=False):
|
|||
is_author = request.user.is_authenticated and doc.documentauthor_set.filter(person__user=request.user).exists()
|
||||
can_view_possibly_replaces = can_edit_replaces or is_author
|
||||
|
||||
rfc_number = name[3:] if name.startswith("rfc") else None
|
||||
draft_name = None
|
||||
for a in aliases:
|
||||
if a.startswith("draft"):
|
||||
draft_name = a
|
||||
|
||||
rfc_aliases = [prettify_std_name(a) for a in aliases
|
||||
if a.startswith("fyi") or a.startswith("std") or a.startswith("bcp")]
|
||||
|
||||
latest_revision = None
|
||||
|
||||
# Workaround to allow displaying last rev of draft that became rfc as a draft
|
||||
# This should be unwound when RFCs become their own documents.
|
||||
if snapshot:
|
||||
doc.name = doc.doc.name
|
||||
name = doc.doc.name
|
||||
else:
|
||||
name = doc.name
|
||||
|
||||
file_urls, found_types = build_file_urls(doc)
|
||||
if not snapshot and doc.get_state_slug() == "rfc":
|
||||
# content
|
||||
content = doc.text_or_error() # pyflakes:ignore
|
||||
content = markup_txt.markup(maybe_split(content, split=split_content))
|
||||
|
||||
content = doc.text_or_error() # pyflakes:ignore
|
||||
content = markup_txt.markup(maybe_split(content, split=split_content))
|
||||
|
||||
if not snapshot and doc.get_state_slug() == "rfc":
|
||||
if not found_types:
|
||||
content = "This RFC is not currently available online."
|
||||
split_content = False
|
||||
elif "txt" not in found_types:
|
||||
content = "This RFC is not available in plain text format."
|
||||
split_content = False
|
||||
else:
|
||||
latest_revision = doc.latest_event(NewRevisionDocEvent, type="new_revision")
|
||||
latest_revision = doc.latest_event(NewRevisionDocEvent, type="new_revision")
|
||||
|
||||
# ballot
|
||||
iesg_ballot_summary = None
|
||||
|
@ -460,7 +618,7 @@ def document_main(request, name, rev=None, document_html=False):
|
|||
|
||||
augment_docs_and_user_with_user_info([doc], request.user)
|
||||
|
||||
published = doc.latest_event(type="published_rfc")
|
||||
published = doc.latest_event(type="published_rfc") # todo rethink this now that published_rfc is on rfc
|
||||
started_iesg_process = doc.latest_event(type="started_iesg_process")
|
||||
|
||||
review_assignments = review_assignments_to_list_for_docs([doc]).get(doc.name, [])
|
||||
|
@ -478,12 +636,6 @@ def document_main(request, name, rev=None, document_html=False):
|
|||
# Do not show the Auth48 URL in the "Additional URLs" section
|
||||
additional_urls = doc.documenturl_set.exclude(tag_id='auth48')
|
||||
|
||||
# Stream description passing test
|
||||
if doc.stream != None:
|
||||
stream_desc = doc.stream.desc
|
||||
else:
|
||||
stream_desc = "(None)"
|
||||
|
||||
html = None
|
||||
js = None
|
||||
css = None
|
||||
|
@ -514,12 +666,11 @@ def document_main(request, name, rev=None, document_html=False):
|
|||
html=html,
|
||||
group=group,
|
||||
top=top,
|
||||
name=name,
|
||||
name=doc.name,
|
||||
content=content,
|
||||
split_content=split_content,
|
||||
revisions=simple_diff_revisions if document_html else revisions,
|
||||
snapshot=snapshot,
|
||||
stream_desc=stream_desc,
|
||||
latest_revision=latest_revision,
|
||||
latest_rev=latest_rev,
|
||||
can_edit=can_edit,
|
||||
|
@ -537,8 +688,7 @@ def document_main(request, name, rev=None, document_html=False):
|
|||
can_request_review=can_request_review,
|
||||
can_submit_unsolicited_review_for_teams=can_submit_unsolicited_review_for_teams,
|
||||
|
||||
rfc_number=rfc_number,
|
||||
draft_name=draft_name,
|
||||
draft_name=doc.name,
|
||||
telechat=telechat,
|
||||
iesg_ballot_summary=iesg_ballot_summary,
|
||||
submission=submission,
|
||||
|
@ -555,7 +705,6 @@ def document_main(request, name, rev=None, document_html=False):
|
|||
conflict_reviews=conflict_reviews,
|
||||
status_changes=status_changes,
|
||||
proposed_status_changes=proposed_status_changes,
|
||||
rfc_aliases=rfc_aliases,
|
||||
has_errata=doc.pk and doc.tags.filter(slug="errata"), # doc.pk == None if using a fake_history_obj
|
||||
published=published,
|
||||
file_urls=file_urls,
|
||||
|
@ -584,7 +733,7 @@ def document_main(request, name, rev=None, document_html=False):
|
|||
diff_revisions=diff_revisions
|
||||
))
|
||||
|
||||
if doc.type_id == "charter":
|
||||
elif doc.type_id == "charter":
|
||||
content = doc.text_or_error() # pyflakes:ignore
|
||||
content = markup_txt.markup(content)
|
||||
|
||||
|
@ -621,7 +770,7 @@ def document_main(request, name, rev=None, document_html=False):
|
|||
can_manage=can_manage,
|
||||
))
|
||||
|
||||
if doc.type_id == "bofreq":
|
||||
elif doc.type_id == "bofreq":
|
||||
content = markdown.markdown(doc.text_or_error())
|
||||
editors = bofreq_editors(doc)
|
||||
responsible = bofreq_responsible(doc)
|
||||
|
@ -641,7 +790,7 @@ def document_main(request, name, rev=None, document_html=False):
|
|||
editor_can_manage=editor_can_manage,
|
||||
))
|
||||
|
||||
if doc.type_id == "conflrev":
|
||||
elif doc.type_id == "conflrev":
|
||||
filename = "%s-%s.txt" % (doc.canonical_name(), doc.rev)
|
||||
pathname = os.path.join(settings.CONFLICT_REVIEW_PATH,filename)
|
||||
|
||||
|
@ -671,7 +820,7 @@ def document_main(request, name, rev=None, document_html=False):
|
|||
approved_states=('appr-reqnopub-pend','appr-reqnopub-sent','appr-noprob-pend','appr-noprob-sent'),
|
||||
))
|
||||
|
||||
if doc.type_id == "statchg":
|
||||
elif doc.type_id == "statchg":
|
||||
filename = "%s-%s.txt" % (doc.canonical_name(), doc.rev)
|
||||
pathname = os.path.join(settings.STATUS_CHANGE_PATH,filename)
|
||||
|
||||
|
@ -705,7 +854,7 @@ def document_main(request, name, rev=None, document_html=False):
|
|||
sorted_relations=sorted_relations,
|
||||
))
|
||||
|
||||
if doc.type_id in ("slides", "agenda", "minutes", "bluesheets", "procmaterials",):
|
||||
elif doc.type_id in ("slides", "agenda", "minutes", "bluesheets", "procmaterials",):
|
||||
can_manage_material = can_manage_materials(request.user, doc.group)
|
||||
presentations = doc.future_presentations()
|
||||
if doc.uploaded_filename:
|
||||
|
@ -761,7 +910,7 @@ def document_main(request, name, rev=None, document_html=False):
|
|||
))
|
||||
|
||||
|
||||
if doc.type_id == "review":
|
||||
elif doc.type_id == "review":
|
||||
basename = "{}.txt".format(doc.name)
|
||||
pathname = os.path.join(doc.get_file_path(), basename)
|
||||
content = get_unicode_document_content(basename, pathname)
|
||||
|
@ -787,7 +936,7 @@ def document_main(request, name, rev=None, document_html=False):
|
|||
assignments=assignments,
|
||||
))
|
||||
|
||||
if doc.type_id in ("chatlog", "polls"):
|
||||
elif doc.type_id in ("chatlog", "polls"):
|
||||
if isinstance(doc,DocHistory):
|
||||
session = doc.doc.sessionpresentation_set.last().session
|
||||
else:
|
||||
|
@ -862,7 +1011,7 @@ def document_html(request, name, rev=None):
|
|||
doc = found.documents.get()
|
||||
rev = found.matched_rev
|
||||
|
||||
if not requested_rev and doc.is_rfc(): # Someone asked for /doc/html/8989
|
||||
if not requested_rev and doc.type_id == "rfc": # Someone asked for /doc/html/8989
|
||||
if not name.startswith('rfc'):
|
||||
return redirect('ietf.doc.views_doc.document_html', name=doc.canonical_name())
|
||||
|
||||
|
@ -872,7 +1021,12 @@ def document_html(request, name, rev=None):
|
|||
if not os.path.exists(doc.get_file_name()):
|
||||
raise Http404("File not found: %s" % doc.get_file_name())
|
||||
|
||||
return document_main(request, name=doc.name if requested_rev else doc.canonical_name(), rev=doc.rev if requested_rev or not doc.is_rfc() else None, document_html=True)
|
||||
return document_main(
|
||||
request,
|
||||
name=doc.name if requested_rev else doc.canonical_name(),
|
||||
rev=doc.rev if requested_rev or doc.type_id != "rfc" else None,
|
||||
document_html=True,
|
||||
)
|
||||
|
||||
def document_pdfized(request, name, rev=None, ext=None):
|
||||
|
||||
|
@ -1028,21 +1182,46 @@ def document_history(request, name):
|
|||
add_events_message_info(events)
|
||||
|
||||
# figure out if the current user can add a comment to the history
|
||||
if doc.type_id == "draft" and doc.group != None:
|
||||
can_add_comment = bool(has_role(request.user, ("Area Director", "Secretariat", "IRTF Chair", "IANA", "RFC Editor")) or (
|
||||
request.user.is_authenticated and
|
||||
Role.objects.filter(name__in=("chair", "secr"),
|
||||
group__acronym=doc.group.acronym,
|
||||
person__user=request.user)))
|
||||
if doc.type_id in ("draft", "rfc") and doc.group is not None:
|
||||
can_add_comment = bool(
|
||||
has_role(
|
||||
request.user,
|
||||
("Area Director", "Secretariat", "IRTF Chair", "IANA", "RFC Editor"),
|
||||
)
|
||||
or (
|
||||
request.user.is_authenticated
|
||||
and Role.objects.filter(
|
||||
name__in=("chair", "secr"),
|
||||
group__acronym=doc.group.acronym,
|
||||
person__user=request.user,
|
||||
)
|
||||
)
|
||||
)
|
||||
else:
|
||||
can_add_comment = has_role(request.user, ("Area Director", "Secretariat", "IRTF Chair"))
|
||||
return render(request, "doc/document_history.html",
|
||||
dict(doc=doc,
|
||||
top=top,
|
||||
diff_revisions=diff_revisions,
|
||||
events=events,
|
||||
can_add_comment=can_add_comment,
|
||||
))
|
||||
can_add_comment = has_role(
|
||||
request.user, ("Area Director", "Secretariat", "IRTF Chair")
|
||||
)
|
||||
|
||||
# Get related docs whose history should be linked
|
||||
if doc.type_id == "draft":
|
||||
related = doc.related_that_doc("became_rfc")
|
||||
elif doc.type_id == "rfc":
|
||||
related = doc.related_that("became_rfc")
|
||||
else:
|
||||
related = []
|
||||
|
||||
return render(
|
||||
request,
|
||||
"doc/document_history.html",
|
||||
{
|
||||
"doc": doc,
|
||||
"top": top,
|
||||
"diff_revisions": diff_revisions,
|
||||
"events": events,
|
||||
"related": related,
|
||||
"can_add_comment": can_add_comment,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
def document_bibtex(request, name, rev=None):
|
||||
|
@ -1058,31 +1237,35 @@ def document_bibtex(request, name, rev=None):
|
|||
|
||||
doc = get_object_or_404(Document, docalias__name=name)
|
||||
|
||||
latest_revision = doc.latest_event(NewRevisionDocEvent, type="new_revision")
|
||||
replaced_by = [d.name for d in doc.related_that("replaces")]
|
||||
published = doc.latest_event(type="published_rfc") is not None
|
||||
rfc = latest_revision.doc if latest_revision and latest_revision.doc.get_state_slug() == "rfc" else None
|
||||
doi = None
|
||||
draft_became_rfc = None
|
||||
replaced_by = None
|
||||
latest_revision = None
|
||||
if doc.type_id == "draft":
|
||||
latest_revision = doc.latest_event(NewRevisionDocEvent, type="new_revision")
|
||||
replaced_by = [d.name for d in doc.related_that("replaces")]
|
||||
draft_became_rfc_alias = next(iter(doc.related_that_doc("became_rfc")), None)
|
||||
|
||||
if rev != None and rev != doc.rev:
|
||||
# find the entry in the history
|
||||
for h in doc.history_set.order_by("-time"):
|
||||
if rev == h.rev:
|
||||
doc = h
|
||||
break
|
||||
|
||||
if doc.is_rfc():
|
||||
if rev != None and rev != doc.rev:
|
||||
# find the entry in the history
|
||||
for h in doc.history_set.order_by("-time"):
|
||||
if rev == h.rev:
|
||||
doc = h
|
||||
break
|
||||
|
||||
if draft_became_rfc_alias:
|
||||
draft_became_rfc = draft_became_rfc_alias.document
|
||||
|
||||
elif doc.type_id == "rfc":
|
||||
# This needs to be replaced with a lookup, as the mapping may change
|
||||
# over time. Probably by updating ietf/sync/rfceditor.py to add the
|
||||
# as a DocAlias, and use a method on Document to retrieve it.
|
||||
doi = f"10.17487/RFC{doc.rfc_number:04d}"
|
||||
else:
|
||||
doi = None
|
||||
|
||||
return render(request, "doc/document_bibtex.bib",
|
||||
dict(doc=doc,
|
||||
replaced_by=replaced_by,
|
||||
published=published,
|
||||
rfc=rfc,
|
||||
published_as=draft_became_rfc,
|
||||
latest_revision=latest_revision,
|
||||
doi=doi,
|
||||
),
|
||||
|
@ -1945,9 +2128,16 @@ def idnits2_rfc_status(request):
|
|||
|
||||
def idnits2_state(request, name, rev=None):
|
||||
doc = get_object_or_404(Document, docalias__name=name)
|
||||
if doc.type_id!='draft':
|
||||
if doc.type_id not in ["draft", "rfc"]:
|
||||
raise Http404
|
||||
zero_revision = NewRevisionDocEvent.objects.filter(doc=doc,rev='00').first()
|
||||
zero_revision = None
|
||||
if doc.type_id == "rfc":
|
||||
draft_alias = next(iter(doc.related_that('became_rfc')), None)
|
||||
if draft_alias:
|
||||
draft = draft_alias.document
|
||||
zero_revision = NewRevisionDocEvent.objects.filter(doc=draft,rev='00').first()
|
||||
else:
|
||||
zero_revision = NewRevisionDocEvent.objects.filter(doc=doc,rev='00').first()
|
||||
if zero_revision:
|
||||
doc.created = zero_revision.time
|
||||
else:
|
||||
|
|
|
@ -117,7 +117,7 @@ class RequestReviewForm(forms.ModelForm):
|
|||
|
||||
@login_required
|
||||
def request_review(request, name):
|
||||
doc = get_object_or_404(Document, name=name)
|
||||
doc = get_object_or_404(Document, type_id="draft", name=name)
|
||||
|
||||
if not can_request_review_of_doc(request.user, doc):
|
||||
permission_denied(request, "You do not have permission to perform this action")
|
||||
|
|
|
@ -409,7 +409,7 @@ def shorten_group_name(name):
|
|||
|
||||
def ad_dashboard_sort_key(doc):
|
||||
|
||||
if doc.type.slug=='rfc' and doc.get_state_slug('rfc') == 'published':
|
||||
if doc.type.slug=='rfc':
|
||||
return "21%04d" % int(doc.rfc_number)
|
||||
if doc.type.slug=='statchg' and doc.get_state_slug('statchg') == 'appr-sent':
|
||||
return "22%d" % 0 # TODO - get the date of the transition into this state here
|
||||
|
@ -805,21 +805,20 @@ def recent_drafts(request, days=7):
|
|||
})
|
||||
|
||||
|
||||
def index_all_drafts(request):
|
||||
def index_all_drafts(request): # Should we rename this
|
||||
# try to be efficient since this view returns a lot of data
|
||||
categories = []
|
||||
|
||||
for s in ("active", "rfc", "expired", "repl", "auth-rm", "ietf-rm"):
|
||||
# Gather drafts
|
||||
for s in ("active", "expired", "repl", "auth-rm", "ietf-rm"):
|
||||
state = State.objects.get(type="draft", slug=s)
|
||||
|
||||
if state.slug == "rfc":
|
||||
heading = "RFCs"
|
||||
elif state.slug in ("ietf-rm", "auth-rm"):
|
||||
if state.slug in ("ietf-rm", "auth-rm"):
|
||||
heading = "Internet-Drafts %s" % state.name
|
||||
else:
|
||||
heading = "%s Internet-Drafts" % state.name
|
||||
|
||||
draft_names = DocAlias.objects.filter(docs__states=state).values_list("name", "docs__name")
|
||||
draft_names = DocAlias.objects.filter(docs__type_id="draft", docs__states=state).values_list("name", "docs__name")
|
||||
|
||||
names = []
|
||||
names_to_skip = set()
|
||||
|
@ -828,24 +827,52 @@ def index_all_drafts(request):
|
|||
if name != doc:
|
||||
if not name.startswith("rfc"):
|
||||
name, doc = doc, name
|
||||
names_to_skip.add(doc)
|
||||
|
||||
if name.startswith("rfc"):
|
||||
name = name.upper()
|
||||
sort_key = '%09d' % (100000000-int(name[3:]))
|
||||
names_to_skip.add(doc) # this is filtering out subseries docaliases (which we will delete, so TODO clean this out after doing so)
|
||||
|
||||
names.append((name, sort_key))
|
||||
|
||||
names.sort(key=lambda t: t[1])
|
||||
|
||||
names = [f'<a href=\"{urlreverse("ietf.doc.views_doc.document_main", kwargs=dict(name=n))}\">{n}</a>'
|
||||
for n, __ in names if n not in names_to_skip]
|
||||
for n, __ in names if n not in names_to_skip]
|
||||
|
||||
categories.append((state,
|
||||
heading,
|
||||
len(names),
|
||||
"<br>".join(names)
|
||||
))
|
||||
|
||||
# gather RFCs
|
||||
rfc_names = DocAlias.objects.filter(docs__type_id="rfc").values_list("name", "docs__name")
|
||||
names = []
|
||||
names_to_skip = set()
|
||||
for name, doc in rfc_names:
|
||||
sort_key = name
|
||||
if name != doc: # There are some std docalias that pointed to rfc names pre-migration.
|
||||
if not name.startswith("rfc"):
|
||||
name, doc = doc, name
|
||||
names_to_skip.add(doc) # this is filtering out those std docaliases (which we will delete, so TODO clean this out after doing so)
|
||||
name = name.upper()
|
||||
sort_key = '%09d' % (100000000-int(name[3:]))
|
||||
|
||||
names.append((name, sort_key))
|
||||
|
||||
names.sort(key=lambda t: t[1])
|
||||
|
||||
names = [f'<a href=\"{urlreverse("ietf.doc.views_doc.document_main", kwargs=dict(name=n))}\">{n}</a>'
|
||||
for n, __ in names if n not in names_to_skip]
|
||||
|
||||
state = State.objects.get(type_id="rfc", slug="published")
|
||||
|
||||
categories.append((state,
|
||||
"RFCs",
|
||||
len(names),
|
||||
"<br>".join(names)
|
||||
))
|
||||
|
||||
# Return to the previous section ordering
|
||||
categories = categories[0:1]+categories[5:]+categories[1:5]
|
||||
|
||||
return render(request, 'doc/index_all_drafts.html', { "categories": categories })
|
||||
|
||||
def index_active_drafts(request):
|
||||
|
|
|
@ -534,7 +534,7 @@ def group_documents_txt(request, acronym, group_type=None):
|
|||
|
||||
rows = []
|
||||
for d in itertools.chain(docs, docs_related):
|
||||
if d.is_rfc():
|
||||
if d.type_id == "rfc":
|
||||
name = str(d.rfc_number)
|
||||
else:
|
||||
name = "%s-%s" % (d.name, d.rev)
|
||||
|
|
|
@ -107,7 +107,7 @@ class IESGAgendaTests(TestCase):
|
|||
super().setUp()
|
||||
mars = GroupFactory(acronym='mars',parent=Group.objects.get(acronym='farfut'))
|
||||
wgdraft = WgDraftFactory(name='draft-ietf-mars-test', group=mars, intended_std_level_id='ps')
|
||||
rfc = IndividualRfcFactory.create(stream_id='irtf', other_aliases=['rfc6666',], states=[('draft','rfc'),('draft-iesg','pub')], std_level_id='inf', )
|
||||
rfc = IndividualRfcFactory.create(stream_id='irtf', rfc_number=6666, std_level_id='inf', )
|
||||
wgdraft.relateddocument_set.create(target=rfc.docalias.get(name='rfc6666'), relationship_id='refnorm')
|
||||
ise_draft = IndividualDraftFactory(name='draft-imaginary-independent-submission')
|
||||
ise_draft.stream = StreamName.objects.get(slug="ise")
|
||||
|
|
|
@ -151,7 +151,7 @@ def agenda_json(request, date=None):
|
|||
if doc.type_id == "draft":
|
||||
docinfo['rev'] = doc.rev
|
||||
docinfo['intended-std-level'] = str(doc.intended_std_level)
|
||||
if doc.is_rfc():
|
||||
if doc.type_id == "rfc":
|
||||
docinfo['rfc-number'] = doc.rfc_number
|
||||
|
||||
iana_state = doc.get_state("draft-iana-review")
|
||||
|
|
|
@ -9919,7 +9919,7 @@
|
|||
"used": true
|
||||
},
|
||||
"model": "name.docrelationshipname",
|
||||
"pk": "became-rfc"
|
||||
"pk": "became_rfc"
|
||||
},
|
||||
{
|
||||
"fields": {
|
||||
|
|
|
@ -14,7 +14,7 @@ def forward(apps, schema_editor):
|
|||
|
||||
DocRelationshipName = apps.get_model("name", "DocRelationshipName")
|
||||
DocRelationshipName.objects.get_or_create(
|
||||
slug="became-rfc",
|
||||
slug="became_rfc",
|
||||
name="became RFC",
|
||||
used=True,
|
||||
revname="came from draft",
|
||||
|
|
|
@ -343,7 +343,7 @@ class NominateForm(forms.ModelForm):
|
|||
'year': self.nomcom.year(),
|
||||
}
|
||||
path = nomcom_template_path + NOMINATION_RECEIPT_TEMPLATE
|
||||
send_mail(None, to_email, from_email, subject, path, context, cc=cc)
|
||||
send_mail(None, to_email, from_email, subject, path, context, cc=cc, copy=False, save=False)
|
||||
|
||||
return nomination
|
||||
|
||||
|
@ -458,7 +458,7 @@ class NominateNewPersonForm(forms.ModelForm):
|
|||
'year': self.nomcom.year(),
|
||||
}
|
||||
path = nomcom_template_path + NOMINATION_RECEIPT_TEMPLATE
|
||||
send_mail(None, to_email, from_email, subject, path, context, cc=cc)
|
||||
send_mail(None, to_email, from_email, subject, path, context, cc=cc, copy=False, save=False)
|
||||
|
||||
return nomination
|
||||
|
||||
|
@ -551,7 +551,7 @@ class FeedbackForm(forms.ModelForm):
|
|||
}
|
||||
path = nomcom_template_path + FEEDBACK_RECEIPT_TEMPLATE
|
||||
# TODO - make the thing above more generic
|
||||
send_mail(None, to_email, from_email, subject, path, context, cc=cc, copy=False)
|
||||
send_mail(None, to_email, from_email, subject, path, context, cc=cc, copy=False, save=False)
|
||||
|
||||
class Meta:
|
||||
model = Feedback
|
||||
|
|
|
@ -122,7 +122,7 @@ class NomcomViewsTest(TestCase):
|
|||
self.check_url_status(url, 200)
|
||||
self.client.logout()
|
||||
login_testing_unauthorized(self, MEMBER_USER, url)
|
||||
return self.check_url_status(url, 200)
|
||||
self.check_url_status(url, 200)
|
||||
|
||||
def access_chair_url(self, url):
|
||||
login_testing_unauthorized(self, COMMUNITY_USER, url)
|
||||
|
@ -134,7 +134,7 @@ class NomcomViewsTest(TestCase):
|
|||
login_testing_unauthorized(self, COMMUNITY_USER, url)
|
||||
login_testing_unauthorized(self, CHAIR_USER, url)
|
||||
login_testing_unauthorized(self, SECRETARIAT_USER, url)
|
||||
return self.check_url_status(url, 200)
|
||||
self.check_url_status(url, 200)
|
||||
|
||||
def test_private_index_view(self):
|
||||
"""Verify private home view"""
|
||||
|
@ -599,6 +599,8 @@ class NomcomViewsTest(TestCase):
|
|||
self.nominate_view(public=True,confirmation=True)
|
||||
|
||||
self.assertEqual(len(outbox), messages_before + 3)
|
||||
self.assertEqual(Message.objects.count(), 2)
|
||||
self.assertFalse(Message.objects.filter(subject="Nomination receipt").exists())
|
||||
|
||||
self.assertEqual('IETF Nomination Information', outbox[-3]['Subject'])
|
||||
self.assertEqual(self.email_from, outbox[-3]['From'])
|
||||
|
@ -625,8 +627,7 @@ class NomcomViewsTest(TestCase):
|
|||
|
||||
def test_private_nominate(self):
|
||||
self.access_member_url(self.private_nominate_url)
|
||||
return self.nominate_view(public=False)
|
||||
self.client.logout()
|
||||
self.nominate_view(public=False)
|
||||
|
||||
def test_public_nominate_newperson(self):
|
||||
login_testing_unauthorized(self, COMMUNITY_USER, self.public_nominate_url)
|
||||
|
@ -666,13 +667,13 @@ class NomcomViewsTest(TestCase):
|
|||
|
||||
def test_private_nominate_newperson(self):
|
||||
self.access_member_url(self.private_nominate_url)
|
||||
return self.nominate_newperson_view(public=False)
|
||||
self.client.logout()
|
||||
self.nominate_newperson_view(public=False, confirmation=True)
|
||||
self.assertFalse(Message.objects.filter(subject="Nomination receipt").exists())
|
||||
|
||||
def test_private_nominate_newperson_who_already_exists(self):
|
||||
EmailFactory(address='nominee@example.com')
|
||||
self.access_member_url(self.private_nominate_newperson_url)
|
||||
return self.nominate_newperson_view(public=False)
|
||||
self.nominate_newperson_view(public=False)
|
||||
|
||||
def test_public_nominate_with_automatic_questionnaire(self):
|
||||
nomcom = get_nomcom_by_year(self.year)
|
||||
|
@ -844,8 +845,7 @@ class NomcomViewsTest(TestCase):
|
|||
|
||||
def test_add_questionnaire(self):
|
||||
self.access_chair_url(self.add_questionnaire_url)
|
||||
return self.add_questionnaire()
|
||||
self.client.logout()
|
||||
self.add_questionnaire()
|
||||
|
||||
def add_questionnaire(self, *args, **kwargs):
|
||||
public = kwargs.pop('public', False)
|
||||
|
@ -906,6 +906,8 @@ class NomcomViewsTest(TestCase):
|
|||
# We're interested in the confirmation receipt here
|
||||
self.assertEqual(len(outbox),3)
|
||||
self.assertEqual('NomCom comment confirmation', outbox[2]['Subject'])
|
||||
self.assertEqual(Message.objects.count(), 2)
|
||||
self.assertFalse(Message.objects.filter(subject="NomCom comment confirmation").exists())
|
||||
email_body = get_payload_text(outbox[2])
|
||||
self.assertIn(position, email_body)
|
||||
self.assertNotIn('$', email_body)
|
||||
|
@ -920,7 +922,7 @@ class NomcomViewsTest(TestCase):
|
|||
|
||||
def test_private_feedback(self):
|
||||
self.access_member_url(self.private_feedback_url)
|
||||
return self.feedback_view(public=False)
|
||||
self.feedback_view(public=False)
|
||||
|
||||
def feedback_view(self, *args, **kwargs):
|
||||
public = kwargs.pop('public', True)
|
||||
|
|
|
@ -1106,6 +1106,41 @@ def edit_template(request, year, template_id):
|
|||
def list_positions(request, year):
|
||||
nomcom = get_nomcom_by_year(year)
|
||||
positions = nomcom.position_set.order_by('-is_open')
|
||||
if request.method == 'POST':
|
||||
if nomcom.group.state_id != 'active':
|
||||
messages.warning(request, "This nomcom is not active. Request administrative assistance if Position state needs to change.")
|
||||
else:
|
||||
action = request.POST.get('action')
|
||||
positions_to_modify = request.POST.getlist('selected')
|
||||
if positions_to_modify:
|
||||
positions = positions.filter(id__in=positions_to_modify)
|
||||
if action == "set_iesg":
|
||||
positions.update(is_iesg_position=True)
|
||||
messages.success(request,'The selected positions have been set as IESG Positions')
|
||||
elif action == "unset_iesg":
|
||||
positions.update(is_iesg_position=False)
|
||||
messages.success(request,'The selected positions have been set as NOT IESG Positions')
|
||||
elif action == "set_open":
|
||||
positions.update(is_open=True)
|
||||
messages.success(request,'The selected positions have been set as Open')
|
||||
elif action == "unset_open":
|
||||
positions.update(is_open=False)
|
||||
messages.success(request,'The selected positions have been set as NOT Open')
|
||||
elif action == "set_accept_nom":
|
||||
positions.update(accepting_nominations=True)
|
||||
messages.success(request,'The selected positions have been set as Accepting Nominations')
|
||||
elif action == "unset_accept_nom":
|
||||
positions.update(accepting_nominations=False)
|
||||
messages.success(request,'The selected positions have been set as NOT Accepting Nominations')
|
||||
elif action == "set_accept_fb":
|
||||
positions.update(accepting_feedback=True)
|
||||
messages.success(request,'The selected positions have been set as Accepting Feedback')
|
||||
elif action == "unset_accept_fb":
|
||||
positions.update(accepting_feedback=False)
|
||||
messages.success(request,'The selected positions have been set as NOT Accepting Feedback')
|
||||
positions = nomcom.position_set.order_by('-is_open')
|
||||
else:
|
||||
messages.warning(request, "Please select some positions to work with")
|
||||
|
||||
return render(request, 'nomcom/list_positions.html',
|
||||
{'positions': positions,
|
||||
|
|
|
@ -50,6 +50,8 @@ def can_request_review_of_doc(user, doc):
|
|||
if not user.is_authenticated:
|
||||
return False
|
||||
|
||||
# This is in a strange place as it has nothing to do with the user
|
||||
# but this utility is used in too many places to move this quickly.
|
||||
if doc.type_id == 'draft' and doc.get_state_slug() != 'active':
|
||||
return False
|
||||
|
||||
|
|
|
@ -730,6 +730,7 @@ def no_session(request, acronym):
|
|||
requested_duration=datetime.timedelta(0),
|
||||
type_id='regular',
|
||||
purpose_id='regular',
|
||||
has_onsite_tool=group.features.acts_like_wg,
|
||||
)
|
||||
SchedulingEvent.objects.create(
|
||||
session=session,
|
||||
|
|
|
@ -67,8 +67,7 @@ class SecrTelechatTestCase(TestCase):
|
|||
def test_doc_detail_draft_with_downref(self):
|
||||
ad = Person.objects.get(user__username="ad")
|
||||
draft = WgDraftFactory(ad=ad, intended_std_level_id='ps', states=[('draft-iesg','pub-req'),])
|
||||
rfc = IndividualRfcFactory.create(stream_id='irtf', other_aliases=['rfc6666',],
|
||||
states=[('draft','rfc'),('draft-iesg','pub')], std_level_id='inf', )
|
||||
rfc = IndividualRfcFactory.create(stream_id='irtf', rfc_number=6666, std_level_id='inf')
|
||||
draft.relateddocument_set.create(target=rfc.docalias.get(name='rfc6666'),
|
||||
relationship_id='refnorm')
|
||||
create_ballot_if_not_open(None, draft, ad, 'approve')
|
||||
|
|
|
@ -704,6 +704,11 @@ class SubmissionAutoUploadForm(SubmissionBaseUploadForm):
|
|||
'replaces',
|
||||
forms.ValidationError("An Internet-Draft can only replace another Internet-Draft"),
|
||||
)
|
||||
elif doc.get_state_slug() == "rfc":
|
||||
self.add_error(
|
||||
'replaces',
|
||||
forms.ValidationError("An Internet-Draft cannot replace another Internet-Draft that has become an RFC"),
|
||||
)
|
||||
elif doc.get_state_slug('draft-iesg') in ('approved', 'ann', 'rfcqueue'):
|
||||
self.add_error(
|
||||
'replaces',
|
||||
|
|
|
@ -32,7 +32,7 @@ from ietf.submit.utils import (expirable_submissions, expire_submission, find_su
|
|||
process_and_accept_uploaded_submission, SubmissionError, process_submission_text,
|
||||
process_submission_xml, process_uploaded_submission,
|
||||
process_and_validate_submission)
|
||||
from ietf.doc.factories import (DocumentFactory, WgDraftFactory, IndividualDraftFactory, IndividualRfcFactory,
|
||||
from ietf.doc.factories import (DocumentFactory, WgDraftFactory, IndividualDraftFactory,
|
||||
ReviewFactory, WgRfcFactory)
|
||||
from ietf.doc.models import ( Document, DocAlias, DocEvent, State,
|
||||
BallotPositionDocEvent, DocumentAuthor, SubmissionDocEvent )
|
||||
|
@ -3090,13 +3090,15 @@ class SubmissionUploadFormTests(BaseSubmitTestCase):
|
|||
|
||||
# can't replace RFC
|
||||
rfc = WgRfcFactory()
|
||||
draft = WgDraftFactory(states=[("draft", "rfc")])
|
||||
draft.relateddocument_set.create(relationship_id="became_rfc", target=rfc.docalias.first())
|
||||
form = SubmissionAutoUploadForm(
|
||||
request_factory.get('/some/url'),
|
||||
data={'user': auth.user.username, 'replaces': rfc.name},
|
||||
data={'user': auth.user.username, 'replaces': draft.name},
|
||||
files=files_dict,
|
||||
)
|
||||
self.assertFalse(form.is_valid())
|
||||
self.assertIn('An Internet-Draft can only replace another Internet-Draft', form.errors['replaces'])
|
||||
self.assertIn('An Internet-Draft can only replace another Internet-Draft that has become an RFC', form.errors['replaces'])
|
||||
|
||||
# can't replace draft approved by iesg
|
||||
existing_drafts[0].set_state(State.objects.get(type='draft-iesg', slug='approved'))
|
||||
|
@ -3688,25 +3690,9 @@ class RefsTests(BaseSubmitTestCase):
|
|||
|
||||
|
||||
class PostSubmissionTests(BaseSubmitTestCase):
|
||||
@override_settings(RFC_FILE_TYPES=('txt', 'xml'), IDSUBMIT_FILE_TYPES=('pdf', 'md'))
|
||||
def test_find_submission_filenames_rfc(self):
|
||||
"""Posting an RFC submission should use RFC_FILE_TYPES"""
|
||||
rfc = IndividualRfcFactory()
|
||||
path = Path(self.staging_dir)
|
||||
for ext in ['txt', 'xml', 'pdf', 'md']:
|
||||
(path / f'{rfc.name}-{rfc.rev}.{ext}').touch()
|
||||
files = find_submission_filenames(rfc)
|
||||
self.assertCountEqual(
|
||||
files,
|
||||
{
|
||||
'txt': f'{path}/{rfc.name}-{rfc.rev}.txt',
|
||||
'xml': f'{path}/{rfc.name}-{rfc.rev}.xml',
|
||||
# should NOT find the pdf or md
|
||||
}
|
||||
)
|
||||
|
||||
@override_settings(RFC_FILE_TYPES=('txt', 'xml'), IDSUBMIT_FILE_TYPES=('pdf', 'md'))
|
||||
def test_find_submission_filenames_draft(self):
|
||||
def test_find_submission_filenames(self):
|
||||
"""Posting an I-D submission should use IDSUBMIT_FILE_TYPES"""
|
||||
draft = WgDraftFactory()
|
||||
path = Path(self.staging_dir)
|
||||
|
|
|
@ -287,7 +287,7 @@ def find_submission_filenames(draft):
|
|||
"""
|
||||
path = pathlib.Path(settings.IDSUBMIT_STAGING_PATH)
|
||||
stem = f'{draft.name}-{draft.rev}'
|
||||
allowed_types = settings.RFC_FILE_TYPES if draft.get_state_slug() == 'rfc' else settings.IDSUBMIT_FILE_TYPES
|
||||
allowed_types = settings.IDSUBMIT_FILE_TYPES
|
||||
candidates = {ext: path / f'{stem}.{ext}' for ext in allowed_types}
|
||||
return {ext: str(filename) for ext, filename in candidates.items() if filename.exists()}
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
{% load ietf_filters %}
|
||||
{% load textfilters %}
|
||||
|
||||
{% if doc.get_state_slug == "rfc" %}
|
||||
{% if doc.type_id == "rfc" %}
|
||||
{% if doc.stream|slugify == "legacy" %}
|
||||
% Datatracker information for RFCs on the Legacy Stream is unfortunately often
|
||||
% incorrect. Please correct the bibtex below based on the information in the
|
||||
|
@ -16,7 +16,7 @@
|
|||
publisher = {RFC Editor},
|
||||
doi = {% templatetag openbrace %}{{ doi }}{% templatetag closebrace %},
|
||||
url = {% templatetag openbrace %}{{ doc.rfc_number|rfceditor_info_url }}{% templatetag closebrace %},{% else %}
|
||||
{% if published %}%% You should probably cite rfc{{ latest_revision.doc.rfc_number }} instead of this I-D.{% else %}{% if replaced_by %}%% You should probably cite {{replaced_by|join:" or "}} instead of this I-D.{% else %}
|
||||
{% if published_as %}%% You should probably cite rfc{{ published_as.rfc_number }} instead of this I-D.{% else %}{% if replaced_by %}%% You should probably cite {{replaced_by|join:" or "}} instead of this I-D.{% else %}
|
||||
{% if doc.rev != latest_revision.rev %}%% You should probably cite {{latest_revision.doc.name}}-{{latest_revision.rev}} instead of this revision.{%endif%}{% endif %}{% endif %}
|
||||
@techreport{% templatetag openbrace %}{{doc.name|slice:"6:"}}-{{doc.rev}},
|
||||
number = {% templatetag openbrace %}{{doc.name}}-{{doc.rev}}{% templatetag closebrace %},
|
||||
|
@ -29,7 +29,7 @@
|
|||
title = {% templatetag openbrace %}{% templatetag openbrace %}{{doc.title|texescape}}{% templatetag closebrace %}{% templatetag closebrace %},
|
||||
pagetotal = {{ doc.pages }},
|
||||
year = {{ doc.pub_date.year }},
|
||||
month = {{ doc.pub_date|date:"b" }},{% if not doc.rfc_number or doc.pub_date.day == 1 and doc.pub_date.month == 4 %}
|
||||
month = {{ doc.pub_date|date:"b" }},{% if not doc.type_id == "rfc" or doc.pub_date.day == 1 and doc.pub_date.month == 4 %}
|
||||
day = {{ doc.pub_date.day }},{% endif %}
|
||||
abstract = {% templatetag openbrace %}{{ doc.abstract|clean_whitespace|texescape }}{% templatetag closebrace %},
|
||||
{% templatetag closebrace %}
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
<link rel="alternate"
|
||||
type="application/atom+xml"
|
||||
href="/feed/document-changes/{{ doc.name }}/">
|
||||
<link rel="stylesheet" href="{% static "ietf/css/list.css" %}">
|
||||
<link rel="stylesheet" href="{% static 'ietf/css/list.css' %}">
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
{% origin %}
|
||||
|
@ -20,7 +20,17 @@
|
|||
<h2 class="my-3">Revision differences</h2>
|
||||
{% include "doc/document_history_form.html" with doc=doc diff_revisions=diff_revisions action=rfcdiff_base_url snapshot=snapshot only %}
|
||||
{% endif %}
|
||||
<h2 class="my-3">Document history</h2>
|
||||
<h2 class="my-3">Document history
|
||||
{% if related %}
|
||||
<div class="float-end">
|
||||
{% for related_docalias in related %}
|
||||
<a class="btn btn-outline-primary btn-sm"
|
||||
href="{% url 'ietf.doc.views_doc.document_history' name=related_docalias.name %}">
|
||||
Related history for {{ related_docalias.name }}
|
||||
</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}</h2>
|
||||
{% if can_add_comment %}
|
||||
<div class="buttonlist">
|
||||
<a class="btn btn-primary"
|
||||
|
@ -34,7 +44,7 @@
|
|||
<thead>
|
||||
<tr>
|
||||
<th scope="col" data-sort="date">Date</th>
|
||||
<th scope="col" data-sort="rev">Rev.</th>
|
||||
{% if doc.type_id != "rfc" %}<th scope="col" data-sort="rev">Rev.</th>{% endif %}
|
||||
<th scope="col" data-sort="by">By</th>
|
||||
<th scope="col" data-sort="action">Action</th>
|
||||
</tr>
|
||||
|
@ -45,7 +55,7 @@
|
|||
<td>
|
||||
<div title="{{ e.time|date:'Y-m-d H:i:s O' }}">{{ e.time|date:"Y-m-d" }}</div>
|
||||
</td>
|
||||
<td class="text-end">{{ e.rev }}</td>
|
||||
{% if doc.type_id != "rfc" %}<td class="text-end">{{ e.rev }}</td>{% endif %}
|
||||
<td>{{ e.by|escape }}</td>
|
||||
<td>{{ e.desc|format_history_text }}</td>
|
||||
</tr>
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<title>
|
||||
{% if not snapshot and doc.get_state_slug == "rfc" %}
|
||||
{% if doc.type_id == "rfc" %}
|
||||
RFC {{ doc.rfc_number }} - {{ doc.title }}
|
||||
{% else %}
|
||||
{{ doc.name }}-{{ doc.rev }}
|
||||
|
|
|
@ -11,15 +11,15 @@
|
|||
<th scope="row">{% if document_html %}Document type{% else %}Type{% endif %}</th>
|
||||
<td class="edit"></td>
|
||||
<td>
|
||||
{% if doc.get_state_slug == "rfc" and not snapshot %}
|
||||
{% if doc.type_id == "rfc" %}
|
||||
<span class="text-success">RFC
|
||||
{% if not document_html %}
|
||||
- {{ doc.std_level }}
|
||||
{% else %}
|
||||
<span class="badge rounded-pill badge-{% if not snapshot %}{{ doc|std_level_to_label_format }}{% else %}draft{% endif %}">{{ doc.std_level }}</span>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<span class="badge rounded-pill badge-{% if not snapshot %}{{ doc|std_level_to_label_format }}{% else %}draft{% endif %}">{{ doc.std_level }}</span>
|
||||
{% endif %}
|
||||
</span>
|
||||
{% if published %}
|
||||
{% if doc.pub_date %}
|
||||
{% if document_html %}<br>{% else %}({% endif %}{{ doc.pub_date|date:"F Y" }}{% if not document_html %}){% endif %}
|
||||
{% else %}
|
||||
<span class="text-muted">(Publication date unknown)</span>
|
||||
|
@ -52,7 +52,6 @@
|
|||
{% if proposed_status_changes %}
|
||||
<div>Proposed status changed by {{ proposed_status_changes|urlize_related_source_list|join:", " }}</div>
|
||||
{% endif %}
|
||||
{% if rfc_aliases %}<div>Also known as {{ rfc_aliases|join:", "|urlize_ietf_docs }}</div>{% endif %}
|
||||
{% if draft_name %}
|
||||
<div>
|
||||
Was
|
||||
|
@ -132,91 +131,93 @@
|
|||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% if replaces or not document_html and can_edit_stream_info %}
|
||||
<tr>
|
||||
<td></td>
|
||||
<th scope="row">Replaces</th>
|
||||
<td class="edit">
|
||||
{% if can_edit_stream_info and not snapshot %}
|
||||
<a class="btn btn-primary btn-sm"
|
||||
href="{% url 'ietf.doc.views_draft.replaces' name=doc.name %}">Edit</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if replaces %}
|
||||
{% if document_html %}
|
||||
{{ replaces|urlize_related_target_list:document_html|join:"<br>" }}
|
||||
{% else %}
|
||||
{{ replaces|urlize_related_target_list:document_html|join:", " }}
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<span class="text-muted">(None)</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% if replaced_by %}
|
||||
<tr>
|
||||
<td></td>
|
||||
<th scope="row">
|
||||
Replaced by
|
||||
</th>
|
||||
<td class="edit">
|
||||
</td>
|
||||
<td>
|
||||
{% if document_html %}
|
||||
{{ replaced_by|urlize_related_source_list:document_html|join:"<br>" }}
|
||||
{% else %}
|
||||
{{ replaced_by|urlize_related_source_list:document_html|join:", " }}
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% if can_view_possibly_replaces %}
|
||||
{% if possibly_replaces %}
|
||||
{% if doc.type_id != "rfc" %}
|
||||
{% if replaces or not document_html and can_edit_stream_info %}
|
||||
<tr>
|
||||
<td></td>
|
||||
<th scope="row">
|
||||
Possibly Replaces
|
||||
</th>
|
||||
<th scope="row">Replaces</th>
|
||||
<td class="edit">
|
||||
{% if can_edit_replaces and not snapshot %}
|
||||
{% if can_edit_stream_info and not snapshot %}
|
||||
<a class="btn btn-primary btn-sm"
|
||||
href="{% url 'ietf.doc.views_draft.review_possibly_replaces' name=doc.name %}">
|
||||
Edit
|
||||
</a>
|
||||
href="{% url 'ietf.doc.views_draft.replaces' name=doc.name %}">Edit</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if document_html %}
|
||||
{{ possibly_replaces|urlize_related_target_list:document_html|join:"<br>" }}
|
||||
{% if replaces %}
|
||||
{% if document_html %}
|
||||
{{ replaces|urlize_related_target_list:document_html|join:"<br>" }}
|
||||
{% else %}
|
||||
{{ replaces|urlize_related_target_list:document_html|join:", " }}
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{{ possibly_replaces|urlize_related_target_list:document_html|join:", " }}
|
||||
<span class="text-muted">(None)</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% if possibly_replaced_by %}
|
||||
{% if replaced_by %}
|
||||
<tr>
|
||||
<td></td>
|
||||
<th scope="row">
|
||||
Possibly Replaced By
|
||||
Replaced by
|
||||
</th>
|
||||
<td class="edit">
|
||||
{% if can_edit_replaces and not snapshot %}
|
||||
{% comment %}<a class="btn btn-primary btn-sm"
|
||||
href="{% url 'ietf.doc.views_draft.review_possibly_replaces' name=doc.name %}">Edit</a>{% endcomment %}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if document_html %}
|
||||
{{ possibly_replaced_by|urlize_related_source_list:document_html|join:"<br>" }}
|
||||
{{ replaced_by|urlize_related_source_list:document_html|join:"<br>" }}
|
||||
{% else %}
|
||||
{{ possibly_replaced_by|urlize_related_source_list:document_html|join:", " }}
|
||||
{{ replaced_by|urlize_related_source_list:document_html|join:", " }}
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% if can_view_possibly_replaces %}
|
||||
{% if possibly_replaces %}
|
||||
<tr>
|
||||
<td></td>
|
||||
<th scope="row">
|
||||
Possibly Replaces
|
||||
</th>
|
||||
<td class="edit">
|
||||
{% if can_edit_replaces and not snapshot %}
|
||||
<a class="btn btn-primary btn-sm"
|
||||
href="{% url 'ietf.doc.views_draft.review_possibly_replaces' name=doc.name %}">
|
||||
Edit
|
||||
</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if document_html %}
|
||||
{{ possibly_replaces|urlize_related_target_list:document_html|join:"<br>" }}
|
||||
{% else %}
|
||||
{{ possibly_replaces|urlize_related_target_list:document_html|join:", " }}
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% if possibly_replaced_by %}
|
||||
<tr>
|
||||
<td></td>
|
||||
<th scope="row">
|
||||
Possibly Replaced By
|
||||
</th>
|
||||
<td class="edit">
|
||||
{% if can_edit_replaces and not snapshot %}
|
||||
{% comment %}<a class="btn btn-primary btn-sm"
|
||||
href="{% url 'ietf.doc.views_draft.review_possibly_replaces' name=doc.name %}">Edit</a>{% endcomment %}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if document_html %}
|
||||
{{ possibly_replaced_by|urlize_related_source_list:document_html|join:"<br>" }}
|
||||
{% else %}
|
||||
{{ possibly_replaced_by|urlize_related_source_list:document_html|join:", " }}
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
<tr>
|
||||
<td></td>
|
||||
|
@ -231,15 +232,15 @@ href="{% url 'ietf.doc.views_draft.review_possibly_replaces' name=doc.name %}">E
|
|||
</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td {% if stream_desc == "(None)" %}class="text-muted"{%endif%}>
|
||||
{% if stream_desc != "(None)" %}
|
||||
<td {% if doc.stream is None %}class="text-muted"{%endif%}>
|
||||
{% if doc.stream is not None %}
|
||||
{% if doc.stream.name|lower in 'iab,irtf,ise,editorial' %}
|
||||
<a href="{% url 'ietf.group.views.stream_documents' acronym=doc.stream.name|lower %}">
|
||||
{% endif %}
|
||||
{% if document_html %}
|
||||
{% if doc.stream.name|lower in 'iab,ietf,irtf' %}
|
||||
<img alt="{{ doc.stream.name|upper }} Logo"
|
||||
title="{{ stream_desc }}"
|
||||
title="{{ doc.stream.desc }}"
|
||||
class="w-25 mt-1"
|
||||
{% if doc.stream.name|lower == 'iab' %}
|
||||
src="{% static 'ietf/images/iab-logo.svg' %}"
|
||||
|
@ -250,20 +251,20 @@ href="{% url 'ietf.doc.views_draft.review_possibly_replaces' name=doc.name %}">E
|
|||
{% endif %}
|
||||
>
|
||||
{% else %}
|
||||
{{ stream_desc }}
|
||||
{{ doc.stream.desc }}
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{{ stream_desc }}
|
||||
{{ doc.stream.desc }}
|
||||
{% endif %}
|
||||
{% if doc.stream.name|lower in 'iab,irtf,ise,editorial' %}
|
||||
</a>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{{ stream_desc }}
|
||||
(None)
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% if doc.get_state_slug != "rfc" and not snapshot %}
|
||||
{% if doc.type_id != "rfc" and not snapshot %}
|
||||
<tr>
|
||||
<td></td>
|
||||
<th scope="row">
|
||||
|
@ -339,67 +340,69 @@ href="{% url 'ietf.doc.views_draft.review_possibly_replaces' name=doc.name %}">E
|
|||
</tr>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% if review_assignments or can_request_review %}
|
||||
<tr>
|
||||
<td></td>
|
||||
<th scope="row">
|
||||
Reviews
|
||||
</th>
|
||||
<td class="edit">
|
||||
</td>
|
||||
<td>
|
||||
{% for review_assignment in review_assignments %}
|
||||
{% include "doc/review_assignment_summary.html" with current_doc_name=doc.name current_rev=doc.rev %}
|
||||
{% endfor %}
|
||||
{% if no_review_from_teams %}
|
||||
{% for team in no_review_from_teams %}
|
||||
{{ team.acronym.upper }}{% if not forloop.last %},{% endif %}
|
||||
{% endfor %}
|
||||
will not review this version
|
||||
{% endif %}
|
||||
{% if can_request_review or can_submit_unsolicited_review_for_teams %}
|
||||
<div {% if review_assignments or no_review_from_teams %}class="mt-3"{% endif %}>
|
||||
{% if can_request_review %}
|
||||
<a class="btn btn-primary btn-sm"
|
||||
href="{% url "ietf.doc.views_review.request_review" doc.name %}">
|
||||
<i class="bi bi-check-circle">
|
||||
</i>
|
||||
Request review
|
||||
</a>
|
||||
{% if doc.type_id != "rfc" %}{# do not show reviews or conflict_reviews for RFCs, even if present #}
|
||||
{% if review_assignments or can_request_review %}
|
||||
<tr>
|
||||
<td></td>
|
||||
<th scope="row">
|
||||
Reviews
|
||||
</th>
|
||||
<td class="edit">
|
||||
</td>
|
||||
<td>
|
||||
{% for review_assignment in review_assignments %}
|
||||
{% include "doc/review_assignment_summary.html" with current_doc_name=doc.name current_rev=doc.rev %}
|
||||
{% endfor %}
|
||||
{% if no_review_from_teams %}
|
||||
{% for team in no_review_from_teams %}
|
||||
{{ team.acronym.upper }}{% if not forloop.last %},{% endif %}
|
||||
{% endfor %}
|
||||
will not review this version
|
||||
{% endif %}
|
||||
{% if can_submit_unsolicited_review_for_teams|length == 1 %}
|
||||
<a class="btn btn-primary btn-sm"
|
||||
href="{% url "ietf.doc.views_review.complete_review" doc.name can_submit_unsolicited_review_for_teams.0.acronym %}">
|
||||
<i class="bi bi-pencil-square">
|
||||
</i>
|
||||
Submit unsolicited review
|
||||
</a>
|
||||
{% elif can_submit_unsolicited_review_for_teams %}
|
||||
<a class="btn btn-primary btn-sm"
|
||||
href="{% url "ietf.doc.views_review.submit_unsolicited_review_choose_team" doc.name %}">
|
||||
<i class="bi bi-pencil-square">
|
||||
</i>
|
||||
Submit unsolicited review
|
||||
</a>
|
||||
{% if can_request_review or can_submit_unsolicited_review_for_teams %}
|
||||
<div {% if review_assignments or no_review_from_teams %}class="mt-3"{% endif %}>
|
||||
{% if can_request_review %}
|
||||
<a class="btn btn-primary btn-sm"
|
||||
href="{% url "ietf.doc.views_review.request_review" doc.name %}">
|
||||
<i class="bi bi-check-circle">
|
||||
</i>
|
||||
Request review
|
||||
</a>
|
||||
{% endif %}
|
||||
{% if can_submit_unsolicited_review_for_teams|length == 1 %}
|
||||
<a class="btn btn-primary btn-sm"
|
||||
href="{% url "ietf.doc.views_review.complete_review" doc.name can_submit_unsolicited_review_for_teams.0.acronym %}">
|
||||
<i class="bi bi-pencil-square">
|
||||
</i>
|
||||
Submit unsolicited review
|
||||
</a>
|
||||
{% elif can_submit_unsolicited_review_for_teams %}
|
||||
<a class="btn btn-primary btn-sm"
|
||||
href="{% url "ietf.doc.views_review.submit_unsolicited_review_choose_team" doc.name %}">
|
||||
<i class="bi bi-pencil-square">
|
||||
</i>
|
||||
Submit unsolicited review
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% if conflict_reviews %}
|
||||
<tr>
|
||||
<td></td>
|
||||
<th scope="row">
|
||||
IETF conflict review
|
||||
</th>
|
||||
<td class="edit">
|
||||
</td>
|
||||
<td>
|
||||
{{ conflict_reviews|join:", "|urlize_ietf_docs }}
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% if conflict_reviews %}
|
||||
<tr>
|
||||
<td></td>
|
||||
<th scope="row">
|
||||
IETF conflict review
|
||||
</th>
|
||||
<td class="edit">
|
||||
</td>
|
||||
<td>
|
||||
{{ conflict_reviews|join:", "|urlize_ietf_docs }}
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% with doc.docextresource_set.all as resources %}
|
||||
{% if resources or doc.group and doc.group.list_archive or can_edit_stream_info or can_edit_individual %}
|
||||
|
|
|
@ -64,7 +64,7 @@
|
|||
</a>
|
||||
</td>
|
||||
<td>
|
||||
{% if ref.source.get_state.slug == 'rfc' %}
|
||||
{% if ref.source.type_id == "rfc" %}
|
||||
{% with ref.source.std_level as lvl %}
|
||||
{% if lvl %}{{ lvl }}{% endif %}
|
||||
{% endwith %}
|
||||
|
|
|
@ -51,7 +51,7 @@
|
|||
</a>
|
||||
</td>
|
||||
<td>
|
||||
{% if ref.target.get_state.slug == 'rfc' %}
|
||||
{% if ref.target.type_id == 'rfc' %}
|
||||
{% with ref.target.std_level as lvl %}
|
||||
{% if lvl %}{{ lvl }}{% endif %}
|
||||
{% endwith %}
|
||||
|
|
339
ietf/templates/doc/document_rfc.html
Normal file
339
ietf/templates/doc/document_rfc.html
Normal file
|
@ -0,0 +1,339 @@
|
|||
{% extends "base.html" %}
|
||||
{# Copyright The IETF Trust 2016-2020, All Rights Reserved #}
|
||||
{% load origin %}
|
||||
{% load static %}
|
||||
{% load ietf_filters %}
|
||||
{% load person_filters %}
|
||||
{% load textfilters %}
|
||||
{% block html_attrs %}prefix="og: http://ogp.me/ns# article: http://ogp.me/ns/article#"{% endblock %}
|
||||
{% block pagehead %}
|
||||
{% include "doc/opengraph.html" %}
|
||||
<link rel="alternate"
|
||||
type="application/atom+xml"
|
||||
title="Document changes"
|
||||
href="/feed/document-changes/{{ name }}/">
|
||||
<meta name="description"
|
||||
content="{{ doc.title }} {% if doc.get_state_slug == 'rfc' and not snapshot %}(RFC {{ rfc_number }}{% if published %}, {{ doc.pub_date|date:'F Y' }}{% endif %}{% if obsoleted_by %}; obsoleted by {% for rel in obsoleted_by %}{{ rel.source.canonical_name|prettystdname}}{% if not forloop.last%}, {% endif %}{% endfor %}{% endif %}){% endif %}">
|
||||
{% endblock %}
|
||||
{% block morecss %}.inline { display: inline; }{% endblock %}
|
||||
{% block title %}
|
||||
RFC {{ rfc_number }} - {{ doc.title }}
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
{% origin %}
|
||||
{{ top|safe }}
|
||||
<div id="timeline"></div>
|
||||
{% if doc.rev != latest_rev %}
|
||||
<div class="alert alert-warning my-3">The information below is for an old version of the document.</div>
|
||||
{% endif %}
|
||||
<table class="table table-sm table-borderless">
|
||||
{% include "doc/document_info.html" %}
|
||||
<tbody class="meta border-top">
|
||||
{% if milestones %}
|
||||
<tr>
|
||||
<td></td>
|
||||
<th scope="row">
|
||||
Associated
|
||||
{% if doc.stream_id == 'ietf' %}
|
||||
WG
|
||||
{% else %}
|
||||
{{ doc.stream }}
|
||||
{% endif %} milestone{{ milestones|pluralize }}</th>
|
||||
<td class="edit"></td>
|
||||
<td>
|
||||
<dl class="row">
|
||||
{% for m in milestones %}
|
||||
<dt class="col-sm-2 my-0">{{ m.due|date:"M Y" }}</dt>
|
||||
<dd class="col-sm-10 my-0">{{ m.desc }}</dd>
|
||||
{% endfor %}
|
||||
</dl>
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
</tbody>
|
||||
{% if doc.stream_id != 'iab' %}
|
||||
<tbody class="meta border-top">
|
||||
<tr>
|
||||
<th scope="row">
|
||||
IESG
|
||||
</th>
|
||||
<th scope="row">
|
||||
Responsible AD
|
||||
</th>
|
||||
<td class="edit">
|
||||
{% if can_edit %}
|
||||
<a class="btn btn-primary btn-sm"
|
||||
href="{% url 'ietf.doc.views_draft.edit_ad' name=doc.name %}">
|
||||
Edit
|
||||
</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if doc.ad %}
|
||||
{% person_link doc.ad %}
|
||||
{% else %}
|
||||
<span class="text-muted">
|
||||
(None)
|
||||
</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<th scope="row">
|
||||
Send notices to
|
||||
</th>
|
||||
<td class="edit">
|
||||
{% if can_edit_notify and not snapshot %}
|
||||
<a class="btn btn-primary btn-sm"
|
||||
href="{% url 'ietf.doc.views_doc.edit_notify' name=doc.name %}">
|
||||
Edit
|
||||
</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if doc.notify %}
|
||||
{{ doc.notify|linkify }}
|
||||
{% else %}
|
||||
<span class="text-muted">
|
||||
(None)
|
||||
</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
{% endif %}
|
||||
{% if rfc_editor_state %}
|
||||
<tbody class="meta border-top">
|
||||
<tr>
|
||||
<th scope="row">
|
||||
RFC Editor
|
||||
</th>
|
||||
<th scope="row">
|
||||
<a href="{% url "ietf.help.views.state" doc=doc.type.slug type="rfceditor" %}">
|
||||
RFC Editor state
|
||||
</a>
|
||||
</th>
|
||||
<td class="edit">
|
||||
</td>
|
||||
<td>
|
||||
{{ rfc_editor_state }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<th scope="row">
|
||||
Details
|
||||
</th>
|
||||
<td class="edit">
|
||||
</td>
|
||||
<td>
|
||||
<div>
|
||||
<a href="https://www.rfc-editor.org/queue2.html#{{ doc.name }}">
|
||||
Publication queue entry
|
||||
</a>
|
||||
</div>
|
||||
{% if rfc_editor_auth48_url %}
|
||||
<div>
|
||||
<a href="{{ rfc_editor_auth48_url }}">
|
||||
Auth48 status
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
{% endif %}
|
||||
</table>
|
||||
<div class="buttonlist">
|
||||
<a class="btn btn-primary btn-sm"
|
||||
href="mailto:{{ doc.name }}@ietf.org?subject=Mail%20regarding%20{{ doc.name }}">
|
||||
<i class="bi bi-envelope">
|
||||
</i>
|
||||
Email authors
|
||||
</a>
|
||||
{% if doc.group.type.slug == 'wg' or doc.group.type.slug == 'rg' %}
|
||||
<a class="btn btn-primary btn-sm"
|
||||
href="mailto:{{ doc.group.list_email }}?subject=Mail%20regarding%20{{ doc.name }}">
|
||||
<i class="bi bi-envelope">
|
||||
</i>
|
||||
Email {{ doc.group.type }}
|
||||
</a>
|
||||
{% endif %}
|
||||
<a class="btn btn-primary btn-sm"
|
||||
href="{% url "ietf.ipr.views.search" %}?submit=draft&id={{ doc.name }}"
|
||||
rel="nofollow">
|
||||
<i class="bi bi-lightning">
|
||||
</i>
|
||||
IPR
|
||||
{% if doc.related_ipr %}
|
||||
<span class="badge rounded-pill">
|
||||
{{ doc.related_ipr|length }}
|
||||
</span>
|
||||
{% endif %}
|
||||
</a>
|
||||
<a class="btn btn-primary btn-sm"
|
||||
href="{% url 'ietf.doc.views_doc.document_references' doc.canonical_name %}"
|
||||
rel="nofollow">
|
||||
<i class="bi bi-arrow-left">
|
||||
</i>
|
||||
References
|
||||
</a>
|
||||
<a class="btn btn-primary btn-sm"
|
||||
href="{% url 'ietf.doc.views_doc.document_referenced_by' doc.canonical_name %}"
|
||||
rel="nofollow">
|
||||
<i class="bi bi-arrow-right">
|
||||
</i>
|
||||
Referenced by
|
||||
</a>
|
||||
{# document_draft shows Nits here, excluded for RFCs #}
|
||||
<div class="dropdown inline">
|
||||
<button class="btn btn-primary btn-sm dropdown-toggle"
|
||||
type="button"
|
||||
id="ddSearchMenu"
|
||||
data-bs-toggle="dropdown"
|
||||
aria-expanded="true">
|
||||
<i class="bi bi-search">
|
||||
</i>
|
||||
Search lists
|
||||
</button>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li role="presentation">
|
||||
<a class="dropdown-item"
|
||||
href="https://mailarchive.ietf.org/arch/search?q=%22{{ doc.name }}%22"
|
||||
rel="nofollow"
|
||||
target="_blank">
|
||||
IETF Mail Archive
|
||||
</a>
|
||||
</li>
|
||||
<li role="presentation">
|
||||
<a class="dropdown-item"
|
||||
href="https://www.google.com/search?as_q={{ doc.name }}&as_sitesearch={{ search_archive }}"
|
||||
rel="nofollow"
|
||||
target="_blank">
|
||||
Google
|
||||
</a>
|
||||
</li>
|
||||
{% if user|has_role:"Area Director" %}
|
||||
<li role="presentation">
|
||||
<a class="dropdown-item"
|
||||
href="https://www.iesg.org/bin/c5i?mid=6&rid=77&target={{ doc.name }}"
|
||||
rel="nofollow"
|
||||
target="_blank">
|
||||
ARO
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
{% if user.is_authenticated %}
|
||||
<a class="btn btn-primary btn-sm track-untrack-doc {% if not doc.tracked_in_personal_community_list %}hide{% endif %}"
|
||||
href="{% url "ietf.community.views.untrack_document" username=user.username name=doc.name %}"
|
||||
title="Remove from your personal I-D list">
|
||||
<i class="bi bi-bookmark-check-fill">
|
||||
</i>
|
||||
Untrack
|
||||
</a>
|
||||
<a class="btn btn-primary btn-sm track-untrack-doc {% if doc.tracked_in_personal_community_list %}hide{% endif %}"
|
||||
href="{% url "ietf.community.views.track_document" username=user.username name=doc.name %}"
|
||||
title="Add to your personal I-D list">
|
||||
<i class="bi bi-bookmark">
|
||||
</i>
|
||||
Track
|
||||
</a>
|
||||
{% endif %}
|
||||
{% if user.review_teams %}
|
||||
<a class="btn btn-primary btn-sm review-wish-add-remove-doc ajax {% if not doc.has_review_wish %}hide{% endif %}"
|
||||
href="{% url "ietf.doc.views_review.review_wishes_remove" name=doc.name %}?next={{ request.get_full_path|urlencode }}"
|
||||
title="Remove from your review wishes for all teams">
|
||||
<i class="bi bi-chat-left-heart-fill">
|
||||
</i>
|
||||
Remove review wishes
|
||||
</a>
|
||||
<a class="btn btn-primary btn-sm review-wish-add-remove-doc {% if user.review_teams|length_is:"1" %}ajax {% endif %}{% if doc.has_review_wish %}hide{% endif %}"
|
||||
href="{% url "ietf.doc.views_review.review_wish_add" name=doc.name %}?next={{ request.get_full_path|urlencode }}"
|
||||
title="Add to your review wishes">
|
||||
<i class="bi bi-chat-left-heart">
|
||||
</i>
|
||||
Add review wish
|
||||
</a>
|
||||
{% endif %}
|
||||
{% if can_edit and iesg_state.slug != 'idexists' %}
|
||||
<a class="btn btn-primary btn-sm"
|
||||
href="{% url 'ietf.doc.views_ballot.lastcalltext' name=doc.name %}">
|
||||
Last call text
|
||||
</a>
|
||||
<a class="btn btn-primary btn-sm"
|
||||
href="{% url 'ietf.doc.views_ballot.ballot_writeupnotes' name=doc.name %}">
|
||||
Ballot text
|
||||
</a>
|
||||
<a class="btn btn-primary btn-sm"
|
||||
href="{% url 'ietf.doc.views_ballot.ballot_approvaltext' name=doc.name %}">
|
||||
Announcement text
|
||||
</a>
|
||||
{% endif %}
|
||||
{% if actions %}
|
||||
{% for label, url in actions %}
|
||||
<a class="btn btn-primary btn-sm" href="{{ url }}">
|
||||
{{ label|capfirst_allcaps }}
|
||||
</a>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% if doc.get_state_slug == "active" or doc.get_state_slug == "rfc" %}
|
||||
<div class="card mt-5">
|
||||
<div class="card-header">
|
||||
{% if doc.get_state_slug == "rfc" and not snapshot %}
|
||||
RFC {{ rfc_number }}
|
||||
{% else %}
|
||||
{{ name }}-{{ doc.rev }}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<pre>{{ content|sanitize|safe|default:"(Unavailable)" }}</pre>
|
||||
</div>
|
||||
</div>
|
||||
{% if split_content %}
|
||||
<a class="btn btn-primary my-3" href="?include_text=1">
|
||||
<i class="bi bi-caret-down">
|
||||
</i>
|
||||
Show full document
|
||||
</a>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<div class="card border-warning mt-5">
|
||||
<div class="card-header bg-warning">
|
||||
<p><b>This Internet-Draft is no longer active. A copy of
|
||||
the expired Internet-Draft is available in these formats:</b></p>
|
||||
|
||||
{% include "doc/document_format_buttons.html" %}
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p class="h5 card-title">
|
||||
Abstract
|
||||
</p>
|
||||
<p class="card-text">
|
||||
{{ doc.abstract }}
|
||||
</p>
|
||||
<p class="h5 card-title">
|
||||
Authors
|
||||
</p>
|
||||
<p class="card-text">
|
||||
{% for author in doc.documentauthor_set.all %}
|
||||
{% person_link author.person %}
|
||||
{% if not forloop.last %}<br>{% endif %}
|
||||
{% endfor %}
|
||||
</p>
|
||||
<p class="text-muted card-text">
|
||||
(Note: The e-mail addresses provided for the authors of this Internet-Draft may no longer be valid.)
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
{% block js %}
|
||||
<script src="{% static 'ietf/js/d3.js' %}">
|
||||
</script>
|
||||
<script src="{% static 'ietf/js/document_timeline.js' %}">
|
||||
</script>
|
||||
{% endblock %}
|
|
@ -1,5 +1,5 @@
|
|||
{% load ietf_filters %}{% filter linebreaks_lf %}{% comment %}
|
||||
{% endcomment %}Doc-tag: {{doc.name}};datatracker{% if doc.is_rfc %}
|
||||
{% endcomment %}Doc-tag: {{doc.name}};datatracker{% if doc.type_id == "rfc" %}
|
||||
Doc-rfcnum: {{doc.rfc_number}}{% endif %}
|
||||
Doc-created: {{doc.created|date:"Y-m-d"}};datatracker{% if doc.deststatus %}
|
||||
Doc-deststatus: {{doc.deststatus}};datatracker{% endif %}
|
||||
|
|
|
@ -31,5 +31,14 @@
|
|||
{% if position %}Save{% else %}Add{% endif %}</button>
|
||||
<a class="btn btn-secondary float-end" href="../">Back</a>
|
||||
</form>
|
||||
{% if position.name %}
|
||||
<h3>
|
||||
Templates
|
||||
</h3>
|
||||
{% for template in position.get_templates %}
|
||||
<a href="{% url 'ietf.nomcom.views.edit_template' year template.id %}">{{ template }}</a>
|
||||
<br>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
{% block content_end %}{{ form.media.js }}{% endblock %}
|
||||
{% block content_end %}{{ form.media.js }}{% endblock %}
|
||||
|
|
|
@ -9,13 +9,20 @@
|
|||
<p id="instructions" class="alert alert-info my-3">
|
||||
{% if nomcom.group.state_id == 'conclude' %}
|
||||
Feedback to this NomCom is closed.
|
||||
{% elif positions|length != 0 and topics|length != 0 %}
|
||||
Select a nominee or topic from the list on the right to obtain a new feedback form.
|
||||
{% elif positions|length != 0 %}
|
||||
Select a nominee from the list on the right to obtain a new feedback form.
|
||||
{% elif topics|length != 0 %}
|
||||
Select a topic from the list on the right to obtain a new feedback form.
|
||||
{% else %}
|
||||
Select a nominee from the list of nominees on the right to obtain a new feedback form.
|
||||
This NomCom is not accepting feedback at this time.
|
||||
{% endif %}
|
||||
</p>
|
||||
{% if nomcom|has_publickey %}
|
||||
<div class="row">
|
||||
<div id="nominees" class="col-sm-2 order-last">
|
||||
{% if positions|length != 0 %}
|
||||
<h2 class="navskip mt-4">Nominees</h2>
|
||||
<p>
|
||||
A number after a name indicates
|
||||
|
@ -43,6 +50,8 @@
|
|||
</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if topics|length != 0 %}
|
||||
<h2 class="navskip mt-4">Topics</h2>
|
||||
<div class="d-grid gap-3">
|
||||
{% for t in topics %}
|
||||
|
@ -58,6 +67,7 @@
|
|||
</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="col-sm-10">
|
||||
{% if form %}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{% extends "nomcom/nomcom_private_base.html" %}
|
||||
{# Copyright The IETF Trust 2015, All Rights Reserved #}
|
||||
{% load origin %}
|
||||
{% load origin static %}
|
||||
{% block subtitle %}- Positions{% endblock %}
|
||||
{% block nomcom_content %}
|
||||
{% origin %}
|
||||
|
@ -13,54 +13,129 @@
|
|||
<a href="{% url 'ietf.nomcom.views.configuration_help' year=nomcom.year %}">Configuration Hints</a>.
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
{% if nomcom.group.state_id == 'active' %}
|
||||
<form class="form-inline" id="batch-action-form" method="post">
|
||||
{% csrf_token %}
|
||||
{% endif %}
|
||||
{% if positions %}
|
||||
{% regroup positions by is_open as posgroups %}
|
||||
{% for group in posgroups %}
|
||||
<h3>{{ group.grouper| yesno:"Open Positions,Closed Positions" }}</h3>
|
||||
{% for position in group.list %}
|
||||
<h4>
|
||||
{{ position.name }}
|
||||
{% if position.is_iesg_position %}(IESG){% endif %}
|
||||
</h4>
|
||||
{% if group.grouper %}
|
||||
<dl class="row">
|
||||
<dt class="col-sm-2">
|
||||
Accepting
|
||||
</dt>
|
||||
<dd class="col-sm-10">
|
||||
{% if position.accepting_nominations %}Nominations{% endif %}
|
||||
{% if position.accepting_nominations and position.accepting_feedback %}and{% endif %}
|
||||
{% if position.accepting_feedback %}Feedback{% endif %}
|
||||
</dd>
|
||||
</dl>
|
||||
{% endif %}
|
||||
<dl class="row">
|
||||
<dt class="col-sm-2">
|
||||
Templates
|
||||
</dt>
|
||||
<dd class="col-sm-10">
|
||||
{% for template in position.get_templates %}
|
||||
<a href="{% url 'ietf.nomcom.views.edit_template' year template.id %}">{{ template }}</a>
|
||||
<br>
|
||||
{% endfor %}
|
||||
</dd>
|
||||
<table class="table table-sm table-striped table-hover tablesorter"
|
||||
id="position-table">
|
||||
<thead>
|
||||
<tr>
|
||||
{% if nomcom.group.state_id == 'active' %}
|
||||
<dt class="col-sm-2">
|
||||
Actions
|
||||
</dt>
|
||||
<dd class="col-sm-10">
|
||||
<a class="btn btn-primary btn-sm"
|
||||
href="{% url 'ietf.nomcom.views.edit_position' year position.id %}">Edit</a>
|
||||
<a class="btn btn-danger btn-sm"
|
||||
href="{% url 'ietf.nomcom.views.remove_position' year position.id %}">Remove</a>
|
||||
</dd>
|
||||
<th scope="colgroup" colspan="3">
|
||||
<i class="bi bi-check"></i>
|
||||
</th>
|
||||
{% endif %}
|
||||
</dl>
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
<th scope="col" data-sort="position">
|
||||
Position
|
||||
</th>
|
||||
<th scope="col" data-sort="iesg">
|
||||
IESG
|
||||
</th>
|
||||
<th scope="col" data-sort="open">
|
||||
Open
|
||||
</th>
|
||||
<th scope="col" data-sort="accept_nom">
|
||||
Accepting Nominations
|
||||
</th>
|
||||
<th scope="col" data-sort="accept_fb">
|
||||
Accepting Feedback
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<!-- [html-validate-disable-block input-missing-label -- labelled via aria-label] -->
|
||||
{% for position in positions %}
|
||||
<tr>
|
||||
{% if nomcom.group.state_id == 'active' %}
|
||||
<td>
|
||||
<input class="batch-select form-check-input"
|
||||
type="checkbox"
|
||||
value="{{ position.id }}"
|
||||
id="id-{{ position.id }}"
|
||||
aria-label="position.name"
|
||||
name="selected">
|
||||
</td>
|
||||
<td class="edit">
|
||||
<a class="btn btn-primary btn-sm"
|
||||
href="{% url 'ietf.nomcom.views.edit_position' year position.id %}">
|
||||
Edit
|
||||
</a>
|
||||
</td>
|
||||
<td class="remove">
|
||||
<a class="btn btn-danger btn-sm"
|
||||
href="{% url 'ietf.nomcom.views.remove_position' year position.id %}">
|
||||
Remove
|
||||
</a>
|
||||
</td>
|
||||
{% endif %}
|
||||
<td>
|
||||
{{ position.name }}
|
||||
</td>
|
||||
<td>
|
||||
{{ position.is_iesg_position|yesno:"✓," }}
|
||||
</td>
|
||||
<td>
|
||||
{{ position.is_open|yesno:"✓," }}
|
||||
</td>
|
||||
<td>
|
||||
{{ position.accepting_nominations|yesno:"✓," }}
|
||||
</td>
|
||||
<td>
|
||||
{{ position.accepting_feedback|yesno:"✓," }}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% if nomcom.group.state_id == 'active' %}
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="action">
|
||||
Action:
|
||||
</label>
|
||||
<select class="form-select" name="action" id="action">
|
||||
<option value="" selected="selected">
|
||||
---------
|
||||
</option>
|
||||
<option value="set_iesg">
|
||||
Is IESG Position: Yes
|
||||
</option>
|
||||
<option value="unset_iesg">
|
||||
Is IESG Position: No
|
||||
</option>
|
||||
<option value="set_open">
|
||||
Is Open: Yes
|
||||
</option>
|
||||
<option value="unset_open">
|
||||
Is Open: No
|
||||
</option>
|
||||
<option value="set_accept_nom">
|
||||
Is Accepting Nominations: Yes
|
||||
</option>
|
||||
<option value="unset_accept_nom">
|
||||
Is Accepting Nominations: No
|
||||
</option>
|
||||
<option value="set_accept_bf">
|
||||
Is Accepting Feedback: Yes
|
||||
</option>
|
||||
<option value="unset_accept_fb">
|
||||
Is Accepting Feedback: No
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
<button class="btn btn-warning" type="submit" title="Run action">
|
||||
Apply
|
||||
</button>
|
||||
</form>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<p>
|
||||
There are no positions defined.
|
||||
</p>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
{% block js %}
|
||||
<script src="{% static "ietf/js/list.js" %}"></script>
|
||||
{% endblock %}
|
||||
|
|
|
@ -54,7 +54,7 @@ class Command(BaseCommand):
|
|||
doc = getattr(obj, docattr)
|
||||
time = getattr(obj, timeattr)
|
||||
if not obj.rev:
|
||||
if not doc.is_rfc():
|
||||
if doc.type_id != "rfc":
|
||||
self.stdout.write("Bad revision number: %-52s: '%s'" % (doc.name, obj.rev))
|
||||
continue
|
||||
rev = int(obj.rev.lstrip('0') or '0')
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
"caniuse-lite": "1.0.30001495",
|
||||
"d3": "7.8.5",
|
||||
"file-saver": "2.0.5",
|
||||
"highcharts": "11.0.1",
|
||||
"highcharts": "11.1.0",
|
||||
"ical.js": "1.5.0",
|
||||
"jquery": "3.7.0",
|
||||
"js-cookie": "3.0.5",
|
||||
|
@ -70,7 +70,7 @@
|
|||
"jquery-migrate": "3.4.1",
|
||||
"parcel": "2.9.1",
|
||||
"pug": "3.0.2",
|
||||
"sass": "1.62.1",
|
||||
"sass": "1.63.4",
|
||||
"seedrandom": "3.0.5",
|
||||
"vite": "4.3.9"
|
||||
},
|
||||
|
|
450
playwright/package-lock.json
generated
450
playwright/package-lock.json
generated
|
@ -6,7 +6,7 @@
|
|||
"packages": {
|
||||
"": {
|
||||
"dependencies": {
|
||||
"@faker-js/faker": "8.0.1",
|
||||
"@faker-js/faker": "8.0.2",
|
||||
"lodash": "4.17.21",
|
||||
"lodash-es": "4.17.21",
|
||||
"luxon": "3.3.0",
|
||||
|
@ -15,14 +15,14 @@
|
|||
"slugify": "1.6.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@playwright/test": "1.33.0",
|
||||
"eslint": "8.39.0",
|
||||
"eslint-config-standard": "17.0.0",
|
||||
"@playwright/test": "1.35.1",
|
||||
"eslint": "8.43.0",
|
||||
"eslint-config-standard": "17.1.0",
|
||||
"eslint-plugin-import": "2.27.5",
|
||||
"eslint-plugin-n": "15.7.0",
|
||||
"eslint-plugin-n": "16.0.1",
|
||||
"eslint-plugin-node": "11.1.0",
|
||||
"eslint-plugin-promise": "6.1.1",
|
||||
"npm-check-updates": "16.10.12"
|
||||
"npm-check-updates": "16.10.13"
|
||||
}
|
||||
},
|
||||
"node_modules/@colors/colors": {
|
||||
|
@ -51,23 +51,23 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@eslint-community/regexpp": {
|
||||
"version": "4.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.4.1.tgz",
|
||||
"integrity": "sha512-BISJ6ZE4xQsuL/FmsyRaiffpq977bMlsKfGHTQrOGFErfByxIe6iZTxPf/00Zon9b9a7iUykfQwejN3s2ZW/Bw==",
|
||||
"version": "4.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.1.tgz",
|
||||
"integrity": "sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": "^12.0.0 || ^14.0.0 || >=16.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@eslint/eslintrc": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.2.tgz",
|
||||
"integrity": "sha512-3W4f5tDUra+pA+FzgugqL2pRimUTDJWKr7BINqOpkZrC0uYI0NIc0/JFgBROCU07HR6GieA5m3/rsPIhDmCXTQ==",
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.3.tgz",
|
||||
"integrity": "sha512-+5gy6OQfk+xx3q0d6jGZZC3f3KzAkXc/IanVxd1is/VIIziRqqt3ongQz0FiTUXqTk0c7aDB3OaFuKnuSoJicQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"ajv": "^6.12.4",
|
||||
"debug": "^4.3.2",
|
||||
"espree": "^9.5.1",
|
||||
"espree": "^9.5.2",
|
||||
"globals": "^13.19.0",
|
||||
"ignore": "^5.2.0",
|
||||
"import-fresh": "^3.2.1",
|
||||
|
@ -83,18 +83,18 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@eslint/js": {
|
||||
"version": "8.39.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.39.0.tgz",
|
||||
"integrity": "sha512-kf9RB0Fg7NZfap83B3QOqOGg9QmD9yBudqQXzzOtn3i4y7ZUXe5ONeW34Gwi+TxhH4mvj72R1Zc300KUMa9Bng==",
|
||||
"version": "8.43.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.43.0.tgz",
|
||||
"integrity": "sha512-s2UHCoiXfxMvmfzqoN+vrQ84ahUSYde9qNO1MdxmoEhyHWsfmwOpFlwYV+ePJEVc7gFnATGUi376WowX1N7tFg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@faker-js/faker": {
|
||||
"version": "8.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-8.0.1.tgz",
|
||||
"integrity": "sha512-kbh5MenpTN9U0B4QcOI1NoTPlZHniSYQ3BHbhAnPjJGAmmFqxoxTE4sGdpy7ZOO9038DPGCuhXyMkjOr05uVwA==",
|
||||
"version": "8.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-8.0.2.tgz",
|
||||
"integrity": "sha512-Uo3pGspElQW91PCvKSIAXoEgAUlRnH29sX2/p89kg7sP1m2PzCufHINd0FhTXQf6DYGiUlVncdSPa2F9wxed2A==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "opencollective",
|
||||
|
@ -113,9 +113,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"node_modules/@humanwhocodes/config-array": {
|
||||
"version": "0.11.8",
|
||||
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz",
|
||||
"integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==",
|
||||
"version": "0.11.10",
|
||||
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz",
|
||||
"integrity": "sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@humanwhocodes/object-schema": "^1.2.1",
|
||||
|
@ -411,19 +411,19 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@playwright/test": {
|
||||
"version": "1.33.0",
|
||||
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.33.0.tgz",
|
||||
"integrity": "sha512-YunBa2mE7Hq4CfPkGzQRK916a4tuZoVx/EpLjeWlTVOnD4S2+fdaQZE0LJkbfhN5FTSKNLdcl7MoT5XB37bTkg==",
|
||||
"version": "1.35.1",
|
||||
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.35.1.tgz",
|
||||
"integrity": "sha512-b5YoFe6J9exsMYg0pQAobNDR85T1nLumUYgUTtKm4d21iX2L7WqKq9dW8NGJ+2vX0etZd+Y7UeuqsxDXm9+5ZA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/node": "*",
|
||||
"playwright-core": "1.33.0"
|
||||
"playwright-core": "1.35.1"
|
||||
},
|
||||
"bin": {
|
||||
"playwright": "cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
"node": ">=16"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"fsevents": "2.3.2"
|
||||
|
@ -557,9 +557,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"node_modules/acorn": {
|
||||
"version": "8.8.2",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz",
|
||||
"integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==",
|
||||
"version": "8.9.0",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.9.0.tgz",
|
||||
"integrity": "sha512-jaVNAFBHNLXspO543WnNNPZFRtavh3skAkITqD0/2aeMkKZTN+254PyhwxFYrk3vQ1xfY+2wbesJMs/JC8/PwQ==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"acorn": "bin/acorn"
|
||||
|
@ -1540,16 +1540,16 @@
|
|||
}
|
||||
},
|
||||
"node_modules/eslint": {
|
||||
"version": "8.39.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.39.0.tgz",
|
||||
"integrity": "sha512-mwiok6cy7KTW7rBpo05k6+p4YVZByLNjAZ/ACB9DRCu4YDRwjXI01tWHp6KAUWelsBetTxKK/2sHB0vdS8Z2Og==",
|
||||
"version": "8.43.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.43.0.tgz",
|
||||
"integrity": "sha512-aaCpf2JqqKesMFGgmRPessmVKjcGXqdlAYLLC3THM8t5nBRZRQ+st5WM/hoJXkdioEXLLbXgclUpM0TXo5HX5Q==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@eslint-community/eslint-utils": "^4.2.0",
|
||||
"@eslint-community/regexpp": "^4.4.0",
|
||||
"@eslint/eslintrc": "^2.0.2",
|
||||
"@eslint/js": "8.39.0",
|
||||
"@humanwhocodes/config-array": "^0.11.8",
|
||||
"@eslint/eslintrc": "^2.0.3",
|
||||
"@eslint/js": "8.43.0",
|
||||
"@humanwhocodes/config-array": "^0.11.10",
|
||||
"@humanwhocodes/module-importer": "^1.0.1",
|
||||
"@nodelib/fs.walk": "^1.2.8",
|
||||
"ajv": "^6.10.0",
|
||||
|
@ -1559,8 +1559,8 @@
|
|||
"doctrine": "^3.0.0",
|
||||
"escape-string-regexp": "^4.0.0",
|
||||
"eslint-scope": "^7.2.0",
|
||||
"eslint-visitor-keys": "^3.4.0",
|
||||
"espree": "^9.5.1",
|
||||
"eslint-visitor-keys": "^3.4.1",
|
||||
"espree": "^9.5.2",
|
||||
"esquery": "^1.4.2",
|
||||
"esutils": "^2.0.2",
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
|
@ -1568,13 +1568,12 @@
|
|||
"find-up": "^5.0.0",
|
||||
"glob-parent": "^6.0.2",
|
||||
"globals": "^13.19.0",
|
||||
"grapheme-splitter": "^1.0.4",
|
||||
"graphemer": "^1.4.0",
|
||||
"ignore": "^5.2.0",
|
||||
"import-fresh": "^3.0.0",
|
||||
"imurmurhash": "^0.1.4",
|
||||
"is-glob": "^4.0.0",
|
||||
"is-path-inside": "^3.0.3",
|
||||
"js-sdsl": "^4.1.4",
|
||||
"js-yaml": "^4.1.0",
|
||||
"json-stable-stringify-without-jsonify": "^1.0.1",
|
||||
"levn": "^0.4.1",
|
||||
|
@ -1597,9 +1596,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/eslint-config-standard": {
|
||||
"version": "17.0.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-17.0.0.tgz",
|
||||
"integrity": "sha512-/2ks1GKyqSOkH7JFvXJicu0iMpoojkwB+f5Du/1SC0PtBL+s8v30k9njRZ21pm2drKYm2342jFnGWzttxPmZVg==",
|
||||
"version": "17.1.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-17.1.0.tgz",
|
||||
"integrity": "sha512-IwHwmaBNtDK4zDHQukFDW5u/aTb8+meQWZvNFWkiGmbWjD6bqyuSSBxxXKkCftCUzc1zwCH2m/baCNDLGmuO5Q==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
|
@ -1615,10 +1614,13 @@
|
|||
"url": "https://feross.org/support"
|
||||
}
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"eslint": "^8.0.1",
|
||||
"eslint-plugin-import": "^2.25.2",
|
||||
"eslint-plugin-n": "^15.0.0",
|
||||
"eslint-plugin-n": "^15.0.0 || ^16.0.0 ",
|
||||
"eslint-plugin-promise": "^6.0.0"
|
||||
}
|
||||
},
|
||||
|
@ -1668,47 +1670,23 @@
|
|||
"ms": "^2.1.1"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-es": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-4.1.0.tgz",
|
||||
"integrity": "sha512-GILhQTnjYE2WorX5Jyi5i4dz5ALWxBIdQECVQavL6s7cI76IZTDWleTHkxz/QT3kvcs2QlGHvKLYsSlPOlPXnQ==",
|
||||
"node_modules/eslint-plugin-es-x": {
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-es-x/-/eslint-plugin-es-x-7.1.0.tgz",
|
||||
"integrity": "sha512-AhiaF31syh4CCQ+C5ccJA0VG6+kJK8+5mXKKE7Qs1xcPRg02CDPOj3mWlQxuWS/AYtg7kxrDNgW9YW3vc0Q+Mw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"eslint-utils": "^2.0.0",
|
||||
"regexpp": "^3.0.0"
|
||||
"@eslint-community/eslint-utils": "^4.1.2",
|
||||
"@eslint-community/regexpp": "^4.5.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.10.0"
|
||||
"node": "^14.18.0 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/mysticatea"
|
||||
"url": "https://github.com/sponsors/ota-meshi"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"eslint": ">=4.19.1"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-es/node_modules/eslint-utils": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz",
|
||||
"integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"eslint-visitor-keys": "^1.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/mysticatea"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-es/node_modules/eslint-visitor-keys": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz",
|
||||
"integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
"eslint": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-import": {
|
||||
|
@ -1771,22 +1749,22 @@
|
|||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-n": {
|
||||
"version": "15.7.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-15.7.0.tgz",
|
||||
"integrity": "sha512-jDex9s7D/Qial8AGVIHq4W7NswpUD5DPDL2RH8Lzd9EloWUuvUkHfv4FRLMipH5q2UtyurorBkPeNi1wVWNh3Q==",
|
||||
"version": "16.0.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-16.0.1.tgz",
|
||||
"integrity": "sha512-CDmHegJN0OF3L5cz5tATH84RPQm9kG+Yx39wIqIwPR2C0uhBGMWfbbOtetR83PQjjidA5aXMu+LEFw1jaSwvTA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@eslint-community/eslint-utils": "^4.4.0",
|
||||
"builtins": "^5.0.1",
|
||||
"eslint-plugin-es": "^4.1.0",
|
||||
"eslint-utils": "^3.0.0",
|
||||
"ignore": "^5.1.1",
|
||||
"is-core-module": "^2.11.0",
|
||||
"eslint-plugin-es-x": "^7.1.0",
|
||||
"ignore": "^5.2.4",
|
||||
"is-core-module": "^2.12.1",
|
||||
"minimatch": "^3.1.2",
|
||||
"resolve": "^1.22.1",
|
||||
"semver": "^7.3.8"
|
||||
"resolve": "^1.22.2",
|
||||
"semver": "^7.5.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.22.0"
|
||||
"node": ">=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/mysticatea"
|
||||
|
@ -1895,37 +1873,10 @@
|
|||
"url": "https://opencollective.com/eslint"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-utils": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz",
|
||||
"integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"eslint-visitor-keys": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^10.0.0 || ^12.0.0 || >= 14.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/mysticatea"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"eslint": ">=5"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-utils/node_modules/eslint-visitor-keys": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz",
|
||||
"integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-visitor-keys": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.0.tgz",
|
||||
"integrity": "sha512-HPpKPUBQcAsZOsHAFwTtIKcYlCje62XB7SEAcxjtmW6TD1WVpkS6i6/hOVtTZIl4zGj/mBqpFVGvaDneik+VoQ==",
|
||||
"version": "3.4.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz",
|
||||
"integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||
|
@ -1935,14 +1886,14 @@
|
|||
}
|
||||
},
|
||||
"node_modules/espree": {
|
||||
"version": "9.5.1",
|
||||
"resolved": "https://registry.npmjs.org/espree/-/espree-9.5.1.tgz",
|
||||
"integrity": "sha512-5yxtHSZXRSW5pvv3hAlXM5+/Oswi1AUFqBmbibKb5s6bp3rGIDkyXU6xCoyuuLhijr4SFwPrXRoZjz0AZDN9tg==",
|
||||
"version": "9.5.2",
|
||||
"resolved": "https://registry.npmjs.org/espree/-/espree-9.5.2.tgz",
|
||||
"integrity": "sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"acorn": "^8.8.0",
|
||||
"acorn-jsx": "^5.3.2",
|
||||
"eslint-visitor-keys": "^3.4.0"
|
||||
"eslint-visitor-keys": "^3.4.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||
|
@ -2455,10 +2406,10 @@
|
|||
"integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/grapheme-splitter": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz",
|
||||
"integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==",
|
||||
"node_modules/graphemer": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
|
||||
"integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/has": {
|
||||
|
@ -2650,9 +2601,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/ignore": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz",
|
||||
"integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==",
|
||||
"version": "5.2.4",
|
||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz",
|
||||
"integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">= 4"
|
||||
|
@ -2855,9 +2806,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/is-core-module": {
|
||||
"version": "2.11.0",
|
||||
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz",
|
||||
"integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==",
|
||||
"version": "2.12.1",
|
||||
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.1.tgz",
|
||||
"integrity": "sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"has": "^1.0.3"
|
||||
|
@ -3133,12 +3084,6 @@
|
|||
"integrity": "sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/js-sdsl": {
|
||||
"version": "4.1.4",
|
||||
"resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.4.tgz",
|
||||
"integrity": "sha512-Y2/yD55y5jteOAmY50JbUZYwk3CP3wnLPEZnlR1w9oKhITrBEtAxwuWKebFf8hMrPMgbYwFoWK/lH2sBkErELw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/js-yaml": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
|
||||
|
@ -3866,9 +3811,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/npm-check-updates": {
|
||||
"version": "16.10.12",
|
||||
"resolved": "https://registry.npmjs.org/npm-check-updates/-/npm-check-updates-16.10.12.tgz",
|
||||
"integrity": "sha512-js/Gg9+5RTyOQZnmFcPswLxf4sK/H5AE/8bl4tkleLJTC1gXhQqqELUFwXqppNvx488aXxN52ZY9k9MSSvEW2A==",
|
||||
"version": "16.10.13",
|
||||
"resolved": "https://registry.npmjs.org/npm-check-updates/-/npm-check-updates-16.10.13.tgz",
|
||||
"integrity": "sha512-ZsWrtHnaMkcxAaCtDFEr8i7jgM0Bz2AYsnsJlmxISgltG8ie43bWC6G9icxFKfYSLeJJtcj/Yw1Mq5f8GL2F3g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"chalk": "^5.2.0",
|
||||
|
@ -4472,15 +4417,15 @@
|
|||
}
|
||||
},
|
||||
"node_modules/playwright-core": {
|
||||
"version": "1.33.0",
|
||||
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.33.0.tgz",
|
||||
"integrity": "sha512-aizyPE1Cj62vAECdph1iaMILpT0WUDCq3E6rW6I+dleSbBoGbktvJtzS6VHkZ4DKNEOG9qJpiom/ZxO+S15LAw==",
|
||||
"version": "1.35.1",
|
||||
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.35.1.tgz",
|
||||
"integrity": "sha512-pNXb6CQ7OqmGDRspEjlxE49w+4YtR6a3X6mT1hZXeJHWmsEz7SunmvZeiG/+y1yyMZdHnnn73WKYdtV1er0Xyg==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"playwright": "cli.js"
|
||||
"playwright-core": "cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
"node": ">=16"
|
||||
}
|
||||
},
|
||||
"node_modules/prelude-ls": {
|
||||
|
@ -4815,12 +4760,12 @@
|
|||
}
|
||||
},
|
||||
"node_modules/resolve": {
|
||||
"version": "1.22.1",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
|
||||
"integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==",
|
||||
"version": "1.22.2",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz",
|
||||
"integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"is-core-module": "^2.9.0",
|
||||
"is-core-module": "^2.11.0",
|
||||
"path-parse": "^1.0.7",
|
||||
"supports-preserve-symlinks-flag": "^1.0.0"
|
||||
},
|
||||
|
@ -4965,9 +4910,9 @@
|
|||
"integrity": "sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg=="
|
||||
},
|
||||
"node_modules/semver": {
|
||||
"version": "7.5.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz",
|
||||
"integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==",
|
||||
"version": "7.5.3",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.3.tgz",
|
||||
"integrity": "sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"lru-cache": "^6.0.0"
|
||||
|
@ -6026,20 +5971,20 @@
|
|||
}
|
||||
},
|
||||
"@eslint-community/regexpp": {
|
||||
"version": "4.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.4.1.tgz",
|
||||
"integrity": "sha512-BISJ6ZE4xQsuL/FmsyRaiffpq977bMlsKfGHTQrOGFErfByxIe6iZTxPf/00Zon9b9a7iUykfQwejN3s2ZW/Bw==",
|
||||
"version": "4.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.1.tgz",
|
||||
"integrity": "sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@eslint/eslintrc": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.2.tgz",
|
||||
"integrity": "sha512-3W4f5tDUra+pA+FzgugqL2pRimUTDJWKr7BINqOpkZrC0uYI0NIc0/JFgBROCU07HR6GieA5m3/rsPIhDmCXTQ==",
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.3.tgz",
|
||||
"integrity": "sha512-+5gy6OQfk+xx3q0d6jGZZC3f3KzAkXc/IanVxd1is/VIIziRqqt3ongQz0FiTUXqTk0c7aDB3OaFuKnuSoJicQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ajv": "^6.12.4",
|
||||
"debug": "^4.3.2",
|
||||
"espree": "^9.5.1",
|
||||
"espree": "^9.5.2",
|
||||
"globals": "^13.19.0",
|
||||
"ignore": "^5.2.0",
|
||||
"import-fresh": "^3.2.1",
|
||||
|
@ -6049,15 +5994,15 @@
|
|||
}
|
||||
},
|
||||
"@eslint/js": {
|
||||
"version": "8.39.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.39.0.tgz",
|
||||
"integrity": "sha512-kf9RB0Fg7NZfap83B3QOqOGg9QmD9yBudqQXzzOtn3i4y7ZUXe5ONeW34Gwi+TxhH4mvj72R1Zc300KUMa9Bng==",
|
||||
"version": "8.43.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.43.0.tgz",
|
||||
"integrity": "sha512-s2UHCoiXfxMvmfzqoN+vrQ84ahUSYde9qNO1MdxmoEhyHWsfmwOpFlwYV+ePJEVc7gFnATGUi376WowX1N7tFg==",
|
||||
"dev": true
|
||||
},
|
||||
"@faker-js/faker": {
|
||||
"version": "8.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-8.0.1.tgz",
|
||||
"integrity": "sha512-kbh5MenpTN9U0B4QcOI1NoTPlZHniSYQ3BHbhAnPjJGAmmFqxoxTE4sGdpy7ZOO9038DPGCuhXyMkjOr05uVwA=="
|
||||
"version": "8.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-8.0.2.tgz",
|
||||
"integrity": "sha512-Uo3pGspElQW91PCvKSIAXoEgAUlRnH29sX2/p89kg7sP1m2PzCufHINd0FhTXQf6DYGiUlVncdSPa2F9wxed2A=="
|
||||
},
|
||||
"@gar/promisify": {
|
||||
"version": "1.1.3",
|
||||
|
@ -6066,9 +6011,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"@humanwhocodes/config-array": {
|
||||
"version": "0.11.8",
|
||||
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz",
|
||||
"integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==",
|
||||
"version": "0.11.10",
|
||||
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz",
|
||||
"integrity": "sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@humanwhocodes/object-schema": "^1.2.1",
|
||||
|
@ -6283,14 +6228,14 @@
|
|||
"optional": true
|
||||
},
|
||||
"@playwright/test": {
|
||||
"version": "1.33.0",
|
||||
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.33.0.tgz",
|
||||
"integrity": "sha512-YunBa2mE7Hq4CfPkGzQRK916a4tuZoVx/EpLjeWlTVOnD4S2+fdaQZE0LJkbfhN5FTSKNLdcl7MoT5XB37bTkg==",
|
||||
"version": "1.35.1",
|
||||
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.35.1.tgz",
|
||||
"integrity": "sha512-b5YoFe6J9exsMYg0pQAobNDR85T1nLumUYgUTtKm4d21iX2L7WqKq9dW8NGJ+2vX0etZd+Y7UeuqsxDXm9+5ZA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/node": "*",
|
||||
"fsevents": "2.3.2",
|
||||
"playwright-core": "1.33.0"
|
||||
"playwright-core": "1.35.1"
|
||||
}
|
||||
},
|
||||
"@pnpm/network.ca-file": {
|
||||
|
@ -6393,9 +6338,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"acorn": {
|
||||
"version": "8.8.2",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz",
|
||||
"integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==",
|
||||
"version": "8.9.0",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.9.0.tgz",
|
||||
"integrity": "sha512-jaVNAFBHNLXspO543WnNNPZFRtavh3skAkITqD0/2aeMkKZTN+254PyhwxFYrk3vQ1xfY+2wbesJMs/JC8/PwQ==",
|
||||
"dev": true
|
||||
},
|
||||
"acorn-jsx": {
|
||||
|
@ -7120,16 +7065,16 @@
|
|||
"dev": true
|
||||
},
|
||||
"eslint": {
|
||||
"version": "8.39.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.39.0.tgz",
|
||||
"integrity": "sha512-mwiok6cy7KTW7rBpo05k6+p4YVZByLNjAZ/ACB9DRCu4YDRwjXI01tWHp6KAUWelsBetTxKK/2sHB0vdS8Z2Og==",
|
||||
"version": "8.43.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.43.0.tgz",
|
||||
"integrity": "sha512-aaCpf2JqqKesMFGgmRPessmVKjcGXqdlAYLLC3THM8t5nBRZRQ+st5WM/hoJXkdioEXLLbXgclUpM0TXo5HX5Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@eslint-community/eslint-utils": "^4.2.0",
|
||||
"@eslint-community/regexpp": "^4.4.0",
|
||||
"@eslint/eslintrc": "^2.0.2",
|
||||
"@eslint/js": "8.39.0",
|
||||
"@humanwhocodes/config-array": "^0.11.8",
|
||||
"@eslint/eslintrc": "^2.0.3",
|
||||
"@eslint/js": "8.43.0",
|
||||
"@humanwhocodes/config-array": "^0.11.10",
|
||||
"@humanwhocodes/module-importer": "^1.0.1",
|
||||
"@nodelib/fs.walk": "^1.2.8",
|
||||
"ajv": "^6.10.0",
|
||||
|
@ -7139,8 +7084,8 @@
|
|||
"doctrine": "^3.0.0",
|
||||
"escape-string-regexp": "^4.0.0",
|
||||
"eslint-scope": "^7.2.0",
|
||||
"eslint-visitor-keys": "^3.4.0",
|
||||
"espree": "^9.5.1",
|
||||
"eslint-visitor-keys": "^3.4.1",
|
||||
"espree": "^9.5.2",
|
||||
"esquery": "^1.4.2",
|
||||
"esutils": "^2.0.2",
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
|
@ -7148,13 +7093,12 @@
|
|||
"find-up": "^5.0.0",
|
||||
"glob-parent": "^6.0.2",
|
||||
"globals": "^13.19.0",
|
||||
"grapheme-splitter": "^1.0.4",
|
||||
"graphemer": "^1.4.0",
|
||||
"ignore": "^5.2.0",
|
||||
"import-fresh": "^3.0.0",
|
||||
"imurmurhash": "^0.1.4",
|
||||
"is-glob": "^4.0.0",
|
||||
"is-path-inside": "^3.0.3",
|
||||
"js-sdsl": "^4.1.4",
|
||||
"js-yaml": "^4.1.0",
|
||||
"json-stable-stringify-without-jsonify": "^1.0.1",
|
||||
"levn": "^0.4.1",
|
||||
|
@ -7168,9 +7112,9 @@
|
|||
}
|
||||
},
|
||||
"eslint-config-standard": {
|
||||
"version": "17.0.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-17.0.0.tgz",
|
||||
"integrity": "sha512-/2ks1GKyqSOkH7JFvXJicu0iMpoojkwB+f5Du/1SC0PtBL+s8v30k9njRZ21pm2drKYm2342jFnGWzttxPmZVg==",
|
||||
"version": "17.1.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-17.1.0.tgz",
|
||||
"integrity": "sha512-IwHwmaBNtDK4zDHQukFDW5u/aTb8+meQWZvNFWkiGmbWjD6bqyuSSBxxXKkCftCUzc1zwCH2m/baCNDLGmuO5Q==",
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
|
@ -7216,31 +7160,14 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"eslint-plugin-es": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-4.1.0.tgz",
|
||||
"integrity": "sha512-GILhQTnjYE2WorX5Jyi5i4dz5ALWxBIdQECVQavL6s7cI76IZTDWleTHkxz/QT3kvcs2QlGHvKLYsSlPOlPXnQ==",
|
||||
"eslint-plugin-es-x": {
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-es-x/-/eslint-plugin-es-x-7.1.0.tgz",
|
||||
"integrity": "sha512-AhiaF31syh4CCQ+C5ccJA0VG6+kJK8+5mXKKE7Qs1xcPRg02CDPOj3mWlQxuWS/AYtg7kxrDNgW9YW3vc0Q+Mw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"eslint-utils": "^2.0.0",
|
||||
"regexpp": "^3.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"eslint-utils": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz",
|
||||
"integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"eslint-visitor-keys": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"eslint-visitor-keys": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz",
|
||||
"integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==",
|
||||
"dev": true
|
||||
}
|
||||
"@eslint-community/eslint-utils": "^4.1.2",
|
||||
"@eslint-community/regexpp": "^4.5.0"
|
||||
}
|
||||
},
|
||||
"eslint-plugin-import": {
|
||||
|
@ -7293,19 +7220,19 @@
|
|||
}
|
||||
},
|
||||
"eslint-plugin-n": {
|
||||
"version": "15.7.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-15.7.0.tgz",
|
||||
"integrity": "sha512-jDex9s7D/Qial8AGVIHq4W7NswpUD5DPDL2RH8Lzd9EloWUuvUkHfv4FRLMipH5q2UtyurorBkPeNi1wVWNh3Q==",
|
||||
"version": "16.0.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-16.0.1.tgz",
|
||||
"integrity": "sha512-CDmHegJN0OF3L5cz5tATH84RPQm9kG+Yx39wIqIwPR2C0uhBGMWfbbOtetR83PQjjidA5aXMu+LEFw1jaSwvTA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@eslint-community/eslint-utils": "^4.4.0",
|
||||
"builtins": "^5.0.1",
|
||||
"eslint-plugin-es": "^4.1.0",
|
||||
"eslint-utils": "^3.0.0",
|
||||
"ignore": "^5.1.1",
|
||||
"is-core-module": "^2.11.0",
|
||||
"eslint-plugin-es-x": "^7.1.0",
|
||||
"ignore": "^5.2.4",
|
||||
"is-core-module": "^2.12.1",
|
||||
"minimatch": "^3.1.2",
|
||||
"resolve": "^1.22.1",
|
||||
"semver": "^7.3.8"
|
||||
"resolve": "^1.22.2",
|
||||
"semver": "^7.5.3"
|
||||
}
|
||||
},
|
||||
"eslint-plugin-node": {
|
||||
|
@ -7372,38 +7299,21 @@
|
|||
"estraverse": "^5.2.0"
|
||||
}
|
||||
},
|
||||
"eslint-utils": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz",
|
||||
"integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"eslint-visitor-keys": "^2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"eslint-visitor-keys": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz",
|
||||
"integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"eslint-visitor-keys": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.0.tgz",
|
||||
"integrity": "sha512-HPpKPUBQcAsZOsHAFwTtIKcYlCje62XB7SEAcxjtmW6TD1WVpkS6i6/hOVtTZIl4zGj/mBqpFVGvaDneik+VoQ==",
|
||||
"version": "3.4.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz",
|
||||
"integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==",
|
||||
"dev": true
|
||||
},
|
||||
"espree": {
|
||||
"version": "9.5.1",
|
||||
"resolved": "https://registry.npmjs.org/espree/-/espree-9.5.1.tgz",
|
||||
"integrity": "sha512-5yxtHSZXRSW5pvv3hAlXM5+/Oswi1AUFqBmbibKb5s6bp3rGIDkyXU6xCoyuuLhijr4SFwPrXRoZjz0AZDN9tg==",
|
||||
"version": "9.5.2",
|
||||
"resolved": "https://registry.npmjs.org/espree/-/espree-9.5.2.tgz",
|
||||
"integrity": "sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"acorn": "^8.8.0",
|
||||
"acorn-jsx": "^5.3.2",
|
||||
"eslint-visitor-keys": "^3.4.0"
|
||||
"eslint-visitor-keys": "^3.4.1"
|
||||
}
|
||||
},
|
||||
"esquery": {
|
||||
|
@ -7777,10 +7687,10 @@
|
|||
"integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==",
|
||||
"dev": true
|
||||
},
|
||||
"grapheme-splitter": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz",
|
||||
"integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==",
|
||||
"graphemer": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
|
||||
"integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
|
||||
"dev": true
|
||||
},
|
||||
"has": {
|
||||
|
@ -7920,9 +7830,9 @@
|
|||
}
|
||||
},
|
||||
"ignore": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz",
|
||||
"integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==",
|
||||
"version": "5.2.4",
|
||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz",
|
||||
"integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==",
|
||||
"dev": true
|
||||
},
|
||||
"ignore-walk": {
|
||||
|
@ -8073,9 +7983,9 @@
|
|||
}
|
||||
},
|
||||
"is-core-module": {
|
||||
"version": "2.11.0",
|
||||
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz",
|
||||
"integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==",
|
||||
"version": "2.12.1",
|
||||
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.1.tgz",
|
||||
"integrity": "sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"has": "^1.0.3"
|
||||
|
@ -8259,12 +8169,6 @@
|
|||
"integrity": "sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==",
|
||||
"dev": true
|
||||
},
|
||||
"js-sdsl": {
|
||||
"version": "4.1.4",
|
||||
"resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.4.tgz",
|
||||
"integrity": "sha512-Y2/yD55y5jteOAmY50JbUZYwk3CP3wnLPEZnlR1w9oKhITrBEtAxwuWKebFf8hMrPMgbYwFoWK/lH2sBkErELw==",
|
||||
"dev": true
|
||||
},
|
||||
"js-yaml": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
|
||||
|
@ -8834,9 +8738,9 @@
|
|||
}
|
||||
},
|
||||
"npm-check-updates": {
|
||||
"version": "16.10.12",
|
||||
"resolved": "https://registry.npmjs.org/npm-check-updates/-/npm-check-updates-16.10.12.tgz",
|
||||
"integrity": "sha512-js/Gg9+5RTyOQZnmFcPswLxf4sK/H5AE/8bl4tkleLJTC1gXhQqqELUFwXqppNvx488aXxN52ZY9k9MSSvEW2A==",
|
||||
"version": "16.10.13",
|
||||
"resolved": "https://registry.npmjs.org/npm-check-updates/-/npm-check-updates-16.10.13.tgz",
|
||||
"integrity": "sha512-ZsWrtHnaMkcxAaCtDFEr8i7jgM0Bz2AYsnsJlmxISgltG8ie43bWC6G9icxFKfYSLeJJtcj/Yw1Mq5f8GL2F3g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chalk": "^5.2.0",
|
||||
|
@ -9271,9 +9175,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"playwright-core": {
|
||||
"version": "1.33.0",
|
||||
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.33.0.tgz",
|
||||
"integrity": "sha512-aizyPE1Cj62vAECdph1iaMILpT0WUDCq3E6rW6I+dleSbBoGbktvJtzS6VHkZ4DKNEOG9qJpiom/ZxO+S15LAw==",
|
||||
"version": "1.35.1",
|
||||
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.35.1.tgz",
|
||||
"integrity": "sha512-pNXb6CQ7OqmGDRspEjlxE49w+4YtR6a3X6mT1hZXeJHWmsEz7SunmvZeiG/+y1yyMZdHnnn73WKYdtV1er0Xyg==",
|
||||
"dev": true
|
||||
},
|
||||
"prelude-ls": {
|
||||
|
@ -9513,12 +9417,12 @@
|
|||
"dev": true
|
||||
},
|
||||
"resolve": {
|
||||
"version": "1.22.1",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
|
||||
"integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==",
|
||||
"version": "1.22.2",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz",
|
||||
"integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-core-module": "^2.9.0",
|
||||
"is-core-module": "^2.11.0",
|
||||
"path-parse": "^1.0.7",
|
||||
"supports-preserve-symlinks-flag": "^1.0.0"
|
||||
}
|
||||
|
@ -9604,9 +9508,9 @@
|
|||
"integrity": "sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg=="
|
||||
},
|
||||
"semver": {
|
||||
"version": "7.5.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz",
|
||||
"integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==",
|
||||
"version": "7.5.3",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.3.tgz",
|
||||
"integrity": "sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"lru-cache": "^6.0.0"
|
||||
|
|
|
@ -7,17 +7,17 @@
|
|||
"test:debug": "playwright test --debug"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@playwright/test": "1.33.0",
|
||||
"eslint": "8.39.0",
|
||||
"eslint-config-standard": "17.0.0",
|
||||
"@playwright/test": "1.35.1",
|
||||
"eslint": "8.43.0",
|
||||
"eslint-config-standard": "17.1.0",
|
||||
"eslint-plugin-import": "2.27.5",
|
||||
"eslint-plugin-n": "15.7.0",
|
||||
"eslint-plugin-n": "16.0.1",
|
||||
"eslint-plugin-node": "11.1.0",
|
||||
"eslint-plugin-promise": "6.1.1",
|
||||
"npm-check-updates": "16.10.12"
|
||||
"npm-check-updates": "16.10.13"
|
||||
},
|
||||
"dependencies": {
|
||||
"@faker-js/faker": "8.0.1",
|
||||
"@faker-js/faker": "8.0.2",
|
||||
"lodash": "4.17.21",
|
||||
"lodash-es": "4.17.21",
|
||||
"luxon": "3.3.0",
|
||||
|
|
|
@ -72,3 +72,4 @@ Unidecode>=1.3.4
|
|||
weasyprint>=59
|
||||
xml2rfc>=3.12.4
|
||||
xym>=0.6,<1.0
|
||||
pydantic<2 # Temporary pin until inflect can catch up.
|
||||
|
|
20
yarn.lock
20
yarn.lock
|
@ -4429,10 +4429,10 @@ browserlist@latest:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"highcharts@npm:11.0.1":
|
||||
version: 11.0.1
|
||||
resolution: "highcharts@npm:11.0.1"
|
||||
checksum: 773a7b876502d616b7c5f522610b061cc714233a6ecdd7f7d073151fdf53bc597c01a758fbda5bba9069a0ee487e7defddfbdb1de73a78db6267a9257250137c
|
||||
"highcharts@npm:11.1.0":
|
||||
version: 11.1.0
|
||||
resolution: "highcharts@npm:11.1.0"
|
||||
checksum: f9b8cdc38b3b41bcc4c3a2331d9b1c769400639e2d0094484a0f5274aaba619551b95b442a69f7f4e47c2c8445681e3651f6036207fe1928a1a982f5278ae85e
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
@ -6651,7 +6651,7 @@ browserlist@latest:
|
|||
eslint-plugin-promise: 6.1.1
|
||||
eslint-plugin-vue: 9.14.1
|
||||
file-saver: 2.0.5
|
||||
highcharts: 11.0.1
|
||||
highcharts: 11.1.0
|
||||
html-validate: 7.18.1
|
||||
ical.js: 1.5.0
|
||||
jquery: 3.7.0
|
||||
|
@ -6670,7 +6670,7 @@ browserlist@latest:
|
|||
pinia: 2.1.3
|
||||
pinia-plugin-persist: 1.0.0
|
||||
pug: 3.0.2
|
||||
sass: 1.62.1
|
||||
sass: 1.63.4
|
||||
seedrandom: 3.0.5
|
||||
select2: 4.1.0-rc.0
|
||||
select2-bootstrap-5-theme: 1.3.0
|
||||
|
@ -6734,16 +6734,16 @@ browserlist@latest:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"sass@npm:1.62.1":
|
||||
version: 1.62.1
|
||||
resolution: "sass@npm:1.62.1"
|
||||
"sass@npm:1.63.4":
|
||||
version: 1.63.4
|
||||
resolution: "sass@npm:1.63.4"
|
||||
dependencies:
|
||||
chokidar: ">=3.0.0 <4.0.0"
|
||||
immutable: ^4.0.0
|
||||
source-map-js: ">=0.6.2 <2.0.0"
|
||||
bin:
|
||||
sass: sass.js
|
||||
checksum: 1b1b3584b38a63dd94156b65f13b90e3f84b170a38c3d5e3fa578b7a32a37aeb349b4926b0eaf9448d48e955e86b1ee01b13993f19611dad8068af07a607c13b
|
||||
checksum: 12bde5beff85a7018157d90c8b9d5aec8b56832f89fcfeca146f10936eecf97e669d22fd41f812b3407ed259bbb114d69c9ecbfc7ee9b15308211fb910cdf5eb
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
|
Loading…
Reference in a new issue