diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ccc6399ab3..0f9b6dcf4c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -5,6 +5,7 @@ on: branches: - main - 'feature/**' + - 'staging/**' env: NG_CLI_ANALYTICS: ci @@ -23,7 +24,7 @@ jobs: submodules: "recursive" - name: Checkout latest commits env: - BRANCH: ${{ github.event.pull_request.head.repo.owner.login == 'OpenSlides' && github.head_ref || github.base_ref }} + BRANCH: ${{ github.event.pull_request.head.repo.owner.login == 'OpenSlides' && contains(github.head_ref, 'feature/') && github.head_ref || github.base_ref }} run: git submodule foreach 'git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*" && ((git fetch origin ${{ env.BRANCH }} && git checkout ${{ env.BRANCH }}) || (git checkout main && git pull origin main)) && git submodule update --init' - name: Delete the client folder run: rm -r openslides-client diff --git a/.github/workflows/close-issues.yml b/.github/workflows/close-issues.yml new file mode 100644 index 0000000000..d6ea45bd24 --- /dev/null +++ b/.github/workflows/close-issues.yml @@ -0,0 +1,52 @@ +on: + pull_request: + types: + - closed + branches: + - "feature/*" + +jobs: + close-issue: + runs-on: ubuntu-latest + if: github.event.pull_request.merged + steps: + - name: Generate access token + uses: tibdex/github-app-token@v2 + id: generate-token + with: + app_id: ${{ secrets.AUTOMATION_APP_ID }} + private_key: ${{ secrets.AUTOMATION_APP_PRIVATE_KEY }} + + - uses: octokit/graphql-action@v2.x + id: get-issues + env: + GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }} + with: + query: | + query getLinkedIssues($owner: String!, $name: String!, $number: Int!) { + repository(owner: $owner, name: $name) { + pullRequest(number: $number) { + closingIssuesReferences(first: 100) { + nodes { + number + repository { + nameWithOwner + } + } + } + } + } + } + variables: | + owner: ${{ github.event.repository.owner.name }} + repo: ${{ github.event.repository.name }} + number: ${{ github.event.pull_request.number }} + + - name: Close issues + env: + GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }} + run: | + issue_data="$(echo "${{ steps.get-issues.outputs.data }}" | jq -r '.data.repository.pullRequest.closingIssuesReferences.nodes[] | [.number,.repository.nameWithOwner] | @tsv')" + echo "$issue_data" | while read number nameWithOwner; do + gh issue close "$number" -r "$nameWithOwner" + done diff --git a/.github/workflows/staging-to-main.yml b/.github/workflows/staging-to-main.yml new file mode 100644 index 0000000000..2bb8525ffc --- /dev/null +++ b/.github/workflows/staging-to-main.yml @@ -0,0 +1,54 @@ +name: Copy staging commits to main + +on: + push: + branches: + - 'staging/4*' + + +jobs: + create-pr-for-main: + name: Create PR against main branch + runs-on: ubuntu-latest + + steps: + - name: Checkout main + uses: actions/checkout@v4 + with: + ref: main + + - name: Set git credentials + run: | + git config --global user.name openslides-automation + git config --global user.email openslides-automation@users.noreply.github.com + + - name: Cherry-pick new commit + id: cherry-pick + run: | + git fetch origin + git cherry-pick ${{ github.sha }} || { + echo "error=1" >> $GITHUB_OUTPUT + git add . + git cherry-pick --continue + } + + - name: Generate access token + uses: tibdex/github-app-token@v2 + id: generate-token + with: + app_id: ${{ secrets.AUTOMATION_APP_ID }} + private_key: ${{ secrets.AUTOMATION_APP_PRIVATE_KEY }} + + - name: Create or update PR + uses: peter-evans/create-pull-request@v6 + with: + token: ${{ steps.generate-token.outputs.token }} + commit-message: ${{ github.event.commits[0].message }} + branch: apply/commit-${{ github.sha }} + delete-branch: true + title: ${{ github.event.commits[0].message }} + body: "Triggered by commit [${{ github.sha }}](https://github.com/${{ github.repository }}/commit/${{ github.sha }})\n\n${{ steps.cherry-pick.outputs.error && 'There were conflicts during the cherry-pick. These were commited without any resolving. Please resolve them manually and push the result to this branch before merging.' || 'The cherry-pick was successful without any conflicts. You should be able to simply merge this PR.' }}" + reviewers: ${{ github.event.commits[0].author.username }} + assignees: ${{ github.event.commits[0].author.username }} + labels: staging-port + milestone: 4 diff --git a/client/.eslintrc.js b/client/.eslintrc.js index 5ac1cddc1e..d8ccee6133 100644 --- a/client/.eslintrc.js +++ b/client/.eslintrc.js @@ -66,6 +66,8 @@ module.exports = { '@typescript-eslint/no-this-alias': ['error'], '@typescript-eslint/adjacent-overload-signatures': ['error'], '@typescript-eslint/ban-types': ['error'], + '@typescript-eslint/explicit-member-accessibility': ['error'], + '@typescript-eslint/explicit-function-return-type': ['warn'], 'jsdoc/require-example': ['off'], 'jsdoc/newline-after-description': ['off'], @@ -85,6 +87,8 @@ module.exports = { files: ['*.spec.ts'], rules: { 'no-restricted-globals': ['error', 'fdescribe', 'fit'], + '@typescript-eslint/explicit-member-accessibility': ['off'], + '@typescript-eslint/explicit-function-return-type': ['off'], } }, { diff --git a/client/angular.json b/client/angular.json index 028543dc0b..b457eab31e 100644 --- a/client/angular.json +++ b/client/angular.json @@ -30,6 +30,8 @@ "assets": [ "src/assets", "src/manifest.webmanifest", + "src/sw.js", + "src/ngsw-safety.json", { "glob": "**/*", "input": "node_modules/tinymce", diff --git a/client/ngsw-config.json b/client/ngsw-config.json index ae4ee94647..1405481722 100644 --- a/client/ngsw-config.json +++ b/client/ngsw-config.json @@ -1,28 +1,31 @@ { "$schema": "./node_modules/@angular/service-worker/config/schema.json", "index": "/index.html", + "version": 2, "assetGroups": [ { "name": "app", "installMode": "prefetch", "resources": { "files": [ - "/favicon.ico", "/index.html", - "/manifest.webmanifest", "/*.css", - "/*.js", - "/fira-sans*", - "/Material-Icons-Baseline.*" + "/*.js" ] } }, { "name": "assets", "installMode": "lazy", - "updateMode": "prefetch", "resources": { - "files": ["/assets/**", "/*.(svg|cur|jpg|jpeg|png|apng|webp|avif|gif|otf|ttf|woff|woff2)"] + "files": [ + "/assets/**", + "/*.(svg|cur|jpg|jpeg|png|apng|webp|avif|gif|otf|ttf|woff|woff2)", + "/fira-sans*", + "/favicon.ico", + "/manifest.webmanifest", + "/Material-Icons-Baseline.*" + ] } } ], diff --git a/client/package-lock.json b/client/package-lock.json index 66be280af8..9ae34c9049 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -8946,13 +8946,14 @@ "dev": true }, "node_modules/es5-ext": { - "version": "0.10.62", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.62.tgz", - "integrity": "sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==", + "version": "0.10.64", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.64.tgz", + "integrity": "sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==", "hasInstallScript": true, "dependencies": { "es6-iterator": "^2.0.3", "es6-symbol": "^3.1.3", + "esniff": "^2.0.1", "next-tick": "^1.1.0" }, "engines": { @@ -9541,6 +9542,25 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/esniff": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/esniff/-/esniff-2.0.1.tgz", + "integrity": "sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==", + "dependencies": { + "d": "^1.0.1", + "es5-ext": "^0.10.62", + "event-emitter": "^0.3.5", + "type": "^2.7.2" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esniff/node_modules/type": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz", + "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==" + }, "node_modules/espree": { "version": "9.5.0", "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.0.tgz", @@ -26558,12 +26578,13 @@ "dev": true }, "es5-ext": { - "version": "0.10.62", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.62.tgz", - "integrity": "sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==", + "version": "0.10.64", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.64.tgz", + "integrity": "sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==", "requires": { "es6-iterator": "^2.0.3", "es6-symbol": "^3.1.3", + "esniff": "^2.0.1", "next-tick": "^1.1.0" } }, @@ -26987,6 +27008,24 @@ "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", "dev": true }, + "esniff": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/esniff/-/esniff-2.0.1.tgz", + "integrity": "sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==", + "requires": { + "d": "^1.0.1", + "es5-ext": "^0.10.62", + "event-emitter": "^0.3.5", + "type": "^2.7.2" + }, + "dependencies": { + "type": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz", + "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==" + } + } + }, "espree": { "version": "9.5.0", "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.0.tgz", diff --git a/client/src/app/domain/definitions/meeting-settings-defaults.ts b/client/src/app/domain/definitions/meeting-settings-defaults.ts index 18c2e4aea4..020beb6b58 100644 --- a/client/src/app/domain/definitions/meeting-settings-defaults.ts +++ b/client/src/app/domain/definitions/meeting-settings-defaults.ts @@ -3,6 +3,7 @@ import { marker as _ } from '@colsen1991/ngx-translate-extract-marker'; export const meetingSettingsDefaults: { [key: string]: any } = { + name: `Meeting title`, enable_anonymous: false, export_csv_separator: `;`, export_csv_encoding: `utf-8`, diff --git a/client/src/app/domain/models/meetings/meeting.ts b/client/src/app/domain/models/meetings/meeting.ts index 685f9eccce..e8e621c53e 100644 --- a/client/src/app/domain/models/meetings/meeting.ts +++ b/client/src/app/domain/models/meetings/meeting.ts @@ -95,8 +95,10 @@ export class Settings { public list_of_speakers_initially_closed!: boolean; public list_of_speakers_enable_pro_contra_speech!: boolean; public list_of_speakers_can_set_contribution_self!: boolean; + public list_of_speakers_allow_multiple_speakers!: boolean; public list_of_speakers_speaker_note_for_everyone!: boolean; public list_of_speakers_closing_disables_point_of_order!: boolean; + public list_of_speakers_can_create_point_of_order_for_others!: boolean; public list_of_speakers_default_structure_level_time: number; public list_of_speakers_enable_interposed_question: boolean; @@ -177,17 +179,17 @@ export class Settings { public assignment_poll_default_backend!: PollBackendDurationType; //topic poll - topic_poll_default_group_ids: Id[]; // (group/used_as_poll_default_id)[]; + public topic_poll_default_group_ids: Id[]; // (group/used_as_poll_default_id)[]; //default poll - poll_ballot_paper_selection: BallotPaperSelection; - poll_ballot_paper_number: number; - poll_sort_poll_result_by_votes: boolean; - poll_default_type: PollType; - poll_default_method: PollMethod; - poll_default_onehundred_percent_base: PollPercentBase; - poll_default_group_ids: Id[]; // (group/used_as_poll_default_id)[]; - poll_default_backend: PollBackendDurationType; + public poll_ballot_paper_selection: BallotPaperSelection; + public poll_ballot_paper_number: number; + public poll_sort_poll_result_by_votes: boolean; + public poll_default_type: PollType; + public poll_default_method: PollMethod; + public poll_default_onehundred_percent_base: PollPercentBase; + public poll_default_group_ids: Id[]; // (group/used_as_poll_default_id)[]; + public poll_default_backend: PollBackendDurationType; //SSO public external_id!: string; @@ -338,7 +340,9 @@ export class Meeting extends BaseModel { `list_of_speakers_show_first_contribution`, `list_of_speakers_enable_point_of_order_speakers`, `list_of_speakers_enable_point_of_order_categories`, + `list_of_speakers_can_create_point_of_order_for_others`, `list_of_speakers_closing_disables_point_of_order`, + `list_of_speakers_allow_multiple_speakers`, `list_of_speakers_enable_pro_contra_speech`, `list_of_speakers_can_set_contribution_self`, `list_of_speakers_speaker_note_for_everyone`, diff --git a/client/src/app/domain/models/motions/motion.ts b/client/src/app/domain/models/motions/motion.ts index 842a4aa1c8..ee6dccc888 100644 --- a/client/src/app/domain/models/motions/motion.ts +++ b/client/src/app/domain/models/motions/motion.ts @@ -44,6 +44,7 @@ export class Motion extends BaseModel implements MotionFormattingReprese public state_extension!: string; public recommendation_extension!: string; public sort_weight!: number; + public additional_submitter!: string; /** * Client-calculated field: The tree_weight indicates the position of a motion in a list of * motions in regard to the call list. @@ -117,6 +118,7 @@ export class Motion extends BaseModel implements MotionFormattingReprese `workflow_timestamp`, `start_line_number`, `forwarded`, + `additional_submitter`, `lead_motion_id`, `amendment_ids`, `sort_parent_id`, diff --git a/client/src/app/domain/models/poll/option.ts b/client/src/app/domain/models/poll/option.ts index 0d539c1217..afd8cd32dc 100644 --- a/client/src/app/domain/models/poll/option.ts +++ b/client/src/app/domain/models/poll/option.ts @@ -11,6 +11,7 @@ export class Option extends BaseDecimalModel