chore: merge main into feat/rfc

This commit is contained in:
Robert Sparks 2023-10-12 15:11:02 -05:00
commit ab931f0510
No known key found for this signature in database
GPG key ID: 6E2A6A5775F91318
106 changed files with 1139 additions and 782 deletions

View file

@ -20,20 +20,20 @@ jobs:
- uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
uses: docker/setup-buildx-action@v3
- name: Login to GitHub Container Registry
uses: docker/login-action@v2
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Docker Build & Push
uses: docker/build-push-action@v4
uses: docker/build-push-action@v5
with:
context: .
file: docker/base.Dockerfile

View file

@ -22,20 +22,20 @@ jobs:
- uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
uses: docker/setup-buildx-action@v3
- name: Login to GitHub Container Registry
uses: docker/login-action@v2
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Docker Build & Push
uses: docker/build-push-action@v4
uses: docker/build-push-action@v5
with:
context: .
file: dev/celery/Dockerfile

View file

@ -24,20 +24,20 @@ jobs:
- uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
uses: docker/setup-buildx-action@v3
- name: Login to GitHub Container Registry
uses: docker/login-action@v2
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Docker Build & Push
uses: docker/build-push-action@v4
uses: docker/build-push-action@v5
with:
context: .
file: dev/mq/Dockerfile

View file

@ -32,14 +32,14 @@ jobs:
- uses: actions/checkout@v4
- name: Login to GitHub Container Registry
uses: docker/login-action@v2
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Docker Build & Push
uses: docker/build-push-action@v4
uses: docker/build-push-action@v5
with:
context: .
file: dev/shared-assets-sync/Dockerfile

View file

@ -45,9 +45,9 @@ jobs:
echo "Running tests..."
if [[ "x${{ github.event.inputs.ignoreLowerCoverage }}" == "xtrue" ]]; then
echo "Lower coverage failures will be ignored."
./ietf/manage.py test --validate-html-harder --settings=settings_test --ignore-lower-coverage
./ietf/manage.py test -v2 --validate-html-harder --settings=settings_test --ignore-lower-coverage
else
./ietf/manage.py test --validate-html-harder --settings=settings_test
./ietf/manage.py test -v2 --validate-html-harder --settings=settings_test
fi
coverage xml

236
.pnp.cjs generated
View file

@ -39,7 +39,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
["@fullcalendar/icalendar", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:6.1.8"],\
["@fullcalendar/interaction", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:6.1.8"],\
["@fullcalendar/list", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:6.1.8"],\
["@fullcalendar/luxon3", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:6.1.8"],\
["@fullcalendar/luxon3", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:6.1.9"],\
["@fullcalendar/timegrid", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:6.1.8"],\
["@fullcalendar/vue3", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:6.1.8"],\
["@parcel/optimizer-data-url", "npm:2.9.3"],\
@ -48,25 +48,25 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
["@popperjs/core", "npm:2.11.8"],\
["@rollup/pluginutils", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:5.0.4"],\
["@twuni/emojify", "npm:1.0.2"],\
["@vitejs/plugin-vue", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:4.3.3"],\
["bootstrap", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:5.3.1"],\
["bootstrap-icons", "npm:1.10.5"],\
["browser-fs-access", "npm:0.34.1"],\
["@vitejs/plugin-vue", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:4.3.4"],\
["bootstrap", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:5.3.2"],\
["bootstrap-icons", "npm:1.11.1"],\
["browser-fs-access", "npm:0.35.0"],\
["browserlist", "npm:1.0.1"],\
["c8", "npm:8.0.1"],\
["caniuse-lite", "npm:1.0.30001519"],\
["caniuse-lite", "npm:1.0.30001538"],\
["d3", "npm:7.8.5"],\
["eslint", "npm:8.48.0"],\
["eslint", "npm:8.49.0"],\
["eslint-config-standard", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:17.1.0"],\
["eslint-plugin-cypress", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:2.14.0"],\
["eslint-plugin-import", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:2.28.1"],\
["eslint-plugin-n", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:16.0.2"],\
["eslint-plugin-n", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:16.1.0"],\
["eslint-plugin-node", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:11.1.0"],\
["eslint-plugin-promise", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:6.1.1"],\
["eslint-plugin-vue", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:9.17.0"],\
["file-saver", "npm:2.0.5"],\
["highcharts", "npm:11.1.0"],\
["html-validate", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:8.3.0"],\
["html-validate", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:8.4.0"],\
["ical.js", "npm:1.5.0"],\
["jquery", "npm:3.7.1"],\
["jquery-migrate", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:3.4.1"],\
@ -74,7 +74,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
["list.js", "npm:2.3.1"],\
["lodash", "npm:4.17.21"],\
["lodash-es", "npm:4.17.21"],\
["luxon", "npm:3.4.0"],\
["luxon", "npm:3.4.3"],\
["moment", "npm:2.29.4"],\
["moment-timezone", "npm:0.5.43"],\
["ms", "npm:2.1.3"],\
@ -84,7 +84,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
["pinia", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:2.1.6"],\
["pinia-plugin-persist", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:1.0.0"],\
["pug", "npm:3.0.2"],\
["sass", "npm:1.66.1"],\
["sass", "npm:1.67.0"],\
["seedrandom", "npm:3.0.5"],\
["select2", "npm:4.1.0-rc.0"],\
["select2-bootstrap-5-theme", "npm:1.3.0"],\
@ -438,12 +438,12 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
],\
"linkType": "SOFT"\
}],\
["virtual:0dd1c3662912d25464a284caa5dbde8cc315ca056be4ded44d6f67e20c4895461cf49fc7bff27c35f254bdb0924477031e3e50d50a333908daaff17dcf43b01d#npm:4.4.0", {\
"packageLocation": "./.yarn/__virtual__/@eslint-community-eslint-utils-virtual-01223f6a8e/0/cache/@eslint-community-eslint-utils-npm-4.4.0-d1791bd5a3-cdfe3ae42b.zip/node_modules/@eslint-community/eslint-utils/",\
["virtual:1b802e43a1d6cfd4888588e031e9b9539c10922666207f02b37e1572beffa71b5952c5b88bdcc1e2ff0080ea3baa9b39a63225d9ea667488d5ab782bed5718c7#npm:4.4.0", {\
"packageLocation": "./.yarn/__virtual__/@eslint-community-eslint-utils-virtual-3145c9a18a/0/cache/@eslint-community-eslint-utils-npm-4.4.0-d1791bd5a3-cdfe3ae42b.zip/node_modules/@eslint-community/eslint-utils/",\
"packageDependencies": [\
["@eslint-community/eslint-utils", "virtual:0dd1c3662912d25464a284caa5dbde8cc315ca056be4ded44d6f67e20c4895461cf49fc7bff27c35f254bdb0924477031e3e50d50a333908daaff17dcf43b01d#npm:4.4.0"],\
["@eslint-community/eslint-utils", "virtual:1b802e43a1d6cfd4888588e031e9b9539c10922666207f02b37e1572beffa71b5952c5b88bdcc1e2ff0080ea3baa9b39a63225d9ea667488d5ab782bed5718c7#npm:4.4.0"],\
["@types/eslint", null],\
["eslint", "npm:8.48.0"],\
["eslint", "npm:8.49.0"],\
["eslint-visitor-keys", "npm:3.3.0"]\
],\
"packagePeers": [\
@ -488,10 +488,10 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
}]\
]],\
["@eslint/js", [\
["npm:8.48.0", {\
"packageLocation": "./.yarn/cache/@eslint-js-npm-8.48.0-cee42a7097-b2755f9c0e.zip/node_modules/@eslint/js/",\
["npm:8.49.0", {\
"packageLocation": "./.yarn/cache/@eslint-js-npm-8.49.0-e8f6510b47-a6601807c8.zip/node_modules/@eslint/js/",\
"packageDependencies": [\
["@eslint/js", "npm:8.48.0"]\
["@eslint/js", "npm:8.49.0"]\
],\
"linkType": "HARD"\
}]\
@ -651,21 +651,21 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
}]\
]],\
["@fullcalendar/luxon3", [\
["npm:6.1.8", {\
"packageLocation": "./.yarn/cache/@fullcalendar-luxon3-npm-6.1.8-7f233a53e1-7e84200641.zip/node_modules/@fullcalendar/luxon3/",\
["npm:6.1.9", {\
"packageLocation": "./.yarn/cache/@fullcalendar-luxon3-npm-6.1.9-d79fc8f961-25122126e2.zip/node_modules/@fullcalendar/luxon3/",\
"packageDependencies": [\
["@fullcalendar/luxon3", "npm:6.1.8"]\
["@fullcalendar/luxon3", "npm:6.1.9"]\
],\
"linkType": "SOFT"\
}],\
["virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:6.1.8", {\
"packageLocation": "./.yarn/__virtual__/@fullcalendar-luxon3-virtual-3a7af6083c/0/cache/@fullcalendar-luxon3-npm-6.1.8-7f233a53e1-7e84200641.zip/node_modules/@fullcalendar/luxon3/",\
["virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:6.1.9", {\
"packageLocation": "./.yarn/__virtual__/@fullcalendar-luxon3-virtual-2026214153/0/cache/@fullcalendar-luxon3-npm-6.1.9-d79fc8f961-25122126e2.zip/node_modules/@fullcalendar/luxon3/",\
"packageDependencies": [\
["@fullcalendar/luxon3", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:6.1.8"],\
["@fullcalendar/luxon3", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:6.1.9"],\
["@fullcalendar/core", "npm:6.1.8"],\
["@types/fullcalendar__core", null],\
["@types/luxon", null],\
["luxon", "npm:3.4.0"]\
["luxon", "npm:3.4.3"]\
],\
"packagePeers": [\
"@fullcalendar/core",\
@ -745,10 +745,10 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
}]\
]],\
["@humanwhocodes/config-array", [\
["npm:0.11.10", {\
"packageLocation": "./.yarn/cache/@humanwhocodes-config-array-npm-0.11.10-7b63df9e7f-1b1302e240.zip/node_modules/@humanwhocodes/config-array/",\
["npm:0.11.11", {\
"packageLocation": "./.yarn/cache/@humanwhocodes-config-array-npm-0.11.11-e3582554ee-db84507375.zip/node_modules/@humanwhocodes/config-array/",\
"packageDependencies": [\
["@humanwhocodes/config-array", "npm:0.11.10"],\
["@humanwhocodes/config-array", "npm:0.11.11"],\
["@humanwhocodes/object-schema", "npm:1.2.1"],\
["debug", "virtual:b86a9fb34323a98c6519528ed55faa0d9b44ca8879307c0b29aa384bde47ff59a7d0c9051b31246f14521dfb71ba3c5d6d0b35c29fffc17bf875aa6ad977d9e8#npm:4.3.4"],\
["minimatch", "npm:3.1.2"]\
@ -2389,10 +2389,10 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
],\
"linkType": "SOFT"\
}],\
["virtual:0f17270113a645b9ccd471681c6953a9ecf2cc875b79eb96d26d7cb579b1f042c2aaab59d6799ee85bf4e9b312f464a118c211e37c33fa47b3e11095c49e32d7#npm:2.0.0", {\
"packageLocation": "./.yarn/__virtual__/@sidvind-better-ajv-errors-virtual-148105bc23/0/cache/@sidvind-better-ajv-errors-npm-2.0.0-3531bddef9-12b0d87855.zip/node_modules/@sidvind/better-ajv-errors/",\
["virtual:baa02fb51e75f1f03e1ff0c1be104192da948332a9fd904d571b0b912d6ac16a98b4b63cb9465421728b6af4a1bb50f995b9b5018f7f90329de80b4a8ff40be4#npm:2.0.0", {\
"packageLocation": "./.yarn/__virtual__/@sidvind-better-ajv-errors-virtual-0c74a59d49/0/cache/@sidvind-better-ajv-errors-npm-2.0.0-3531bddef9-12b0d87855.zip/node_modules/@sidvind/better-ajv-errors/",\
"packageDependencies": [\
["@sidvind/better-ajv-errors", "virtual:0f17270113a645b9ccd471681c6953a9ecf2cc875b79eb96d26d7cb579b1f042c2aaab59d6799ee85bf4e9b312f464a118c211e37c33fa47b3e11095c49e32d7#npm:2.0.0"],\
["@sidvind/better-ajv-errors", "virtual:baa02fb51e75f1f03e1ff0c1be104192da948332a9fd904d571b0b912d6ac16a98b4b63cb9465421728b6af4a1bb50f995b9b5018f7f90329de80b4a8ff40be4#npm:2.0.0"],\
["@babel/code-frame", "npm:7.16.7"],\
["@types/ajv", null],\
["ajv", "npm:8.11.0"],\
@ -2638,17 +2638,17 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
}]\
]],\
["@vitejs/plugin-vue", [\
["npm:4.3.3", {\
"packageLocation": "./.yarn/cache/@vitejs-plugin-vue-npm-4.3.3-ffc8f9f2ac-17f8d73708.zip/node_modules/@vitejs/plugin-vue/",\
["npm:4.3.4", {\
"packageLocation": "./.yarn/cache/@vitejs-plugin-vue-npm-4.3.4-0e0b5c48a9-95bf6c85c0.zip/node_modules/@vitejs/plugin-vue/",\
"packageDependencies": [\
["@vitejs/plugin-vue", "npm:4.3.3"]\
["@vitejs/plugin-vue", "npm:4.3.4"]\
],\
"linkType": "SOFT"\
}],\
["virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:4.3.3", {\
"packageLocation": "./.yarn/__virtual__/@vitejs-plugin-vue-virtual-c26a0d639a/0/cache/@vitejs-plugin-vue-npm-4.3.3-ffc8f9f2ac-17f8d73708.zip/node_modules/@vitejs/plugin-vue/",\
["virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:4.3.4", {\
"packageLocation": "./.yarn/__virtual__/@vitejs-plugin-vue-virtual-d66cb5aa6a/0/cache/@vitejs-plugin-vue-npm-4.3.4-0e0b5c48a9-95bf6c85c0.zip/node_modules/@vitejs/plugin-vue/",\
"packageDependencies": [\
["@vitejs/plugin-vue", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:4.3.3"],\
["@vitejs/plugin-vue", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:4.3.4"],\
["@types/vite", null],\
["@types/vue", null],\
["vite", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:4.4.9"],\
@ -3191,10 +3191,10 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
],\
"linkType": "SOFT"\
}],\
["npm:5.3.1", {\
"packageLocation": "./.yarn/cache/bootstrap-npm-5.3.1-9ad45c2765-f8176376aa.zip/node_modules/bootstrap/",\
["npm:5.3.2", {\
"packageLocation": "./.yarn/cache/bootstrap-npm-5.3.2-20b391b636-d5580b253d.zip/node_modules/bootstrap/",\
"packageDependencies": [\
["bootstrap", "npm:5.3.1"]\
["bootstrap", "npm:5.3.2"]\
],\
"linkType": "SOFT"\
}],\
@ -3211,10 +3211,10 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
],\
"linkType": "HARD"\
}],\
["virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:5.3.1", {\
"packageLocation": "./.yarn/__virtual__/bootstrap-virtual-94a6bfc3bc/0/cache/bootstrap-npm-5.3.1-9ad45c2765-f8176376aa.zip/node_modules/bootstrap/",\
["virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:5.3.2", {\
"packageLocation": "./.yarn/__virtual__/bootstrap-virtual-b366fabcb3/0/cache/bootstrap-npm-5.3.2-20b391b636-d5580b253d.zip/node_modules/bootstrap/",\
"packageDependencies": [\
["bootstrap", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:5.3.1"],\
["bootstrap", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:5.3.2"],\
["@popperjs/core", "npm:2.11.8"],\
["@types/popperjs__core", null]\
],\
@ -3226,10 +3226,10 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
}]\
]],\
["bootstrap-icons", [\
["npm:1.10.5", {\
"packageLocation": "./.yarn/cache/bootstrap-icons-npm-1.10.5-36f80ab074-8a0cfbd237.zip/node_modules/bootstrap-icons/",\
["npm:1.11.1", {\
"packageLocation": "./.yarn/cache/bootstrap-icons-npm-1.11.1-9f55aea76a-d78ff24a83.zip/node_modules/bootstrap-icons/",\
"packageDependencies": [\
["bootstrap-icons", "npm:1.10.5"]\
["bootstrap-icons", "npm:1.11.1"]\
],\
"linkType": "HARD"\
}]\
@ -3264,10 +3264,10 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
}]\
]],\
["browser-fs-access", [\
["npm:0.34.1", {\
"packageLocation": "./.yarn/cache/browser-fs-access-npm-0.34.1-7fcd7d9328-339865241c.zip/node_modules/browser-fs-access/",\
["npm:0.35.0", {\
"packageLocation": "./.yarn/cache/browser-fs-access-npm-0.35.0-1577b5a7ba-5f3bf1ec17.zip/node_modules/browser-fs-access/",\
"packageDependencies": [\
["browser-fs-access", "npm:0.34.1"]\
["browser-fs-access", "npm:0.35.0"]\
],\
"linkType": "HARD"\
}]\
@ -3382,10 +3382,10 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
],\
"linkType": "HARD"\
}],\
["npm:1.0.30001519", {\
"packageLocation": "./.yarn/cache/caniuse-lite-npm-1.0.30001519-1d6b5bc825-66085133ed.zip/node_modules/caniuse-lite/",\
["npm:1.0.30001538", {\
"packageLocation": "./.yarn/cache/caniuse-lite-npm-1.0.30001538-68bfe8259b-94c5d55757.zip/node_modules/caniuse-lite/",\
"packageDependencies": [\
["caniuse-lite", "npm:1.0.30001519"]\
["caniuse-lite", "npm:1.0.30001538"]\
],\
"linkType": "HARD"\
}]\
@ -4630,15 +4630,15 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
}]\
]],\
["eslint", [\
["npm:8.48.0", {\
"packageLocation": "./.yarn/cache/eslint-npm-8.48.0-0dd1c36629-f20b359a4f.zip/node_modules/eslint/",\
["npm:8.49.0", {\
"packageLocation": "./.yarn/cache/eslint-npm-8.49.0-1b802e43a1-4dfe257e1e.zip/node_modules/eslint/",\
"packageDependencies": [\
["eslint", "npm:8.48.0"],\
["@eslint-community/eslint-utils", "virtual:0dd1c3662912d25464a284caa5dbde8cc315ca056be4ded44d6f67e20c4895461cf49fc7bff27c35f254bdb0924477031e3e50d50a333908daaff17dcf43b01d#npm:4.4.0"],\
["eslint", "npm:8.49.0"],\
["@eslint-community/eslint-utils", "virtual:1b802e43a1d6cfd4888588e031e9b9539c10922666207f02b37e1572beffa71b5952c5b88bdcc1e2ff0080ea3baa9b39a63225d9ea667488d5ab782bed5718c7#npm:4.4.0"],\
["@eslint-community/regexpp", "npm:4.8.0"],\
["@eslint/eslintrc", "npm:2.1.2"],\
["@eslint/js", "npm:8.48.0"],\
["@humanwhocodes/config-array", "npm:0.11.10"],\
["@eslint/js", "npm:8.49.0"],\
["@humanwhocodes/config-array", "npm:0.11.11"],\
["@humanwhocodes/module-importer", "npm:1.0.1"],\
["@nodelib/fs.walk", "npm:1.2.8"],\
["ajv", "npm:6.12.6"],\
@ -4691,9 +4691,9 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
["@types/eslint-plugin-import", null],\
["@types/eslint-plugin-n", null],\
["@types/eslint-plugin-promise", null],\
["eslint", "npm:8.48.0"],\
["eslint", "npm:8.49.0"],\
["eslint-plugin-import", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:2.28.1"],\
["eslint-plugin-n", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:16.0.2"],\
["eslint-plugin-n", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:16.1.0"],\
["eslint-plugin-promise", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:6.1.1"]\
],\
"packagePeers": [\
@ -4740,7 +4740,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
["@types/typescript-eslint__parser", null],\
["@typescript-eslint/parser", null],\
["debug", "virtual:65bed195431eadffc59e2238eb20cc12d9a1665bc7458ce780a9320ff795091b03cb5c4c2094938315ddd967b5b02c0f1df67b3ed435c69b7457092b7cc06ed8#npm:3.2.7"],\
["eslint", "npm:8.48.0"],\
["eslint", "npm:8.49.0"],\
["eslint-import-resolver-node", "npm:0.3.7"],\
["eslint-import-resolver-typescript", null],\
["eslint-import-resolver-webpack", null]\
@ -4773,7 +4773,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
"packageDependencies": [\
["eslint-plugin-cypress", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:2.14.0"],\
["@types/eslint", null],\
["eslint", "npm:8.48.0"],\
["eslint", "npm:8.49.0"],\
["globals", "npm:13.21.0"]\
],\
"packagePeers": [\
@ -4796,7 +4796,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
"packageDependencies": [\
["eslint-plugin-es", "virtual:5cccaf00e87dfff96dbbb5eaf7a3055373358b8114d6a1adfb32f54ed6b40ba06068d3aa1fdd8062899a0cad040f68c17cc6b72bac2cdbe9700f3d6330d112f3#npm:3.0.1"],\
["@types/eslint", null],\
["eslint", "npm:8.48.0"],\
["eslint", "npm:8.49.0"],\
["eslint-utils", "npm:2.1.0"],\
["regexpp", "npm:3.2.0"]\
],\
@ -4815,14 +4815,14 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
],\
"linkType": "SOFT"\
}],\
["virtual:40d6f5c942a7ef0ae65f54bca96af56e7db0d52fb7321d7f8d1da62ed519e1f8c80fdfb1299383ab8a4a5e7182ecc1d4bae33d806b79817d62ed4ad091e77615#npm:7.1.0", {\
"packageLocation": "./.yarn/__virtual__/eslint-plugin-es-x-virtual-3346953c48/0/cache/eslint-plugin-es-x-npm-7.1.0-35735e8bbc-a19924313c.zip/node_modules/eslint-plugin-es-x/",\
["virtual:9781ae938be7131b5685249f65c2d227d13395e62123d3b23a131614e18b016978a73fff3ac8d9c3709f25fa05a3e0f4cdf798416576354013fb49b6cd33487d#npm:7.1.0", {\
"packageLocation": "./.yarn/__virtual__/eslint-plugin-es-x-virtual-276ea3759f/0/cache/eslint-plugin-es-x-npm-7.1.0-35735e8bbc-a19924313c.zip/node_modules/eslint-plugin-es-x/",\
"packageDependencies": [\
["eslint-plugin-es-x", "virtual:40d6f5c942a7ef0ae65f54bca96af56e7db0d52fb7321d7f8d1da62ed519e1f8c80fdfb1299383ab8a4a5e7182ecc1d4bae33d806b79817d62ed4ad091e77615#npm:7.1.0"],\
["@eslint-community/eslint-utils", "virtual:0dd1c3662912d25464a284caa5dbde8cc315ca056be4ded44d6f67e20c4895461cf49fc7bff27c35f254bdb0924477031e3e50d50a333908daaff17dcf43b01d#npm:4.4.0"],\
["eslint-plugin-es-x", "virtual:9781ae938be7131b5685249f65c2d227d13395e62123d3b23a131614e18b016978a73fff3ac8d9c3709f25fa05a3e0f4cdf798416576354013fb49b6cd33487d#npm:7.1.0"],\
["@eslint-community/eslint-utils", "virtual:1b802e43a1d6cfd4888588e031e9b9539c10922666207f02b37e1572beffa71b5952c5b88bdcc1e2ff0080ea3baa9b39a63225d9ea667488d5ab782bed5718c7#npm:4.4.0"],\
["@eslint-community/regexpp", "npm:4.5.1"],\
["@types/eslint", null],\
["eslint", "npm:8.48.0"]\
["eslint", "npm:8.49.0"]\
],\
"packagePeers": [\
"@types/eslint",\
@ -4852,7 +4852,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
["array.prototype.flatmap", "npm:1.3.1"],\
["debug", "virtual:65bed195431eadffc59e2238eb20cc12d9a1665bc7458ce780a9320ff795091b03cb5c4c2094938315ddd967b5b02c0f1df67b3ed435c69b7457092b7cc06ed8#npm:3.2.7"],\
["doctrine", "npm:2.1.0"],\
["eslint", "npm:8.48.0"],\
["eslint", "npm:8.49.0"],\
["eslint-import-resolver-node", "npm:0.3.7"],\
["eslint-module-utils", "virtual:ef2ff17f0affe5aeeb05f2e27f2212e975bb78d898c026b74cc62e05a17de36abb35a54f0831f2ff5fced26e6128bfc2c0cf332f7c60149823619b008d0ea480#npm:2.8.0"],\
["has", "npm:1.0.3"],\
@ -4875,22 +4875,23 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
}]\
]],\
["eslint-plugin-n", [\
["npm:16.0.2", {\
"packageLocation": "./.yarn/cache/eslint-plugin-n-npm-16.0.2-6a256d6ab7-44cffe32a3.zip/node_modules/eslint-plugin-n/",\
["npm:16.1.0", {\
"packageLocation": "./.yarn/cache/eslint-plugin-n-npm-16.1.0-d4092716f8-6b70bf8eec.zip/node_modules/eslint-plugin-n/",\
"packageDependencies": [\
["eslint-plugin-n", "npm:16.0.2"]\
["eslint-plugin-n", "npm:16.1.0"]\
],\
"linkType": "SOFT"\
}],\
["virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:16.0.2", {\
"packageLocation": "./.yarn/__virtual__/eslint-plugin-n-virtual-40d6f5c942/0/cache/eslint-plugin-n-npm-16.0.2-6a256d6ab7-44cffe32a3.zip/node_modules/eslint-plugin-n/",\
["virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:16.1.0", {\
"packageLocation": "./.yarn/__virtual__/eslint-plugin-n-virtual-9781ae938b/0/cache/eslint-plugin-n-npm-16.1.0-d4092716f8-6b70bf8eec.zip/node_modules/eslint-plugin-n/",\
"packageDependencies": [\
["eslint-plugin-n", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:16.0.2"],\
["@eslint-community/eslint-utils", "virtual:0dd1c3662912d25464a284caa5dbde8cc315ca056be4ded44d6f67e20c4895461cf49fc7bff27c35f254bdb0924477031e3e50d50a333908daaff17dcf43b01d#npm:4.4.0"],\
["eslint-plugin-n", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:16.1.0"],\
["@eslint-community/eslint-utils", "virtual:1b802e43a1d6cfd4888588e031e9b9539c10922666207f02b37e1572beffa71b5952c5b88bdcc1e2ff0080ea3baa9b39a63225d9ea667488d5ab782bed5718c7#npm:4.4.0"],\
["@types/eslint", null],\
["builtins", "npm:5.0.1"],\
["eslint", "npm:8.48.0"],\
["eslint-plugin-es-x", "virtual:40d6f5c942a7ef0ae65f54bca96af56e7db0d52fb7321d7f8d1da62ed519e1f8c80fdfb1299383ab8a4a5e7182ecc1d4bae33d806b79817d62ed4ad091e77615#npm:7.1.0"],\
["eslint", "npm:8.49.0"],\
["eslint-plugin-es-x", "virtual:9781ae938be7131b5685249f65c2d227d13395e62123d3b23a131614e18b016978a73fff3ac8d9c3709f25fa05a3e0f4cdf798416576354013fb49b6cd33487d#npm:7.1.0"],\
["get-tsconfig", "npm:4.7.2"],\
["ignore", "npm:5.2.4"],\
["is-core-module", "npm:2.12.1"],\
["minimatch", "npm:3.1.2"],\
@ -4917,7 +4918,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
"packageDependencies": [\
["eslint-plugin-node", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:11.1.0"],\
["@types/eslint", null],\
["eslint", "npm:8.48.0"],\
["eslint", "npm:8.49.0"],\
["eslint-plugin-es", "virtual:5cccaf00e87dfff96dbbb5eaf7a3055373358b8114d6a1adfb32f54ed6b40ba06068d3aa1fdd8062899a0cad040f68c17cc6b72bac2cdbe9700f3d6330d112f3#npm:3.0.1"],\
["eslint-utils", "npm:2.1.0"],\
["ignore", "npm:5.2.0"],\
@ -4945,7 +4946,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
"packageDependencies": [\
["eslint-plugin-promise", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:6.1.1"],\
["@types/eslint", null],\
["eslint", "npm:8.48.0"]\
["eslint", "npm:8.49.0"]\
],\
"packagePeers": [\
"@types/eslint",\
@ -4966,9 +4967,9 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
"packageLocation": "./.yarn/__virtual__/eslint-plugin-vue-virtual-e39e5d6bef/0/cache/eslint-plugin-vue-npm-9.17.0-c32115eab8-2ef53a0387.zip/node_modules/eslint-plugin-vue/",\
"packageDependencies": [\
["eslint-plugin-vue", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:9.17.0"],\
["@eslint-community/eslint-utils", "virtual:0dd1c3662912d25464a284caa5dbde8cc315ca056be4ded44d6f67e20c4895461cf49fc7bff27c35f254bdb0924477031e3e50d50a333908daaff17dcf43b01d#npm:4.4.0"],\
["@eslint-community/eslint-utils", "virtual:1b802e43a1d6cfd4888588e031e9b9539c10922666207f02b37e1572beffa71b5952c5b88bdcc1e2ff0080ea3baa9b39a63225d9ea667488d5ab782bed5718c7#npm:4.4.0"],\
["@types/eslint", null],\
["eslint", "npm:8.48.0"],\
["eslint", "npm:8.49.0"],\
["natural-compare", "npm:1.4.0"],\
["nth-check", "npm:2.1.1"],\
["postcss-selector-parser", "npm:6.0.13"],\
@ -5420,6 +5421,16 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
"linkType": "HARD"\
}]\
]],\
["get-tsconfig", [\
["npm:4.7.2", {\
"packageLocation": "./.yarn/cache/get-tsconfig-npm-4.7.2-8fbccd9fcf-1723589032.zip/node_modules/get-tsconfig/",\
"packageDependencies": [\
["get-tsconfig", "npm:4.7.2"],\
["resolve-pkg-maps", "npm:1.0.0"]\
],\
"linkType": "HARD"\
}]\
]],\
["glob", [\
["npm:10.2.4", {\
"packageLocation": "./.yarn/cache/glob-npm-10.2.4-49f715fccc-29845faaa1.zip/node_modules/glob/",\
@ -5651,20 +5662,20 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
}]\
]],\
["html-validate", [\
["npm:8.3.0", {\
"packageLocation": "./.yarn/cache/html-validate-npm-8.3.0-71b7ba49e2-fd96a96fa7.zip/node_modules/html-validate/",\
["npm:8.4.0", {\
"packageLocation": "./.yarn/cache/html-validate-npm-8.4.0-4d1a9d1021-5a063e3bb0.zip/node_modules/html-validate/",\
"packageDependencies": [\
["html-validate", "npm:8.3.0"]\
["html-validate", "npm:8.4.0"]\
],\
"linkType": "SOFT"\
}],\
["virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:8.3.0", {\
"packageLocation": "./.yarn/__virtual__/html-validate-virtual-0f17270113/0/cache/html-validate-npm-8.3.0-71b7ba49e2-fd96a96fa7.zip/node_modules/html-validate/",\
["virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:8.4.0", {\
"packageLocation": "./.yarn/__virtual__/html-validate-virtual-baa02fb51e/0/cache/html-validate-npm-8.4.0-4d1a9d1021-5a063e3bb0.zip/node_modules/html-validate/",\
"packageDependencies": [\
["html-validate", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:8.3.0"],\
["html-validate", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:8.4.0"],\
["@babel/code-frame", "npm:7.16.7"],\
["@html-validate/stylish", "npm:4.1.0"],\
["@sidvind/better-ajv-errors", "virtual:0f17270113a645b9ccd471681c6953a9ecf2cc875b79eb96d26d7cb579b1f042c2aaab59d6799ee85bf4e9b312f464a118c211e37c33fa47b3e11095c49e32d7#npm:2.0.0"],\
["@sidvind/better-ajv-errors", "virtual:baa02fb51e75f1f03e1ff0c1be104192da948332a9fd904d571b0b912d6ac16a98b4b63cb9465421728b6af4a1bb50f995b9b5018f7f90329de80b4a8ff40be4#npm:2.0.0"],\
["@types/jest", null],\
["@types/jest-diff", null],\
["@types/jest-snapshot", null],\
@ -6701,10 +6712,10 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
}]\
]],\
["luxon", [\
["npm:3.4.0", {\
"packageLocation": "./.yarn/cache/luxon-npm-3.4.0-8e0b97226e-ca9b6d0e0a.zip/node_modules/luxon/",\
["npm:3.4.3", {\
"packageLocation": "./.yarn/cache/luxon-npm-3.4.3-1b54517fa6-3eade81506.zip/node_modules/luxon/",\
"packageDependencies": [\
["luxon", "npm:3.4.0"]\
["luxon", "npm:3.4.3"]\
],\
"linkType": "HARD"\
}]\
@ -8043,6 +8054,15 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
"linkType": "HARD"\
}]\
]],\
["resolve-pkg-maps", [\
["npm:1.0.0", {\
"packageLocation": "./.yarn/cache/resolve-pkg-maps-npm-1.0.0-135b70c854-1012afc566.zip/node_modules/resolve-pkg-maps/",\
"packageDependencies": [\
["resolve-pkg-maps", "npm:1.0.0"]\
],\
"linkType": "HARD"\
}]\
]],\
["retry", [\
["npm:0.12.0", {\
"packageLocation": "./.yarn/cache/retry-npm-0.12.0-72ac7fb4cc-623bd7d2e5.zip/node_modules/retry/",\
@ -8101,7 +8121,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
["@fullcalendar/icalendar", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:6.1.8"],\
["@fullcalendar/interaction", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:6.1.8"],\
["@fullcalendar/list", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:6.1.8"],\
["@fullcalendar/luxon3", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:6.1.8"],\
["@fullcalendar/luxon3", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:6.1.9"],\
["@fullcalendar/timegrid", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:6.1.8"],\
["@fullcalendar/vue3", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:6.1.8"],\
["@parcel/optimizer-data-url", "npm:2.9.3"],\
@ -8110,25 +8130,25 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
["@popperjs/core", "npm:2.11.8"],\
["@rollup/pluginutils", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:5.0.4"],\
["@twuni/emojify", "npm:1.0.2"],\
["@vitejs/plugin-vue", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:4.3.3"],\
["bootstrap", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:5.3.1"],\
["bootstrap-icons", "npm:1.10.5"],\
["browser-fs-access", "npm:0.34.1"],\
["@vitejs/plugin-vue", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:4.3.4"],\
["bootstrap", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:5.3.2"],\
["bootstrap-icons", "npm:1.11.1"],\
["browser-fs-access", "npm:0.35.0"],\
["browserlist", "npm:1.0.1"],\
["c8", "npm:8.0.1"],\
["caniuse-lite", "npm:1.0.30001519"],\
["caniuse-lite", "npm:1.0.30001538"],\
["d3", "npm:7.8.5"],\
["eslint", "npm:8.48.0"],\
["eslint", "npm:8.49.0"],\
["eslint-config-standard", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:17.1.0"],\
["eslint-plugin-cypress", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:2.14.0"],\
["eslint-plugin-import", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:2.28.1"],\
["eslint-plugin-n", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:16.0.2"],\
["eslint-plugin-n", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:16.1.0"],\
["eslint-plugin-node", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:11.1.0"],\
["eslint-plugin-promise", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:6.1.1"],\
["eslint-plugin-vue", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:9.17.0"],\
["file-saver", "npm:2.0.5"],\
["highcharts", "npm:11.1.0"],\
["html-validate", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:8.3.0"],\
["html-validate", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:8.4.0"],\
["ical.js", "npm:1.5.0"],\
["jquery", "npm:3.7.1"],\
["jquery-migrate", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:3.4.1"],\
@ -8136,7 +8156,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
["list.js", "npm:2.3.1"],\
["lodash", "npm:4.17.21"],\
["lodash-es", "npm:4.17.21"],\
["luxon", "npm:3.4.0"],\
["luxon", "npm:3.4.3"],\
["moment", "npm:2.29.4"],\
["moment-timezone", "npm:0.5.43"],\
["ms", "npm:2.1.3"],\
@ -8146,7 +8166,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
["pinia", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:2.1.6"],\
["pinia-plugin-persist", "virtual:dc3fc578bfa5e06182a4d2be39ede0bc5b74940b1ffe0d70c26892ab140a4699787750fba175dc306292e80b4aa2c8c5f68c2a821e69b2c37e360c0dff36ff66#npm:1.0.0"],\
["pug", "npm:3.0.2"],\
["sass", "npm:1.66.1"],\
["sass", "npm:1.67.0"],\
["seedrandom", "npm:3.0.5"],\
["select2", "npm:4.1.0-rc.0"],\
["select2-bootstrap-5-theme", "npm:1.3.0"],\
@ -8243,10 +8263,10 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
],\
"linkType": "HARD"\
}],\
["npm:1.66.1", {\
"packageLocation": "./.yarn/cache/sass-npm-1.66.1-563acb4a8f-74fc11d0fc.zip/node_modules/sass/",\
["npm:1.67.0", {\
"packageLocation": "./.yarn/cache/sass-npm-1.67.0-d0fceb9574-9e7566e8b7.zip/node_modules/sass/",\
"packageDependencies": [\
["sass", "npm:1.66.1"],\
["sass", "npm:1.67.0"],\
["chokidar", "npm:3.5.3"],\
["immutable", "npm:4.0.0"],\
["source-map-js", "npm:1.0.2"]\
@ -9029,7 +9049,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
["lightningcss", null],\
["postcss", "npm:8.4.27"],\
["rollup", "npm:3.28.0"],\
["sass", "npm:1.66.1"],\
["sass", "npm:1.67.0"],\
["stylus", null],\
["sugarss", null],\
["terser", null]\
@ -9162,7 +9182,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
["vue-eslint-parser", "virtual:e39e5d6bef7a93bd3b21c5c9ba6ef825c92fc73c8d9c9e01699e1dc11e40fd3bc150ba16509e2cf59495cb098c32b2e4a85c0c21802fddeffc3208b01f4f5a16#npm:9.3.1"],\
["@types/eslint", null],\
["debug", "virtual:b86a9fb34323a98c6519528ed55faa0d9b44ca8879307c0b29aa384bde47ff59a7d0c9051b31246f14521dfb71ba3c5d6d0b35c29fffc17bf875aa6ad977d9e8#npm:4.3.4"],\
["eslint", "npm:8.48.0"],\
["eslint", "npm:8.49.0"],\
["eslint-scope", "npm:7.1.1"],\
["eslint-visitor-keys", "npm:3.3.0"],\
["espree", "npm:9.3.2"],\

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -9,15 +9,15 @@
"version": "1.0.0",
"license": "BSD-3-Clause",
"dependencies": {
"@actions/core": "1.10.0",
"@actions/core": "1.10.1",
"@actions/github": "5.1.1",
"chart.js": "3.5.1",
"chartjs-node-canvas": "4.1.6",
"lodash": "4.17.21",
"luxon": "3.4.0"
"luxon": "3.4.3"
},
"devDependencies": {
"eslint": "8.48.0",
"eslint": "8.49.0",
"eslint-config-standard": "17.1.0",
"eslint-plugin-import": "2.28.1",
"eslint-plugin-node": "11.1.0",
@ -35,9 +35,9 @@
}
},
"node_modules/@actions/core": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.10.0.tgz",
"integrity": "sha512-2aZDDa3zrrZbP5ZYg159sNoLRb61nQ7awl5pSvIq5Qpj81vwDzdMRKzkWJGJuwVvWpvZKx7vspJALyvaaIQyug==",
"version": "1.10.1",
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.10.1.tgz",
"integrity": "sha512-3lBR9EDAY+iYIpTnTIXmWcNbX3T2kCkAEQGIQx4NVQ0575nk2k3GRZDTPQG+vVtS2izSLmINlxXf0uLtnrTP+g==",
"dependencies": {
"@actions/http-client": "^2.0.1",
"uuid": "^8.3.2"
@ -120,18 +120,18 @@
}
},
"node_modules/@eslint/js": {
"version": "8.48.0",
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.48.0.tgz",
"integrity": "sha512-ZSjtmelB7IJfWD2Fvb7+Z+ChTIKWq6kjda95fLcQKNS5aheVHn4IkfgRQE3sIIzTcSLwLcLZUD9UBt+V7+h+Pw==",
"version": "8.49.0",
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.49.0.tgz",
"integrity": "sha512-1S8uAY/MTJqVx0SC4epBq+N2yhuwtNwLbJYNZyhL2pO1ZVKn5HFXav5T41Ryzy9K9V7ZId2JB2oy/W4aCd9/2w==",
"dev": true,
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
}
},
"node_modules/@humanwhocodes/config-array": {
"version": "0.11.10",
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz",
"integrity": "sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==",
"version": "0.11.11",
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.11.tgz",
"integrity": "sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA==",
"dev": true,
"dependencies": {
"@humanwhocodes/object-schema": "^1.2.1",
@ -1765,16 +1765,16 @@
}
},
"node_modules/eslint": {
"version": "8.48.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.48.0.tgz",
"integrity": "sha512-sb6DLeIuRXxeM1YljSe1KEx9/YYeZFQWcV8Rq9HfigmdDEugjLEVEa1ozDjL6YDjBpQHPJxJzze+alxi4T3OLg==",
"version": "8.49.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.49.0.tgz",
"integrity": "sha512-jw03ENfm6VJI0jA9U+8H5zfl5b+FvuU3YYvZRdZHOlU2ggJkxrlkJH4HcDrZpj6YwD8kuYqvQM8LyesoazrSOQ==",
"dev": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.2.0",
"@eslint-community/regexpp": "^4.6.1",
"@eslint/eslintrc": "^2.1.2",
"@eslint/js": "8.48.0",
"@humanwhocodes/config-array": "^0.11.10",
"@eslint/js": "8.49.0",
"@humanwhocodes/config-array": "^0.11.11",
"@humanwhocodes/module-importer": "^1.0.1",
"@nodelib/fs.walk": "^1.2.8",
"ajv": "^6.12.4",
@ -3550,9 +3550,9 @@
}
},
"node_modules/luxon": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/luxon/-/luxon-3.4.0.tgz",
"integrity": "sha512-7eDo4Pt7aGhoCheGFIuq4Xa2fJm4ZpmldpGhjTYBNUYNCN6TIEP6v7chwwwt3KRp7YR+rghbfvjyo3V5y9hgBw==",
"version": "3.4.3",
"resolved": "https://registry.npmjs.org/luxon/-/luxon-3.4.3.tgz",
"integrity": "sha512-tFWBiv3h7z+T/tDaoxA8rqTxy1CHV6gHS//QdaH4pulbq/JuBSGgQspQQqcgnwdAx6pNI7cmvz5Sv/addzHmUg==",
"engines": {
"node": ">=12"
}
@ -6080,9 +6080,9 @@
"dev": true
},
"@actions/core": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.10.0.tgz",
"integrity": "sha512-2aZDDa3zrrZbP5ZYg159sNoLRb61nQ7awl5pSvIq5Qpj81vwDzdMRKzkWJGJuwVvWpvZKx7vspJALyvaaIQyug==",
"version": "1.10.1",
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.10.1.tgz",
"integrity": "sha512-3lBR9EDAY+iYIpTnTIXmWcNbX3T2kCkAEQGIQx4NVQ0575nk2k3GRZDTPQG+vVtS2izSLmINlxXf0uLtnrTP+g==",
"requires": {
"@actions/http-client": "^2.0.1",
"uuid": "^8.3.2"
@ -6147,15 +6147,15 @@
}
},
"@eslint/js": {
"version": "8.48.0",
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.48.0.tgz",
"integrity": "sha512-ZSjtmelB7IJfWD2Fvb7+Z+ChTIKWq6kjda95fLcQKNS5aheVHn4IkfgRQE3sIIzTcSLwLcLZUD9UBt+V7+h+Pw==",
"version": "8.49.0",
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.49.0.tgz",
"integrity": "sha512-1S8uAY/MTJqVx0SC4epBq+N2yhuwtNwLbJYNZyhL2pO1ZVKn5HFXav5T41Ryzy9K9V7ZId2JB2oy/W4aCd9/2w==",
"dev": true
},
"@humanwhocodes/config-array": {
"version": "0.11.10",
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz",
"integrity": "sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==",
"version": "0.11.11",
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.11.tgz",
"integrity": "sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA==",
"dev": true,
"requires": {
"@humanwhocodes/object-schema": "^1.2.1",
@ -7373,16 +7373,16 @@
"dev": true
},
"eslint": {
"version": "8.48.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.48.0.tgz",
"integrity": "sha512-sb6DLeIuRXxeM1YljSe1KEx9/YYeZFQWcV8Rq9HfigmdDEugjLEVEa1ozDjL6YDjBpQHPJxJzze+alxi4T3OLg==",
"version": "8.49.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.49.0.tgz",
"integrity": "sha512-jw03ENfm6VJI0jA9U+8H5zfl5b+FvuU3YYvZRdZHOlU2ggJkxrlkJH4HcDrZpj6YwD8kuYqvQM8LyesoazrSOQ==",
"dev": true,
"requires": {
"@eslint-community/eslint-utils": "^4.2.0",
"@eslint-community/regexpp": "^4.6.1",
"@eslint/eslintrc": "^2.1.2",
"@eslint/js": "8.48.0",
"@humanwhocodes/config-array": "^0.11.10",
"@eslint/js": "8.49.0",
"@humanwhocodes/config-array": "^0.11.11",
"@humanwhocodes/module-importer": "^1.0.1",
"@nodelib/fs.walk": "^1.2.8",
"ajv": "^6.12.4",
@ -8658,9 +8658,9 @@
}
},
"luxon": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/luxon/-/luxon-3.4.0.tgz",
"integrity": "sha512-7eDo4Pt7aGhoCheGFIuq4Xa2fJm4ZpmldpGhjTYBNUYNCN6TIEP6v7chwwwt3KRp7YR+rghbfvjyo3V5y9hgBw=="
"version": "3.4.3",
"resolved": "https://registry.npmjs.org/luxon/-/luxon-3.4.3.tgz",
"integrity": "sha512-tFWBiv3h7z+T/tDaoxA8rqTxy1CHV6gHS//QdaH4pulbq/JuBSGgQspQQqcgnwdAx6pNI7cmvz5Sv/addzHmUg=="
},
"make-dir": {
"version": "3.1.0",

View file

@ -6,15 +6,15 @@
"author": "IETF Trust",
"license": "BSD-3-Clause",
"dependencies": {
"@actions/core": "1.10.0",
"@actions/core": "1.10.1",
"@actions/github": "5.1.1",
"chart.js": "3.5.1",
"chartjs-node-canvas": "4.1.6",
"lodash": "4.17.21",
"luxon": "3.4.0"
"luxon": "3.4.3"
},
"devDependencies": {
"eslint": "8.48.0",
"eslint": "8.49.0",
"eslint-config-standard": "17.1.0",
"eslint-plugin-import": "2.28.1",
"eslint-plugin-node": "11.1.0",

View file

@ -8,7 +8,7 @@ const octokit = new Octokit({
const oldestDate = DateTime.utc().minus({ days: 7 })
for (const pkgName of ['datatracker-db', 'datatracker-db-pg']) {
for (const pkgName of ['datatracker-db']) {
let hasMore = true
let currentPage = 1

View file

@ -8,10 +8,10 @@
"dependencies": {
"dockerode": "^3.3.5",
"fs-extra": "^11.1.1",
"nanoid": "4.0.2",
"nanoid": "5.0.1",
"nanoid-dictionary": "5.0.0-beta.1",
"slugify": "1.6.6",
"tar": "^6.1.15",
"tar": "^6.2.0",
"yargs": "^17.7.2"
},
"engines": {
@ -337,9 +337,9 @@
"optional": true
},
"node_modules/nanoid": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-4.0.2.tgz",
"integrity": "sha512-7ZtY5KTCNheRGfEFxnedV5zFiORN1+Y1N6zvPTnHQd8ENUvfaDBeuJDZb2bN/oXwXxu3qkTXDzy57W5vAmDTBw==",
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.1.tgz",
"integrity": "sha512-vWeVtV5Cw68aML/QaZvqN/3QQXc6fBfIieAlu05m7FZW2Dgb+3f0xc0TTxuJW+7u30t7iSDTV/j3kVI0oJqIfQ==",
"funding": [
{
"type": "github",
@ -350,7 +350,7 @@
"nanoid": "bin/nanoid.js"
},
"engines": {
"node": "^14 || ^16 || >=18"
"node": "^18 || >=20"
}
},
"node_modules/nanoid-dictionary": {
@ -483,9 +483,9 @@
}
},
"node_modules/tar": {
"version": "6.1.15",
"resolved": "https://registry.npmjs.org/tar/-/tar-6.1.15.tgz",
"integrity": "sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==",
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz",
"integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==",
"dependencies": {
"chownr": "^2.0.0",
"fs-minipass": "^2.0.0",
@ -878,9 +878,9 @@
"optional": true
},
"nanoid": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-4.0.2.tgz",
"integrity": "sha512-7ZtY5KTCNheRGfEFxnedV5zFiORN1+Y1N6zvPTnHQd8ENUvfaDBeuJDZb2bN/oXwXxu3qkTXDzy57W5vAmDTBw=="
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.1.tgz",
"integrity": "sha512-vWeVtV5Cw68aML/QaZvqN/3QQXc6fBfIieAlu05m7FZW2Dgb+3f0xc0TTxuJW+7u30t7iSDTV/j3kVI0oJqIfQ=="
},
"nanoid-dictionary": {
"version": "5.0.0-beta.1",
@ -977,9 +977,9 @@
}
},
"tar": {
"version": "6.1.15",
"resolved": "https://registry.npmjs.org/tar/-/tar-6.1.15.tgz",
"integrity": "sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==",
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz",
"integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==",
"requires": {
"chownr": "^2.0.0",
"fs-minipass": "^2.0.0",

View file

@ -4,10 +4,10 @@
"dependencies": {
"dockerode": "^3.3.5",
"fs-extra": "^11.1.1",
"nanoid": "4.0.2",
"nanoid": "5.0.1",
"nanoid-dictionary": "5.0.0-beta.1",
"slugify": "1.6.6",
"tar": "^6.1.15",
"tar": "^6.2.0",
"yargs": "^17.7.2"
},
"engines": {

View file

@ -15,9 +15,9 @@
"keypress": "^0.2.1",
"listr2": "^6.6.1",
"lodash-es": "^4.17.21",
"luxon": "^3.4.0",
"luxon": "^3.4.3",
"pretty-bytes": "^6.1.1",
"tar": "^6.1.15",
"tar": "^6.2.0",
"yargs": "^17.7.2"
},
"engines": {
@ -859,9 +859,9 @@
}
},
"node_modules/luxon": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/luxon/-/luxon-3.4.0.tgz",
"integrity": "sha512-7eDo4Pt7aGhoCheGFIuq4Xa2fJm4ZpmldpGhjTYBNUYNCN6TIEP6v7chwwwt3KRp7YR+rghbfvjyo3V5y9hgBw==",
"version": "3.4.3",
"resolved": "https://registry.npmjs.org/luxon/-/luxon-3.4.3.tgz",
"integrity": "sha512-tFWBiv3h7z+T/tDaoxA8rqTxy1CHV6gHS//QdaH4pulbq/JuBSGgQspQQqcgnwdAx6pNI7cmvz5Sv/addzHmUg==",
"engines": {
"node": ">=12"
}
@ -1193,9 +1193,9 @@
}
},
"node_modules/tar": {
"version": "6.1.15",
"resolved": "https://registry.npmjs.org/tar/-/tar-6.1.15.tgz",
"integrity": "sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==",
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz",
"integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==",
"dependencies": {
"chownr": "^2.0.0",
"fs-minipass": "^2.0.0",
@ -1950,9 +1950,9 @@
"integrity": "sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ=="
},
"luxon": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/luxon/-/luxon-3.4.0.tgz",
"integrity": "sha512-7eDo4Pt7aGhoCheGFIuq4Xa2fJm4ZpmldpGhjTYBNUYNCN6TIEP6v7chwwwt3KRp7YR+rghbfvjyo3V5y9hgBw=="
"version": "3.4.3",
"resolved": "https://registry.npmjs.org/luxon/-/luxon-3.4.3.tgz",
"integrity": "sha512-tFWBiv3h7z+T/tDaoxA8rqTxy1CHV6gHS//QdaH4pulbq/JuBSGgQspQQqcgnwdAx6pNI7cmvz5Sv/addzHmUg=="
},
"mimic-fn": {
"version": "2.1.0",
@ -2173,9 +2173,9 @@
}
},
"tar": {
"version": "6.1.15",
"resolved": "https://registry.npmjs.org/tar/-/tar-6.1.15.tgz",
"integrity": "sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==",
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz",
"integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==",
"requires": {
"chownr": "^2.0.0",
"fs-minipass": "^2.0.0",

View file

@ -11,9 +11,9 @@
"keypress": "^0.2.1",
"listr2": "^6.6.1",
"lodash-es": "^4.17.21",
"luxon": "^3.4.0",
"luxon": "^3.4.3",
"pretty-bytes": "^6.1.1",
"tar": "^6.1.15",
"tar": "^6.2.0",
"yargs": "^17.7.2"
},
"engines": {

View file

@ -1,6 +1,9 @@
import os
import scout_apm.celery
from celery import Celery
from scout_apm.api import Config
# Set the default Django settings module for the 'celery' program
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'ietf.settings')
@ -13,6 +16,25 @@ app = Celery('ietf')
# should have a `CELERY_` prefix.
app.config_from_object('django.conf:settings', namespace='CELERY')
# Turn on Scout APM celery instrumentation if configured in the environment
scout_key = os.environ.get("SCOUT_KEY", "")
scout_name = os.environ.get("SCOUT_NAME", "")
scout_core_agent_socket_path = os.environ.get("SCOUT_CORE_AGENT_SOCKET_PATH", "tcp://scoutapm:6590")
if scout_key and scout_name:
Config.set(
key=scout_key,
name=scout_name,
monitor=True,
core_agent_download=False,
core_agent_launch=False,
core_agent_path=scout_core_agent_socket_path,
)
# Note: Passing the Celery app to install() method as recommended in the
# Scout documentation causes failure at startup, likely because Scout
# ingests the config greedily before Django is ready. Have not found a
# workaround for this other than explicitly configuring Scout.
scout_apm.celery.install()
# Load task modules from all registered Django apps.
app.autodiscover_tasks()

View file

@ -750,7 +750,7 @@ Man Expires September 22, 2015 [Page 3]
stream_id=draft.stream_id, group_id=draft.group_id, abstract=draft.abstract,stream=draft.stream, rev=draft.rev,
pages=draft.pages, intended_std_level_id=draft.intended_std_level_id,
shepherd_id=draft.shepherd_id, ad_id=draft.ad_id, expires=draft.expires,
notify=draft.notify, note=draft.note)
notify=draft.notify)
rel = RelatedDocument.objects.create(source=replacement,
target=draft,
relationship_id="replaces")

View file

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# Copyright The IETF Trust 2011-2020, All Rights Reserved
# Copyright The IETF Trust 2011-2023, All Rights Reserved
import datetime
@ -837,6 +837,19 @@ class EditCharterTests(TestCase):
self.assertEqual(group.groupmilestone_set.filter(state="active", desc=m1.desc).count(), 1)
self.assertEqual(group.groupmilestone_set.filter(state="active", desc=m4.desc).count(), 1)
def test_approve_irtf(self):
charter = CharterFactory(group__type_id='rg')
url = urlreverse('ietf.doc.views_charter.approve', kwargs=dict(name=charter.name))
login_testing_unauthorized(self, "secretary", url)
empty_outbox()
r = self.client.post(url, dict())
self.assertEqual(r.status_code, 302)
self.assertEqual(len(outbox), 2)
self.assertTrue("IRTF" in outbox[1]['From'])
self.assertTrue("irtf-announce" in outbox[1]['To'])
self.assertTrue(charter.group.acronym in outbox[1]['Cc'])
self.assertTrue("RG Action" in outbox[1]['Subject'])
def test_charter_with_milestones(self):
charter = CharterFactory()

View file

@ -1,4 +1,4 @@
# Copyright The IETF Trust 2012-2020, All Rights Reserved
# Copyright The IETF Trust 2012-2023, All Rights Reserved
# -*- coding: utf-8 -*-
@ -13,8 +13,8 @@ from django.urls import reverse as urlreverse
import debug # pyflakes:ignore
from ietf.doc.factories import IndividualDraftFactory, ConflictReviewFactory
from ietf.doc.models import Document, DocEvent, NewRevisionDocEvent, BallotPositionDocEvent, TelechatDocEvent, State
from ietf.doc.factories import IndividualDraftFactory, ConflictReviewFactory, RgDraftFactory
from ietf.doc.models import Document, DocEvent, NewRevisionDocEvent, BallotPositionDocEvent, TelechatDocEvent, State, DocTagName
from ietf.doc.utils import create_ballot_if_not_open
from ietf.doc.views_conflict_review import default_approval_text
from ietf.group.models import Person
@ -168,6 +168,21 @@ class ConflictReviewTests(TestCase):
self.assertTrue(review_doc.active_ballot())
self.assertEqual(review_doc.latest_event(BallotPositionDocEvent, type="changed_ballot_position").pos_id,'yes')
# try to change to an AD-forbidden state
appr_noprob_sent_pk = str(State.objects.get(used=True, slug='appr-noprob-sent',type__slug='conflrev').pk)
r = self.client.post(url,dict(review_state=appr_noprob_sent_pk,comment='xyzzy'))
self.assertEqual(r.status_code, 200)
q = PyQuery(r.content)
self.assertTrue(q('form .invalid-feedback'))
# try again as secretariat
self.client.logout()
login_testing_unauthorized(self, 'secretary', url)
r = self.client.post(url,dict(review_state=appr_noprob_sent_pk,comment='xyzzy'))
self.assertEqual(r.status_code, 302)
review_doc = Document.objects.get(name='conflict-review-imaginary-irtf-submission')
self.assertEqual(review_doc.get_state('conflrev').slug, 'appr-noprob-sent')
def test_edit_notices(self):
doc = Document.objects.get(name='conflict-review-imaginary-irtf-submission')
@ -450,3 +465,65 @@ class ConflictReviewSubmitTests(TestCase):
def setUp(self):
super().setUp()
ConflictReviewFactory(name='conflict-review-imaginary-irtf-submission',review_of=IndividualDraftFactory(name='draft-imaginary-irtf-submission',stream_id='irtf'),notify='notifyme@example.net')
class ConflictReviewIrtfStateTests(TestCase):
def start_review(self, role, kwargs=None):
doc = RgDraftFactory()
url = urlreverse('ietf.doc.views_conflict_review.start_review', kwargs=dict(name=doc.name))
login_testing_unauthorized(self, role, url)
r = self.client.post(url, kwargs)
self.assertEqual(r.status_code, 302)
self.assertEqual(doc.get_state('draft-stream-irtf').slug, 'iesg-rev')
def test_start_review_as_secretary(self):
ad_strpk = str(Person.objects.get(name='Areað Irector').pk)
state_strpk = str(State.objects.get(used=True, slug='needshep', type__slug='conflrev').pk)
self.start_review('secretary', kwargs=dict(ad=ad_strpk, create_in_state=state_strpk))
def test_start_review_as_stream_owner(self):
self.start_review('irtf-chair')
def close_review(self, close_type, role):
doc = RgDraftFactory()
review = ConflictReviewFactory(review_of=doc)
url = urlreverse('ietf.doc.views_conflict_review.change_state', kwargs=dict(name=review.name))
login_testing_unauthorized(self, role, url)
strpk = str(State.objects.get(used=True, slug=close_type, type__slug='conflrev').pk)
r = self.client.post(url, dict(review_state=strpk))
self.assertEqual(r.status_code, 302)
self.assertEqual(doc.get_state('draft-stream-irtf').slug, 'chair-w')
self.assertIn(DocTagName.objects.get(pk='iesg-com'), doc.tags.all())
def test_close_review_reqnopub_as_secretary(self):
self.close_review('appr-reqnopub-sent', 'secretary')
def test_close_review_noprob_as_secretary(self):
self.close_review('appr-noprob-sent', 'secretary')
def test_close_review_withdraw_as_secretary(self):
self.close_review('withdraw', 'secretary')
def test_close_review_dead_as_secretary(self):
self.close_review('dead', 'secretary')
def test_close_review_withdraw_as_ad(self):
self.close_review('withdraw', 'ad')
def test_close_review_dead_as_ad(self):
self.close_review('dead', 'ad')
def test_approve_review(self):
doc = RgDraftFactory()
review = ConflictReviewFactory(review_of=doc)
review.set_state(State.objects.get(used=True, slug='appr-noprob-pend', type='conflrev'))
url = urlreverse('ietf.doc.views_conflict_review.approve_conflict_review', kwargs=dict(name=review.name))
login_testing_unauthorized(self, 'secretary', url)
r = self.client.post(url, dict(announcement_text=default_approval_text(review)))
self.assertEqual(r.status_code, 302)
self.assertEqual(doc.get_state('draft-stream-irtf').slug, 'chair-w')
self.assertIn(DocTagName.objects.get(pk='iesg-com'), doc.tags.all())

View file

@ -98,7 +98,7 @@ class ChangeStateTests(TestCase):
draft.action_holders.add(ad)
url = urlreverse('ietf.doc.views_draft.change_state', kwargs=dict(name=draft.name))
login_testing_unauthorized(self, "secretary", url)
login_testing_unauthorized(self, "ad", url)
first_state = draft.get_state("draft-iesg")
next_states = first_state.next_states.all()
@ -154,6 +154,20 @@ class ChangeStateTests(TestCase):
q = PyQuery(r.content)
self.assertEqual(len(q('form [type=submit]:contains("%s")' % first_state.name)), 1)
# try to change to an AD-forbidden state
r = self.client.post(url, dict(state=State.objects.get(used=True, type='draft-iesg', slug='ann').pk, comment='Test comment'))
self.assertEqual(r.status_code, 200)
q = PyQuery(r.content)
self.assertTrue(q('form .invalid-feedback'))
# try again as secretariat
self.client.logout()
login_testing_unauthorized(self, 'secretary', url)
r = self.client.post(url, dict(state=State.objects.get(used=True, type='draft-iesg', slug='ann').pk, comment='Test comment'))
self.assertEqual(r.status_code, 302)
draft = Document.objects.get(name=draft.name)
self.assertEqual(draft.get_state_slug('draft-iesg'), 'ann')
def test_pull_from_rfc_queue(self):
ad = Person.objects.get(user__username="ad")
draft = WgDraftFactory(
@ -362,16 +376,14 @@ class EditInfoTests(TestCase):
stream=draft.stream_id,
ad=str(new_ad.pk),
notify="test@example.com",
note="New note",
telechat_date="",
))
self.assertEqual(r.status_code, 302)
draft = Document.objects.get(name=draft.name)
self.assertEqual(draft.ad, new_ad)
self.assertEqual(draft.note, "New note")
self.assertTrue(not draft.latest_event(TelechatDocEvent, type="scheduled_for_telechat"))
self.assertEqual(draft.docevent_set.count(), events_before + 3)
self.assertEqual(draft.docevent_set.count(), events_before + 2)
self.assertEqual(len(outbox), mailbox_before + 1)
self.assertTrue(draft.name in outbox[-1]['Subject'])
@ -386,7 +398,6 @@ class EditInfoTests(TestCase):
stream=draft.stream_id,
ad=str(draft.ad_id),
notify=draft.notify,
note="",
)
# get
@ -489,7 +500,6 @@ class EditInfoTests(TestCase):
ad=ad.pk,
create_in_state=State.objects.get(used=True, type="draft-iesg", slug="watching").pk,
notify="test@example.com",
note="This is a note",
telechat_date="",
))
self.assertEqual(r.status_code, 302)
@ -497,12 +507,11 @@ class EditInfoTests(TestCase):
draft = Document.objects.get(name=draft.name)
self.assertEqual(draft.get_state_slug("draft-iesg"), "watching")
self.assertEqual(draft.ad, ad)
self.assertEqual(draft.note, "This is a note")
self.assertTrue(not draft.latest_event(TelechatDocEvent, type="scheduled_for_telechat"))
self.assertEqual(draft.docevent_set.count(), events_before + 5)
self.assertEqual(draft.docevent_set.count(), events_before + 4)
self.assertCountEqual(draft.action_holders.all(), [draft.ad])
events = list(draft.docevent_set.order_by('time', 'id'))
self.assertEqual(events[-5].type, "started_iesg_process")
self.assertEqual(events[-4].type, "started_iesg_process")
self.assertEqual(len(outbox), mailbox_before+1)
self.assertTrue('IESG processing' in outbox[-1]['Subject'])
self.assertTrue('draft-ietf-mars-test2@' in outbox[-1]['To'])
@ -518,7 +527,6 @@ class EditInfoTests(TestCase):
ad=ad.pk,
create_in_state=State.objects.get(used=True, type="draft-iesg", slug="pub-req").pk,
notify="test@example.com",
note="This is a note",
telechat_date="",
))
self.assertEqual(r.status_code, 302)
@ -1043,23 +1051,6 @@ class IndividualInfoFormsTests(TestCase):
doc = Document.objects.get(name=self.docname)
self.assertEqual(doc.latest_event(TelechatDocEvent, "scheduled_for_telechat").telechat_date,None)
def test_doc_change_iesg_note(self):
url = urlreverse('ietf.doc.views_draft.edit_iesg_note', kwargs=dict(name=self.docname))
login_testing_unauthorized(self, "secretary", url)
# get
r = self.client.get(url)
self.assertEqual(r.status_code,200)
q = PyQuery(r.content)
self.assertEqual(len(q('[type=submit]:contains("Save")')),1)
# post
r = self.client.post(url,dict(note='ZpyQFGmA\r\nZpyQFGmA'))
self.assertEqual(r.status_code,302)
doc = Document.objects.get(name=self.docname)
self.assertEqual(doc.note,'ZpyQFGmA\nZpyQFGmA')
self.assertTrue('ZpyQFGmA' in doc.latest_event(DocEvent,type='added_comment').desc)
def test_doc_change_ad(self):
url = urlreverse('ietf.doc.views_draft.edit_ad', kwargs=dict(name=self.docname))
login_testing_unauthorized(self, "secretary", url)

View file

@ -1,4 +1,4 @@
# Copyright The IETF Trust 2016-2020, All Rights Reserved
# Copyright The IETF Trust 2016-2023, All Rights Reserved
# -*- coding: utf-8 -*-
@ -363,6 +363,23 @@ class ReviewTests(TestCase):
request_events = review_req.reviewrequestdocevent_set.all()
self.assertEqual(request_events.count(), 0)
def test_assign_reviewer_after_reject(self):
doc = WgDraftFactory()
review_team = ReviewTeamFactory()
rev_role = RoleFactory(group=review_team,person__user__username='reviewer',person__user__email='reviewer@example.com',name_id='reviewer')
reviewer_email = Email.objects.get(person__user__username="reviewer")
RoleFactory(group=review_team,person__user__username='reviewsecretary',name_id='secr')
review_req = ReviewRequestFactory(team=review_team,doc=doc)
ReviewAssignmentFactory(review_request=review_req, state_id='rejected', reviewer=rev_role.person.email_set.first())
url = urlreverse('ietf.doc.views_review.assign_reviewer', kwargs={ "name": doc.name, "request_id": review_req.pk })
login_testing_unauthorized(self, "reviewsecretary", url)
r = self.client.get(url)
self.assertEqual(r.status_code, 200)
q = PyQuery(r.content)
reviewer_label = q("option[value=\"{}\"]".format(reviewer_email.address)).text().lower()
self.assertIn("rejected review of document before", reviewer_label)
def test_previously_reviewed_replaced_doc(self):
review_team = ReviewTeamFactory(acronym="reviewteam", name="Review Team", type_id="review", list_email="reviewteam@ietf.org", parent=Group.objects.get(acronym="farfut"))
rev_role = RoleFactory(group=review_team,person__user__username='reviewer',person__user__email='reviewer@example.com',person__name='Some Reviewer',name_id='reviewer')
@ -577,6 +594,29 @@ class ReviewTests(TestCase):
self.assertContains(r, '<button type="submit"')
def test_accept_reviewer_assignment_after_reject(self):
doc = WgDraftFactory()
review_team = ReviewTeamFactory()
rev_role = RoleFactory(group=review_team,name_id='reviewer')
review_req = ReviewRequestFactory(doc=doc,team=review_team)
assignment = ReviewAssignmentFactory(review_request=review_req, state_id='rejected', reviewer=rev_role.person.email_set.first())
url = urlreverse('ietf.doc.views_review.review_request', kwargs={ "name": doc.name, "request_id": review_req.pk })
username = assignment.reviewer.person.user.username
self.client.login(username=username, password=username + "+password")
r = self.client.get(url)
self.assertEqual(r.status_code, 200)
q = PyQuery(r.content)
d = q('.reviewer-assignment-not-accepted')
self.assertTrue(d("[name=action][value=accept]"))
# accept
r = self.client.post(url, { "action": "accept" })
self.assertEqual(r.status_code, 302)
assignment = reload_db_objects(assignment)
self.assertEqual(assignment.state_id, "accepted")
def make_test_mbox_tarball(self, review_req):
mbox_path = os.path.join(self.review_dir, "testmbox.tar.gz")
with tarfile.open(mbox_path, "w:gz") as tar:

View file

@ -252,6 +252,7 @@ This test section has some text.
statement.latest_event(NewRevisionDocEvent).rev, "00"
)
self.assertIsNotNone(statement.latest_event(type="published_statement"))
self.assertIsNotNone(statement.history_set.last().latest_event(type="published_statement"))
if postdict["statement_submission"] == "enter":
self.assertEqual(statement.text_or_error(), "some stuff")
else:

View file

@ -148,6 +148,21 @@ class StatusChangeTests(TestCase):
self.assertTrue(doc.active_ballot())
self.assertEqual(doc.latest_event(BallotPositionDocEvent, type="changed_ballot_position").pos_id,'yes')
# try to change to an AD-forbidden state
appr_sent_pk = str(State.objects.get(used=True, slug='appr-sent',type__slug='statchg').pk)
r = self.client.post(url, dict(new_state=appr_sent_pk, comment='xyzzy'))
self.assertEqual(r.status_code, 200)
q = PyQuery(r.content)
self.assertTrue(q('form .invalid-feedback'))
# try again as secretariat
self.client.logout()
login_testing_unauthorized(self, 'secretary', url)
r = self.client.post(url, dict(new_state=appr_sent_pk, comment='xyzzy'))
self.assertEqual(r.status_code, 302)
doc = Document.objects.get(name='status-change-imaginary-mid-review')
self.assertEqual(doc.get_state('statchg').slug, 'appr-sent')
def test_edit_notices(self):
doc = Document.objects.get(name='status-change-imaginary-mid-review')
url = urlreverse('ietf.doc.views_doc.edit_notify;status-change',kwargs=dict(name=doc.name))

View file

@ -136,7 +136,6 @@ urlpatterns = [
url(r'^%(name)s/edit/suggested-replaces/$' % settings.URL_REGEXPS, views_draft.review_possibly_replaces),
url(r'^%(name)s/edit/status/$' % settings.URL_REGEXPS, views_draft.change_intention),
url(r'^%(name)s/edit/telechat/$' % settings.URL_REGEXPS, views_doc.telechat_date),
url(r'^%(name)s/edit/iesgnote/$' % settings.URL_REGEXPS, views_draft.edit_iesg_note),
url(r'^%(name)s/edit/ad/$' % settings.URL_REGEXPS, views_draft.edit_ad),
url(r'^%(name)s/edit/authors/$' % settings.URL_REGEXPS, views_doc.edit_authors),
url(r'^%(name)s/edit/consensus/$' % settings.URL_REGEXPS, views_draft.edit_consensus),

View file

@ -1,4 +1,4 @@
# Copyright The IETF Trust 2012-2020, All Rights Reserved
# Copyright The IETF Trust 2012-2023, All Rights Reserved
# -*- coding: utf-8 -*-
@ -25,6 +25,7 @@ from ietf.doc.forms import AdForm
from ietf.group.models import Role, Group
from ietf.iesg.models import TelechatDate
from ietf.ietfauth.utils import has_role, role_required, is_authorized_in_doc_stream
from ietf.name.models import DocTagName
from ietf.person.models import Person
from ietf.utils import log
from ietf.utils.mail import send_mail_preformatted
@ -35,6 +36,12 @@ class ChangeStateForm(forms.Form):
review_state = forms.ModelChoiceField(State.objects.filter(used=True, type="conflrev"), label="Conflict review state", empty_label=None, required=True)
comment = forms.CharField(widget=forms.Textarea, help_text="Optional comment for the review history.", required=False, strip=False)
def __init__(self, *args, **kwargs):
user = kwargs.pop("user")
super(ChangeStateForm, self).__init__(*args, **kwargs)
if not has_role(user, "Secretariat"):
self.fields["review_state"].queryset = self.fields["review_state"].queryset.exclude(slug__in=("appr-reqnopub-sent","appr-noprob-sent"))
@role_required("Area Director", "Secretariat")
def change_state(request, name, option=None):
"""Change state of an IESG review for IETF conflicts in other stream's documents, notifying parties as necessary
@ -44,7 +51,7 @@ def change_state(request, name, option=None):
login = request.user.person
if request.method == 'POST':
form = ChangeStateForm(request.POST)
form = ChangeStateForm(request.POST, user=request.user)
if form.is_valid():
clean = form.cleaned_data
new_state = clean['review_state']
@ -90,12 +97,16 @@ def change_state(request, name, option=None):
review,
ok_to_publish)
if new_state.slug in ["appr-reqnopub-sent", "appr-noprob-sent", "withdraw", "dead"]:
doc = review.related_that_doc("conflrev")[0].document
if doc.stream_id == "irtf":
close_review_irtf_state(doc, login)
return redirect('ietf.doc.views_doc.document_main', name=review.name)
else:
s = review.get_state()
init = dict(review_state=s.pk if s else None)
form = ChangeStateForm(initial=init)
form = ChangeStateForm(initial=init, user=request.user)
return render(request, 'doc/change_state.html',
dict(form=form,
@ -355,6 +366,10 @@ def approve_conflict_review(request, name):
c.desc = "The following approval message was sent\n"+form.cleaned_data['announcement_text']
c.save()
doc = review.related_that_doc("conflrev")[0].document
if doc.stream_id == "irtf":
close_review_irtf_state(doc, login)
return HttpResponseRedirect(review.get_absolute_url())
else:
@ -485,6 +500,9 @@ def start_review_as_secretariat(request, name):
send_conflict_review_started_email(request, conflict_review)
if doc_to_review.stream_id == 'irtf':
start_review_irtf_state(doc_to_review, login)
return HttpResponseRedirect(conflict_review.get_absolute_url())
else:
notify_addresses = build_notify_addresses(doc_to_review)
@ -519,6 +537,9 @@ def start_review_as_stream_owner(request, name):
send_conflict_review_started_email(request, conflict_review)
if doc_to_review.stream_id == 'irtf':
start_review_irtf_state(doc_to_review, login)
return HttpResponseRedirect(conflict_review.get_absolute_url())
else:
notify_addresses = build_notify_addresses(doc_to_review)
@ -533,3 +554,26 @@ def start_review_as_stream_owner(request, name):
'doc_to_review': doc_to_review,
},
)
def start_review_irtf_state(doc, by):
prev_state = doc.get_state('draft-stream-irtf')
new_state = State.objects.get(type_id='draft-stream-irtf', slug='iesg-rev')
if new_state != prev_state:
doc.set_state(new_state)
events = []
events.append(add_state_change_event(doc, by, prev_state, new_state))
doc.save_with_history(events)
def close_review_irtf_state(doc, by):
prev_state = doc.get_state("draft-stream-irtf")
new_state = State.objects.get(type_id="draft-stream-irtf", slug="chair-w")
prev_tags = set(doc.tags.all())
new_tags = set(DocTagName.objects.filter(pk="iesg-com"))
if new_state != prev_state:
doc.set_state(new_state)
doc.tags.clear()
doc.tags.set(new_tags)
events = [add_state_change_event(doc, by, prev_state, new_state, prev_tags, new_tags)]
doc.save_with_history(events)

View file

@ -1,4 +1,4 @@
# Copyright The IETF Trust 2010-2020, All Rights Reserved
# Copyright The IETF Trust 2010-2023, All Rights Reserved
# -*- coding: utf-8 -*-
@ -61,6 +61,12 @@ class ChangeStateForm(forms.Form):
substate = forms.ModelChoiceField(DocTagName.objects.filter(slug__in=IESG_SUBSTATE_TAGS), required=False)
comment = forms.CharField(widget=forms.Textarea, required=False, strip=False)
def __init__(self, *args, **kwargs):
user = kwargs.pop("user")
super(ChangeStateForm, self).__init__(*args, **kwargs)
if not has_role(user, "Secretariat"):
self.fields["state"].queryset = self.fields["state"].queryset.exclude(slug="ann")
def clean(self):
retclean = self.cleaned_data
state = self.cleaned_data.get('state', '(None)')
@ -94,7 +100,7 @@ def change_state(request, name):
login = request.user.person
if request.method == 'POST':
form = ChangeStateForm(request.POST)
form = ChangeStateForm(request.POST, user=request.user)
form.docname=name
if form.is_valid():
@ -175,7 +181,8 @@ def change_state(request, name):
state = doc.get_state("draft-iesg")
t = doc.tags.filter(slug__in=IESG_SUBSTATE_TAGS)
form = ChangeStateForm(initial=dict(state=state.pk if state else None,
substate=t[0].pk if t else None))
substate=t[0].pk if t else None),
user=request.user)
form.docname=name
state = doc.get_state("draft-iesg")
@ -491,7 +498,6 @@ class EditInfoForm(forms.Form):
help_text="Separate email addresses with commas.",
required=False,
)
note = forms.CharField(widget=forms.Textarea, label="IESG note", required=False, strip=False)
telechat_date = forms.TypedChoiceField(coerce=lambda x: datetime.datetime.strptime(x, '%Y-%m-%d').date(), empty_value=None, required=False, widget=forms.Select(attrs={'onchange':'make_bold()'}))
returning_item = forms.BooleanField(required=False)
@ -515,9 +521,6 @@ class EditInfoForm(forms.Form):
# returning item is rendered non-standard
self.standard_fields = [x for x in self.visible_fields() if x.name not in ('returning_item',)]
def clean_note(self):
return self.cleaned_data['note'].replace('\r', '').strip()
def to_iesg(request,name):
""" Submit an IETF stream document to the IESG for publication """
doc = get_object_or_404(Document, name=name, stream='ietf')
@ -715,18 +718,6 @@ def edit_info(request, name):
diff('ad', "Responsible AD")
diff('notify', "State Change Notice email list")
if r['note'] != doc.note:
if not r['note']:
if doc.note:
changes.append("Note field has been cleared")
else:
if doc.note:
changes.append("Note changed to '%s'" % r['note'])
else:
changes.append("Note added '%s'" % r['note'])
doc.note = r['note']
if doc.group.type_id in ("individ", "area"):
if not r["area"]:
r["area"] = Group.objects.get(type="individ")
@ -769,7 +760,6 @@ def edit_info(request, name):
area=doc.group_id,
ad=doc.ad_id,
notify=doc.notify,
note=doc.note,
telechat_date=initial_telechat_date,
returning_item=initial_returning_item,
)
@ -862,52 +852,6 @@ def restore_draft_file(request, draft):
log.log(" Exception %s when attempting to move %s" % (ex, file))
class IESGNoteForm(forms.Form):
note = forms.CharField(widget=forms.Textarea, label="IESG note", required=False, strip=False)
def clean_note(self):
# not munging the database content to use html line breaks --
# that has caused a lot of pain in the past.
return self.cleaned_data['note'].replace('\r', '').strip()
@role_required("Area Director", "Secretariat")
def edit_iesg_note(request, name):
doc = get_object_or_404(Document, type="draft", name=name)
login = request.user.person
initial = dict(note=doc.note)
if request.method == "POST":
form = IESGNoteForm(request.POST, initial=initial)
if form.is_valid():
new_note = form.cleaned_data['note']
if new_note != doc.note:
if not new_note:
if doc.note:
log_message = "Note field has been cleared"
else:
if doc.note:
log_message = "Note changed to '%s'" % new_note
else:
log_message = "Note added '%s'" % new_note
c = DocEvent(type="added_comment", doc=doc, rev=doc.rev, by=login)
c.desc = log_message
c.save()
doc.note = new_note
doc.save_with_history([c])
return redirect('ietf.doc.views_doc.document_main', name=doc.name)
else:
form = IESGNoteForm(initial=initial)
return render(request, 'doc/draft/edit_iesg_note.html',
dict(doc=doc,
form=form,
))
class ShepherdWriteupUploadForm(forms.Form):
content = forms.CharField(widget=forms.Textarea, label="Shepherd writeup", help_text="Edit the shepherd writeup.", required=False, strip=False)
txt = forms.FileField(label=".txt format", help_text="Or upload a .txt file.", required=False)

View file

@ -223,7 +223,7 @@ def review_request(request, name, request_id):
for assignment in assignments:
assignment.is_reviewer = user_is_person(request.user, assignment.reviewer.person)
assignment.can_accept_reviewer_assignment = (assignment.state_id == "assigned"
assignment.can_accept_reviewer_assignment = (assignment.state_id in ["assigned", "rejected"]
and (assignment.is_reviewer or can_manage_request))
assignment.can_reject_reviewer_assignment = (assignment.state_id in ["assigned", "accepted"]

View file

@ -239,6 +239,7 @@ def new_statement(request):
rev=statement.rev,
by=request.user.person,
desc="Statement published",
time=statement.time,
)
statement.save_with_history([e1, e2])
markdown_content = ""

View file

@ -42,6 +42,12 @@ class ChangeStateForm(forms.Form):
new_state = forms.ModelChoiceField(State.objects.filter(type="statchg", used=True), label="Status Change Evaluation State", empty_label=None, required=True)
comment = forms.CharField(widget=forms.Textarea, help_text="Optional comment for the review history.", required=False, strip=False)
def __init__(self, *args, **kwargs):
user = kwargs.pop("user")
super(ChangeStateForm, self).__init__(*args, **kwargs)
if not has_role(user, "Secretariat"):
self.fields["new_state"].queryset = self.fields["new_state"].queryset.exclude(slug="appr-sent")
@role_required("Area Director", "Secretariat")
def change_state(request, name, option=None):
@ -52,7 +58,7 @@ def change_state(request, name, option=None):
login = request.user.person
if request.method == 'POST':
form = ChangeStateForm(request.POST)
form = ChangeStateForm(request.POST, user=request.user)
if form.is_valid():
clean = form.cleaned_data
new_state = clean['new_state']
@ -116,7 +122,7 @@ def change_state(request, name, option=None):
type='statchg',
label='Status Change Evaluation State',
)
form = ChangeStateForm(initial=init)
form = ChangeStateForm(initial=init, user=request.user)
return render(request, 'doc/change_state.html',
dict(form=form,

View file

@ -27,7 +27,7 @@ class GroupFactory(factory.django.DjangoModelFactory):
django_get_or_create = ('acronym',)
skip_postgeneration_save = True
name = factory.Faker('sentence',nb_words=6)
name = factory.Faker('text', max_nb_chars=80)
acronym = factory.Sequence(lambda n: 'acronym%d' %n)
state_id = 'active'
type_id = 'wg'

View file

@ -1,4 +1,4 @@
# Copyright The IETF Trust 2016-2020, All Rights Reserved
# Copyright The IETF Trust 2016-2023, All Rights Reserved
# -*- coding: utf-8 -*-
@ -711,6 +711,22 @@ class ReviewTests(TestCase):
self.assertEqual(settings.max_items_to_show_in_reviewer_list, 10)
self.assertEqual(settings.days_to_show_in_reviewer_list, 365)
def test_assign_reviewer_after_reject(self):
team = ReviewTeamFactory()
reviewer = RoleFactory(name_id='reviewer', group=team).person
ReviewerSettingsFactory(person=reviewer, team=team)
review_req = ReviewRequestFactory(team=team)
ReviewAssignmentFactory(review_request=review_req, state_id='rejected', reviewer=reviewer.email())
unassigned_url = urlreverse(ietf.group.views.manage_review_requests, kwargs={ 'acronym': team.acronym, 'group_type': team.type_id, "assignment_status": "unassigned" })
login_testing_unauthorized(self, "secretary", unassigned_url)
r = self.client.get(unassigned_url)
self.assertEqual(r.status_code, 200)
q = PyQuery(r.content)
reviewer_label = q("option[value=\"{}\"]".format(reviewer.email())).text().lower()
self.assertIn("rejected review of document before", reviewer_label)
class BulkAssignmentTests(TestCase):

View file

@ -142,8 +142,6 @@ def agenda_json(request, date=None):
'ad':doc.ad.name if doc.ad else None,
}
if doc.note:
docinfo['note'] = doc.note
defer = doc.active_defer_event()
if defer:
docinfo['defer-by'] = defer.by.name

View file

@ -109,7 +109,9 @@ class DraftForm(forms.ModelForm):
cleaned_data = super().clean()
revisions = cleaned_data.get("revisions")
document = cleaned_data.get("document")
if not document.name.startswith("rfc"):
if not document:
self.add_error("document", "Identifying the Internet-Draft or RFC for this disclosure is required.")
elif not document.name.startswith("rfc"):
if revisions.strip() == "":
self.add_error("revisions", "Revisions of this Internet-Draft for which this disclosure is relevant must be specified.")
return cleaned_data

View file

@ -1,7 +1,7 @@
import factory
from ietf.group.factories import GroupFactory
from ietf.liaisons.models import LiaisonStatement, LiaisonStatementEvent, LiaisonStatementAttachment
from ietf.liaisons.models import LiaisonStatement, LiaisonStatementEvent, LiaisonStatementAttachment, RelatedLiaisonStatement
class LiaisonStatementFactory(factory.django.DjangoModelFactory):
class Meta:
@ -50,3 +50,12 @@ class LiaisonStatementAttachmentFactory(factory.django.DjangoModelFactory):
type_id='liai-att',
# TODO: Make name more convenient (the default now is to try to generate a draftname)
)
class RelatedLiaisonStatementFactory(factory.django.DjangoModelFactory):
class Meta:
model = RelatedLiaisonStatement
source = factory.SubFactory(LiaisonStatementFactory)
target = factory.SubFactory(LiaisonStatementFactory)
relationship_id = "refunk"

View file

@ -518,8 +518,7 @@ class EditLiaisonForm(LiaisonModelForm):
super(EditLiaisonForm, self).__init__(*args, **kwargs)
self.edit = True
self.fields['attachments'].initial = self.instance.liaisonstatementattachment_set.exclude(removed=True)
related = [ str(x.pk) for x in self.instance.source_of_set.all() ]
self.fields['related_to'].initial = ','.join(related)
self.fields['related_to'].initial = [ x.target for x in self.instance.source_of_set.all() ]
self.fields['submitted_date'].initial = self.instance.submitted
def save(self, *args, **kwargs):

View file

@ -24,7 +24,7 @@ from ietf.utils.mail import outbox
from ietf.group.factories import GroupFactory, RoleFactory
from ietf.liaisons.factories import ( LiaisonStatementFactory,
LiaisonStatementEventFactory, LiaisonStatementAttachmentFactory, )
LiaisonStatementEventFactory, LiaisonStatementAttachmentFactory, RelatedLiaisonStatementFactory)
from ietf.liaisons.models import (LiaisonStatement, LiaisonStatementPurposeName,
LiaisonStatementAttachment)
from ietf.person.models import Person
@ -393,6 +393,8 @@ class LiaisonManagementTests(TestCase):
LiaisonStatementEventFactory(statement=liaison,type_id='posted')
from_group = liaison.from_groups.first()
to_group = liaison.to_groups.first()
rel1 = RelatedLiaisonStatementFactory(source=liaison)
rel2 = RelatedLiaisonStatementFactory(source=liaison)
url = urlreverse('ietf.liaisons.views.liaison_edit', kwargs=dict(object_id=liaison.pk))
login_testing_unauthorized(self, "secretary", url)
@ -402,6 +404,13 @@ class LiaisonManagementTests(TestCase):
self.assertEqual(r.status_code, 200)
q = PyQuery(r.content)
self.assertEqual(len(q('form input[name=from_contact]')), 1)
json_data = q('form select[name=related_to]').attr('data-pre')
try:
decoded = json.loads(json_data)
except json.JSONDecodeError as e:
self.fail('data-pre contained invalid JSON data: %s' % str(e))
decoded_ids = [item['id'] for item in decoded]
self.assertEqual(decoded_ids, [rel1.target.id, rel2.target.id])
# edit
attachments_before = liaison.attachments.count()

View file

@ -0,0 +1,26 @@
# Copyright The IETF Trust 2023, All Rights Reserved
from django.db import migrations
def forward(apps, schema_editor):
MailTrigger = apps.get_model("mailtrigger", "MailTrigger")
Recipient = apps.get_model("mailtrigger", "Recipient")
mt = MailTrigger.objects.get(pk="ballot_approved_charter")
mt.to.remove(mt.to.first())
mt.to.add(Recipient.objects.get(slug="group_stream_announce"))
def reverse(apps, schema_editor):
MailTrigger = apps.get_model("mailtrigger", "MailTrigger")
Recipient = apps.get_model("mailtrigger", "Recipient")
mt = MailTrigger.objects.get(pk="ballot_approved_charter")
mt.to.remove(mt.to.first())
mt.to.add(Recipient.objects.get(slug="ietf_announce"))
class Migration(migrations.Migration):
dependencies = [
("mailtrigger", "0002_slidesubmitter"),
]
operations = [
migrations.RunPython(forward, reverse)
]

View file

@ -3811,7 +3811,7 @@
],
"desc": "Recipients when a charter is approved",
"to": [
"ietf_announce"
"group_stream_announce"
]
},
"model": "mailtrigger.mailtrigger",

View file

@ -1327,6 +1327,36 @@ class InactiveNomcomTests(TestCase):
q = PyQuery(response.content)
self.assertIn('not active', q('.alert-warning').text() )
def test_filter_nominees(self):
url = reverse(
"ietf.nomcom.views.private_index", kwargs={"year": self.nc.year()}
)
login_testing_unauthorized(self, self.chair.user.username, url)
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
states = list(NomineePositionStateName.objects.values_list("slug", flat=True))
states += ["not-declined", "questionnaire"]
for state in states:
response = self.client.get(url, {"state": state})
self.assertEqual(response.status_code, 200)
q = PyQuery(response.content)
nps = []
if state == "not-declined":
nps = NomineePosition.objects.exclude(state__slug="declined")
elif state == "questionnaire":
nps = [
np
for np in NomineePosition.objects.not_duplicated()
if np.questionnaires
]
else:
nps = NomineePosition.objects.filter(state__slug=state)
# nomination state is in third table column
self.assertEqual(
len(nps), len(q("#nominee-position-table td:nth-child(3)"))
)
def test_email_pasting_closed(self):
url = reverse('ietf.nomcom.views.private_feedback_email', kwargs={'year':self.nc.year()})
login_testing_unauthorized(self, self.chair.user.username, url)
@ -2389,6 +2419,7 @@ class rfc8713EligibilityTests(TestCase):
self.eligible_people = list()
self.ineligible_people = list()
# Section 4.14 qualification criteria
for combo_len in range(0,6):
for combo in combinations(meetings,combo_len):
p = PersonFactory()
@ -2399,6 +2430,18 @@ class rfc8713EligibilityTests(TestCase):
else:
self.eligible_people.append(p)
# Section 4.15 disqualification criteria
def ineligible_person_with_role(**kwargs):
p = RoleFactory(**kwargs).person
for m in meetings:
MeetingRegistrationFactory(person=p, meeting=m, attended=True)
self.ineligible_people.append(p)
for group in ['isocbot', 'ietf-trust', 'llc-board', 'iab']:
for role in ['member', 'chair']:
ineligible_person_with_role(group__acronym=group, name_id=role)
ineligible_person_with_role(group__type_id='area', group__state_id='active',name_id='ad')
ineligible_person_with_role(group=self.nomcom.group, name_id='chair')
# No-one is eligible for the other_nomcom
self.other_nomcom = NomComFactory(group__acronym='nomcom2018',first_call_for_volunteers=datetime.date(2018,5,1))

View file

@ -22,8 +22,8 @@ urlpatterns = [
url(r'^(?P<year>\d{4})/private/view-feedback/nominee/(?P<nominee_id>\d+)$', views.view_feedback_nominee),
url(r'^(?P<year>\d{4})/private/view-feedback/topic/(?P<topic_id>\d+)$', views.view_feedback_topic),
url(r'^(?P<year>\d{4})/private/edit/nominee/(?P<nominee_id>\d+)$', views.edit_nominee),
url(r'^(?P<year>\d{4})/private/merge-nominee/?$', views.private_merge_nominee),
url(r'^(?P<year>\d{4})/private/merge-person/?$', views.private_merge_person),
url(r'^(?P<year>\d{4})/private/merge-nominee/$', views.private_merge_nominee),
url(r'^(?P<year>\d{4})/private/merge-person/$', views.private_merge_person),
url(r'^(?P<year>\d{4})/private/send-reminder-mail/(?P<type>\w+)/$', views.send_reminder_mail),
url(r'^(?P<year>\d{4})/private/extract-email-lists/$', views.extract_email_lists),
url(r'^(?P<year>\d{4})/private/edit-members/$', views.edit_members),

View file

@ -1,4 +1,4 @@
# Copyright The IETF Trust 2012-2022, All Rights Reserved
# Copyright The IETF Trust 2012-2023, All Rights Reserved
# -*- coding: utf-8 -*-
@ -66,8 +66,11 @@ DEFAULT_NOMCOM_TEMPLATES = [HOME_TEMPLATE,
]
# See RFC8713 section 4.15
# This potentially over-disqualifies past nomcom chairs if some
# nomcom 2+ nomcoms ago is still in the active state
DISQUALIFYING_ROLE_QUERY_EXPRESSION = ( Q(group__acronym__in=['isocbot', 'ietf-trust', 'llc-board', 'iab'], name_id__in=['member', 'chair'])
| Q(group__type_id='area', group__state='active',name_id='ad')
| Q(group__type_id='nomcom', group__state='active', name_id='chair')
)

View file

@ -77,7 +77,6 @@ def year_index(request, year):
return render(request, 'nomcom/year_index.html',
{'nomcom': nomcom,
'year': year,
'selected': 'index',
'template': template})
def announcements(request):
@ -182,8 +181,7 @@ def private_key(request, year):
{'nomcom': nomcom,
'year': year,
'back_url': back_url,
'form': form,
'selected': 'private_key'})
'form': form})
@role_required("Nomcom")
@ -216,10 +214,11 @@ def private_index(request, year):
filters = {}
questionnaire_state = "questionnaire"
not_declined_state = "not-declined"
selected_state = request.GET.get('state')
selected_position = request.GET.get('position')
if selected_state and not selected_state == questionnaire_state:
if selected_state and selected_state not in [questionnaire_state, not_declined_state]:
filters['state__slug'] = selected_state
if selected_position:
@ -231,13 +230,15 @@ def private_index(request, year):
if selected_state == questionnaire_state:
nominee_positions = [np for np in nominee_positions if np.questionnaires]
elif selected_state == not_declined_state:
nominee_positions = nominee_positions.exclude(state__slug='declined')
positions = Position.objects.get_by_nomcom(nomcom=nomcom)
stats = [ { 'position__name':p.name,
'position__id':p.pk,
'position': p,
} for p in positions]
states = [{'slug': questionnaire_state, 'name': 'Accepted and sent Questionnaire'}] + list(NomineePositionStateName.objects.values('slug', 'name'))
states = [{'slug': questionnaire_state, 'name': 'Accepted and sent Questionnaire'}, {'slug': not_declined_state, 'name': 'Not declined'}] + list(NomineePositionStateName.objects.values('slug', 'name'))
positions = set([ n.position for n in all_nominee_positions.order_by('position__name') ])
for s in stats:
for state in states:
@ -280,7 +281,6 @@ def private_index(request, year):
'positions': positions,
'selected_state': selected_state,
'selected_position': selected_position and int(selected_position) or None,
'selected': 'index',
'is_chair': is_chair,
'mailto': mailto,
})
@ -305,13 +305,11 @@ def send_reminder_mail(request, year, type):
interesting_state = 'pending'
mail_path = nomcom_template_path + NOMINEE_ACCEPT_REMINDER_TEMPLATE
reminder_description = 'accept (or decline) a nomination'
selected_tab = 'send_accept_reminder'
state_description = NomineePositionStateName.objects.get(slug=interesting_state).name
elif type=='questionnaire':
interesting_state = 'accepted'
mail_path = nomcom_template_path + NOMINEE_QUESTIONNAIRE_REMINDER_TEMPLATE
reminder_description = 'complete the questionnaire for a nominated position'
selected_tab = 'send_questionnaire_reminder'
state_description = NomineePositionStateName.objects.get(slug=interesting_state).name+' but no questionnaire has been received'
else:
raise Http404
@ -346,7 +344,6 @@ def send_reminder_mail(request, year, type):
'year': year,
'nominees': annotated_nominees,
'mail_template': mail_template,
'selected': selected_tab,
'reminder_description': reminder_description,
'state_description': state_description,
'is_chair_task' : True,
@ -373,7 +370,6 @@ def private_merge_person(request, year):
{'nomcom': nomcom,
'year': year,
'form': form,
'selected': 'merge_person',
'is_chair_task' : True,
})
@ -398,7 +394,6 @@ def private_merge_nominee(request, year):
{'nomcom': nomcom,
'year': year,
'form': form,
'selected': 'merge_nominee',
'is_chair_task' : True,
})
@ -408,8 +403,7 @@ def requirements(request, year):
return render(request, 'nomcom/requirements.html',
{'nomcom': nomcom,
'positions': positions,
'year': year,
'selected': 'requirements'})
'year': year})
def questionnaires(request, year):
@ -418,8 +412,7 @@ def questionnaires(request, year):
return render(request, 'nomcom/questionnaires.html',
{'nomcom': nomcom,
'positions': positions,
'year': year,
'selected': 'questionnaires'})
'year': year})
@login_required
@ -453,15 +446,13 @@ def nominate(request, year, public, newperson):
messages.warning(request, "This Nomcom is not yet accepting nominations")
return render(request, template,
{'nomcom': nomcom,
'year': year,
'selected': 'nominate'})
'year': year})
if nomcom.group.state_id == 'conclude':
messages.warning(request, "Nominations to this Nomcom are closed.")
return render(request, template,
{'nomcom': nomcom,
'year': year,
'selected': 'nominate'})
'year': year})
if request.method == 'POST':
if newperson:
@ -485,8 +476,7 @@ def nominate(request, year, public, newperson):
{'form': form,
'nomcom': nomcom,
'year': year,
'positions': nomcom.position_set.filter(is_open=True),
'selected': 'nominate'})
'positions': nomcom.position_set.filter(is_open=True)})
@login_required
def public_feedback(request, year):
@ -550,7 +540,6 @@ def feedback(request, year, public):
return render(request, 'nomcom/feedback.html', {
'nomcom': nomcom,
'year': year,
'selected': 'feedback',
'counts' : counts,
'base_template': base_template
})
@ -561,7 +550,6 @@ def feedback(request, year, public):
'form': None,
'nomcom': nomcom,
'year': year,
'selected': 'feedback',
'positions': positions,
'topics': topics,
'counts' : counts,
@ -575,7 +563,6 @@ def feedback(request, year, public):
'form': None,
'nomcom': nomcom,
'year': year,
'selected': 'feedback',
'positions': positions,
'topics': topics,
'counts' : counts,
@ -622,7 +609,6 @@ def feedback(request, year, public):
'year': year,
'positions': positions,
'topics': topics,
'selected': 'feedback',
'counts': counts,
'topic_counts': topic_counts,
'base_template': base_template
@ -648,7 +634,6 @@ def private_feedback_email(request, year):
return render(request, template,
{'nomcom': nomcom,
'year': year,
'selected': 'feedback_email',
'is_chair_task' : True,
})
@ -668,8 +653,7 @@ def private_feedback_email(request, year):
return render(request, template,
{'form': form,
'nomcom': nomcom,
'year': year,
'selected': 'feedback_email'})
'year': year})
@role_required("Nomcom Chair", "Nomcom Advisor")
def private_questionnaire(request, year):
@ -691,7 +675,6 @@ def private_questionnaire(request, year):
return render(request, template,
{'nomcom': nomcom,
'year': year,
'selected': 'questionnaire',
'is_chair_task' : True,
})
@ -710,8 +693,7 @@ def private_questionnaire(request, year):
{'form': form,
'questionnaire_response': questionnaire_response,
'nomcom': nomcom,
'year': year,
'selected': 'questionnaire'})
'year': year})
def process_nomination_status(request, year, nominee_position_id, state, date, hash):
@ -765,7 +747,6 @@ def process_nomination_status(request, year, nominee_position_id, state, date, h
'nominee_position': nominee_position,
'state': state,
'need_confirmation': need_confirmation,
'selected': 'feedback',
'form': form })
@role_required("Nomcom")
@ -830,7 +811,6 @@ def view_feedback(request, year):
return render(request, 'nomcom/view_feedback.html',
{'year': year,
'selected': 'view_feedback',
'nominees': nominees,
'nominee_feedback_types': nominee_feedback_types,
'independent_feedback_types': independent_feedback_types,
@ -927,7 +907,6 @@ def view_feedback_pending(request, year):
form.set_nomcom(nomcom, request.user)
return render(request, 'nomcom/view_feedback_pending.html',
{'year': year,
'selected': 'feedback_pending',
'formset': formset,
'extra_step': extra_step,
'extra_ids': extra_ids,
@ -1090,7 +1069,6 @@ def edit_nominee(request, year, nominee_id):
return render(request, 'nomcom/edit_nominee.html',
{'year': year,
'selected': 'index',
'nominee': nominee,
'form': form,
'nomcom': nomcom,
@ -1128,7 +1106,6 @@ def edit_nomcom(request, year):
'formset': formset,
'nomcom': nomcom,
'year': year,
'selected': 'edit_nomcom',
'is_chair_task' : True,
})
@ -1142,7 +1119,6 @@ def list_templates(request, year):
return render(request, 'nomcom/list_templates.html',
{'template_list': template_list,
'year': year,
'selected': 'edit_templates',
'nomcom': nomcom,
'is_chair_task' : True,
})
@ -1215,7 +1191,6 @@ def list_positions(request, year):
return render(request, 'nomcom/list_positions.html',
{'positions': positions,
'year': year,
'selected': 'edit_positions',
'nomcom': nomcom,
'is_chair_task' : True,
})
@ -1282,7 +1257,6 @@ def list_topics(request, year):
return render(request, 'nomcom/list_topics.html',
{'topics': topics,
'year': year,
'selected': 'edit_topics',
'nomcom': nomcom,
'is_chair_task' : True,
})
@ -1364,8 +1338,7 @@ def edit_members(request, year):
return render(request, 'nomcom/new_edit_members.html',
{'nomcom' : nomcom,
'year' : year,
'form': form,
})
'form': form})
@role_required("Nomcom Chair", "Nomcom Advisor")
def extract_email_lists(request, year):
@ -1385,8 +1358,7 @@ def extract_email_lists(request, year):
'pending': pending,
'accepted': accepted,
'noresp': noresp,
'bypos': bypos,
})
'bypos': bypos})
@login_required
def volunteer(request):

View file

@ -1,4 +1,4 @@
# Copyright The IETF Trust 2019-2021, All Rights Reserved
# Copyright The IETF Trust 2019-2023, All Rights Reserved
import re
@ -10,6 +10,7 @@ from simple_history.utils import bulk_update_with_history
from ietf.doc.models import DocumentAuthor
from ietf.doc.utils import extract_complete_replaces_ancestor_mapping_for_docs
from ietf.group.models import Role
from ietf.name.models import ReviewAssignmentStateName
from ietf.person.models import Person
import debug # pyflakes:ignore
from ietf.review.models import NextReviewerInTeam, ReviewerSettings, ReviewWish, ReviewRequest, \
@ -55,8 +56,6 @@ def persons_with_previous_review(team, review_req, possible_person_ids, state_id
reviewassignment__state=state_id,
team=team,
).distinct()
if review_req.pk is not None:
has_reviewed_previous = has_reviewed_previous.exclude(pk=review_req.pk)
has_reviewed_previous = set(
has_reviewed_previous.values_list("reviewassignment__reviewer__person", flat=True))
return has_reviewed_previous
@ -70,7 +69,14 @@ class AbstractReviewerQueuePolicy:
"""Assign a reviewer to a request and update policy state accordingly"""
# Update policy state first - needed by LRU policy to correctly compute whether assignment was in-order
self.update_policy_state_for_assignment(review_req, reviewer.person, add_skip)
return review_req.reviewassignment_set.create(state_id='assigned', reviewer=reviewer, assigned_on=timezone.now())
assignment = review_req.reviewassignment_set.filter(reviewer=reviewer).first()
if assignment:
assignment.state = ReviewAssignmentStateName.objects.get(slug='assigned', used=True)
assignment.assigned_on = timezone.now()
assignment.save()
return assignment
else:
return review_req.reviewassignment_set.create(state_id='assigned', reviewer=reviewer, assigned_on=timezone.now())
def default_reviewer_rotation_list(self, include_unavailable=False):
""" Return a list of reviewers (Person objects) in the default reviewer rotation for a policy.
@ -168,15 +174,15 @@ class AbstractReviewerQueuePolicy:
PersonEmailChoiceField(label="Assign Reviewer", empty_label="(None)")
"""
# Collect a set of person IDs for people who have either not responded
# to or outright rejected reviewing this document in the past
# Collect a set of person IDs for people who have not responded
# to this document in the past
rejecting_reviewer_ids = review_req.doc.reviewrequest_set.filter(
reviewassignment__state__slug__in=('rejected', 'no-response')
reviewassignment__state__slug='no-response'
).values_list(
'reviewassignment__reviewer__person_id', flat=True
)
# Query the Email objects for reviewers who haven't rejected or
# Query the Email objects for reviewers who haven't
# not responded to this document in the past
field.queryset = field.queryset.filter(
role__name="reviewer",

View file

@ -1,4 +1,4 @@
# Copyright The IETF Trust 2016-2021, All Rights Reserved
# Copyright The IETF Trust 2016-2023, All Rights Reserved
import debug # pyflakes:ignore
import datetime
@ -471,9 +471,6 @@ class _Wrapper(TestCase):
addresses = list( map( lambda choice: choice[0], field.choices ) )
self.assertNotIn(
str(rejected_reviewer.email()), addresses,
"Reviews should not suggest people who have rejected this request in the past")
self.assertNotIn(
str(no_response_reviewer.email()), addresses,
"Reviews should not suggest people who have not responded to this request in the past.")

View file

@ -390,8 +390,10 @@ def assign_review_request_to_reviewer(request, review_req, reviewer, add_skip=Fa
log.assertion('reviewer is not None')
# cannot reference reviewassignment_set relation until pk exists
if review_req.pk is not None and review_req.reviewassignment_set.filter(reviewer=reviewer).exists():
return
if review_req.pk is not None:
reviewassignment_set = review_req.reviewassignment_set.filter(reviewer=reviewer)
if reviewassignment_set.exists() and not reviewassignment_set.filter(state_id='rejected').exists():
return
# Note that assigning a review no longer unassigns other reviews

View file

@ -165,7 +165,8 @@ class SessionRequestTestCase(TestCase):
self.assertContains(r, 'Schedule the sessions on subsequent days')
self.assertContains(r, 'Thursday early afternoon, Thursday late afternoon')
self.assertContains(r, group2.acronym)
self.assertContains(r, 'Second session with: {} {}'.format(group3.acronym, group4.acronym))
# The sessions can be in any order in the HTML, deal with that
self.assertRegex(r.content.decode(), r'Second session with: ({} {}|{} {})'.format(group3.acronym, group4.acronym, group4.acronym, group3.acronym))
# check that a notification was sent
self.assertEqual(len(outbox), 1)

View file

@ -57,7 +57,7 @@ $(document)
var text = $(this)
.text();
// insert some <wbr> at strategic places
var newtext = text.replace(/([@._])/g, "$1<wbr>");
var newtext = text.replace(/([@._+])/g, "$1<wbr>");
if (newtext === text) {
return;
}

View file

@ -1,16 +1,21 @@
import * as List from "list.js";
var dummy = new List();
import {
default as List
} from "list.js";
function text_sort(a, b, options) {
function prep(e, options) {
return $($.parseHTML(e.values()[options.valueName]))
.text()
.trim()
.replaceAll(/\s+/g, ' ');
}
// sort by text content
return dummy.utils.naturalSort.caseInsensitive($($.parseHTML(a.values()[options.valueName]))
.text()
.trim()
.replaceAll(/\s+/g, ' '), $($.parseHTML(b.values()[options.valueName]))
.text()
.trim()
.replaceAll(/\s+/g, ' '));
return prep(a, options).localeCompare(prep(b, options), "en", {
sensitivity: "base",
ignorePunctuation: true
});
}
function replace_with_internal(table, internal_table, i) {
@ -204,12 +209,12 @@ $(document)
}
let newlist = new List(hook, pagination ? {
valueNames: fields,
pagination: pagination,
page: items_per_page
} : {
valueNames: fields
});
valueNames: fields,
pagination: pagination,
page: items_per_page
} : {
valueNames: fields
});
// override search module with a patched version
// see https://github.com/javve/list.js/issues/699
// TODO: check if this is still needed if list.js ever sees an update
@ -220,7 +225,7 @@ $(document)
if (enable_search) {
reset_search.on("click", function () {
search_field.val("");
$.each(list_instance, (i, e) => {
$.each(list_instance, (_, e) => {
e.search();
});
});
@ -229,7 +234,7 @@ $(document)
if (event.key == "Escape") {
reset_search.trigger("click");
} else {
$.each(list_instance, (i, e) => {
$.each(list_instance, (_, e) => {
e.search($(this)
.val());
});
@ -242,16 +247,19 @@ $(document)
.on("click", function () {
var order = $(this)
.hasClass("asc") ? "desc" : "asc";
$.each(list_instance, (i, e) => {
$.each(list_instance, (_, e) => {
e.sort($(this)
.attr("data-sort"), { order: order, sortFunction: text_sort });
.attr("data-sort"), {
order: order,
sortFunction: text_sort
});
});
});
$.each(list_instance, (i, e) => {
e.on("sortComplete", function () {
replace_with_internal(table, internal_table, i);
$(table).find("[data-bs-original-title]").tooltip();
$(table).find("[data-bs-original-title]").tooltip();
if (i == list_instance.length - 1) {
$(table)
.find("thead:first tr")
@ -267,6 +275,9 @@ $(document)
});
}
});
e.on("searchComplete", function () {
replace_with_internal(table, internal_table, i);
});
});
$(table.addClass("tablesorter-done"));
@ -284,8 +295,11 @@ $(document)
if (presort_col) {
const order = presort_col.attr("data-default-sort");
if (order === "asc" || order === "desc") {
$.each(list_instance, (i, e) => {
e.sort(presort_col.attr("data-sort"), { order: order, sortFunction: text_sort });
$.each(list_instance, (_, e) => {
e.sort(presort_col.attr("data-sort"), {
order: order,
sortFunction: text_sort
});
});
}
}

View file

@ -207,11 +207,12 @@ const interimRequest = (function() {
toggleLocation: function () {
if (this.checked) {
$(".location")
$(".location input, .location select")
.prop('disabled', false);
} else {
$(".location")
.prop('disabled', true);
$(".location input, .location select")
.prop('disabled', true)
.val('');
}
},

View file

@ -34,7 +34,7 @@ function filter_calendar_events(filter_params, event_list) {
}
// format a moment in a tz
var moment_formats = { time: 'HH:mm', date: 'YYYY-MM-DD', datetime: 'YYYY-MM-DD HH:mm' };
var moment_formats = { time: 'HH:mm', date: 'YYYY-MM-DD', datetime: 'YYYY-MM-DD HH:mm' , timezone: 'z'};
function format_moment(t_moment, tz, fmt_type) {
return t_moment.tz(tz)
@ -43,6 +43,9 @@ function format_moment(t_moment, tz, fmt_type) {
function make_display_events(event_data, tz) {
var calendarEl = document.getElementById('calendar');
if (!calendarEl) {
return;
}
var glue = calendarEl.clientWidth > 720 ? ' ' : '\n';
return $.map(event_data, function (src_event) {
var title;
@ -83,6 +86,9 @@ function update_calendar(tz, filter_params) {
* filtered events.
*/
var calendarEl = document.getElementById('calendar');
if (!calendarEl) {
return;
}
event_calendar = new FullCalendar(calendarEl, {
plugins: [dayGridPlugin, bootstrap5Plugin],
initialView: 'dayGridMonth',
@ -136,7 +142,7 @@ function format_session_time(session_elt, tz) {
.attr('data-start-utc'));
var end = moment.utc($(session_elt)
.attr('data-end-utc'));
return format_moment(start, tz, 'datetime') + '-' + format_moment(end, tz, 'time');
return format_moment(start, tz, 'datetime') + '-' + format_moment(end, tz, 'time') + ' ' + format_moment(start, tz, 'timezone');
}
function format_meeting_time(meeting_elt, tz) {

View file

@ -355,7 +355,6 @@ class SubmitTests(BaseSubmitTestCase):
ad=draft.ad,
expires=timezone.now() + datetime.timedelta(days=settings.INTERNET_DRAFT_DAYS_TO_EXPIRE),
notify="aliens@example.mars",
note="",
)
sug_replaced_draft.set_state(State.objects.get(used=True, type="draft", slug="active"))
@ -1401,7 +1400,6 @@ class SubmitTests(BaseSubmitTestCase):
"submitter-name": "Some Random Test Person",
"submitter-email": "random@example.com",
"replaces": [str(draft.pk)],
"edit-note": "no comments",
"authors-0-name": "Person 1",
"authors-0-email": "person1@example.com",
"authors-1-name": "Person 2",
@ -1417,7 +1415,6 @@ class SubmitTests(BaseSubmitTestCase):
self.assertEqual(submission.document_date, document_date)
self.assertEqual(submission.abstract, "some abstract")
self.assertEqual(submission.pages, 123)
self.assertEqual(submission.note, "no comments")
self.assertEqual(submission.submitter, "Some Random Test Person <random@example.com>")
self.assertEqual(submission.replaces, draft.name)
self.assertEqual(submission.state_id, "manual")

View file

@ -14,7 +14,7 @@
{% csrf_token %}
{% bootstrap_form ballot_writeup_form %}
<div class="form-text my-3">
Technical summary, Working Group summary, document quality, personnel, IRTF note, IESG note, IANA note. This text will be appended to all announcements and messages to the IRTF or RFC Editor.
Technical summary, Working Group summary, document quality, personnel, IANA note. This text will be appended to all announcements and messages to the IRTF or RFC Editor.
{% if ballot_issue_danger %}
<p class="text-danger">
This document has not completed IETF Last Call. Please do not issue the ballot early without good reason.

View file

@ -1,4 +1,4 @@
{% load ietf_filters %}{% autoescape off %}From: The IESG <iesg-secretary@ietf.org>
{% load ietf_filters %}{% autoescape off %}From: {% if group.type_id == "rg" %}The IRTF <irtf-chair@irtf.org>{% else %}The IESG <iesg-secretary@ietf.org>{% endif %}
To: {{ to }}{% if cc %}
Cc: {{ cc }} {% endif %}
Subject: {{ group.type.name }} Action: {{ action_type }} {{ group.name }} ({{ group.acronym }})

View file

@ -36,14 +36,6 @@ RFC Editor Note
(Insert RFC Editor Note here or remove section)
IRTF Note
(Insert IRTF Note here or remove section)
IESG Note
(Insert IESG Note here or remove section)
IANA Note
(Insert IANA Note here or remove section)

View file

@ -13,7 +13,7 @@
<form class="mt-3" method="post">
{% csrf_token %}
{% bootstrap_form ballot_writeup_form %}
<div class="form-text mb-3">Working group summary, personnel, IAB note, IESG note, IANA note.</div>
<div class="form-text mb-3">Working group summary, personnel, IANA note.</div>
<button type="submit"
class="btn btn-primary"
name="save_ballot_writeup"

View file

@ -408,32 +408,19 @@
{% endif %}
</td>
</tr>
{% if iesg_state.slug != 'idexists' %}
{% if doc.note or can_edit %}
<tr>
<td></td>
<th scope="row">
IESG note
</th>
<td class="edit">
{% if can_edit and not snapshot %}
<a class="btn btn-primary btn-sm"
href="{% url 'ietf.doc.views_draft.edit_iesg_note' name=doc.name %}">
Edit
</a>
{% endif %}
</td>
<td>
{% if doc.note %}
{{ doc.note|linebreaksbr }}
{% else %}
<span class="text-body-secondary">
(None)
</span>
{% endif %}
</td>
</tr>
{% endif %}
{% if iesg_state.slug != 'idexists' and doc.note %}
<tr>
<td></td>
<th scope="row">
IESG note
</th>
<td class="edit">
{# IESG Notes are historic and read-only now #}
</td>
<td>
{{ doc.notedoc.note|urlize_ietf_docs|linkify|linebreaksbr }}
</td>
</tr>
{% endif %}
<tr>
<td></td>

View file

@ -2,7 +2,7 @@
{# Copyright The IETF Trust 2015, All Rights Reserved #}
{% load origin %}
{% load static %}
{% load ietf_filters textfilters %}
{% load ietf_filters textfilters tz %}
{% block title %}{{ doc.title|default:"Untitled" }}{% endblock %}
{% block content %}
{% origin %}
@ -29,6 +29,24 @@
{% if snapshot %}<span class="badge rounded-pill text-bg-warning">Snapshot</span>{% endif %}
</td>
</tr>
{% if doc.meeting_related %}
<tr>
<th scope="row">
Date and time
</th>
<td></td>
<td>
{% with session=doc.get_related_session %}
{% with timeslot=session.official_timeslotassignment.timeslot %}
{% if session.meeting %}
<span class="session-time date me-3" data-start-utc="{{ timeslot.time|utc|date:'Y-m-d H:i' }}" data-end-utc="{{ timeslot.end_time|utc|date:'Y-m-d H:i' }}"></span>
{% include "meeting/tz-display.html" with meeting_timezone=session.meeting.time_zone id_suffix="" minimal=True only %}
{% endif %}
{% endwith %}
{% endwith %}
</td>
</tr>
{% endif %}
<tr>
<th scope="row">Title</th>
<td class="edit">
@ -97,7 +115,21 @@
{% if presentations %}
{% for pres in presentations %}
{{ pres.session.short_name }} at {{ pres.session.meeting }}
{% if pres.rev != doc.rev %}(version -{{ pres.rev }}){% endif %}{% if not forloop.last %},{% endif %}
{% if pres.rev != doc.rev %}(version -{{ pres.rev }}){% endif %}
<br>
<b>Remote instructions:</b>
{% if pres.session.agenda_note|first_url|conference_url %}
<a href="{{ pres.session.agenda_note|first_url }}" title="Online conference">
<i class="bi bi-beople"></i>
</a>
{% elif pres.session.remote_instructions|first_url|conference_url %}
<a href="{{ pres.session.remote_instructions|first_url }}"
title="Online conference">
<i class="bi bi-people"></i>
</a>
{% endif %}
{{ pres.session.remote_instructions|linkify }}
{% if not forloop.last %}<br>{% endif %}
{% endfor %}
{% else %}
<span class="text-body-secondary">(None)</span>
@ -142,4 +174,16 @@
{% block js %}
<script src="{% static 'ietf/js/d3.js' %}"></script>
<script src="{% static 'ietf/js/document_timeline.js' %}"></script>
{% if doc.meeting_related %}
<script src="{% static 'ietf/js/moment.js' %}"></script>
<script src="{% static 'ietf/js/upcoming.js' %}"></script>
<script src="{% static 'ietf/js/timezone.js' %}"></script>
<script>
$(function () {
// Init with best guess at local timezone.
ietf_timezone.set_tz_change_callback(timezone_changed);
ietf_timezone.initialize('local');
});
</script>
{% endif %}
{% endblock %}

View file

@ -1,19 +0,0 @@
{% extends "base.html" %}
{# Copyright The IETF Trust 2015, All Rights Reserved #}
{% load origin %}
{% load django_bootstrap5 %}
{% block title %}Edit IESG note for {{ doc.name }}{% endblock %}
{% block content %}
{% origin %}
<h1>
Edit IESG note
<br>
<small class="text-body-secondary">{{ doc.name }}</small>
</h1>
<form class="mt-3" method="post">
{% csrf_token %}
{% bootstrap_form form %}
<button type="submit" class="btn btn-primary">Save</button>
<a class="btn btn-secondary float-end" href="{{ doc.get_absolute_url }}">Back</a>
</form>
{% endblock %}

View file

@ -33,13 +33,6 @@ Personnel
Who is the Document Shepherd for this document? Who is the
Responsible Area Director?
{% endif %}
{% if doc.stream.slug == "irtf" %}IRTF Note
(Insert IRTF Note here or remove section)
{% elif doc.stream.slug == "ietf" %}IESG Note
(Insert IESG Note here or remove section)
{% endif %}
IANA Note
{% if iana %}
{% filter wordwrap:"76"|indent:2 %}{{ iana }}{% endfilter %}

View file

@ -177,6 +177,8 @@
<div class="reviewer-assignment-not-accepted">
{% if assignment.state_id == "assigned" %}
Assignment not accepted yet
{% elif assignment.state_id == "rejected" %}
<span class="text-danger">Assignment rejected</span>
{% else %}
<span class="text-success">Assignment accepted</span>
{% endif %}

View file

@ -26,7 +26,7 @@
{% for state in states %}
<tr id="{{ state.slug|default:"idexists" }}">
<th scope="row">{{ state.name }}</th>
<td>{{ state.desc|urlize_ietf_docs|linkify }}</td>
<td>{{ state.desc|safe|urlize_ietf_docs|linkify }}</td>
{% if has_next_states %}
<td>
{% for s in state.next_states.all %}

View file

@ -8,7 +8,8 @@
<h1>{{ group_type | upper }} {{ role }} photos</h1>
{% regroup roles|dictsort:"last_initial" by last_initial as alphabet_blocks %}
{% for letter in alphabet_blocks %}
<h2 class="mt-4" {% if letter.grouper|slugify %}id="{{ letter.grouper|slugify }}"{% endif %}>{{ letter.grouper }}</h2>
<!-- [html-validate-disable-next valid-id -- Unicode IDs are OK in HTML5] -->
<h2 class="mt-4" {% if letter.grouper|slugify %}id="{{ letter.grouper }}"{% endif %}>{{ letter.grouper }}</h2>
{% regroup letter.list by person as person_groups %}
{# keep in sync with group_photos.html #}
<div class="mt-0 row row-cols-2 row-cols-sm-2 row-cols-md-3 row-cols-lg-4 row-cols-xl-4 row-cols-xxl-5 g-2">

View file

@ -1,7 +1,6 @@
{% load origin tz %}
{% origin %}
{% for s in sessions %}
{% timezone s.meeting.time_zone %}
<tr>
<td>
{% if s.meeting.type.slug == 'ietf' %}
@ -12,9 +11,11 @@
</td>
<td>
{% if s.current_status == "sched" %}
{{ s.time|date:"Y-m-d" }}
{% with timeslot=s.official_timeslotassignment.timeslot %}
<span class="session-time date me-3" data-start-utc="{{ timeslot.time|utc|date:'Y-m-d H:i' }}" data-end-utc="{{ timeslot.end_time|utc|date:'Y-m-d H:i' }}"></span>
{% endwith %}
{% else %}
<i>{{ s.current_status_name }}</i>
<div class="badge rounded-pill text-bg-secondary">{{ s.current_status_name }}</div>
{% endif %}
{% if show_request and s.meeting.type_id == 'ietf' %}
{% if can_edit %}
@ -28,9 +29,6 @@
<td>
{% if s.name %}{{ s.name }}{% endif %}
</td>
<td>
{% if s.current_status == "sched" %}{{ s.time|date:"D" }}{% endif %}
</td>
<td>
{% if show_ical and s.current_status == "sched" %}
{% if s.meeting.type_id == 'ietf' %}
@ -78,5 +76,4 @@
{% endif %}
</td>
</tr>
{% endtimezone %}
{% endfor %}

View file

@ -1,6 +1,5 @@
{% extends "group/group_base.html" %}
{# Copyright The IETF Trust 2015-2022, All Rights Reserved #}
{% load origin %}
{% load origin static %}
{% block title %}
Meetings
{% if group %}for {{ group.acronym }}{% endif %}
@ -19,15 +18,15 @@
{% endblock %}
{% block group_content %}
{% origin %}
{% include "meeting/tz-display.html" with meeting_timezone=None id_suffix="" minimal=False only %}
{% if in_progress %}
<h2 class="mt-3" id="inprogressmeets">Meetings in progress</h2>
<h2 class="mt-5" id="inprogressmeets">Meetings in progress</h2>
{% with sessions=in_progress show_request=True show_ical=True can_edit_materials=can_edit %}
<table class="table table-sm table-striped tablesorter">
<thead>
<tr>
<th scope="col" data-sort="meeting">Meeting</th>
<th scope="col" data-sort="date">Date</th>
<th scope="col"></th>
<th class="col-3" scope="col" data-sort="meeting">Meeting</th>
<th class="col-3" scope="col" data-sort="date">Date</th>
<th scope="col"></th>
<th scope="col">Materials</th>
</tr>
@ -39,7 +38,7 @@
{% endwith %}
{% endif %}
{% if future %}
<h2 class="mt-3" id="futuremeets">
<h2 class="mt-5" id="futuremeets">
Future Meetings
<a class="float-end"
aria-label="icalendar entry for all scheduled future {{ group.acronym }} meetings"
@ -51,9 +50,8 @@
<table class="table table-sm table-striped tablesorter">
<thead>
<tr>
<th scope="col" data-sort="meeting">Meeting</th>
<th scope="col" data-sort="date">Date</th>
<th scope="col"></th>
<th class="col-3" scope="col" data-sort="meeting">Meeting</th>
<th class="col-3" scope="col" data-sort="date">Date</th>
<th scope="col"></th>
<th scope="col">Materials</th>
</tr>
@ -66,13 +64,12 @@
</table>
{% endif %}
{% if past or recent %}
<h2 class="mt-3" id="pastmeets">Past Meetings (within the last four years)</h2>
<h2 class="mt-5" id="pastmeets">Past Meetings (within the last four years)</h2>
<table class="table table-sm table-striped tablesorter">
<thead>
<tr>
<th scope="col" data-sort="meeting">Meeting</th>
<th scope="col" data-sort="date">Date</th>
<th scope="col"></th>
<th class="col-3" scope="col" data-sort="meeting">Meeting</th>
<th class="col-3" scope="col" data-sort="date">Date</th>
<th scope="col"></th>
<th scope="col">Materials</th>
</tr>
@ -100,13 +97,12 @@
older_sessions value, this block will need to be adjusted.
{% endcomment %}
{% if far_past %}
<h2 class="mt-3" id="farpastmeets">Meetings more than four years ago</h2>
<h2 class="mt-5" id="farpastmeets">Meetings more than four years ago</h2>
<table class="table table-sm table-striped tablesorter">
<thead>
<tr>
<th scope="col" data-sort="meeting">Meeting</th>
<th scope="col" data-sort="date">Date</th>
<th scope="col"></th>
<th class="col-3" scope="col" data-sort="meeting">Meeting</th>
<th class="col-3" scope="col" data-sort="date">Date</th>
<th scope="col"></th>
<th scope="col">Materials</th>
</tr>
@ -160,3 +156,16 @@
{% endif %}
{% endif %}
{% endblock %}
{% block js %}
<script src="{% static 'ietf/js/list.js' %}"></script>
<script src="{% static 'ietf/js/moment.js' %}"></script>
<script src="{% static 'ietf/js/upcoming.js' %}"></script>
<script src="{% static 'ietf/js/timezone.js' %}"></script>
<script>
$(function () {
// Init with best guess at local timezone.
ietf_timezone.set_tz_change_callback(timezone_changed);
ietf_timezone.initialize('local');
});
</script>
{% endblock %}

View file

@ -1,7 +1,7 @@
{# Copyright The IETF Trust 2015, All Rights Reserved #}
{% load origin %}
{% origin %}
{% load ietf_filters ballot_icon person_filters %}
{% load ietf_filters ballot_icon person_filters textfilters %}
<div class="card mb-3">
<div class="position-absolute top-0 end-0 m-3">{% ballot_icon doc %}</div>
<div class="card-body">
@ -27,7 +27,7 @@
{% if conflictdoc.note %}
<div class="row">
<div class="col-3 text-end fw-bold">Note</div>
<div class="col">{{ conflictdoc.note|linebreaksbr }}</div>
<div class="col">{{ conflictdoc.note|urlize_ietf_docs|linkify|linebreaksbr }}</div>
</div>
{% endif %}
<div class="row">

View file

@ -3,6 +3,5 @@
{% filter wordwrap:"68"|indent|indent %}{{ doc.title }}{% endfilter %}
{{ conflictdoc.name }}-{{ conflictdoc.rev }}
{% filter wordwrap:"66"|indent:"4" %}{{ conflictdoc.title }} ({{ conflictdoc.stream }}: {{ conflictdoc.intended_std_level }}){% endfilter %}
{% if conflictdoc.note %}{# note: note is not escaped #} {% filter wordwrap:"64"|indent:"6" %}Note: {{ conflictdoc.note|striptags }}{% endfilter %}
{% endif %} Token: {{ doc.ad }}
Token: {{ doc.ad }}
{% with doc.active_defer_event as defer %}{% if defer %} Was deferred by {{defer.by}} on {{defer.time|date:"Y-m-d"}}{% endif %}{% endwith %}{% endwith %}

View file

@ -1,8 +1,7 @@
{% load ietf_filters %}{% with doc.rfc_number as rfc_number %}
o {{doc.name}}{% if not rfc_number %}-{{doc.rev}}{% endif %}{% endwith %}{%if doc.has_rfc_editor_note %} (Has RFC Editor Note){% endif %}{% if doc.stream %} - {{ doc.stream }} stream{% endif %}
{% filter wordwrap:"68"|indent|indent %}{{ doc.title }} ({{ doc.intended_std_level }}){% endfilter %}
{% if doc.note %}{# note: note is not escaped #} {% filter wordwrap:"68"|indent|indent %}Note: {{ doc.note|striptags }}{% endfilter %}
{% endif %} Token: {{ doc.ad }}{% if doc.iana_review_state %}
Token: {{ doc.ad }}{% if doc.iana_review_state %}
IANA Review: {{ doc.iana_review_state }}{% endif %}{% if doc.consensus %}
Consensus: {{ doc.consensus }}{% endif %}{% if doc.lastcall_expires %}
Last call expires: {{ doc.lastcall_expires|date:"Y-m-d" }}{% endif %}{% if doc.review_assignments %}

View file

@ -93,7 +93,7 @@ Parts Copyright (c) 2009 The IETF Trust, all rights reserved.
<p>If APPROVED with caveats - The Secretariat will send a working
group submission, Protocol Action Announcement that includes the
[RFC Editor Note, IESG Note, etc.] to be drafted by [Name that
[RFC Editor Note, etc.] to be drafted by [Name that
AD].</p>
{% endif %}
@ -103,7 +103,7 @@ Parts Copyright (c) 2009 The IETF Trust, all rights reserved.
<p>If APPROVED with caveats - The Secretariat will send an
individual submission, Protocol Action Announcement that includes
the [RFC Editor Note, IESG Note, etc.] to be drafted by [Name that
the [RFC Editor Note, etc.] to be drafted by [Name that
AD].</p>
{% endif %}
@ -113,7 +113,7 @@ Parts Copyright (c) 2009 The IETF Trust, all rights reserved.
<p>If APPROVED with caveats - The Secretariat will send the
associated status change Protocol Action Announcements that includes the
[RFC Editor Note, IESG Note, etc.] to be drafted by [Name that
[RFC Editor Note, etc.] to be drafted by [Name that
AD].</p>
{% endif %}
@ -123,7 +123,7 @@ Parts Copyright (c) 2009 The IETF Trust, all rights reserved.
<p>If APPROVED with caveats - The Secretariat will send a working
group submission Document Action announcement that includes the [RFC
Ed. Note, IESG, note, etc.] from [Name that AD].</p>
Ed. Note, etc.] from [Name that AD].</p>
{% endif %}
{% if num|startswith:"3.2.1" or num|startswith:"3.2.2" %}
@ -132,7 +132,7 @@ Parts Copyright (c) 2009 The IETF Trust, all rights reserved.
<p>If APPROVED with caveats - The Secretariat will send an
individual submission Document Action announcement that includes the
[RFC Ed. Note, IESG, note, etc.] from [Name that AD].</p>
[RFC Ed. Note, etc.] from [Name that AD].</p>
{% endif %}
{% if num|startswith:"3.3.1" or num|startswith:"3.3.2" %}
@ -141,13 +141,12 @@ Parts Copyright (c) 2009 The IETF Trust, all rights reserved.
<p>If APPROVED with caveats - The Secretariat will send the associated
status change Document Action announcements that includes the [RFC
Ed. Note, IESG, note, etc.] from [Name that AD].</p>
Ed. Note, etc.] from [Name that AD].</p>
{% endif %}
{% if num|startswith:"3.4.1" or num|startswith:"3.4.2" %}
<p>If APPROVED - The Secretariat will send a standard no problem
message to the RFC Editor. [Name of AD] will you supply the text for
the IESG Note?</p>
message to the RFC Editor.</p>
<p>If APPROVED with caveats - The Secretariat will send a standard
no problem message to the RFC Editor that includes the note drafted

View file

@ -24,8 +24,8 @@
</div>
{% endif %}
{% bootstrap_field form.meeting_type layout='horizontal' %}
{% bootstrap_field form.city layout='horizontal' %}
{% bootstrap_field form.country layout='horizontal' %}
{% bootstrap_field form.city layout='horizontal' wrapper_class='location mb-3' %}
{% bootstrap_field form.country layout='horizontal' wrapper_class='location mb-3' %}
{% bootstrap_field form.time_zone layout='horizontal' %}
{{ formset.management_form }}
{% if formset.non_form_errors %}<div class="my-3 alert alert-danger">{{ formset.non_form_errors }}</div>{% endif %}

View file

@ -25,7 +25,7 @@
</div>
<div class="row mb-3">
<label for="{{ form.subject.id_for_label }}" class="col-md-2 fw-bold col-form-label">Subject</label>
<div class="col-md-10">{% render_field form.subject class="form-control" readonly="readonly" %}</div>
<div class="col-md-10">{% render_field form.subject class="form-control" %}</div>
</div>
<div class="row mb-3">
<label for="{{ form.body.id_for_label }}" class="col-md-2 fw-bold col-form-label">Body</label>

View file

@ -57,6 +57,17 @@
{% endif %}
{% endblock %}
{% block js %}
<script src="{% static 'ietf/js/list.js' %}"></script>
<script src="{% static 'ietf/js/moment.js' %}"></script>
<script src="{% static 'ietf/js/upcoming.js' %}"></script>
<script src="{% static 'ietf/js/timezone.js' %}"></script>
<script>
$(function () {
// Init with best guess at local timezone.
ietf_timezone.set_tz_change_callback(timezone_changed);
ietf_timezone.initialize('local');
});
</script>
{% if can_manage_materials %}
<script src="{% static 'ietf/js/sortable.js' %}"></script>
<script>

View file

@ -17,8 +17,8 @@
{% if sessions|length > 1 %}Session {{ forloop.counter }} :{% endif %}
{% for time in session.times %}
{% if not forloop.first %},{% endif %}
{{ time|timezone:session.meeting.time_zone|dateformat:"l Y-m-d H:i T" }}
{% if time.tzinfo.zone != "UTC" %}<span class="small">({{ time|utc|dateformat:"H:i T" }})</span>{% endif %}
<span class="session-time date me-3" data-start-utc="{{ timeslot.time|utc|date:'Y-m-d H:i' }}" data-end-utc="{{ timeslot.end_time|utc|date:'Y-m-d H:i' }}"></span>
{% include "meeting/tz-display.html" with meeting_timezone=session.meeting.time_zone id_suffix=session.pk minimal=True only %}
{% endfor %}
{% if session.cancelled %}
<small class="badge rounded-pill text-bg-warning">Cancelled</small>

View file

@ -12,8 +12,8 @@ As long as id_suffix is different, should allow for as many copies of the widget
{% load origin %}
{% origin %}
{% firstof id_suffix "" as suffix %}
<div class="tz-display flex-fill {% if minimal %}btn-group btn-group-sm my-2{% else %}input-group my-3{% endif %} flex-wrap">
{% if not minimal %}<label class="input-group-text border-primary bg-white fw-bold">Time zone:</label>{% endif %}
<span class="tz-display flex-fill {% if minimal %}btn-group btn-group-sm my-2{% else %}input-group my-3{% endif %} flex-wrap">
{% if not minimal %}<label class="input-group-text border-primary bg-transparent fw-bold">Time zone:</label>{% endif %}
{% if meeting_timezone is not None %}
<input type="radio"
name="tzradio{{ suffix }}"
@ -46,4 +46,4 @@ As long as id_suffix is different, should allow for as many copies of the widget
</option>
</select>
{% endif %}
</div>
</span>

View file

@ -4,9 +4,6 @@
{% load django_bootstrap5 textfilters person_filters %}
{% load static %}
{% block subtitle %}- Eligible People{% endblock %}
{% block pagehead %}
<link rel="stylesheet" href="{% static "ietf/css/list.css" %}">
{% endblock %}
{% block nomcom_content %}
{% origin %}
<h2>Eligible People for {{ nomcom.group }}</h2>
@ -42,6 +39,3 @@
</table>
}
{% endblock %}
{% block js %}
<script src="{% static "ietf/js/list.js" %}"></script>
{% endblock %}

View file

@ -24,23 +24,24 @@
<thead>
<tr>
{% if nomcom.group.state_id == 'active' %}
<th scope="colgroup" colspan="3">
<i class="bi bi-check"></i>
<th scope="col">
</th>
<th scope="col"></th>
{% endif %}
<th scope="col" data-sort="position">
Position
</th>
<th scope="col" data-sort="iesg">
<th class="text-center" scope="col" data-sort="iesg">
IESG
</th>
<th scope="col" data-sort="open">
<th class="text-center" scope="col" data-sort="open">
Open
</th>
<th scope="col" data-sort="accept_nom">
<th class="text-center" scope="col" data-sort="accept_nom">
Accepting Nominations
</th>
<th scope="col" data-sort="accept_fb">
<th class="text-center" scope="col" data-sort="accept_fb">
Accepting Feedback
</th>
</tr>
@ -58,13 +59,11 @@
aria-label="position.name"
name="selected">
</td>
<td class="edit">
<td class="text-nowrap">
<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
@ -74,16 +73,16 @@
<td>
{{ position.name }}
</td>
<td>
<td class="text-center">
{{ position.is_iesg_position|yesno:"✓," }}
</td>
<td>
<td class="text-center">
{{ position.is_open|yesno:"✓," }}
</td>
<td>
<td class="text-center">
{{ position.accepting_nominations|yesno:"✓," }}
</td>
<td>
<td class="text-center">
{{ position.accepting_feedback|yesno:"✓," }}
</td>
</tr>
@ -117,7 +116,7 @@
<option value="unset_accept_nom">
Is Accepting Nominations: No
</option>
<option value="set_accept_bf">
<option value="set_accept_fb">
Is Accepting Feedback: Yes
</option>
<option value="unset_accept_fb">
@ -136,6 +135,3 @@
</p>
{% endif %}
{% endblock %}
{% block js %}
<script src="{% static "ietf/js/list.js" %}"></script>
{% endblock %}

View file

@ -1,14 +1,18 @@
{% extends "base.html" %}
{# Copyright The IETF Trust 2015, All Rights Reserved #}
{% load origin %}
{% load origin static %}
{% load nomcom_tags %}
{% load ietf_filters %}
{% block pagehead %}
<link rel="stylesheet" href="{% static "ietf/css/list.css" %}">
{% endblock %}
{% block title %}
NomCom {{ year }} Private
{% block subtitle %}{% endblock %}
{% endblock %}
{% block content %}
{% origin %}
{% with selected=request.path|split:'/'|slice:'4:-1'|join:'-' %}
<h1>
NomCom {{ year }}
{% if nomcom.group.state_id == 'conclude' %}<span class="badge rounded-pill text-bg-info">Concluded</span>{% endif %}
@ -19,129 +23,140 @@
</h1>
<ul class="nav nav-tabs my-3">
<li class="nav-item">
<a class="nav-link {% if selected == "index" %}active{% endif %}"
<a class="nav-link {% if selected == '' %}active{% endif %}"
href="{% url "ietf.nomcom.views.private_index" year %}">
Nominees
</a>
</li>
{% if nomcom|has_publickey %}
<li class="nav-item">
<a class="nav-link {% if selected == "nominate" %}active{% endif %}"
<a class="nav-link {% if selected == 'nominate' %}active{% endif %}"
href="{% url 'ietf.nomcom.views.private_nominate' year %}">
Nominate
</a>
</li>
<li class="nav-item">
<a class="nav-link {% if selected == "feedback" %}active{% endif %}"
{% endif %}
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle {% if selected in 'feedback,view-feedback'|split:',' %}active{% endif %}" data-bs-toggle="dropdown" href="#">Feedback</a>
<ul class="dropdown-menu mt-n1" role="menu">
{% if nomcom|has_publickey %}
<li>
<a class="dropdown-item {% if selected == 'feedback' %}active{% endif %}"
href="{% url 'ietf.nomcom.views.private_feedback' year %}">
Enter feedback
</a>
</li>
{% endif %}
<li class="nav-item">
<a class="nav-link {% if selected == "view_feedback" %}active{% endif %}"
href="{% url 'ietf.nomcom.views.view_feedback' year %}">
View feedback
</a>
{% endif %}
<li>
<a class="dropdown-item {% if selected == 'view-feedback' %}active{% endif %}"
href="{% url 'ietf.nomcom.views.view_feedback' year %}">
View feedback
</a>
</li>
</ul>
</li>
<li class="nav-item">
<a class="nav-link {% if selected == "private_key" %}active{% endif %}"
<a class="nav-link {% if selected == 'key' %}active{% endif %}"
href="{% url 'ietf.nomcom.views.private_key' year %}">
Private key
</a>
</li>
{% if user|is_chair_or_advisor:year %}
<li class="nav-item">
<a class="nav-link {% if selected == "feedback_pending" %}active{% endif %}"
<a class="nav-link {% if selected == 'view-feedback-pending' %}active{% endif %}"
href="{% url 'ietf.nomcom.views.view_feedback_pending' year %}">
Pending emails
{% if nomcom.pending_email_count %}<span class="badge rounded-pill text-bg-primary">{{ nomcom.pending_email_count }}</span>{% endif %}
</a>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" data-bs-toggle="dropdown" href="#">Chair/Advisor Tasks</a>
<a class="nav-link dropdown-toggle {% if selected in 'feedback-email,questionnaire-response,extract-email-lists,send-reminder-mail-accept,send-reminder-mail-questionnaire,merge-person,merge-nominee,edit-nomcom,chair-templates,chair-position,chair-topic,edit-members,help'|split:',' %}active{% endif %}" data-bs-toggle="dropdown" href="#">Chair/advisor tasks</a>
<ul class="dropdown-menu mt-n1" role="menu">
{% if nomcom.group.state_id == 'active' %}
<li role="presentation" class="dropdown-header">Feedback Management</li>
<li class="dropdown-item">
<a href="{% url 'ietf.nomcom.views.private_feedback_email' year %}">Enter email feedback</a>
<li>
<a class="dropdown-item {% if selected == 'feedback-email' %}active{% endif %}" href="{% url 'ietf.nomcom.views.private_feedback_email' year %}">Enter email feedback</a>
</li>
<li class="dropdown-item">
<a href="{% url 'ietf.nomcom.views.private_questionnaire' year %}">Enter questionnaire response</a>
<li>
<a class="dropdown-item {% if selected == 'questionnaire-response' %}active{% endif %}" href="{% url 'ietf.nomcom.views.private_questionnaire' year %}">Enter questionnaire response</a>
</li>
<li class="dropdown-item">
<a href="{% url 'ietf.nomcom.views.extract_email_lists' year %}">Extract email lists</a>
<li>
<a class="dropdown-item {% if selected == 'extract-email-lists' %}active{% endif %}" href="{% url 'ietf.nomcom.views.extract_email_lists' year %}">Extract email lists</a>
</li>
<li class="dropdown-item">
<a href="{% url 'ietf.nomcom.views.send_reminder_mail' year "accept" %}">Send accept reminder</a>
<li>
<a class="dropdown-item {% if selected == 'send-reminder-mail-accept' %}active{% endif %}" href="{% url 'ietf.nomcom.views.send_reminder_mail' year "accept" %}">Send accept reminder</a>
</li>
<li class="dropdown-item">
<a href="{% url 'ietf.nomcom.views.send_reminder_mail' year "questionnaire" %}">Send questionnaire reminder</a>
<li>
<a class="dropdown-item {% if selected == 'send-reminder-mail-questionnaire' %}active{% endif %}" href="{% url 'ietf.nomcom.views.send_reminder_mail' year "questionnaire" %}">Send questionnaire reminder</a>
</li>
<li class="dropdown-item">
<a href="{% url "ietf.nomcom.views.private_merge_person" year %}">Request person record merge</a>
<li>
<a class="dropdown-item {% if selected == 'merge-person' %}active{% endif %}" href="{% url "ietf.nomcom.views.private_merge_person" year %}">Request person record merge</a>
</li>
<li class="dropdown-item">
<a href="{% url "ietf.nomcom.views.private_merge_nominee" year %}">Merge nominee records</a>
<li>
<a class="dropdown-item {% if selected == 'merge-nominee' %}active{% endif %}" href="{% url "ietf.nomcom.views.private_merge_nominee" year %}">Merge nominee records</a>
</li>
<li><hr class="dropdown-divider"></li>
{% endif %}
<li role="presentation" class="dropdown-header">NomCom configuration</li>
<li class="dropdown-item">
<a href="{% url 'ietf.nomcom.views.edit_nomcom' year %}">Edit settings</a>
<li>
<a class="dropdown-item {% if selected == 'edit-nomcom' %}active{% endif %}" href="{% url 'ietf.nomcom.views.edit_nomcom' year %}">Edit settings</a>
</li>
<li class="dropdown-item">
<a href="{% url 'ietf.nomcom.views.list_templates' year %}">Edit pages</a>
<li>
<a class="dropdown-item {% if selected == 'chair-templates' %}active{% endif %}" href="{% url 'ietf.nomcom.views.list_templates' year %}">Edit pages</a>
</li>
<li class="dropdown-item">
<a href="{% url 'ietf.nomcom.views.list_positions' year %}">Edit positions</a>
<li>
<a class="dropdown-item {% if selected == 'chair-position' %}active{% endif %}" href="{% url 'ietf.nomcom.views.list_positions' year %}">Edit positions</a>
</li>
<li class="dropdown-item">
<a href="{% url 'ietf.nomcom.views.list_topics' year %}">Edit topics</a>
<li>
<a class="dropdown-item {% if selected == 'chair-topic' %}active{% endif %}" href="{% url 'ietf.nomcom.views.list_topics' year %}">Edit topics</a>
</li>
{% if nomcom.group.state_id == 'active' %}
<li class="dropdown-item">
<a href="{% url 'ietf.nomcom.views.edit_members' year %}">Edit members</a>
<li>
<a class="dropdown-item {% if selected == 'edit-members' %}active{% endif %}" href="{% url 'ietf.nomcom.views.edit_members' year %}">Edit members</a>
</li>
{% endif %}
<li class="dropdown-item">
<a href="{% url 'ietf.nomcom.views.configuration_help' year %}">Configuration help</a>
<li>
<a class="dropdown-item {% if selected == 'help' %}active{% endif %}" href="{% url 'ietf.nomcom.views.configuration_help' year %}">Configuration help</a>
</li>
<li><hr class="dropdown-divider"></li>
<li role="presentation" class="dropdown-header">Other tools</li>
<li class="dropdown-item">
<a href="{% url 'ietf.secr.announcement.views.main' %}">Announcement tool</a>
</li>
<li class="dropdown-item">
<a href="https://www.ietf.org/registration/nomcom_chair/nomcomstaff.py">Secretariat private eligibility checker</a>
</li>
<li class="dropdown-item">
<a href="https://www.ietf.org/registration/nomcom.py">Secretariat public eligibility checker</a>
<li>
<a class="dropdown-item" href="{% url 'ietf.secr.announcement.views.main' %}">Announcement tool</a>
</li>
</ul>
</li>
{% endif %}
{% if user|is_chair_or_advisor:year or user|has_role:"Secretariat" %}
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" data-bs-toggle="dropdown" href="#">
<a class="nav-link dropdown-toggle {% if selected in 'chair-eligible,chair-volunteers'|split:',' %}active{% endif %}" data-bs-toggle="dropdown" href="#">
Volunteers
</a>
<ul class="dropdown-menu mt-n1" role="menu">
<li class="dropdown-item">
<a href="{% url 'ietf.nomcom.views.private_eligible' year %}">
<li>
<a class="dropdown-item {% if selected == 'chair-eligible' %}active{% endif %}" href="{% url 'ietf.nomcom.views.private_eligible' year %}">
View eligible
</a>
</li>
<li class="dropdown-item">
<a href="{% url 'ietf.nomcom.views.private_volunteers' year %}">
<li>
<a class="dropdown-item {% if selected == 'chair-volunteers' %}active{% endif %}" href="{% url 'ietf.nomcom.views.private_volunteers' year %}">
View volunteers
</a>
</li>
</ul>
</li>
{% endif %}
<li class="nav-item">
<a class="nav-link"
href="/nomcom/{{ nomcom.year }}">
Public pages &raquo;
</a>
</li>
</ul>
{% block nomcom_content %}{% endblock %}
{% endwith %}
{% endblock %}
{% block js %}
<script src="{% static "ietf/js/list.js" %}"></script>
<script>
// Javascript to enable link to tab
var url=document.location.toString();

View file

@ -1,21 +1,25 @@
{% extends "base.html" %}
{# Copyright The IETF Trust 2015, All Rights Reserved #}
{% load origin %}
{% load origin static %}
{% load nomcom_tags %}
{% load ietf_filters %}
{% block pagehead %}
<link rel="stylesheet" href="{% static "ietf/css/list.css" %}">
{% endblock %}
{% block title %}
NomCom {{ year }}
{% block subtitle %}{% endblock %}
{% endblock %}
{% block content %}
{% origin %}
{% with selected=request.path|split:'/'|slice:'3:-1'|join:'-' %}
<h1>
NomCom {{ year }}
{% if nomcom.group.state_id == 'conclude' %}<span class="badge rounded-pill text-bg-info">Concluded</span>{% endif %}
</h1>
<ul class="nav nav-tabs my-3">
<li class="nav-item">
<a class="nav-link {% if selected == "index" %}active{% endif %}"
<a class="nav-link {% if selected == '' %}active{% endif %}"
href="{% url 'ietf.nomcom.views.year_index' year %}">
Home
</a>
@ -35,7 +39,7 @@
</li>
{% endif %}
<li class="nav-item">
<a class="nav-link {% if selected == "requirements" %}active{% endif %}"
<a class="nav-link {% if selected == "expertise" %}active{% endif %}"
href="{% url 'ietf.nomcom.views.requirements' year %}">
Desired expertise
</a>
@ -48,14 +52,14 @@
</li>
{% if user|is_chair_or_advisor:year or user|has_role:"Secretariat" %}
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" data-bs-toggle="dropdown" href="#">Volunteers</a>
<a class="nav-link dropdown-toggle {% if selected in 'eligible,volunteers'|split:',' %}active{% endif %}" data-bs-toggle="dropdown" href="#">Volunteers</a>
<ul class="dropdown-menu mt-n1" role="menu">
<li class="nav-item">
<a class="dropdown-item"
<a class="dropdown-item {% if selected == 'eligible' %}active{% endif %}"
href="{% url 'ietf.nomcom.views.public_eligible' year %}">View eligible</a>
</li>
<li class="nav-item">
<a class="dropdown-item"
<a class="dropdown-item {% if selected == 'volunteers' %}active{% endif %}"
href="{% url 'ietf.nomcom.views.public_volunteers' year %}">View volunteers</a>
</li>
</ul>
@ -63,8 +67,10 @@
{% endif %}
</ul>
{% block nomcom_content %}{% endblock %}
{% endwith %}
{% endblock %}
{% block js %}
<script src="{% static "ietf/js/list.js" %}"></script>
<script>
$(document)
.ready(function () {

View file

@ -2,9 +2,6 @@
{# Copyright The IETF Trust 2015-2020, All Rights Reserved #}
{% load origin static %}
{% block subtitle %}- Administration{% endblock %}
{% block pagehead %}
<link rel="stylesheet" href="{% static "ietf/css/list.css" %}">
{% endblock %}
{% block nomcom_content %}
{% origin %}
<h2 class="mt-3">Nomination status</h2>
@ -252,6 +249,3 @@
{% endif %}
{% endif %}
{% endblock %}
{% block js %}
<script src="{% static "ietf/js/list.js" %}"></script>
{% endblock %}

View file

@ -3,9 +3,6 @@
{% load origin static %}
{% load nomcom_tags %}
{% block subtitle %}- View feedback{% endblock %}
{% block pagehead %}
<link rel="stylesheet" href="{% static "ietf/css/list.css" %}">
{% endblock %}
{% block nomcom_content %}
{% origin %}
<h2 class="mt-3">Feedback related to nominees</h2>
@ -114,6 +111,3 @@
</table>
{% endif %}
{% endblock %}
{% block js %}
<script src="{% static "ietf/js/list.js" %}"></script>
{% endblock %}

View file

@ -1,12 +1,9 @@
{% extends public|yesno:"nomcom/nomcom_public_base.html,nomcom/nomcom_private_base.html" %}
{# Copyright The IETF Trust 2021, All Rights Reserved #}
{% load origin %}
{% load django_bootstrap5 textfilters person_filters %}
{% load django_bootstrap5 textfilters person_filters ietf_filters%}
{% load static %}
{% block subtitle %}- Volunteers{% endblock %}
{% block pagehead %}
<link rel="stylesheet" href="{% static "ietf/css/list.css" %}">
{% endblock %}
{% block nomcom_content %}
{% origin %}
<h2>Volunteers for {{ nomcom.group }}</h2>
@ -34,7 +31,7 @@
{% for v in eligibility_group.list %}
<tr>
<td>{{ forloop.counter }}</td>
<td>{{ v.person.last_name }}</td>
<td>{{ v.person.last_name|split:'+'|join:'+<wbr>' }}</td>
<td>{{ v.person.first_name }}</td>
<td>{{ v.person.ascii_name }}</td>
<td>{% person_link v.person %}</td>
@ -47,6 +44,3 @@
</table>
{% endfor %}
{% endblock %}
{% block js %}
<script src="{% static "ietf/js/list.js" %}"></script>
{% endblock %}

View file

@ -21,7 +21,6 @@
</p>
<ul>
<li>Only XML-only uploads are supported, not text or combined.</li>
<li>Document replacement information cannot be supplied.</li>
<li>
The server expects <code>multipart/form-data</code>, supported by <code>curl</code> but <b>not</b> by <code>wget</code>.
</li>

Some files were not shown because too many files have changed in this diff Show more