├── .eslintrc.cjs ├── .gitattributes ├── .github ├── CODEOWNERS └── workflows │ ├── appstore-build-publish.yml │ ├── lint-eslint.yml │ ├── lint-info-xml.yml │ ├── lint-php-cs.yml │ ├── lint-php.yml │ ├── lint-stylelint.yml │ ├── phpunit-mysql.yml │ ├── phpunit-pgsql.yml │ ├── phpunit-sqlite.yml │ ├── phpunit-summary-when-unrelated.yml │ ├── pr-feedback.yml │ ├── psalm.yml │ └── reuse.yml ├── .gitignore ├── .l10nignore ├── .nextcloudignore ├── .php-cs-fixer.dist.php ├── .tx └── config ├── AUTHORS.md ├── CHANGELOG.md ├── COPYING ├── LICENSES ├── AGPL-3.0-or-later.txt ├── Apache-2.0.txt ├── CC0-1.0.txt ├── LicenseRef-GithubTrademarks.txt └── MIT.txt ├── README.md ├── REUSE.toml ├── appinfo ├── info.xml └── routes.php ├── composer.json ├── composer.lock ├── css └── dashboard.css ├── img ├── app-dark.svg ├── app.svg ├── issue-dark.svg ├── issue-white.svg ├── issue.svg ├── pull_request-dark.svg ├── pull_request-white.svg ├── pull_request.svg ├── reactions │ ├── confused.png │ ├── eyes.png │ ├── heart.png │ ├── laugh.png │ ├── minus1.png │ ├── plus1.png │ ├── rocket.png │ └── tada.png ├── release.svg ├── repo-dark.svg ├── repo-white.svg ├── screenshot1.jpg └── unsub.svg ├── krankerl.toml ├── l10n ├── .gitkeep ├── af.js ├── af.json ├── ar.js ├── ar.json ├── ast.js ├── ast.json ├── az.js ├── az.json ├── bg.js ├── bg.json ├── br.js ├── br.json ├── ca.js ├── ca.json ├── cs.js ├── cs.json ├── da.js ├── da.json ├── de.js ├── de.json ├── de_DE.js ├── de_DE.json ├── el.js ├── el.json ├── en_GB.js ├── en_GB.json ├── eo.js ├── eo.json ├── es.js ├── es.json ├── es_419.js ├── es_419.json ├── es_AR.js ├── es_AR.json ├── es_CL.js ├── es_CL.json ├── es_CO.js ├── es_CO.json ├── es_CR.js ├── es_CR.json ├── es_DO.js ├── es_DO.json ├── es_EC.js ├── es_EC.json ├── es_GT.js ├── es_GT.json ├── es_HN.js ├── es_HN.json ├── es_MX.js ├── es_MX.json ├── es_NI.js ├── es_NI.json ├── es_PA.js ├── es_PA.json ├── es_PE.js ├── es_PE.json ├── es_PR.js ├── es_PR.json ├── es_PY.js ├── es_PY.json ├── es_SV.js ├── es_SV.json ├── es_UY.js ├── es_UY.json ├── et_EE.js ├── et_EE.json ├── eu.js ├── eu.json ├── fa.js ├── fa.json ├── fi.js ├── fi.json ├── fr.js ├── fr.json ├── ga.js ├── ga.json ├── gl.js ├── gl.json ├── he.js ├── he.json ├── hr.js ├── hr.json ├── hu.js ├── hu.json ├── id.js ├── id.json ├── is.js ├── is.json ├── it.js ├── it.json ├── ja.js ├── ja.json ├── ka.js ├── ka.json ├── ka_GE.js ├── ka_GE.json ├── ko.js ├── ko.json ├── lt_LT.js ├── lt_LT.json ├── lv.js ├── lv.json ├── mk.js ├── mk.json ├── nb.js ├── nb.json ├── nl.js ├── nl.json ├── nn_NO.js ├── nn_NO.json ├── oc.js ├── oc.json ├── pl.js ├── pl.json ├── pt_BR.js ├── pt_BR.json ├── pt_PT.js ├── pt_PT.json ├── ro.js ├── ro.json ├── ru.js ├── ru.json ├── sc.js ├── sc.json ├── sk.js ├── sk.json ├── sl.js ├── sl.json ├── sq.js ├── sq.json ├── sr.js ├── sr.json ├── sv.js ├── sv.json ├── th.js ├── th.json ├── tr.js ├── tr.json ├── ug.js ├── ug.json ├── uk.js ├── uk.json ├── uz.js ├── uz.json ├── vi.js ├── vi.json ├── zh_CN.js ├── zh_CN.json ├── zh_HK.js ├── zh_HK.json ├── zh_TW.js └── zh_TW.json ├── lib ├── AppInfo │ └── Application.php ├── BackgroundJob │ └── CheckGithubNotificationsJob.php ├── Controller │ ├── ConfigController.php │ └── GithubAPIController.php ├── Dashboard │ └── GithubWidget.php ├── Listener │ ├── ContentSecurityPolicyListener.php │ └── GithubReferenceListener.php ├── Migration │ └── Version030010Date20241002015812.php ├── Notification │ └── GitHubNotifier.php ├── Reference │ ├── GithubCodeReferenceProvider.php │ └── GithubIssuePrReferenceProvider.php ├── Search │ ├── GithubSearchIssuesProvider.php │ └── GithubSearchReposProvider.php ├── Service │ ├── GithubAPIService.php │ └── SecretService.php └── Settings │ ├── Admin.php │ ├── AdminSection.php │ ├── Personal.php │ └── PersonalSection.php ├── makefile ├── package-lock.json ├── package.json ├── psalm.xml ├── src ├── adminSettings.js ├── bootstrap.js ├── components │ ├── AdminSettings.vue │ ├── CommentReactions.vue │ ├── PersonalSettings.vue │ ├── UserPopover.vue │ └── icons │ │ ├── CommentIcon.vue │ │ ├── CommitIcon.vue │ │ ├── GithubIcon.vue │ │ ├── IssueClosedIcon.vue │ │ ├── IssueClosedNotPlannedIcon.vue │ │ ├── IssueOpenIcon.vue │ │ ├── LocationIcon.vue │ │ ├── MilestoneIcon.vue │ │ ├── PrClosedIcon.vue │ │ ├── PrMergedIcon.vue │ │ ├── PrOpenDraftIcon.vue │ │ ├── PrOpenIcon.vue │ │ ├── RepositoryIcon.vue │ │ └── RocketIcon.vue ├── dashboard.js ├── personalSettings.js ├── popupSuccess.js ├── reference.js ├── utils.js └── views │ ├── Dashboard.vue │ ├── GithubCodePermalinkReferenceWidget.vue │ └── GithubIssuePrReferenceWidget.vue ├── stylelint.config.cjs ├── templates ├── adminSettings.php ├── personalSettings.php └── popupSuccess.php ├── tests ├── bootstrap.php ├── phpunit.xml ├── psalm-baseline.xml └── unit │ ├── Controller │ ├── GithubAPIControllerTest.php │ └── data │ │ ├── avatar.jpg │ │ ├── issue.json │ │ ├── issue_comment.json │ │ ├── issue_comment_reactions.json │ │ ├── issue_reactions.json │ │ ├── notification.json │ │ ├── pr_info.json │ │ ├── users.json │ │ └── users_contextual.json │ └── Service │ └── GithubAPIServiceTest.php ├── vendor-bin ├── php-cs-fixer │ ├── composer.json │ └── composer.lock ├── phpunit │ ├── composer.json │ └── composer.lock └── psalm │ ├── composer.json │ └── composer.lock ├── vite.config.ts └── webpack.js /.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | /** 2 | * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors 3 | * SPDX-License-Identifier: AGPL-3.0-or-later 4 | */ 5 | 6 | module.exports = { 7 | globals: { 8 | appVersion: true 9 | }, 10 | parserOptions: { 11 | requireConfigFile: false 12 | }, 13 | extends: [ 14 | '@nextcloud' 15 | ], 16 | rules: { 17 | 'jsdoc/require-jsdoc': 'off', 18 | 'jsdoc/tag-lines': 'off', 19 | 'vue/first-attribute-linebreak': 'off', 20 | 'import/extensions': 'off' 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | /vendor-bin/**/composer.lock binary -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @kyteinsky @julien-nc 2 | -------------------------------------------------------------------------------- /.github/workflows/lint-eslint.yml: -------------------------------------------------------------------------------- 1 | # This workflow is provided via the organization template repository 2 | # 3 | # https://github.com/nextcloud/.github 4 | # https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization 5 | # 6 | # Use lint-eslint together with lint-eslint-when-unrelated to make eslint a required check for GitHub actions 7 | # https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/defining-the-mergeability-of-pull-requests/troubleshooting-required-status-checks#handling-skipped-but-required-checks 8 | 9 | name: Lint eslint 10 | 11 | on: pull_request 12 | 13 | permissions: 14 | contents: read 15 | 16 | concurrency: 17 | group: lint-eslint-${{ github.head_ref || github.run_id }} 18 | cancel-in-progress: true 19 | 20 | jobs: 21 | changes: 22 | runs-on: ubuntu-latest-low 23 | 24 | outputs: 25 | src: ${{ steps.changes.outputs.src}} 26 | 27 | steps: 28 | - uses: dorny/paths-filter@0bc4621a3135347011ad047f9ecf449bf72ce2bd # v3.0.0 29 | id: changes 30 | continue-on-error: true 31 | with: 32 | filters: | 33 | src: 34 | - '.github/workflows/**' 35 | - 'src/**' 36 | - 'appinfo/info.xml' 37 | - 'package.json' 38 | - 'package-lock.json' 39 | - 'tsconfig.json' 40 | - '.eslintrc.*' 41 | - '.eslintignore' 42 | - '**.js' 43 | - '**.ts' 44 | - '**.vue' 45 | 46 | lint: 47 | runs-on: ubuntu-latest 48 | 49 | needs: changes 50 | if: needs.changes.outputs.src != 'false' 51 | 52 | name: NPM lint 53 | 54 | steps: 55 | - name: Checkout 56 | uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 57 | 58 | - name: Read package.json node and npm engines version 59 | uses: skjnldsv/read-package-engines-version-actions@8205673bab74a63eb9b8093402fd9e0e018663a1 # v2.2 60 | id: versions 61 | with: 62 | fallbackNode: '^20' 63 | fallbackNpm: '^10' 64 | 65 | - name: Set up node ${{ steps.versions.outputs.nodeVersion }} 66 | uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v3 67 | with: 68 | node-version: ${{ steps.versions.outputs.nodeVersion }} 69 | 70 | - name: Set up npm ${{ steps.versions.outputs.npmVersion }} 71 | run: npm i -g npm@"${{ steps.versions.outputs.npmVersion }}" 72 | 73 | - name: Install dependencies 74 | env: 75 | CYPRESS_INSTALL_BINARY: 0 76 | PUPPETEER_SKIP_DOWNLOAD: true 77 | run: npm ci 78 | 79 | - name: Lint 80 | run: npm run lint 81 | 82 | summary: 83 | permissions: 84 | contents: none 85 | runs-on: ubuntu-latest-low 86 | needs: [changes, lint] 87 | 88 | if: always() 89 | 90 | # This is the summary, we just avoid to rename it so that branch protection rules still match 91 | name: eslint 92 | 93 | steps: 94 | - name: Summary status 95 | run: if ${{ needs.changes.outputs.src != 'false' && needs.lint.result != 'success' }}; then exit 1; fi -------------------------------------------------------------------------------- /.github/workflows/lint-info-xml.yml: -------------------------------------------------------------------------------- 1 | # This workflow is provided via the organization template repository 2 | # 3 | # https://github.com/nextcloud/.github 4 | # https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization 5 | 6 | name: Lint info.xml 7 | 8 | on: pull_request 9 | 10 | permissions: 11 | contents: read 12 | 13 | concurrency: 14 | group: lint-info-xml-${{ github.head_ref || github.run_id }} 15 | cancel-in-progress: true 16 | 17 | jobs: 18 | xml-linters: 19 | runs-on: ubuntu-latest-low 20 | 21 | name: info.xml lint 22 | steps: 23 | - name: Checkout 24 | uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 25 | 26 | - name: Download schema 27 | run: wget https://raw.githubusercontent.com/nextcloud/appstore/master/nextcloudappstore/api/v1/release/info.xsd 28 | 29 | - name: Lint info.xml 30 | uses: ChristophWurst/xmllint-action@36f2a302f84f8c83fceea0b9c59e1eb4a616d3c1 # v1.2 31 | with: 32 | xml-file: ./appinfo/info.xml 33 | xml-schema-file: ./info.xsd -------------------------------------------------------------------------------- /.github/workflows/lint-php-cs.yml: -------------------------------------------------------------------------------- 1 | # This workflow is provided via the organization template repository 2 | # 3 | # https://github.com/nextcloud/.github 4 | # https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization 5 | 6 | name: Lint php-cs 7 | 8 | on: pull_request 9 | 10 | permissions: 11 | contents: read 12 | 13 | concurrency: 14 | group: lint-php-cs-${{ github.head_ref || github.run_id }} 15 | cancel-in-progress: true 16 | 17 | jobs: 18 | lint: 19 | runs-on: ubuntu-latest 20 | 21 | name: php-cs 22 | 23 | steps: 24 | - name: Checkout 25 | uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 26 | 27 | - name: Set up php8.2 28 | uses: shivammathur/setup-php@6d7209f44a25a59e904b1ee9f3b0c33ab2cd888d # v2 29 | with: 30 | php-version: 8.2 31 | extensions: bz2, ctype, curl, dom, fileinfo, gd, iconv, intl, json, libxml, mbstring, openssl, pcntl, posix, session, simplexml, xmlreader, xmlwriter, zip, zlib, sqlite, pdo_sqlite 32 | coverage: none 33 | ini-file: development 34 | env: 35 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 36 | 37 | - name: Install dependencies 38 | run: composer i 39 | 40 | - name: Lint 41 | run: composer run cs:check || ( echo 'Please run `composer run cs:fix` to format your code' && exit 1 ) -------------------------------------------------------------------------------- /.github/workflows/lint-php.yml: -------------------------------------------------------------------------------- 1 | # This workflow is provided via the organization template repository 2 | # 3 | # https://github.com/nextcloud/.github 4 | # https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization 5 | 6 | name: Lint php 7 | 8 | on: pull_request 9 | 10 | permissions: 11 | contents: read 12 | 13 | concurrency: 14 | group: lint-php-${{ github.head_ref || github.run_id }} 15 | cancel-in-progress: true 16 | 17 | jobs: 18 | php-lint: 19 | runs-on: ubuntu-latest 20 | strategy: 21 | matrix: 22 | php-versions: ['8.1', '8.2', '8.3'] 23 | 24 | name: php-lint 25 | 26 | steps: 27 | - name: Checkout 28 | uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 29 | 30 | - name: Set up php ${{ matrix.php-versions }} 31 | uses: shivammathur/setup-php@6d7209f44a25a59e904b1ee9f3b0c33ab2cd888d # v2 32 | with: 33 | php-version: ${{ matrix.php-versions }} 34 | extensions: bz2, ctype, curl, dom, fileinfo, gd, iconv, intl, json, libxml, mbstring, openssl, pcntl, posix, session, simplexml, xmlreader, xmlwriter, zip, zlib, sqlite, pdo_sqlite 35 | coverage: none 36 | ini-file: development 37 | env: 38 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 39 | 40 | - name: Lint 41 | run: composer run lint 42 | 43 | summary: 44 | permissions: 45 | contents: none 46 | runs-on: ubuntu-latest-low 47 | needs: php-lint 48 | 49 | if: always() 50 | 51 | name: php-lint-summary 52 | 53 | steps: 54 | - name: Summary status 55 | run: if ${{ needs.php-lint.result != 'success' && needs.php-lint.result != 'skipped' }}; then exit 1; fi 56 | -------------------------------------------------------------------------------- /.github/workflows/lint-stylelint.yml: -------------------------------------------------------------------------------- 1 | # This workflow is provided via the organization template repository 2 | # 3 | # https://github.com/nextcloud/.github 4 | # https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization 5 | 6 | name: Lint stylelint 7 | 8 | on: pull_request 9 | 10 | permissions: 11 | contents: read 12 | 13 | concurrency: 14 | group: lint-stylelint-${{ github.head_ref || github.run_id }} 15 | cancel-in-progress: true 16 | 17 | jobs: 18 | lint: 19 | runs-on: ubuntu-latest 20 | 21 | name: stylelint 22 | 23 | steps: 24 | - name: Checkout 25 | uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 26 | 27 | - name: Read package.json node and npm engines version 28 | uses: skjnldsv/read-package-engines-version-actions@8205673bab74a63eb9b8093402fd9e0e018663a1 # v2.2 29 | id: versions 30 | with: 31 | fallbackNode: '^20' 32 | fallbackNpm: '^10' 33 | 34 | - name: Set up node ${{ steps.versions.outputs.nodeVersion }} 35 | uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v3 36 | with: 37 | node-version: ${{ steps.versions.outputs.nodeVersion }} 38 | 39 | - name: Set up npm ${{ steps.versions.outputs.npmVersion }} 40 | run: npm i -g npm@"${{ steps.versions.outputs.npmVersion }}" 41 | 42 | - name: Install dependencies 43 | env: 44 | CYPRESS_INSTALL_BINARY: 0 45 | run: npm ci 46 | 47 | - name: Lint 48 | run: npm run stylelint -------------------------------------------------------------------------------- /.github/workflows/phpunit-summary-when-unrelated.yml: -------------------------------------------------------------------------------- 1 | # This workflow is provided via the organization template repository 2 | # 3 | # https://github.com/nextcloud/.github 4 | # https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization 5 | 6 | name: PHPUnit 7 | 8 | on: 9 | pull_request: 10 | paths-ignore: 11 | - '.github/workflows/**' 12 | - 'appinfo/**' 13 | - 'lib/**' 14 | - 'templates/**' 15 | - 'tests/**' 16 | - 'vendor/**' 17 | - 'vendor-bin/**' 18 | - '.php-cs-fixer.dist.php' 19 | - 'composer.json' 20 | - 'composer.lock' 21 | 22 | permissions: 23 | contents: read 24 | 25 | jobs: 26 | summary-mysql: 27 | permissions: 28 | contents: none 29 | runs-on: ubuntu-latest 30 | 31 | name: phpunit-mysql-summary 32 | 33 | steps: 34 | - name: Summary status 35 | run: 'echo "No PHP files changed, skipped PHPUnit"' 36 | 37 | summary-oci: 38 | permissions: 39 | contents: none 40 | runs-on: ubuntu-latest 41 | 42 | name: phpunit-oci-summary 43 | 44 | steps: 45 | - name: Summary status 46 | run: 'echo "No PHP files changed, skipped PHPUnit"' 47 | 48 | summary-pgsql: 49 | permissions: 50 | contents: none 51 | runs-on: ubuntu-latest 52 | 53 | name: phpunit-pgsql-summary 54 | 55 | steps: 56 | - name: Summary status 57 | run: 'echo "No PHP files changed, skipped PHPUnit"' 58 | 59 | summary-sqlite: 60 | permissions: 61 | contents: none 62 | runs-on: ubuntu-latest 63 | 64 | name: phpunit-sqlite-summary 65 | 66 | steps: 67 | - name: Summary status 68 | run: 'echo "No PHP files changed, skipped PHPUnit"' 69 | -------------------------------------------------------------------------------- /.github/workflows/pr-feedback.yml: -------------------------------------------------------------------------------- 1 | # This workflow is provided via the organization template repository 2 | # 3 | # https://github.com/nextcloud/.github 4 | # https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization 5 | 6 | # SPDX-FileCopyrightText: 2023-2024 Nextcloud GmbH and Nextcloud contributors 7 | # SPDX-FileCopyrightText: 2023 Marcel Klehr 8 | # SPDX-FileCopyrightText: 2023 Joas Schilling <213943+nickvergessen@users.noreply.github.com> 9 | # SPDX-FileCopyrightText: 2023 Daniel Kesselberg 10 | # SPDX-FileCopyrightText: 2023 Florian Steffens 11 | # SPDX-License-Identifier: MIT 12 | 13 | name: 'Ask for feedback on PRs' 14 | on: 15 | schedule: 16 | - cron: '30 1 * * *' 17 | 18 | jobs: 19 | pr-feedback: 20 | runs-on: ubuntu-latest 21 | steps: 22 | - name: The get-github-handles-from-website action 23 | uses: marcelklehr/get-github-handles-from-website-action@a739600f6b91da4957f51db0792697afbb2f143c # v1.0.0 24 | id: scrape 25 | with: 26 | website: 'https://nextcloud.com/team/' 27 | 28 | - name: Get blocklist 29 | id: blocklist 30 | run: | 31 | blocklist=$(curl https://raw.githubusercontent.com/nextcloud/.github/master/non-community-usernames.txt | paste -s -d, -) 32 | echo "blocklist=$blocklist" >> "$GITHUB_OUTPUT" 33 | 34 | - uses: marcelklehr/pr-feedback-action@1883b38a033fb16f576875e0cf45f98b857655c4 35 | with: 36 | feedback-message: | 37 | Hello there, 38 | Thank you so much for taking the time and effort to create a pull request to our Nextcloud project. 39 | 40 | We hope that the review process is going smooth and is helpful for you. We want to ensure your pull request is reviewed to your satisfaction. If you have a moment, our community management team would very much appreciate your feedback on your experience with this PR review process. 41 | 42 | Your feedback is valuable to us as we continuously strive to improve our community developer experience. Please take a moment to complete our short survey by clicking on the following link: https://cloud.nextcloud.com/apps/forms/s/i9Ago4EQRZ7TWxjfmeEpPkf6 43 | 44 | Thank you for contributing to Nextcloud and we hope to hear from you soon! 45 | 46 | (If you believe you should not receive this message, you can add yourself to the [blocklist](https://github.com/nextcloud/.github/blob/master/non-community-usernames.txt).) 47 | days-before-feedback: 14 48 | start-date: "2024-04-30" 49 | exempt-authors: "${{ steps.blocklist.outputs.blocklist }},${{ steps.scrape.outputs.users }},nextcloud-command,nextcloud-android-bot" 50 | exempt-bots: true 51 | -------------------------------------------------------------------------------- /.github/workflows/psalm.yml: -------------------------------------------------------------------------------- 1 | # This workflow is provided via the organization template repository 2 | # 3 | # https://github.com/nextcloud/.github 4 | # https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization 5 | 6 | name: Psalm static analysis 7 | 8 | on: 9 | pull_request: 10 | paths: 11 | - .github/workflows/psalm.yml 12 | - appinfo/** 13 | - composer.* 14 | - lib/** 15 | - templates/** 16 | - tests/** 17 | push: 18 | branches: 19 | - main 20 | - stable* 21 | - test 22 | paths: 23 | - .github/workflows/psalm.yml 24 | - appinfo/** 25 | - composer.* 26 | - lib/** 27 | - templates/** 28 | - tests/** 29 | 30 | concurrency: 31 | group: psalm-${{ github.head_ref || github.run_id }} 32 | cancel-in-progress: true 33 | 34 | jobs: 35 | static-analysis: 36 | runs-on: ubuntu-latest 37 | strategy: 38 | # do not stop on another job's failure 39 | fail-fast: false 40 | matrix: 41 | ocp-version: ['^29', '^30', '^31', 'dev-master'] 42 | php-version: ['8.1', '8.2', '8.3'] 43 | 44 | 45 | name: Psalm check on PHP ${{ matrix.php-version }} and OCP ${{ matrix.ocp-version }} 46 | steps: 47 | - name: Checkout 48 | uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 49 | 50 | - name: Set up php 51 | uses: shivammathur/setup-php@7fdd3ece872ec7ec4c098ae5ab7637d5e0a96067 # v2 52 | with: 53 | php-version: ${{ matrix.php-version }} 54 | coverage: none 55 | ini-file: development 56 | env: 57 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 58 | 59 | - name: Install dependencies 60 | run: composer i 61 | 62 | - name: Install dependencies 63 | run: composer require --dev nextcloud/ocp:${{ matrix.ocp-version }} --ignore-platform-reqs --with-dependencies 64 | 65 | - name: Install dependencies 66 | run: composer require --dev 67 | 68 | - name: Run coding standards check 69 | run: composer run psalm 70 | 71 | summary: 72 | runs-on: ubuntu-latest 73 | needs: static-analysis 74 | 75 | if: always() 76 | 77 | name: static-psalm-analysis-summary 78 | 79 | steps: 80 | - name: Summary status 81 | run: if ${{ needs.static-analysis.result != 'success' }}; then exit 1; fi 82 | -------------------------------------------------------------------------------- /.github/workflows/reuse.yml: -------------------------------------------------------------------------------- 1 | # This workflow is provided via the organization template repository 2 | # 3 | # https://github.com/nextcloud/.github 4 | # https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization 5 | 6 | # SPDX-FileCopyrightText: 2022 Free Software Foundation Europe e.V. 7 | # 8 | # SPDX-License-Identifier: CC0-1.0 9 | 10 | name: REUSE Compliance Check 11 | 12 | on: [pull_request] 13 | 14 | jobs: 15 | reuse-compliance-check: 16 | runs-on: ubuntu-latest 17 | steps: 18 | - name: Checkout 19 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 20 | with: 21 | persist-credentials: false 22 | 23 | - name: REUSE Compliance Check 24 | uses: fsfe/reuse-action@bb774aa972c2a89ff34781233d275075cbddf542 # v5.0.0 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | js/ 2 | .code-workspace 3 | .DS_Store 4 | .idea/ 5 | .vscode/ 6 | .vscode-upload.json 7 | .*.sw* 8 | node_modules 9 | /vendor/ 10 | /tests/.phpunit.result.cache 11 | .php-cs-fixer.cache 12 | /vendor-bin/**/vendor/ -------------------------------------------------------------------------------- /.l10nignore: -------------------------------------------------------------------------------- 1 | # compiled vue templates 2 | js/ 3 | -------------------------------------------------------------------------------- /.nextcloudignore: -------------------------------------------------------------------------------- 1 | 2 | # SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors 3 | # SPDX-License-Identifier: AGPL-3.0-or-later 4 | .git 5 | .github 6 | .gitignore 7 | .tx 8 | .vscode 9 | .php-cs-fixer.* 10 | /.codecov.yml 11 | /.eslintrc.js 12 | /.gitattributes 13 | /.gitignore 14 | /.l10nignore 15 | /.nextcloudignore 16 | /.travis.yml 17 | /.pre-commit-config.yaml 18 | /babel.config.js 19 | /build 20 | /CODE_OF_CONDUCT.md 21 | /composer.* 22 | /node_modules 23 | /screenshots 24 | /src 25 | /vendor/bin 26 | /jest.config.js 27 | /Makefile 28 | /makefile 29 | /krankerl.toml 30 | /package-lock.json 31 | /package.json 32 | /postcss.config.js 33 | /psalm.xml 34 | /pyproject.toml 35 | /renovate.json 36 | /stylelint.config.js 37 | /webpack.config.js 38 | /webpack.js 39 | /vite.config.ts 40 | tests 41 | -------------------------------------------------------------------------------- /.php-cs-fixer.dist.php: -------------------------------------------------------------------------------- 1 | 5 | // SPDX-License-Identifier: AGPL-3.0-or-later 6 | 7 | require_once './vendor/autoload.php'; 8 | require_once './vendor-bin/php-cs-fixer/vendor/autoload.php'; 9 | 10 | use Nextcloud\CodingStandard\Config; 11 | 12 | $config = new Config(); 13 | $config 14 | ->getFinder() 15 | ->ignoreVCSIgnored(true) 16 | ->notPath('build') 17 | ->notPath('l10n') 18 | ->notPath('src') 19 | ->notPath('vendor') 20 | ->in(__DIR__); 21 | return $config; 22 | -------------------------------------------------------------------------------- /.tx/config: -------------------------------------------------------------------------------- 1 | [main] 2 | host = https://www.transifex.com 3 | lang_map = hu_HU: hu, nb_NO: nb, sk_SK: sk, th_TH: th, ja_JP: ja, bg_BG: bg, cs_CZ: cs, fi_FI: fi 4 | 5 | [o:nextcloud:p:nextcloud:r:integration_github] 6 | file_filter = translationfiles//integration_github.po 7 | source_file = translationfiles/templates/integration_github.pot 8 | source_lang = en 9 | type = PO 10 | 11 | -------------------------------------------------------------------------------- /AUTHORS.md: -------------------------------------------------------------------------------- 1 | 5 | # Authors 6 | 7 | - Anupam Kumar 8 | - Julien Veyssier 9 | - Sami Finnilä 10 | -------------------------------------------------------------------------------- /LICENSES/LicenseRef-GithubTrademarks.txt: -------------------------------------------------------------------------------- 1 | GitHub Logos and Usage 2 | 3 | We’ve put together some guidelines for those times when you want to use our logos to show off your GitHub integration or link back to us. Happy coding! 4 | 5 | 6 | Do these awesome things 7 | 8 | * Use a permitted GitHub logo to link to GitHub. 9 | * Use the Invertocat logo as a social button to link to your GitHub profile or project. 10 | * Use a permitted GitHub logo to inform others that your project integrates with GitHub. 11 | * Use the GitHub logo in a blog post or news article about GitHub. 12 | * Use the permitted GitHub logos less prominently than your own company or product name or logo. 13 | 14 | Please don’t do these things 15 | 16 | * Do not use the GitHub name or any GitHub logo in a way that suggests you are GitHub, your offering or project is by GitHub, or that GitHub is endorsing you or your offering or project. 17 | * Do not use any GitHub logo as the icon or logo for your business/organization, offering, project, domain name, social media account, or website. 18 | * Do not modify the permitted GitHub logos, including changing the color, dimensions, or combining with other words or design elements. 19 | * Do not use GitHub trademarks, logos, or artwork without GitHub’s prior written permission. 20 | 21 | 22 | Legal 23 | 24 | In short, the GitHub logos represent only GitHub and should not be used to represent you or your projects, products, or company. You may also 25 | if you’re into that. 26 | 27 | 28 | Logo and Octocat terms of use 29 | 30 | GITHUB®, the GITHUB® logo design, the INVERTOCAT logo design, OCTOCAT®, and the OCTOCAT® logo design are trademarks of GitHub, Inc., registered in the United States and other countries. 31 | 32 | The OCTOCAT design is the exclusive property of GitHub, Inc and has been federally registered with the United States Copyright Office. All rights reserved. 33 | 34 | No adaptation or use of any kind of any of our registered trademarks or copyrights, or any other contents of this website, is allowed without the express written permission of GitHub, Inc. 35 | 36 | For more information regarding the authorized uses of these items, please contact us (https://github.com/contact). 37 | 38 | 39 | A copy can be found at https://github.com/logos 40 | -------------------------------------------------------------------------------- /LICENSES/MIT.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 5 | # GitHub integration in Nextcloud 6 | 7 | [![REUSE status](https://api.reuse.software/badge/github.com/nextcloud/integration_github)](https://api.reuse.software/info/github.com/nextcloud/integration_github) 8 | 9 | 🐙 Put an octopus in your engine! 10 | 11 | This app adds: 12 | * A dashboard widget to see your most important GitHub notifications 13 | * A search provider for repositories, issues and pull requests 14 | * A link reference provider to render links to issues, pull requests and comments in Talk and Text 15 | 16 | ## 🔧 Configuration 17 | 18 | ### User settings 19 | 20 | The account configuration happens in the "Connected accounts" user settings section. It requires to create a personal access token in your GitHub settings. 21 | 22 | A link to the "Connected accounts" user settings section will be displayed in the widget for users who didn't configure a GitHub account. 23 | 24 | ### Admin settings 25 | 26 | There also is a "Connected accounts" **admin** settings section if you want to allow your Nextcloud users to use OAuth to authenticate to GitHub. 27 | -------------------------------------------------------------------------------- /REUSE.toml: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors 2 | # SPDX-License-Identifier: AGPL-3.0-or-later 3 | version = 1 4 | SPDX-PackageName = "integration_github" 5 | SPDX-PackageSupplier = "Nextcloud " 6 | SPDX-PackageDownloadLocation = "https://github.com/nextcloud/integration_github" 7 | 8 | [[annotations]] 9 | path = [".gitattributes", ".github/**", ".editorconfig", "babel.config.js", ".php-cs-fixer.dist.php", "package-lock.json", "package.json", "composer.json", "composer.lock", "webpack.js", "stylelint.config.js", ".eslintrc.js", ".gitignore", ".jshintrc", ".l10nignore", "action/.gitignore", "action/package.json", "action/package-lock.json", "action/dist/index.js", "tests/**", "psalm.xml", "cypress/.env", "cypress/.eslintrc.js", "cypress/docker-compose.yml", "cypress/plugins/index.js", "cypress/tsconfig.json", "cypress.config.ts", "vendor-bin/**/composer.json", "stylelint.config.cjs", "vendor-bin/**/composer.lock", ".tx/config", "webpack.config.js", "tsconfig.json", "vite.config.ts", "js/vendor.LICENSE.txt", "krankerl.toml", ".npmignore", "cypress/fixtures/**", "postcss.config.js", "cypress/dockerNode.ts", "jest.config.js"] 10 | precedence = "aggregate" 11 | SPDX-FileCopyrightText = "none" 12 | SPDX-License-Identifier = "CC0-1.0" 13 | 14 | [[annotations]] 15 | path = ["l10n/**.js", "l10n/**.json", "js/**.js.map", "js/**.js", "js/**.mjs", "js/**.mjs.map", "js/templates/**.handlebars", "img/screenshot1.jpg"] 16 | precedence = "aggregate" 17 | SPDX-FileCopyrightText = "2020 Nextcloud GmbH and Nextcloud contributors" 18 | SPDX-License-Identifier = "AGPL-3.0-or-later" 19 | 20 | [[annotations]] 21 | path = ["img/app.svg", "img/app-dark.svg", "img/issue-dark.svg", "img/issue-white.svg", "img/pull_request-dark.svg", "img/pull_request-white.svg", "img/repo-dark.svg", "img/repo-white.svg"] 22 | precedence = "aggregate" 23 | SPDX-FileCopyrightText = "2020 GitHub, Inc." 24 | SPDX-License-Identifier = "LicenseRef-GithubTrademarks" 25 | 26 | [[annotations]] 27 | path = ["img/release.svg", "img/issue.svg", "img/pull_request.svg", "img/unsub.svg"] 28 | precedence = "aggregate" 29 | SPDX-FileCopyrightText = "2018-2024 Google LLC" 30 | SPDX-License-Identifier = "Apache-2.0" 31 | 32 | [[annotations]] 33 | path = "img/reactions/**" 34 | precedence = "aggregate" 35 | SPDX-FileCopyrightText = "2018-2024 Google LLC / Noto Emoji Project (https://github.com/googlefonts/noto-emoji)" 36 | SPDX-License-Identifier = "Apache-2.0" 37 | -------------------------------------------------------------------------------- /appinfo/info.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | integration_github 8 | GitHub integration 9 | Integration of GitHub software development management service 10 | 13 | 3.2.1 14 | agpl 15 | Julien Veyssier 16 | Github 17 | 18 | https://github.com/nextcloud/integration_github 19 | 20 | integration 21 | dashboard 22 | https://github.com/nextcloud/integration_github 23 | https://github.com/nextcloud/integration_github/issues 24 | https://github.com/nextcloud/integration_github/raw/main/img/screenshot1.jpg 25 | 26 | 27 | 28 | 29 | OCA\Github\BackgroundJob\CheckGithubNotificationsJob 30 | 31 | 32 | OCA\Github\Settings\Admin 33 | OCA\Github\Settings\AdminSection 34 | OCA\Github\Settings\Personal 35 | OCA\Github\Settings\PersonalSection 36 | 37 | 38 | -------------------------------------------------------------------------------- /appinfo/routes.php: -------------------------------------------------------------------------------- 1 | [ 10 | ['name' => 'config#oauthRedirect', 'url' => '/oauth-redirect', 'verb' => 'GET'], 11 | ['name' => 'config#setConfig', 'url' => '/config', 'verb' => 'PUT'], 12 | ['name' => 'config#setAdminConfig', 'url' => '/admin-config', 'verb' => 'PUT'], 13 | ['name' => 'config#setSensitiveAdminConfig', 'url' => '/sensitive-admin-config', 'verb' => 'PUT'], 14 | ['name' => 'config#popupSuccessPage', 'url' => '/popup-success', 'verb' => 'GET'], 15 | 16 | ['name' => 'githubAPI#getNotifications', 'url' => '/notifications', 'verb' => 'GET'], 17 | ['name' => 'githubAPI#unsubscribeNotification', 'url' => '/notifications/{id}/unsubscribe', 'verb' => 'PUT'], 18 | ['name' => 'githubAPI#markNotificationAsRead', 'url' => '/notifications/{id}/mark-read', 'verb' => 'PUT'], 19 | ['name' => 'githubAPI#getAvatar', 'url' => '/avatar/{githubLogin}', 'verb' => 'GET'], 20 | // get user/issue/pr information 21 | ['name' => 'githubAPI#getUserInfo', 'url' => '/users/{githubUserLogin}', 'verb' => 'GET'], 22 | ['name' => 'githubAPI#getContextualUserInfo', 'url' => '/users/{githubUserLogin}/hovercard/{subjectType}/{subjectId}', 'verb' => 'GET'], 23 | ['name' => 'githubAPI#getIssueInfo', 'url' => '/repos/{owner}/{repo}/issues/{issueNumber}', 'verb' => 'GET'], 24 | ['name' => 'githubAPI#getIssueReactionsInfo', 'url' => '/repos/{owner}/{repo}/issues/{issueNumber}/reactions', 'verb' => 'GET'], 25 | ['name' => 'githubAPI#getIssueCommentInfo', 'url' => '/repos/{owner}/{repo}/issues/comments/{commentId}', 'verb' => 'GET'], 26 | ['name' => 'githubAPI#getIssueCommentReactionsInfo', 'url' => '/repos/{owner}/{repo}/issues/comments/{commentId}/reactions', 'verb' => 'GET'], 27 | ['name' => 'githubAPI#getPrInfo', 'url' => '/repos/{owner}/{repo}/pulls/{prNumber}', 'verb' => 'GET'], 28 | ] 29 | ]; 30 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nextcloud/integration_github", 3 | "authors": [ 4 | { 5 | "name": "Julien Veyssier", 6 | "email": "julien-nc@posteo.net" 7 | } 8 | ], 9 | "require": { 10 | "league/commonmark": "^2.3", 11 | "php": "^8.1", 12 | "bamarni/composer-bin-plugin": "^1.8" 13 | }, 14 | "scripts": { 15 | "lint": "find . -name \\*.php -not -path './vendor*' -print0 | xargs -0 -n1 php -l", 16 | "cs:check": "php-cs-fixer fix --dry-run --diff", 17 | "cs:fix": "php-cs-fixer fix", 18 | "psalm": "psalm.phar --no-cache", 19 | "test:unit": "phpunit -c tests/phpunit.xml --no-coverage", 20 | "post-install-cmd": [ 21 | "@composer bin all install --ansi", 22 | "composer dump-autoload" 23 | ], 24 | "post-update-cmd": [ 25 | "@composer bin all update --ansi", 26 | "composer dump-autoload" 27 | ] 28 | }, 29 | "config": { 30 | "optimize-autoloader": true, 31 | "classmap-authoritative": true, 32 | "platform": { 33 | "php": "8.1" 34 | }, 35 | "allow-plugins": { 36 | "bamarni/composer-bin-plugin": true, 37 | "composer/package-versions-deprecated": true 38 | } 39 | }, 40 | "require-dev": { 41 | "ext-mbstring": "*", 42 | "nextcloud/ocp": "dev-master" 43 | }, 44 | "extra": { 45 | "bamarni-bin": { 46 | "bin-links": true, 47 | "target-directory": "vendor-bin", 48 | "forward-command": true 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /css/dashboard.css: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors 3 | * SPDX-License-Identifier: AGPL-3.0-or-later 4 | */ 5 | .icon-github { 6 | background-image: url('../img/app-dark.svg'); 7 | filter: var(--background-invert-if-dark); 8 | } 9 | 10 | body.theme--dark .icon-github { 11 | background-image: url('../img/app.svg'); 12 | } 13 | 14 | .icon-github-unsubscribe { 15 | background-color: var(--color-main-text); 16 | padding: 0 !important; 17 | mask: url('../img/unsub.svg') no-repeat; 18 | mask-size: 18px 18px; 19 | mask-position: center; 20 | -webkit-mask: url('../img/unsub.svg') no-repeat; 21 | -webkit-mask-size: 18px 18px; 22 | -webkit-mask-position: center; 23 | min-width: 44px !important; 24 | min-height: 44px !important; 25 | } 26 | -------------------------------------------------------------------------------- /img/app-dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /img/app.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /img/issue.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 20 | 22 | image/svg+xml 23 | 25 | 26 | 27 | 28 | 30 | 50 | 62 | 67 | 68 | -------------------------------------------------------------------------------- /img/pull_request.svg: -------------------------------------------------------------------------------- 1 | 2 | 57 | -------------------------------------------------------------------------------- /img/reactions/confused.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nextcloud/integration_github/15249ea1ec9ac375e0d4074c59c74311f981249c/img/reactions/confused.png -------------------------------------------------------------------------------- /img/reactions/eyes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nextcloud/integration_github/15249ea1ec9ac375e0d4074c59c74311f981249c/img/reactions/eyes.png -------------------------------------------------------------------------------- /img/reactions/heart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nextcloud/integration_github/15249ea1ec9ac375e0d4074c59c74311f981249c/img/reactions/heart.png -------------------------------------------------------------------------------- /img/reactions/laugh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nextcloud/integration_github/15249ea1ec9ac375e0d4074c59c74311f981249c/img/reactions/laugh.png -------------------------------------------------------------------------------- /img/reactions/minus1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nextcloud/integration_github/15249ea1ec9ac375e0d4074c59c74311f981249c/img/reactions/minus1.png -------------------------------------------------------------------------------- /img/reactions/plus1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nextcloud/integration_github/15249ea1ec9ac375e0d4074c59c74311f981249c/img/reactions/plus1.png -------------------------------------------------------------------------------- /img/reactions/rocket.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nextcloud/integration_github/15249ea1ec9ac375e0d4074c59c74311f981249c/img/reactions/rocket.png -------------------------------------------------------------------------------- /img/reactions/tada.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nextcloud/integration_github/15249ea1ec9ac375e0d4074c59c74311f981249c/img/reactions/tada.png -------------------------------------------------------------------------------- /img/release.svg: -------------------------------------------------------------------------------- 1 | 2 | 58 | -------------------------------------------------------------------------------- /img/screenshot1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nextcloud/integration_github/15249ea1ec9ac375e0d4074c59c74311f981249c/img/screenshot1.jpg -------------------------------------------------------------------------------- /img/unsub.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /krankerl.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | before_cmds = [ 3 | "composer install --no-dev -a", 4 | "npm ci", 5 | "npm run build", 6 | ] 7 | -------------------------------------------------------------------------------- /l10n/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nextcloud/integration_github/15249ea1ec9ac375e0d4074c59c74311f981249c/l10n/.gitkeep -------------------------------------------------------------------------------- /l10n/af.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "integration_github", 3 | { 4 | "GitHub" : "GitHub", 5 | "Comment" : "Kommentaar", 6 | "Client ID" : "Kliënt-ID", 7 | "Unknown error" : "Onbekende fout", 8 | "Owner" : "Eienaar" 9 | }, 10 | "nplurals=2; plural=(n != 1);"); 11 | -------------------------------------------------------------------------------- /l10n/af.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "GitHub" : "GitHub", 3 | "Comment" : "Kommentaar", 4 | "Client ID" : "Kliënt-ID", 5 | "Unknown error" : "Onbekende fout", 6 | "Owner" : "Eienaar" 7 | },"pluralForm" :"nplurals=2; plural=(n != 1);" 8 | } -------------------------------------------------------------------------------- /l10n/ast.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "integration_github", 3 | { 4 | "GitHub" : "GitHub", 5 | "Comment" : "Comentariu", 6 | "Client ID" : "ID de veceru", 7 | "Client secret" : "Secretu de veceru", 8 | "Failed to save GitHub options" : "Nun se puen guardar les opciones de GitHub", 9 | "Loading..." : "Cargando...", 10 | "Failed to get GitHub notifications" : "Nun se puen consiguir los avisos de GitHub", 11 | "Failed to edit GitHub notification" : "Nun se pue editar l'avisu de GitHub", 12 | "Line {line}" : "Llinia {line}", 13 | "Unknown error" : "Error desconocíu", 14 | "Draft" : "Borrador", 15 | "Author" : "Autoría", 16 | "Owner" : "Propietariu" 17 | }, 18 | "nplurals=2; plural=(n != 1);"); 19 | -------------------------------------------------------------------------------- /l10n/ast.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "GitHub" : "GitHub", 3 | "Comment" : "Comentariu", 4 | "Client ID" : "ID de veceru", 5 | "Client secret" : "Secretu de veceru", 6 | "Failed to save GitHub options" : "Nun se puen guardar les opciones de GitHub", 7 | "Loading..." : "Cargando...", 8 | "Failed to get GitHub notifications" : "Nun se puen consiguir los avisos de GitHub", 9 | "Failed to edit GitHub notification" : "Nun se pue editar l'avisu de GitHub", 10 | "Line {line}" : "Llinia {line}", 11 | "Unknown error" : "Error desconocíu", 12 | "Draft" : "Borrador", 13 | "Author" : "Autoría", 14 | "Owner" : "Propietariu" 15 | },"pluralForm" :"nplurals=2; plural=(n != 1);" 16 | } -------------------------------------------------------------------------------- /l10n/az.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "integration_github", 3 | { 4 | "Comment" : "Komentariya", 5 | "Client ID" : "Müştəri İD-s", 6 | "Client secret" : "Müxtəri sirri", 7 | "Unknown error" : "Bəlli olmayan səhv baş verdi", 8 | "Owner" : "Owner" 9 | }, 10 | "nplurals=2; plural=(n != 1);"); 11 | -------------------------------------------------------------------------------- /l10n/az.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Comment" : "Komentariya", 3 | "Client ID" : "Müştəri İD-s", 4 | "Client secret" : "Müxtəri sirri", 5 | "Unknown error" : "Bəlli olmayan səhv baş verdi", 6 | "Owner" : "Owner" 7 | },"pluralForm" :"nplurals=2; plural=(n != 1);" 8 | } -------------------------------------------------------------------------------- /l10n/br.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "integration_github", 3 | { 4 | "GitHub" : "GitHub", 5 | "Comment" : "Displegadenn", 6 | "Client ID" : "ID kliant", 7 | "Unknown error" : "Fazi dizanv", 8 | "Owner" : "Perc'henner" 9 | }, 10 | "nplurals=5; plural=((n%10 == 1) && (n%100 != 11) && (n%100 !=71) && (n%100 !=91) ? 0 :(n%10 == 2) && (n%100 != 12) && (n%100 !=72) && (n%100 !=92) ? 1 :(n%10 ==3 || n%10==4 || n%10==9) && (n%100 < 10 || n% 100 > 19) && (n%100 < 70 || n%100 > 79) && (n%100 < 90 || n%100 > 99) ? 2 :(n != 0 && n % 1000000 == 0) ? 3 : 4);"); 11 | -------------------------------------------------------------------------------- /l10n/br.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "GitHub" : "GitHub", 3 | "Comment" : "Displegadenn", 4 | "Client ID" : "ID kliant", 5 | "Unknown error" : "Fazi dizanv", 6 | "Owner" : "Perc'henner" 7 | },"pluralForm" :"nplurals=5; plural=((n%10 == 1) && (n%100 != 11) && (n%100 !=71) && (n%100 !=91) ? 0 :(n%10 == 2) && (n%100 != 12) && (n%100 !=72) && (n%100 !=92) ? 1 :(n%10 ==3 || n%10==4 || n%10==9) && (n%100 < 10 || n% 100 > 19) && (n%100 < 70 || n%100 > 79) && (n%100 < 90 || n%100 > 99) ? 2 :(n != 0 && n % 1000000 == 0) ? 3 : 4);" 8 | } -------------------------------------------------------------------------------- /l10n/ca.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "integration_github", 3 | { 4 | "GitHub" : "GitHub", 5 | "Error getting OAuth access token" : "S'ha produït un error en obtenir el testimoni d'accés d'OAuth", 6 | "Error during OAuth exchanges" : "S'ha produït un error durant els intercanvis d'OAuth", 7 | "GitHub notifications" : "Notificacions de GitHub", 8 | "Comment" : "Comentari", 9 | "GitHub issues and pull requests" : "Problemes i sol·licituds d'incorporació de GitHub", 10 | "GitHub repositories" : "Dipòsits de GitHub", 11 | "Bad HTTP method" : "Mètode HTTP incorrecte", 12 | "Bad credentials" : "Credencials incorrectes", 13 | "OAuth access token refused" : "S'ha rebutjat el testimoni d'accés d'OAuth", 14 | "Connected accounts" : "Comptes connectats", 15 | "GitHub integration" : "Integració de GitHub", 16 | "Integration of GitHub software development management service" : "Integració de Github, servei d'administració del desenvolupament de programari", 17 | "GitHub admin options saved" : "S'han desat les opcions d'administració de GitHub", 18 | "Failed to save GitHub admin options" : "No s'han pogut desar les opcions d'administració de GitHub", 19 | "If you want to allow your Nextcloud users to use OAuth to authenticate to https://github.com, create an OAuth application in your GitHub settings." : "Si voleu permetre que els usuaris del Nextcloud puguin utilitzar OAuth per a autenticar-se a https://github.com, creeu una aplicació d'OAuth en els paràmetres de GitHub.", 20 | "GitHub OAuth settings" : "Paràmetres d'OAuth de GitHub", 21 | "Your Nextcloud users will then see a \"Connect to GitHub\" button in their personal settings." : "Els usuaris del Nextcloud veuran un botó «Connecta't a GitHub» en els paràmetres personals.", 22 | "Client ID" : "ID del client", 23 | "Client ID of your GitHub application" : "ID del client de l'aplicació de GitHub", 24 | "Client secret" : "Secret del client", 25 | "Client secret of your GitHub application" : "Secret del client de l'aplicació de GitHub", 26 | "Connected as {user}" : "Connectat com a {user}", 27 | "Connected to GitHub!" : "S'ha connectat a GitHub!", 28 | "GitHub OAuth error:" : "Error d'OAuth de GitHub:", 29 | "GitHub options saved" : "S'han desat les opcions de GitHub", 30 | "Failed to save GitHub options" : "No s'han pogut desar les opcions de GitHub", 31 | "Enable navigation link" : "Habilita l'enllaç de navegació", 32 | "When you create a personal access token yourself, give it at least \"read:user\", \"user:email\" and \"notifications\" permissions." : "Quan creeu un testimoni d'accés personal, doneu-li com a mínim els permisos «read:user», «user:email» i «notifications».", 33 | "GitHub personal access tokens" : "Testimonis d'accés personal de GitHub", 34 | "Personal access token" : "Testimoni d'accés personal", 35 | "Disconnect from GitHub" : "Desconnecta't de GitHub", 36 | "Enable searching for repositories" : "Habilita la cerca de dipòsits", 37 | "Enable searching for issues and pull requests" : "Habilita la cerca de problemes i sol·licituds d'incorporació", 38 | "Warning, everything you type in the search bar will be sent to GitHub." : "Avís: tot el que escriviu en la barra de cerca s'enviarà a GitHub.", 39 | "Mark as read" : "Marca com a llegit", 40 | "Unsubscribe" : "Cancel·la la subscripció", 41 | "No GitHub account connected" : "No s'ha connectat cap compte de GitHub", 42 | "Error connecting to GitHub" : "S'ha produït un error en connectar-se a GitHub", 43 | "No GitHub notifications!" : "No hi ha cap notificació de GitHub!", 44 | "Loading..." : "Carregant...", 45 | "Failed to get GitHub notifications" : "No s'han pogut obtenir les notificacions de GitHub", 46 | "Successfully unsubscribed" : "La subscripció s'ha cancel·lat correctament", 47 | "Failed to edit GitHub notification" : "No s'ha pogut editar la notificació de GitHub", 48 | "Connect to GitHub" : "Connecta't a GitHub", 49 | "Line {line}" : "Línia {line}", 50 | "Unknown error" : "Error desconegut", 51 | "Draft" : "Esborrany", 52 | "by {creator}" : "per {creator}", 53 | "Author" : "Autor/a", 54 | "Owner" : "Propietari", 55 | "Failed to save GitHub OAuth state" : "No s'ha pogut desar l'estat d'OAuth de GitHub" 56 | }, 57 | "nplurals=2; plural=(n != 1);"); 58 | -------------------------------------------------------------------------------- /l10n/ca.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "GitHub" : "GitHub", 3 | "Error getting OAuth access token" : "S'ha produït un error en obtenir el testimoni d'accés d'OAuth", 4 | "Error during OAuth exchanges" : "S'ha produït un error durant els intercanvis d'OAuth", 5 | "GitHub notifications" : "Notificacions de GitHub", 6 | "Comment" : "Comentari", 7 | "GitHub issues and pull requests" : "Problemes i sol·licituds d'incorporació de GitHub", 8 | "GitHub repositories" : "Dipòsits de GitHub", 9 | "Bad HTTP method" : "Mètode HTTP incorrecte", 10 | "Bad credentials" : "Credencials incorrectes", 11 | "OAuth access token refused" : "S'ha rebutjat el testimoni d'accés d'OAuth", 12 | "Connected accounts" : "Comptes connectats", 13 | "GitHub integration" : "Integració de GitHub", 14 | "Integration of GitHub software development management service" : "Integració de Github, servei d'administració del desenvolupament de programari", 15 | "GitHub admin options saved" : "S'han desat les opcions d'administració de GitHub", 16 | "Failed to save GitHub admin options" : "No s'han pogut desar les opcions d'administració de GitHub", 17 | "If you want to allow your Nextcloud users to use OAuth to authenticate to https://github.com, create an OAuth application in your GitHub settings." : "Si voleu permetre que els usuaris del Nextcloud puguin utilitzar OAuth per a autenticar-se a https://github.com, creeu una aplicació d'OAuth en els paràmetres de GitHub.", 18 | "GitHub OAuth settings" : "Paràmetres d'OAuth de GitHub", 19 | "Your Nextcloud users will then see a \"Connect to GitHub\" button in their personal settings." : "Els usuaris del Nextcloud veuran un botó «Connecta't a GitHub» en els paràmetres personals.", 20 | "Client ID" : "ID del client", 21 | "Client ID of your GitHub application" : "ID del client de l'aplicació de GitHub", 22 | "Client secret" : "Secret del client", 23 | "Client secret of your GitHub application" : "Secret del client de l'aplicació de GitHub", 24 | "Connected as {user}" : "Connectat com a {user}", 25 | "Connected to GitHub!" : "S'ha connectat a GitHub!", 26 | "GitHub OAuth error:" : "Error d'OAuth de GitHub:", 27 | "GitHub options saved" : "S'han desat les opcions de GitHub", 28 | "Failed to save GitHub options" : "No s'han pogut desar les opcions de GitHub", 29 | "Enable navigation link" : "Habilita l'enllaç de navegació", 30 | "When you create a personal access token yourself, give it at least \"read:user\", \"user:email\" and \"notifications\" permissions." : "Quan creeu un testimoni d'accés personal, doneu-li com a mínim els permisos «read:user», «user:email» i «notifications».", 31 | "GitHub personal access tokens" : "Testimonis d'accés personal de GitHub", 32 | "Personal access token" : "Testimoni d'accés personal", 33 | "Disconnect from GitHub" : "Desconnecta't de GitHub", 34 | "Enable searching for repositories" : "Habilita la cerca de dipòsits", 35 | "Enable searching for issues and pull requests" : "Habilita la cerca de problemes i sol·licituds d'incorporació", 36 | "Warning, everything you type in the search bar will be sent to GitHub." : "Avís: tot el que escriviu en la barra de cerca s'enviarà a GitHub.", 37 | "Mark as read" : "Marca com a llegit", 38 | "Unsubscribe" : "Cancel·la la subscripció", 39 | "No GitHub account connected" : "No s'ha connectat cap compte de GitHub", 40 | "Error connecting to GitHub" : "S'ha produït un error en connectar-se a GitHub", 41 | "No GitHub notifications!" : "No hi ha cap notificació de GitHub!", 42 | "Loading..." : "Carregant...", 43 | "Failed to get GitHub notifications" : "No s'han pogut obtenir les notificacions de GitHub", 44 | "Successfully unsubscribed" : "La subscripció s'ha cancel·lat correctament", 45 | "Failed to edit GitHub notification" : "No s'ha pogut editar la notificació de GitHub", 46 | "Connect to GitHub" : "Connecta't a GitHub", 47 | "Line {line}" : "Línia {line}", 48 | "Unknown error" : "Error desconegut", 49 | "Draft" : "Esborrany", 50 | "by {creator}" : "per {creator}", 51 | "Author" : "Autor/a", 52 | "Owner" : "Propietari", 53 | "Failed to save GitHub OAuth state" : "No s'ha pogut desar l'estat d'OAuth de GitHub" 54 | },"pluralForm" :"nplurals=2; plural=(n != 1);" 55 | } -------------------------------------------------------------------------------- /l10n/da.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "integration_github", 3 | { 4 | "GitHub" : "GitHub", 5 | "Error getting OAuth access token" : "Fejl ved anmodning om OAuth adgangsnøgle", 6 | "Error during OAuth exchanges" : "Fejl under OAuth-udvekslinger", 7 | "Comment" : "Kommenter", 8 | "Bad HTTP method" : "Dårlig HTTP metode", 9 | "Bad credentials" : "Forkerte legitimationsoplysninger", 10 | "OAuth access token refused" : "OAuth adgangsnøgle afvist", 11 | "Connected accounts" : "Forbundne konti", 12 | "Client ID" : "Klient ID", 13 | "Client secret" : "Klienthemmelighed", 14 | "Connected as {user}" : "Forbundet som {user}", 15 | "Enable navigation link" : "Aktiver navigationslink", 16 | "Personal access token" : "Personligt adgangstoken", 17 | "Mark as read" : "Marker som læst", 18 | "Loading..." : "Indlæser...", 19 | "Line {line}" : "Linje {line}", 20 | "Unknown error" : "Ukendt fejl", 21 | "Draft" : "Kladde", 22 | "by {creator}" : "af {creator}", 23 | "Author" : "Forfatter", 24 | "Owner" : "Ejer" 25 | }, 26 | "nplurals=2; plural=(n != 1);"); 27 | -------------------------------------------------------------------------------- /l10n/da.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "GitHub" : "GitHub", 3 | "Error getting OAuth access token" : "Fejl ved anmodning om OAuth adgangsnøgle", 4 | "Error during OAuth exchanges" : "Fejl under OAuth-udvekslinger", 5 | "Comment" : "Kommenter", 6 | "Bad HTTP method" : "Dårlig HTTP metode", 7 | "Bad credentials" : "Forkerte legitimationsoplysninger", 8 | "OAuth access token refused" : "OAuth adgangsnøgle afvist", 9 | "Connected accounts" : "Forbundne konti", 10 | "Client ID" : "Klient ID", 11 | "Client secret" : "Klienthemmelighed", 12 | "Connected as {user}" : "Forbundet som {user}", 13 | "Enable navigation link" : "Aktiver navigationslink", 14 | "Personal access token" : "Personligt adgangstoken", 15 | "Mark as read" : "Marker som læst", 16 | "Loading..." : "Indlæser...", 17 | "Line {line}" : "Linje {line}", 18 | "Unknown error" : "Ukendt fejl", 19 | "Draft" : "Kladde", 20 | "by {creator}" : "af {creator}", 21 | "Author" : "Forfatter", 22 | "Owner" : "Ejer" 23 | },"pluralForm" :"nplurals=2; plural=(n != 1);" 24 | } -------------------------------------------------------------------------------- /l10n/eo.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "integration_github", 3 | { 4 | "Comment" : "Komento", 5 | "Client ID" : "Klientidentigilo", 6 | "Client secret" : "Klientosekreto", 7 | "Unknown error" : "Nekonata eraro", 8 | "Owner" : "Posedanto" 9 | }, 10 | "nplurals=2; plural=(n != 1);"); 11 | -------------------------------------------------------------------------------- /l10n/eo.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Comment" : "Komento", 3 | "Client ID" : "Klientidentigilo", 4 | "Client secret" : "Klientosekreto", 5 | "Unknown error" : "Nekonata eraro", 6 | "Owner" : "Posedanto" 7 | },"pluralForm" :"nplurals=2; plural=(n != 1);" 8 | } -------------------------------------------------------------------------------- /l10n/es_419.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "integration_github", 3 | { 4 | "Comment" : "Comentario", 5 | "Client ID" : "ID del cliente", 6 | "Client secret" : "Secreto del cliente", 7 | "Loading..." : "Cargando...", 8 | "Unknown error" : "Error desconocido", 9 | "Owner" : "Dueño" 10 | }, 11 | "nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"); 12 | -------------------------------------------------------------------------------- /l10n/es_419.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Comment" : "Comentario", 3 | "Client ID" : "ID del cliente", 4 | "Client secret" : "Secreto del cliente", 5 | "Loading..." : "Cargando...", 6 | "Unknown error" : "Error desconocido", 7 | "Owner" : "Dueño" 8 | },"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;" 9 | } -------------------------------------------------------------------------------- /l10n/es_AR.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "integration_github", 3 | { 4 | "GitHub" : "GitHub", 5 | "Comment" : "Comentario", 6 | "Client ID" : "ID del cliente", 7 | "Client secret" : "Secreto del cliente", 8 | "Loading..." : "Cargando...", 9 | "Unknown error" : "Error desconocido", 10 | "Owner" : "Dueño" 11 | }, 12 | "nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"); 13 | -------------------------------------------------------------------------------- /l10n/es_AR.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "GitHub" : "GitHub", 3 | "Comment" : "Comentario", 4 | "Client ID" : "ID del cliente", 5 | "Client secret" : "Secreto del cliente", 6 | "Loading..." : "Cargando...", 7 | "Unknown error" : "Error desconocido", 8 | "Owner" : "Dueño" 9 | },"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;" 10 | } -------------------------------------------------------------------------------- /l10n/es_CL.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "integration_github", 3 | { 4 | "Comment" : "Comentario", 5 | "Client ID" : "ID del cliente", 6 | "Client secret" : "Secreto del cliente", 7 | "Loading..." : "Cargando...", 8 | "Unknown error" : "Se presentó un error desconocido", 9 | "Owner" : "Dueño" 10 | }, 11 | "nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"); 12 | -------------------------------------------------------------------------------- /l10n/es_CL.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Comment" : "Comentario", 3 | "Client ID" : "ID del cliente", 4 | "Client secret" : "Secreto del cliente", 5 | "Loading..." : "Cargando...", 6 | "Unknown error" : "Se presentó un error desconocido", 7 | "Owner" : "Dueño" 8 | },"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;" 9 | } -------------------------------------------------------------------------------- /l10n/es_CO.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "integration_github", 3 | { 4 | "Comment" : "Comentario", 5 | "Client ID" : "ID del cliente", 6 | "Client secret" : "Secreto del cliente", 7 | "Loading..." : "Cargando...", 8 | "Unknown error" : "Error desconocido", 9 | "Owner" : "Dueño" 10 | }, 11 | "nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"); 12 | -------------------------------------------------------------------------------- /l10n/es_CO.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Comment" : "Comentario", 3 | "Client ID" : "ID del cliente", 4 | "Client secret" : "Secreto del cliente", 5 | "Loading..." : "Cargando...", 6 | "Unknown error" : "Error desconocido", 7 | "Owner" : "Dueño" 8 | },"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;" 9 | } -------------------------------------------------------------------------------- /l10n/es_CR.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "integration_github", 3 | { 4 | "Comment" : "Comentario", 5 | "Client ID" : "ID del cliente", 6 | "Client secret" : "Secreto del cliente", 7 | "Loading..." : "Cargando...", 8 | "Unknown error" : "Error desconocido", 9 | "Owner" : "Dueño" 10 | }, 11 | "nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"); 12 | -------------------------------------------------------------------------------- /l10n/es_CR.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Comment" : "Comentario", 3 | "Client ID" : "ID del cliente", 4 | "Client secret" : "Secreto del cliente", 5 | "Loading..." : "Cargando...", 6 | "Unknown error" : "Error desconocido", 7 | "Owner" : "Dueño" 8 | },"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;" 9 | } -------------------------------------------------------------------------------- /l10n/es_DO.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "integration_github", 3 | { 4 | "Comment" : "Comentario", 5 | "Client ID" : "ID del cliente", 6 | "Client secret" : "Secreto del cliente", 7 | "Loading..." : "Cargando...", 8 | "Unknown error" : "Error desconocido", 9 | "Owner" : "Dueño" 10 | }, 11 | "nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"); 12 | -------------------------------------------------------------------------------- /l10n/es_DO.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Comment" : "Comentario", 3 | "Client ID" : "ID del cliente", 4 | "Client secret" : "Secreto del cliente", 5 | "Loading..." : "Cargando...", 6 | "Unknown error" : "Error desconocido", 7 | "Owner" : "Dueño" 8 | },"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;" 9 | } -------------------------------------------------------------------------------- /l10n/es_GT.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "integration_github", 3 | { 4 | "Comment" : "Comentario", 5 | "Client ID" : "ID del cliente", 6 | "Client secret" : "Secreto del cliente", 7 | "Loading..." : "Cargando...", 8 | "Unknown error" : "Error desconocido", 9 | "Owner" : "Dueño" 10 | }, 11 | "nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"); 12 | -------------------------------------------------------------------------------- /l10n/es_GT.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Comment" : "Comentario", 3 | "Client ID" : "ID del cliente", 4 | "Client secret" : "Secreto del cliente", 5 | "Loading..." : "Cargando...", 6 | "Unknown error" : "Error desconocido", 7 | "Owner" : "Dueño" 8 | },"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;" 9 | } -------------------------------------------------------------------------------- /l10n/es_HN.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "integration_github", 3 | { 4 | "Comment" : "Comentario", 5 | "Client ID" : "ID del cliente", 6 | "Client secret" : "Secreto del cliente", 7 | "Loading..." : "Cargando...", 8 | "Unknown error" : "Error desconocido", 9 | "Owner" : "Dueño" 10 | }, 11 | "nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"); 12 | -------------------------------------------------------------------------------- /l10n/es_HN.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Comment" : "Comentario", 3 | "Client ID" : "ID del cliente", 4 | "Client secret" : "Secreto del cliente", 5 | "Loading..." : "Cargando...", 6 | "Unknown error" : "Error desconocido", 7 | "Owner" : "Dueño" 8 | },"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;" 9 | } -------------------------------------------------------------------------------- /l10n/es_MX.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "integration_github", 3 | { 4 | "Comment" : "Comentario", 5 | "Client ID" : "ID del cliente", 6 | "Client secret" : "Secreto del cliente", 7 | "Loading..." : "Cargando...", 8 | "Line {line}" : "Línea {line}", 9 | "Unknown error" : "Se presentó un error desconocido", 10 | "Author" : "Autor", 11 | "Owner" : "Dueño" 12 | }, 13 | "nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"); 14 | -------------------------------------------------------------------------------- /l10n/es_MX.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Comment" : "Comentario", 3 | "Client ID" : "ID del cliente", 4 | "Client secret" : "Secreto del cliente", 5 | "Loading..." : "Cargando...", 6 | "Line {line}" : "Línea {line}", 7 | "Unknown error" : "Se presentó un error desconocido", 8 | "Author" : "Autor", 9 | "Owner" : "Dueño" 10 | },"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;" 11 | } -------------------------------------------------------------------------------- /l10n/es_NI.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "integration_github", 3 | { 4 | "Comment" : "Comentario", 5 | "Client ID" : "ID del cliente", 6 | "Client secret" : "Secreto del cliente", 7 | "Loading..." : "Cargando...", 8 | "Unknown error" : "Error desconocido", 9 | "Owner" : "Dueño" 10 | }, 11 | "nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"); 12 | -------------------------------------------------------------------------------- /l10n/es_NI.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Comment" : "Comentario", 3 | "Client ID" : "ID del cliente", 4 | "Client secret" : "Secreto del cliente", 5 | "Loading..." : "Cargando...", 6 | "Unknown error" : "Error desconocido", 7 | "Owner" : "Dueño" 8 | },"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;" 9 | } -------------------------------------------------------------------------------- /l10n/es_PA.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "integration_github", 3 | { 4 | "Comment" : "Comentario", 5 | "Client ID" : "ID del cliente", 6 | "Client secret" : "Secreto del cliente", 7 | "Loading..." : "Cargando...", 8 | "Unknown error" : "Error desconocido", 9 | "Owner" : "Dueño" 10 | }, 11 | "nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"); 12 | -------------------------------------------------------------------------------- /l10n/es_PA.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Comment" : "Comentario", 3 | "Client ID" : "ID del cliente", 4 | "Client secret" : "Secreto del cliente", 5 | "Loading..." : "Cargando...", 6 | "Unknown error" : "Error desconocido", 7 | "Owner" : "Dueño" 8 | },"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;" 9 | } -------------------------------------------------------------------------------- /l10n/es_PE.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "integration_github", 3 | { 4 | "Comment" : "Comentario", 5 | "Client ID" : "ID del cliente", 6 | "Client secret" : "Secreto del cliente", 7 | "Loading..." : "Cargando...", 8 | "Unknown error" : "Error desconocido", 9 | "Owner" : "Dueño" 10 | }, 11 | "nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"); 12 | -------------------------------------------------------------------------------- /l10n/es_PE.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Comment" : "Comentario", 3 | "Client ID" : "ID del cliente", 4 | "Client secret" : "Secreto del cliente", 5 | "Loading..." : "Cargando...", 6 | "Unknown error" : "Error desconocido", 7 | "Owner" : "Dueño" 8 | },"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;" 9 | } -------------------------------------------------------------------------------- /l10n/es_PR.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "integration_github", 3 | { 4 | "Comment" : "Comentario", 5 | "Client ID" : "ID del cliente", 6 | "Client secret" : "Secreto del cliente", 7 | "Loading..." : "Cargando...", 8 | "Unknown error" : "Error desconocido", 9 | "Owner" : "Dueño" 10 | }, 11 | "nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"); 12 | -------------------------------------------------------------------------------- /l10n/es_PR.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Comment" : "Comentario", 3 | "Client ID" : "ID del cliente", 4 | "Client secret" : "Secreto del cliente", 5 | "Loading..." : "Cargando...", 6 | "Unknown error" : "Error desconocido", 7 | "Owner" : "Dueño" 8 | },"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;" 9 | } -------------------------------------------------------------------------------- /l10n/es_PY.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "integration_github", 3 | { 4 | "Comment" : "Comentario", 5 | "Client ID" : "ID del cliente", 6 | "Client secret" : "Secreto del cliente", 7 | "Loading..." : "Cargando...", 8 | "Unknown error" : "Error desconocido", 9 | "Owner" : "Dueño" 10 | }, 11 | "nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"); 12 | -------------------------------------------------------------------------------- /l10n/es_PY.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Comment" : "Comentario", 3 | "Client ID" : "ID del cliente", 4 | "Client secret" : "Secreto del cliente", 5 | "Loading..." : "Cargando...", 6 | "Unknown error" : "Error desconocido", 7 | "Owner" : "Dueño" 8 | },"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;" 9 | } -------------------------------------------------------------------------------- /l10n/es_SV.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "integration_github", 3 | { 4 | "Comment" : "Comentario", 5 | "Client ID" : "ID del cliente", 6 | "Client secret" : "Secreto del cliente", 7 | "Loading..." : "Cargando...", 8 | "Unknown error" : "Error desconocido", 9 | "Owner" : "Dueño" 10 | }, 11 | "nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"); 12 | -------------------------------------------------------------------------------- /l10n/es_SV.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Comment" : "Comentario", 3 | "Client ID" : "ID del cliente", 4 | "Client secret" : "Secreto del cliente", 5 | "Loading..." : "Cargando...", 6 | "Unknown error" : "Error desconocido", 7 | "Owner" : "Dueño" 8 | },"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;" 9 | } -------------------------------------------------------------------------------- /l10n/es_UY.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "integration_github", 3 | { 4 | "Comment" : "Comentario", 5 | "Client ID" : "ID del cliente", 6 | "Client secret" : "Secreto del cliente", 7 | "Loading..." : "Cargando...", 8 | "Unknown error" : "Error desconocido", 9 | "Owner" : "Dueño" 10 | }, 11 | "nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"); 12 | -------------------------------------------------------------------------------- /l10n/es_UY.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Comment" : "Comentario", 3 | "Client ID" : "ID del cliente", 4 | "Client secret" : "Secreto del cliente", 5 | "Loading..." : "Cargando...", 6 | "Unknown error" : "Error desconocido", 7 | "Owner" : "Dueño" 8 | },"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;" 9 | } -------------------------------------------------------------------------------- /l10n/et_EE.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "integration_github", 3 | { 4 | "GitHub" : "GitHub", 5 | "Comment" : "Kommentaar", 6 | "Bad HTTP method" : "Vigane HTTP-meetod", 7 | "Bad credentials" : "Vale kasutajanimi, salasõna või tunnusluba", 8 | "Connected accounts" : "Ühendatud kasutajakontod", 9 | "Client ID" : "Kliendi ID", 10 | "Client secret" : "Kliendi salasõna", 11 | "Connected as {user}" : "Ühendatud kui {user}", 12 | "Enable GitHub dashboard widget" : "Lülita GitHubi juhtpaneeli vidin sisse", 13 | "{logins} reacted with {emoji} emoji" : "{logins} regeeris {emoji} emojiga", 14 | "Connected to GitHub!" : "Ühendus GitHubiga on olemas!", 15 | "GitHub OAuth error:" : "GitHubi OAuth viga", 16 | "GitHub options saved" : "GitHubi eelistused on salvestatud", 17 | "Invalid access token" : "Vigane tunnusluba ligipääsuks", 18 | "Failed to save GitHub options" : "GitHubi eelistuste on salvestamine ei õnnestunud", 19 | "Personal access token" : "Isiklik tunnusluba ligipääsuks", 20 | "Loading data" : "Laadin andmeid", 21 | "Mark as read" : "Märgi loetuks", 22 | "Unsubscribe" : "Lõpeta tellimus", 23 | "Line {line}" : "Rida {line}", 24 | "Unknown error" : "Tundmatu viga", 25 | "Draft" : "Kavand", 26 | "Assigned to {login}" : "Määratud kasutajale {login}", 27 | "by {creator}" : "kasutajalt {creator}", 28 | "Author" : "Autor", 29 | "Owner" : "Omanik" 30 | }, 31 | "nplurals=2; plural=(n != 1);"); 32 | -------------------------------------------------------------------------------- /l10n/et_EE.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "GitHub" : "GitHub", 3 | "Comment" : "Kommentaar", 4 | "Bad HTTP method" : "Vigane HTTP-meetod", 5 | "Bad credentials" : "Vale kasutajanimi, salasõna või tunnusluba", 6 | "Connected accounts" : "Ühendatud kasutajakontod", 7 | "Client ID" : "Kliendi ID", 8 | "Client secret" : "Kliendi salasõna", 9 | "Connected as {user}" : "Ühendatud kui {user}", 10 | "Enable GitHub dashboard widget" : "Lülita GitHubi juhtpaneeli vidin sisse", 11 | "{logins} reacted with {emoji} emoji" : "{logins} regeeris {emoji} emojiga", 12 | "Connected to GitHub!" : "Ühendus GitHubiga on olemas!", 13 | "GitHub OAuth error:" : "GitHubi OAuth viga", 14 | "GitHub options saved" : "GitHubi eelistused on salvestatud", 15 | "Invalid access token" : "Vigane tunnusluba ligipääsuks", 16 | "Failed to save GitHub options" : "GitHubi eelistuste on salvestamine ei õnnestunud", 17 | "Personal access token" : "Isiklik tunnusluba ligipääsuks", 18 | "Loading data" : "Laadin andmeid", 19 | "Mark as read" : "Märgi loetuks", 20 | "Unsubscribe" : "Lõpeta tellimus", 21 | "Line {line}" : "Rida {line}", 22 | "Unknown error" : "Tundmatu viga", 23 | "Draft" : "Kavand", 24 | "Assigned to {login}" : "Määratud kasutajale {login}", 25 | "by {creator}" : "kasutajalt {creator}", 26 | "Author" : "Autor", 27 | "Owner" : "Omanik" 28 | },"pluralForm" :"nplurals=2; plural=(n != 1);" 29 | } -------------------------------------------------------------------------------- /l10n/he.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "integration_github", 3 | { 4 | "GitHub" : "GitHub", 5 | "Error getting OAuth access token" : "שגיאה בקבלת אסימון גישה עם OAuth", 6 | "Error during OAuth exchanges" : "שגיאה במהלך החלפות OAuth", 7 | "GitHub notifications" : "התראות GitHub", 8 | "Comment" : "הערה", 9 | "GitHub issues and pull requests" : "דיווחים ובקשות דחיפה ב־GitHub", 10 | "GitHub repositories" : "מאגרי GitHub", 11 | "Bad HTTP method" : "שגיאה במתודת HTTP", 12 | "Bad credentials" : "פרטי גישה שגויים", 13 | "OAuth access token refused" : "אסימון הגישה ב־OAuth סורב", 14 | "Connected accounts" : "חשבונות מקושרים", 15 | "GitHub integration" : "שילוב עם GitHub", 16 | "GitHub OAuth settings" : "הגדרות OAuth של GitHub", 17 | "Client ID" : "מזהה לקו", 18 | "Client secret" : "סוד לקוח", 19 | "Connected to GitHub!" : "התחברות ל־GitHub!", 20 | "GitHub OAuth error:" : "שגיאת OAuth מול GitHub:", 21 | "GitHub options saved" : "האפשרויות של GitHub נשמרו", 22 | "Enable navigation link" : "הפעלת קישור ניווט", 23 | "Personal access token" : "אסימון גישה פרטי", 24 | "Disconnect from GitHub" : "ניתוק מ־GitHub", 25 | "Mark as read" : "סימון כנקרא", 26 | "Error connecting to GitHub" : "שגיאה בהתחברות ל־GitHub", 27 | "No GitHub notifications!" : "אין התראות של GitHub!", 28 | "Connect to GitHub" : "התחברות ל־GitHub", 29 | "Unknown error" : "שגיאה בלתי ידועה", 30 | "Owner" : "בעלות" 31 | }, 32 | "nplurals=3; plural=(n == 1 && n % 1 == 0) ? 0 : (n == 2 && n % 1 == 0) ? 1: 2;"); 33 | -------------------------------------------------------------------------------- /l10n/he.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "GitHub" : "GitHub", 3 | "Error getting OAuth access token" : "שגיאה בקבלת אסימון גישה עם OAuth", 4 | "Error during OAuth exchanges" : "שגיאה במהלך החלפות OAuth", 5 | "GitHub notifications" : "התראות GitHub", 6 | "Comment" : "הערה", 7 | "GitHub issues and pull requests" : "דיווחים ובקשות דחיפה ב־GitHub", 8 | "GitHub repositories" : "מאגרי GitHub", 9 | "Bad HTTP method" : "שגיאה במתודת HTTP", 10 | "Bad credentials" : "פרטי גישה שגויים", 11 | "OAuth access token refused" : "אסימון הגישה ב־OAuth סורב", 12 | "Connected accounts" : "חשבונות מקושרים", 13 | "GitHub integration" : "שילוב עם GitHub", 14 | "GitHub OAuth settings" : "הגדרות OAuth של GitHub", 15 | "Client ID" : "מזהה לקו", 16 | "Client secret" : "סוד לקוח", 17 | "Connected to GitHub!" : "התחברות ל־GitHub!", 18 | "GitHub OAuth error:" : "שגיאת OAuth מול GitHub:", 19 | "GitHub options saved" : "האפשרויות של GitHub נשמרו", 20 | "Enable navigation link" : "הפעלת קישור ניווט", 21 | "Personal access token" : "אסימון גישה פרטי", 22 | "Disconnect from GitHub" : "ניתוק מ־GitHub", 23 | "Mark as read" : "סימון כנקרא", 24 | "Error connecting to GitHub" : "שגיאה בהתחברות ל־GitHub", 25 | "No GitHub notifications!" : "אין התראות של GitHub!", 26 | "Connect to GitHub" : "התחברות ל־GitHub", 27 | "Unknown error" : "שגיאה בלתי ידועה", 28 | "Owner" : "בעלות" 29 | },"pluralForm" :"nplurals=3; plural=(n == 1 && n % 1 == 0) ? 0 : (n == 2 && n % 1 == 0) ? 1: 2;" 30 | } -------------------------------------------------------------------------------- /l10n/is.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "integration_github", 3 | { 4 | "GitHub" : "GitHub", 5 | "Error getting OAuth access token" : "Villa við að ná í OAuth-aðgangsteikn", 6 | "Error during OAuth exchanges" : "Villa í OAuth-samskiptum", 7 | "Comment" : "Athugasemd", 8 | "Bad credentials" : "Gölluð auðkenni", 9 | "OAuth access token refused" : "OAuth-aðgangsteikni hafnað", 10 | "Connected accounts" : "Tengdir aðgangar", 11 | "Client ID" : "Biðlaraauðkenni", 12 | "Client secret" : "Leynilykill biðlara", 13 | "Connected as {user}" : "Tengt sem {user}", 14 | "Enable navigation link" : "Virkja flakktengil", 15 | "Mark as read" : "Merkja sem lesið", 16 | "Unsubscribe" : "Hætta í áskrift", 17 | "Loading..." : "Hleð...", 18 | "Line {line}" : "Lína {line}", 19 | "Unknown error" : "Óþekkt villa", 20 | "Draft" : "Drög", 21 | "Author" : "Höfundur", 22 | "Owner" : "Eigandi" 23 | }, 24 | "nplurals=2; plural=(n % 10 != 1 || n % 100 == 11);"); 25 | -------------------------------------------------------------------------------- /l10n/is.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "GitHub" : "GitHub", 3 | "Error getting OAuth access token" : "Villa við að ná í OAuth-aðgangsteikn", 4 | "Error during OAuth exchanges" : "Villa í OAuth-samskiptum", 5 | "Comment" : "Athugasemd", 6 | "Bad credentials" : "Gölluð auðkenni", 7 | "OAuth access token refused" : "OAuth-aðgangsteikni hafnað", 8 | "Connected accounts" : "Tengdir aðgangar", 9 | "Client ID" : "Biðlaraauðkenni", 10 | "Client secret" : "Leynilykill biðlara", 11 | "Connected as {user}" : "Tengt sem {user}", 12 | "Enable navigation link" : "Virkja flakktengil", 13 | "Mark as read" : "Merkja sem lesið", 14 | "Unsubscribe" : "Hætta í áskrift", 15 | "Loading..." : "Hleð...", 16 | "Line {line}" : "Lína {line}", 17 | "Unknown error" : "Óþekkt villa", 18 | "Draft" : "Drög", 19 | "Author" : "Höfundur", 20 | "Owner" : "Eigandi" 21 | },"pluralForm" :"nplurals=2; plural=(n % 10 != 1 || n % 100 == 11);" 22 | } -------------------------------------------------------------------------------- /l10n/ja.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "integration_github", 3 | { 4 | "GitHub" : "GitHub", 5 | "Error getting OAuth access token" : "OAuthアクセストークン取得時のエラー", 6 | "Error during OAuth exchanges" : "OAuth通信中のエラー", 7 | "GitHub notifications" : "GitHubの通知", 8 | "Comment" : "コメント", 9 | "GitHub repositories" : "GitHubリポジトリ", 10 | "Bad HTTP method" : "不正なHTTPメソッド", 11 | "Bad credentials" : "不正な資格情報", 12 | "OAuth access token refused" : "OAuthアクセストークンが拒否されました", 13 | "Connected accounts" : "接続済みアカウント", 14 | "GitHub integration" : "GitHub統合", 15 | "Client ID" : "クライアントID", 16 | "Client secret" : "クライアント秘密鍵", 17 | "Connected as {user}" : "{user} を接続済み", 18 | "Connected to GitHub!" : "GitHubに接続しました!", 19 | "Enable navigation link" : "ナビゲーションリンクを有効化", 20 | "Disconnect from GitHub" : "GitHubから接続を解除", 21 | "Mark as read" : "既読にする", 22 | "Unsubscribe" : "購読解除", 23 | "No GitHub notifications!" : "GitHub通知がありません!", 24 | "Loading..." : "読み込み中…", 25 | "Successfully unsubscribed" : "購読の解除に成功しました", 26 | "Connect to GitHub" : "GitHubに接続", 27 | "Line {line}" : "行 {line}", 28 | "Unknown error" : "不明なエラー", 29 | "Draft" : "下書き", 30 | "Author" : "作者", 31 | "Owner" : "所有者" 32 | }, 33 | "nplurals=1; plural=0;"); 34 | -------------------------------------------------------------------------------- /l10n/ja.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "GitHub" : "GitHub", 3 | "Error getting OAuth access token" : "OAuthアクセストークン取得時のエラー", 4 | "Error during OAuth exchanges" : "OAuth通信中のエラー", 5 | "GitHub notifications" : "GitHubの通知", 6 | "Comment" : "コメント", 7 | "GitHub repositories" : "GitHubリポジトリ", 8 | "Bad HTTP method" : "不正なHTTPメソッド", 9 | "Bad credentials" : "不正な資格情報", 10 | "OAuth access token refused" : "OAuthアクセストークンが拒否されました", 11 | "Connected accounts" : "接続済みアカウント", 12 | "GitHub integration" : "GitHub統合", 13 | "Client ID" : "クライアントID", 14 | "Client secret" : "クライアント秘密鍵", 15 | "Connected as {user}" : "{user} を接続済み", 16 | "Connected to GitHub!" : "GitHubに接続しました!", 17 | "Enable navigation link" : "ナビゲーションリンクを有効化", 18 | "Disconnect from GitHub" : "GitHubから接続を解除", 19 | "Mark as read" : "既読にする", 20 | "Unsubscribe" : "購読解除", 21 | "No GitHub notifications!" : "GitHub通知がありません!", 22 | "Loading..." : "読み込み中…", 23 | "Successfully unsubscribed" : "購読の解除に成功しました", 24 | "Connect to GitHub" : "GitHubに接続", 25 | "Line {line}" : "行 {line}", 26 | "Unknown error" : "不明なエラー", 27 | "Draft" : "下書き", 28 | "Author" : "作者", 29 | "Owner" : "所有者" 30 | },"pluralForm" :"nplurals=1; plural=0;" 31 | } -------------------------------------------------------------------------------- /l10n/ka.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "integration_github", 3 | { 4 | "Comment" : "Comment", 5 | "Client ID" : "Client ID", 6 | "Client secret" : "Client secret", 7 | "Mark as read" : "Mark as read", 8 | "Unsubscribe" : "Unsubscribe", 9 | "Line {line}" : "Line {line}", 10 | "Unknown error" : "Unknown error", 11 | "Draft" : "Draft", 12 | "Author" : "Author", 13 | "Owner" : "Owner" 14 | }, 15 | "nplurals=2; plural=(n!=1);"); 16 | -------------------------------------------------------------------------------- /l10n/ka.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Comment" : "Comment", 3 | "Client ID" : "Client ID", 4 | "Client secret" : "Client secret", 5 | "Mark as read" : "Mark as read", 6 | "Unsubscribe" : "Unsubscribe", 7 | "Line {line}" : "Line {line}", 8 | "Unknown error" : "Unknown error", 9 | "Draft" : "Draft", 10 | "Author" : "Author", 11 | "Owner" : "Owner" 12 | },"pluralForm" :"nplurals=2; plural=(n!=1);" 13 | } -------------------------------------------------------------------------------- /l10n/ka_GE.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "integration_github", 3 | { 4 | "Comment" : "კომენტარი", 5 | "Client ID" : "კლიენტის ID", 6 | "Client secret" : "კლიენტის საიდუმლო", 7 | "Mark as read" : "წაკითხულად მონიშვნა", 8 | "Loading..." : "იტვირთება…", 9 | "Unknown error" : "უცნობი შეცდომა", 10 | "Owner" : "მფლობელი" 11 | }, 12 | "nplurals=2; plural=(n!=1);"); 13 | -------------------------------------------------------------------------------- /l10n/ka_GE.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Comment" : "კომენტარი", 3 | "Client ID" : "კლიენტის ID", 4 | "Client secret" : "კლიენტის საიდუმლო", 5 | "Mark as read" : "წაკითხულად მონიშვნა", 6 | "Loading..." : "იტვირთება…", 7 | "Unknown error" : "უცნობი შეცდომა", 8 | "Owner" : "მფლობელი" 9 | },"pluralForm" :"nplurals=2; plural=(n!=1);" 10 | } -------------------------------------------------------------------------------- /l10n/ko.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "integration_github", 3 | { 4 | "GitHub" : "GitHub", 5 | "Error getting OAuth access token" : "OAuth 액세스 토큰을 가져오는데 오류가 발생했습니다.", 6 | "Error during OAuth exchanges" : "OAuth 교환 중 오류가 발생했습니다.", 7 | "GitHub notifications" : "GitHub 알림", 8 | "Comment" : "설명", 9 | "GitHub repositories" : "GitHub 저장소", 10 | "Bad HTTP method" : "옳지 않은 HTTP 메소드", 11 | "Bad credentials" : "잘못된 자격 증명", 12 | "OAuth access token refused" : "OAuth 액세스 토큰 거부됨", 13 | "Connected accounts" : "계정 연결됨", 14 | "GitHub integration" : "GitHub와 통합", 15 | "Client ID" : "클라이언트 ID", 16 | "Client ID of your GitHub application" : "당신의 GitHub 애플리케이션 클라이언트 ID", 17 | "Client secret" : "클라이언트 비밀 값", 18 | "Client secret of your GitHub application" : "당신의 GitHub 애플리케이션 클라이언트 비밀 값", 19 | "Connected as {user}" : "{user}로 연결됨", 20 | "Connected to GitHub!" : "GitHub와 연결되었습니다!", 21 | "GitHub OAuth error:" : "GitHub OAuth 오류:", 22 | "Disconnect from GitHub" : "GitHub와 연결 해제", 23 | "Mark as read" : "읽은 것으로 표시", 24 | "Unsubscribe" : "구독 취소", 25 | "No GitHub account connected" : "연결된 GitHub 계정 없음", 26 | "Error connecting to GitHub" : "GitHub와 연결하는 중 오류 발생", 27 | "No GitHub notifications!" : "GitHub 알림 없음!", 28 | "Loading..." : "불러오는 중...", 29 | "Successfully unsubscribed" : "성공적으로 구독 취소되었습니다.", 30 | "Connect to GitHub" : "GitHub에 연결", 31 | "Unknown error" : "알 수 없는 오류", 32 | "GitHub connected accounts settings" : "GitHub 연결 계정 설정", 33 | "Draft" : "임시 저장", 34 | "Author" : "저자", 35 | "Owner" : "소유자" 36 | }, 37 | "nplurals=1; plural=0;"); 38 | -------------------------------------------------------------------------------- /l10n/ko.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "GitHub" : "GitHub", 3 | "Error getting OAuth access token" : "OAuth 액세스 토큰을 가져오는데 오류가 발생했습니다.", 4 | "Error during OAuth exchanges" : "OAuth 교환 중 오류가 발생했습니다.", 5 | "GitHub notifications" : "GitHub 알림", 6 | "Comment" : "설명", 7 | "GitHub repositories" : "GitHub 저장소", 8 | "Bad HTTP method" : "옳지 않은 HTTP 메소드", 9 | "Bad credentials" : "잘못된 자격 증명", 10 | "OAuth access token refused" : "OAuth 액세스 토큰 거부됨", 11 | "Connected accounts" : "계정 연결됨", 12 | "GitHub integration" : "GitHub와 통합", 13 | "Client ID" : "클라이언트 ID", 14 | "Client ID of your GitHub application" : "당신의 GitHub 애플리케이션 클라이언트 ID", 15 | "Client secret" : "클라이언트 비밀 값", 16 | "Client secret of your GitHub application" : "당신의 GitHub 애플리케이션 클라이언트 비밀 값", 17 | "Connected as {user}" : "{user}로 연결됨", 18 | "Connected to GitHub!" : "GitHub와 연결되었습니다!", 19 | "GitHub OAuth error:" : "GitHub OAuth 오류:", 20 | "Disconnect from GitHub" : "GitHub와 연결 해제", 21 | "Mark as read" : "읽은 것으로 표시", 22 | "Unsubscribe" : "구독 취소", 23 | "No GitHub account connected" : "연결된 GitHub 계정 없음", 24 | "Error connecting to GitHub" : "GitHub와 연결하는 중 오류 발생", 25 | "No GitHub notifications!" : "GitHub 알림 없음!", 26 | "Loading..." : "불러오는 중...", 27 | "Successfully unsubscribed" : "성공적으로 구독 취소되었습니다.", 28 | "Connect to GitHub" : "GitHub에 연결", 29 | "Unknown error" : "알 수 없는 오류", 30 | "GitHub connected accounts settings" : "GitHub 연결 계정 설정", 31 | "Draft" : "임시 저장", 32 | "Author" : "저자", 33 | "Owner" : "소유자" 34 | },"pluralForm" :"nplurals=1; plural=0;" 35 | } -------------------------------------------------------------------------------- /l10n/lt_LT.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "integration_github", 3 | { 4 | "GitHub" : "„GitHub“", 5 | "Error getting OAuth access token" : "Klaida gaunant „OAuth“ prieigos raktą", 6 | "Error during OAuth exchanges" : "Klaida „OAuth“ apsikeitimo metu", 7 | "GitHub notifications" : "„GitHub“ pranešimai", 8 | "More notifications" : "Daugiau pranešimų", 9 | "Comment" : "Komentaras", 10 | "GitHub repositories" : "„GitHub“ saugyklos", 11 | "Bad HTTP method" : "Blogas HTTP metodas", 12 | "Bad credentials" : "Blogi prisijungimo duomenys", 13 | "OAuth access token refused" : "„OAuth“ prieigos raktas atmestas", 14 | "Connected accounts" : "Prijungtos paskyros", 15 | "GitHub integration" : "„GitHub“ integracija", 16 | "Client ID" : "Kliento ID", 17 | "Client secret" : "Trečiųjų šalių programinės įrangos kliento identifikacijos raktas", 18 | "Connected as {user}" : "Prisijungta kaip {user}", 19 | "Connected to GitHub!" : "Prisijungta prie „GitHub“!", 20 | "GitHub options saved" : "„GitHub“ parinktys įrašytos", 21 | "Failed to save GitHub options" : "Nepavyko įrašyti „GitHub“ parinkčių", 22 | "Disconnect from GitHub" : "Atsijungti nuo „GitHub“", 23 | "Enable searching for repositories" : "Įjungti saugyklų paiešką", 24 | "Warning, everything you type in the search bar will be sent to GitHub." : "Įspėjimas: viskas, ką rašysite paieškos juostoje, bus siunčiama į „GitHub“.", 25 | "Loading data" : "Įkeliami duomenys", 26 | "Mark as read" : "Žymėti kaip skaitytą", 27 | "Unsubscribe" : "Atsisakyti prenumeratos", 28 | "No GitHub account connected" : "Neprijungta jokia „GitHub“ paskyra", 29 | "Error connecting to GitHub" : "Klaida jungiantis prie „GitHub“", 30 | "No GitHub notifications!" : "Nėra „GitHub“ pranešimų!", 31 | "Loading..." : "Įkeliama...", 32 | "Failed to get GitHub notifications" : "Nepavyko gauti „GitHub“ pranešimų", 33 | "Successfully unsubscribed" : "Sėkmingai atsisakyta prenumeratos", 34 | "Failed to edit GitHub notification" : "Nepavyko taisyti „GitHub“ pranešimo", 35 | "Unknown error" : "Nežinoma klaida", 36 | "Unknown state" : "Nežinoma būsena", 37 | "Draft" : "Juodraštis", 38 | "Author" : "Autorius", 39 | "Owner" : "Savininkas" 40 | }, 41 | "nplurals=4; plural=(n % 10 == 1 && (n % 100 > 19 || n % 100 < 11) ? 0 : (n % 10 >= 2 && n % 10 <=9) && (n % 100 > 19 || n % 100 < 11) ? 1 : n % 1 != 0 ? 2: 3);"); 42 | -------------------------------------------------------------------------------- /l10n/lt_LT.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "GitHub" : "„GitHub“", 3 | "Error getting OAuth access token" : "Klaida gaunant „OAuth“ prieigos raktą", 4 | "Error during OAuth exchanges" : "Klaida „OAuth“ apsikeitimo metu", 5 | "GitHub notifications" : "„GitHub“ pranešimai", 6 | "More notifications" : "Daugiau pranešimų", 7 | "Comment" : "Komentaras", 8 | "GitHub repositories" : "„GitHub“ saugyklos", 9 | "Bad HTTP method" : "Blogas HTTP metodas", 10 | "Bad credentials" : "Blogi prisijungimo duomenys", 11 | "OAuth access token refused" : "„OAuth“ prieigos raktas atmestas", 12 | "Connected accounts" : "Prijungtos paskyros", 13 | "GitHub integration" : "„GitHub“ integracija", 14 | "Client ID" : "Kliento ID", 15 | "Client secret" : "Trečiųjų šalių programinės įrangos kliento identifikacijos raktas", 16 | "Connected as {user}" : "Prisijungta kaip {user}", 17 | "Connected to GitHub!" : "Prisijungta prie „GitHub“!", 18 | "GitHub options saved" : "„GitHub“ parinktys įrašytos", 19 | "Failed to save GitHub options" : "Nepavyko įrašyti „GitHub“ parinkčių", 20 | "Disconnect from GitHub" : "Atsijungti nuo „GitHub“", 21 | "Enable searching for repositories" : "Įjungti saugyklų paiešką", 22 | "Warning, everything you type in the search bar will be sent to GitHub." : "Įspėjimas: viskas, ką rašysite paieškos juostoje, bus siunčiama į „GitHub“.", 23 | "Loading data" : "Įkeliami duomenys", 24 | "Mark as read" : "Žymėti kaip skaitytą", 25 | "Unsubscribe" : "Atsisakyti prenumeratos", 26 | "No GitHub account connected" : "Neprijungta jokia „GitHub“ paskyra", 27 | "Error connecting to GitHub" : "Klaida jungiantis prie „GitHub“", 28 | "No GitHub notifications!" : "Nėra „GitHub“ pranešimų!", 29 | "Loading..." : "Įkeliama...", 30 | "Failed to get GitHub notifications" : "Nepavyko gauti „GitHub“ pranešimų", 31 | "Successfully unsubscribed" : "Sėkmingai atsisakyta prenumeratos", 32 | "Failed to edit GitHub notification" : "Nepavyko taisyti „GitHub“ pranešimo", 33 | "Unknown error" : "Nežinoma klaida", 34 | "Unknown state" : "Nežinoma būsena", 35 | "Draft" : "Juodraštis", 36 | "Author" : "Autorius", 37 | "Owner" : "Savininkas" 38 | },"pluralForm" :"nplurals=4; plural=(n % 10 == 1 && (n % 100 > 19 || n % 100 < 11) ? 0 : (n % 10 >= 2 && n % 10 <=9) && (n % 100 > 19 || n % 100 < 11) ? 1 : n % 1 != 0 ? 2: 3);" 39 | } -------------------------------------------------------------------------------- /l10n/lv.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "integration_github", 3 | { 4 | "Comment" : "Piebilde", 5 | "Bad HTTP method" : "Nederīgs HTTP pieprasījuma veids", 6 | "Bad credentials" : "Nederīgi pieteikšanās dati", 7 | "Connected accounts" : "Sasaistītie konti", 8 | "Client ID" : "Klienta ID", 9 | "{logins} reacted with {emoji} emoji" : "{logins} atsaucās ar emocijzīmi {emoji}", 10 | "No GitHub account connected" : "Nav sasaistītu GitHub kontu", 11 | "Loading..." : "Notiek ielāde...", 12 | "Unknown error" : "Nezināma kļūda", 13 | "GitHub connected accounts settings" : "Sasaistīto GitHub kontu iestatījumi", 14 | "opened {relativeDate}" : "atvēra {relativeDate}", 15 | "Comment from {login}" : "Piebilde no {login}", 16 | "Owner" : "Īpašnieks" 17 | }, 18 | "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2);"); 19 | -------------------------------------------------------------------------------- /l10n/lv.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Comment" : "Piebilde", 3 | "Bad HTTP method" : "Nederīgs HTTP pieprasījuma veids", 4 | "Bad credentials" : "Nederīgi pieteikšanās dati", 5 | "Connected accounts" : "Sasaistītie konti", 6 | "Client ID" : "Klienta ID", 7 | "{logins} reacted with {emoji} emoji" : "{logins} atsaucās ar emocijzīmi {emoji}", 8 | "No GitHub account connected" : "Nav sasaistītu GitHub kontu", 9 | "Loading..." : "Notiek ielāde...", 10 | "Unknown error" : "Nezināma kļūda", 11 | "GitHub connected accounts settings" : "Sasaistīto GitHub kontu iestatījumi", 12 | "opened {relativeDate}" : "atvēra {relativeDate}", 13 | "Comment from {login}" : "Piebilde no {login}", 14 | "Owner" : "Īpašnieks" 15 | },"pluralForm" :"nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2);" 16 | } -------------------------------------------------------------------------------- /l10n/mk.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "integration_github", 3 | { 4 | "GitHub" : "GitHub", 5 | "Error getting OAuth access token" : "Грешка при добивање на OAuth пристапен токен", 6 | "Error during OAuth exchanges" : "Грешка при размена на податоци за OAuth ", 7 | "Comment" : "Коментар", 8 | "Bad credentials" : "Неточни акредитиви", 9 | "OAuth access token refused" : "Одбиен OAuth пристапен токен ", 10 | "Connected accounts" : "Поврзани сметки", 11 | "Put the OAuth app \"Client ID\" and \"Client secret\" below." : "Внесете ги OAuth app \"Клиент ИД\" и \"Тајна на клиент\" овде.", 12 | "Client ID" : "Клиент ИД", 13 | "Client secret" : "Тајна на клиент", 14 | "Connected as {user}" : "Поврзан како {user}", 15 | "Enable navigation link" : "Овозможи линк за навигација", 16 | "Mark as read" : "Означи како прочитано", 17 | "Unknown error" : "Непозната грешка", 18 | "Draft" : "Шаблон", 19 | "Author" : "Автор", 20 | "Owner" : "Сопственик" 21 | }, 22 | "nplurals=2; plural=(n % 10 == 1 && n % 100 != 11) ? 0 : 1;"); 23 | -------------------------------------------------------------------------------- /l10n/mk.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "GitHub" : "GitHub", 3 | "Error getting OAuth access token" : "Грешка при добивање на OAuth пристапен токен", 4 | "Error during OAuth exchanges" : "Грешка при размена на податоци за OAuth ", 5 | "Comment" : "Коментар", 6 | "Bad credentials" : "Неточни акредитиви", 7 | "OAuth access token refused" : "Одбиен OAuth пристапен токен ", 8 | "Connected accounts" : "Поврзани сметки", 9 | "Put the OAuth app \"Client ID\" and \"Client secret\" below." : "Внесете ги OAuth app \"Клиент ИД\" и \"Тајна на клиент\" овде.", 10 | "Client ID" : "Клиент ИД", 11 | "Client secret" : "Тајна на клиент", 12 | "Connected as {user}" : "Поврзан како {user}", 13 | "Enable navigation link" : "Овозможи линк за навигација", 14 | "Mark as read" : "Означи како прочитано", 15 | "Unknown error" : "Непозната грешка", 16 | "Draft" : "Шаблон", 17 | "Author" : "Автор", 18 | "Owner" : "Сопственик" 19 | },"pluralForm" :"nplurals=2; plural=(n % 10 == 1 && n % 100 != 11) ? 0 : 1;" 20 | } -------------------------------------------------------------------------------- /l10n/nn_NO.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "integration_github", 3 | { 4 | "GitHub" : "GitHub", 5 | "Comment" : "Kommentér", 6 | "Connected accounts" : "Tilkopla kontoar", 7 | "Client ID" : "Klient-ID", 8 | "Unknown error" : "Ukjend feil", 9 | "Owner" : "Owner" 10 | }, 11 | "nplurals=2; plural=(n != 1);"); 12 | -------------------------------------------------------------------------------- /l10n/nn_NO.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "GitHub" : "GitHub", 3 | "Comment" : "Kommentér", 4 | "Connected accounts" : "Tilkopla kontoar", 5 | "Client ID" : "Klient-ID", 6 | "Unknown error" : "Ukjend feil", 7 | "Owner" : "Owner" 8 | },"pluralForm" :"nplurals=2; plural=(n != 1);" 9 | } -------------------------------------------------------------------------------- /l10n/oc.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "integration_github", 3 | { 4 | "GitHub" : "GitHub", 5 | "Comment" : "Comentaris", 6 | "Bad credentials" : "Marrits identificants", 7 | "Connected accounts" : "Comptes connectats", 8 | "Client ID" : "ID client", 9 | "Connected as {user}" : "Connectat coma {user}", 10 | "Mark as read" : "Marcar coma legit", 11 | "Unknown error" : "Error desconeguda", 12 | "Owner" : "Owner" 13 | }, 14 | "nplurals=2; plural=(n > 1);"); 15 | -------------------------------------------------------------------------------- /l10n/oc.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "GitHub" : "GitHub", 3 | "Comment" : "Comentaris", 4 | "Bad credentials" : "Marrits identificants", 5 | "Connected accounts" : "Comptes connectats", 6 | "Client ID" : "ID client", 7 | "Connected as {user}" : "Connectat coma {user}", 8 | "Mark as read" : "Marcar coma legit", 9 | "Unknown error" : "Error desconeguda", 10 | "Owner" : "Owner" 11 | },"pluralForm" :"nplurals=2; plural=(n > 1);" 12 | } -------------------------------------------------------------------------------- /l10n/pt_PT.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "integration_github", 3 | { 4 | "Error during OAuth exchanges" : "Erro durante trocas com o OAuth", 5 | "Comment" : "Comentário", 6 | "Bad HTTP method" : "Método HTTP incorreto", 7 | "Bad credentials" : "Credenciais inválidas", 8 | "Client ID" : "Id. do Cliente", 9 | "Client secret" : "Segredo do cliente\\\\", 10 | "Unknown error" : "Erro desconhecido", 11 | "Author" : "Autor", 12 | "Owner" : "Proprietário" 13 | }, 14 | "nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"); 15 | -------------------------------------------------------------------------------- /l10n/pt_PT.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Error during OAuth exchanges" : "Erro durante trocas com o OAuth", 3 | "Comment" : "Comentário", 4 | "Bad HTTP method" : "Método HTTP incorreto", 5 | "Bad credentials" : "Credenciais inválidas", 6 | "Client ID" : "Id. do Cliente", 7 | "Client secret" : "Segredo do cliente\\\\", 8 | "Unknown error" : "Erro desconhecido", 9 | "Author" : "Autor", 10 | "Owner" : "Proprietário" 11 | },"pluralForm" :"nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;" 12 | } -------------------------------------------------------------------------------- /l10n/ro.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "integration_github", 3 | { 4 | "GitHub" : "GitHub", 5 | "Error getting OAuth access token" : "Eroare în obținerea token-ului OAuth", 6 | "Error during OAuth exchanges" : "Eroare în schimbarea OAuth", 7 | "Comment" : "Comentariu", 8 | "Bad HTTP method" : "Metodă HTTP nepotrivită", 9 | "Bad credentials" : "Credențiale greșite", 10 | "OAuth access token refused" : "Token-ul OAuth a fost refuzat", 11 | "Connected accounts" : "Conturile conectate", 12 | "Client ID" : "ID client", 13 | "Client secret" : "Secret client", 14 | "Enable navigation link" : "Pornește link-ul de navifare", 15 | "Mark as read" : "Marchează ca citit", 16 | "Unsubscribe" : "Desubscrie", 17 | "Unknown error" : "Eroare necunoscută", 18 | "Draft" : "Schiță", 19 | "Author" : "Autor", 20 | "Owner" : "Proprietar" 21 | }, 22 | "nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?2:1));"); 23 | -------------------------------------------------------------------------------- /l10n/ro.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "GitHub" : "GitHub", 3 | "Error getting OAuth access token" : "Eroare în obținerea token-ului OAuth", 4 | "Error during OAuth exchanges" : "Eroare în schimbarea OAuth", 5 | "Comment" : "Comentariu", 6 | "Bad HTTP method" : "Metodă HTTP nepotrivită", 7 | "Bad credentials" : "Credențiale greșite", 8 | "OAuth access token refused" : "Token-ul OAuth a fost refuzat", 9 | "Connected accounts" : "Conturile conectate", 10 | "Client ID" : "ID client", 11 | "Client secret" : "Secret client", 12 | "Enable navigation link" : "Pornește link-ul de navifare", 13 | "Mark as read" : "Marchează ca citit", 14 | "Unsubscribe" : "Desubscrie", 15 | "Unknown error" : "Eroare necunoscută", 16 | "Draft" : "Schiță", 17 | "Author" : "Autor", 18 | "Owner" : "Proprietar" 19 | },"pluralForm" :"nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?2:1));" 20 | } -------------------------------------------------------------------------------- /l10n/sq.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "integration_github", 3 | { 4 | "Comment" : "Koment", 5 | "Client ID" : "ID klienti", 6 | "Client secret" : "E fshehtë klienti", 7 | "Mark as read" : "Shënoje si të lexuar", 8 | "Loading..." : "Po ngarkohet", 9 | "Unknown error" : "Gabim i panjohur", 10 | "Owner" : "Zotëruesi" 11 | }, 12 | "nplurals=2; plural=(n != 1);"); 13 | -------------------------------------------------------------------------------- /l10n/sq.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Comment" : "Koment", 3 | "Client ID" : "ID klienti", 4 | "Client secret" : "E fshehtë klienti", 5 | "Mark as read" : "Shënoje si të lexuar", 6 | "Loading..." : "Po ngarkohet", 7 | "Unknown error" : "Gabim i panjohur", 8 | "Owner" : "Zotëruesi" 9 | },"pluralForm" :"nplurals=2; plural=(n != 1);" 10 | } -------------------------------------------------------------------------------- /l10n/sv.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "integration_github", 3 | { 4 | "GitHub" : "GitHub", 5 | "Error getting OAuth access token" : "Kunde inte hämta OAuth-token", 6 | "Error during OAuth exchanges" : "Fel vid utväxling av OAuth-token", 7 | "GitHub notifications" : "GitHub-aviseringar", 8 | "More notifications" : "Fler aviseringar", 9 | "_You have %s new unread notification with recent activity on GitHub._::_You have %s new unread notifications with recent activity on GitHub._" : ["Du har %s ny oläst avisering med ny aktivitet på GitHub.","Du har %s nya olästa aviseringar med ny aktivitet på GitHub."], 10 | "GitHub code permalink" : "Permalänk till GitHub-kod", 11 | "GitHub issues, pull requests and comments" : "GitHub-ärenden, pull-begäranden och kommentarer", 12 | "Comment" : "Kommentar", 13 | "GitHub issues and pull requests" : "Ärenden och pull-förfrågningar på GitHub", 14 | "GitHub repositories" : "GitHub-arkiv", 15 | "Bad HTTP method" : "Felaktig HTTP-metod", 16 | "Bad credentials" : "Ogiltiga inloggningsuppgifter", 17 | "OAuth access token refused" : "OAuth-token avvisades", 18 | "Connected accounts" : "Anslutna konton", 19 | "GitHub integration" : "GitHub-integrering", 20 | "Integration of GitHub software development management service" : "Integrering av GitHub-tjänster för mjukvaruutveckling", 21 | "Client ID" : "Klient-ID", 22 | "Client ID of your GitHub application" : "Klient-id för din GitHub-applikation", 23 | "Client secret" : "Klienthemlighet", 24 | "Connected as {user}" : "Ansluten som {user}", 25 | "Connected to GitHub!" : "Ansluten till GitHub!", 26 | "Invalid access token" : "Ogiltig åtkomsttoken", 27 | "Enable navigation link" : "Aktivera navigeringslänk", 28 | "GitHub personal access tokens" : "Personliga åtkomst-tokens för GitHub", 29 | "Personal access token" : "Personlig åtkomst-token", 30 | "Disconnect from GitHub" : "Koppla ner från GitHub", 31 | "Enable searching for repositories" : "Aktivera sökning efter arkiv", 32 | "Enable searching for issues and pull requests" : "Aktivera sökning efter ärenden och pull-förfrågningar", 33 | "Warning, everything you type in the search bar will be sent to GitHub." : "Varning, allt du skriver i sökfältet skickas till GitHub.", 34 | "Mark as read" : "Markera som läst", 35 | "Unsubscribe" : "Avsluta prenumeration", 36 | "No GitHub account connected" : "Inget GitHub-konto anslutet", 37 | "Error connecting to GitHub" : "Kunde inte ansluta till GitHub", 38 | "No GitHub notifications!" : "Inga GitHub-aviseringar!", 39 | "Loading..." : "Laddar...", 40 | "Failed to get GitHub notifications" : "Kunde inte hämta GitHub-aviseringar", 41 | "Successfully unsubscribed" : "Prenumerationen har avslutats", 42 | "Failed to edit GitHub notification" : "Kunde inte ändra GitHub-aviseringar", 43 | "Connect to GitHub" : "Anslut till GitHub", 44 | "Line {line}" : "Rad {line}", 45 | "Unknown error" : "Okänt fel", 46 | "Draft" : "Utkast", 47 | "by {creator}" : "av {creator}", 48 | "Author" : "Upphovsman", 49 | "Owner" : "Ägare" 50 | }, 51 | "nplurals=2; plural=(n != 1);"); 52 | -------------------------------------------------------------------------------- /l10n/sv.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "GitHub" : "GitHub", 3 | "Error getting OAuth access token" : "Kunde inte hämta OAuth-token", 4 | "Error during OAuth exchanges" : "Fel vid utväxling av OAuth-token", 5 | "GitHub notifications" : "GitHub-aviseringar", 6 | "More notifications" : "Fler aviseringar", 7 | "_You have %s new unread notification with recent activity on GitHub._::_You have %s new unread notifications with recent activity on GitHub._" : ["Du har %s ny oläst avisering med ny aktivitet på GitHub.","Du har %s nya olästa aviseringar med ny aktivitet på GitHub."], 8 | "GitHub code permalink" : "Permalänk till GitHub-kod", 9 | "GitHub issues, pull requests and comments" : "GitHub-ärenden, pull-begäranden och kommentarer", 10 | "Comment" : "Kommentar", 11 | "GitHub issues and pull requests" : "Ärenden och pull-förfrågningar på GitHub", 12 | "GitHub repositories" : "GitHub-arkiv", 13 | "Bad HTTP method" : "Felaktig HTTP-metod", 14 | "Bad credentials" : "Ogiltiga inloggningsuppgifter", 15 | "OAuth access token refused" : "OAuth-token avvisades", 16 | "Connected accounts" : "Anslutna konton", 17 | "GitHub integration" : "GitHub-integrering", 18 | "Integration of GitHub software development management service" : "Integrering av GitHub-tjänster för mjukvaruutveckling", 19 | "Client ID" : "Klient-ID", 20 | "Client ID of your GitHub application" : "Klient-id för din GitHub-applikation", 21 | "Client secret" : "Klienthemlighet", 22 | "Connected as {user}" : "Ansluten som {user}", 23 | "Connected to GitHub!" : "Ansluten till GitHub!", 24 | "Invalid access token" : "Ogiltig åtkomsttoken", 25 | "Enable navigation link" : "Aktivera navigeringslänk", 26 | "GitHub personal access tokens" : "Personliga åtkomst-tokens för GitHub", 27 | "Personal access token" : "Personlig åtkomst-token", 28 | "Disconnect from GitHub" : "Koppla ner från GitHub", 29 | "Enable searching for repositories" : "Aktivera sökning efter arkiv", 30 | "Enable searching for issues and pull requests" : "Aktivera sökning efter ärenden och pull-förfrågningar", 31 | "Warning, everything you type in the search bar will be sent to GitHub." : "Varning, allt du skriver i sökfältet skickas till GitHub.", 32 | "Mark as read" : "Markera som läst", 33 | "Unsubscribe" : "Avsluta prenumeration", 34 | "No GitHub account connected" : "Inget GitHub-konto anslutet", 35 | "Error connecting to GitHub" : "Kunde inte ansluta till GitHub", 36 | "No GitHub notifications!" : "Inga GitHub-aviseringar!", 37 | "Loading..." : "Laddar...", 38 | "Failed to get GitHub notifications" : "Kunde inte hämta GitHub-aviseringar", 39 | "Successfully unsubscribed" : "Prenumerationen har avslutats", 40 | "Failed to edit GitHub notification" : "Kunde inte ändra GitHub-aviseringar", 41 | "Connect to GitHub" : "Anslut till GitHub", 42 | "Line {line}" : "Rad {line}", 43 | "Unknown error" : "Okänt fel", 44 | "Draft" : "Utkast", 45 | "by {creator}" : "av {creator}", 46 | "Author" : "Upphovsman", 47 | "Owner" : "Ägare" 48 | },"pluralForm" :"nplurals=2; plural=(n != 1);" 49 | } -------------------------------------------------------------------------------- /l10n/th.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "integration_github", 3 | { 4 | "Comment" : "ความคิดเห็น", 5 | "Client ID" : "รหัสไคลเอ็นต์", 6 | "Client secret" : "ข้อมูลลับไคลเอ็นต์", 7 | "Connected as {user}" : "เชื่อมต่อเป็น {user} แล้ว", 8 | "Unknown error" : "ข้อผิดพลาดที่ไม่รู้จัก", 9 | "Owner" : "เจ้าของ" 10 | }, 11 | "nplurals=1; plural=0;"); 12 | -------------------------------------------------------------------------------- /l10n/th.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Comment" : "ความคิดเห็น", 3 | "Client ID" : "รหัสไคลเอ็นต์", 4 | "Client secret" : "ข้อมูลลับไคลเอ็นต์", 5 | "Connected as {user}" : "เชื่อมต่อเป็น {user} แล้ว", 6 | "Unknown error" : "ข้อผิดพลาดที่ไม่รู้จัก", 7 | "Owner" : "เจ้าของ" 8 | },"pluralForm" :"nplurals=1; plural=0;" 9 | } -------------------------------------------------------------------------------- /l10n/uk.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "integration_github", 3 | { 4 | "GitHub" : "GitHub", 5 | "Error getting OAuth access token" : "Помилка отримання токена доступу OAuth", 6 | "Error during OAuth exchanges" : "Помилка під час обміну OAuth", 7 | "Comment" : "Коментар", 8 | "Bad HTTP method" : "Поганий метод HTTP", 9 | "Bad credentials" : "Погані облікові дані", 10 | "OAuth access token refused" : "Токен доступу OAuth відхилено", 11 | "Connected accounts" : "Підключені облікові записи", 12 | "Client ID" : "Ідентифікатор клієнта", 13 | "Client secret" : "Ключ клієнта", 14 | "{logins} reacted with {emoji} emoji" : "{logins} відреагував з емоційкою {emoji}", 15 | "Mark as read" : "Відмітити прочитаним", 16 | "Unsubscribe" : "Відписатися", 17 | "Loading..." : "Завантаження...", 18 | "Line {line}" : "Рядок {line}", 19 | "GitHub API error" : "Помилка API GitHub", 20 | "Unknown error" : "Невідома помилка", 21 | "GitHub connected accounts settings" : "Налаштування підключених облікових записів GitHub", 22 | "Open issue" : "Відкрите питання", 23 | "Closed as not planned issue" : "Закрито як незапланований випуск", 24 | "Closed issue" : "Закрите питання", 25 | "Open draft pull request" : "Відкрити запит на отримання чернетки", 26 | "Open pull request" : "Відкрити запит на отримання", 27 | "Merged pull request" : "Об’єднаний запит на отримання", 28 | "Closed pull request" : "Закритий запит на отримання", 29 | "Unknown state" : "Невідомий стан", 30 | "Draft" : "Чернетка", 31 | "Review requested" : "Надіслано запит на перегляд", 32 | "Comment from {login}" : "Коментар від {login}", 33 | "Assigned to {login}" : "Призначено для {login}", 34 | "Author" : "Автор", 35 | "Owner" : "Власник" 36 | }, 37 | "nplurals=4; plural=(n % 1 == 0 && n % 10 == 1 && n % 100 != 11 ? 0 : n % 1 == 0 && n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 12 || n % 100 > 14) ? 1 : n % 1 == 0 && (n % 10 ==0 || (n % 10 >=5 && n % 10 <=9) || (n % 100 >=11 && n % 100 <=14 )) ? 2: 3);"); 38 | -------------------------------------------------------------------------------- /l10n/uk.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "GitHub" : "GitHub", 3 | "Error getting OAuth access token" : "Помилка отримання токена доступу OAuth", 4 | "Error during OAuth exchanges" : "Помилка під час обміну OAuth", 5 | "Comment" : "Коментар", 6 | "Bad HTTP method" : "Поганий метод HTTP", 7 | "Bad credentials" : "Погані облікові дані", 8 | "OAuth access token refused" : "Токен доступу OAuth відхилено", 9 | "Connected accounts" : "Підключені облікові записи", 10 | "Client ID" : "Ідентифікатор клієнта", 11 | "Client secret" : "Ключ клієнта", 12 | "{logins} reacted with {emoji} emoji" : "{logins} відреагував з емоційкою {emoji}", 13 | "Mark as read" : "Відмітити прочитаним", 14 | "Unsubscribe" : "Відписатися", 15 | "Loading..." : "Завантаження...", 16 | "Line {line}" : "Рядок {line}", 17 | "GitHub API error" : "Помилка API GitHub", 18 | "Unknown error" : "Невідома помилка", 19 | "GitHub connected accounts settings" : "Налаштування підключених облікових записів GitHub", 20 | "Open issue" : "Відкрите питання", 21 | "Closed as not planned issue" : "Закрито як незапланований випуск", 22 | "Closed issue" : "Закрите питання", 23 | "Open draft pull request" : "Відкрити запит на отримання чернетки", 24 | "Open pull request" : "Відкрити запит на отримання", 25 | "Merged pull request" : "Об’єднаний запит на отримання", 26 | "Closed pull request" : "Закритий запит на отримання", 27 | "Unknown state" : "Невідомий стан", 28 | "Draft" : "Чернетка", 29 | "Review requested" : "Надіслано запит на перегляд", 30 | "Comment from {login}" : "Коментар від {login}", 31 | "Assigned to {login}" : "Призначено для {login}", 32 | "Author" : "Автор", 33 | "Owner" : "Власник" 34 | },"pluralForm" :"nplurals=4; plural=(n % 1 == 0 && n % 10 == 1 && n % 100 != 11 ? 0 : n % 1 == 0 && n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 12 || n % 100 > 14) ? 1 : n % 1 == 0 && (n % 10 ==0 || (n % 10 >=5 && n % 10 <=9) || (n % 100 >=11 && n % 100 <=14 )) ? 2: 3);" 35 | } -------------------------------------------------------------------------------- /l10n/uz.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "integration_github", 3 | { 4 | "Comment" : "Izoh", 5 | "Bad HTTP method" : "Yomon HTTP usuli", 6 | "Bad credentials" : "Akkaunt ma'lumotlari xato", 7 | "Client ID" : "Mijoz identifikatori", 8 | "Personal access token" : "Shaxsiy kirish belgisi", 9 | "Unknown error" : "Unknown error", 10 | "Comment from {login}" : "Comment from {login}", 11 | "Owner" : "Owner" 12 | }, 13 | "nplurals=1; plural=0;"); 14 | -------------------------------------------------------------------------------- /l10n/uz.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Comment" : "Izoh", 3 | "Bad HTTP method" : "Yomon HTTP usuli", 4 | "Bad credentials" : "Akkaunt ma'lumotlari xato", 5 | "Client ID" : "Mijoz identifikatori", 6 | "Personal access token" : "Shaxsiy kirish belgisi", 7 | "Unknown error" : "Unknown error", 8 | "Comment from {login}" : "Comment from {login}", 9 | "Owner" : "Owner" 10 | },"pluralForm" :"nplurals=1; plural=0;" 11 | } -------------------------------------------------------------------------------- /l10n/vi.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "integration_github", 3 | { 4 | "Comment" : "Bình luận", 5 | "Bad HTTP method" : "Phương thức HTTP không hợp lệ", 6 | "Bad credentials" : "Thông tin đăng nhập không hợp lệ.", 7 | "Connected accounts" : "Đã kết nối tài khoản", 8 | "Client ID" : "ID khách hàng", 9 | "Connected as {user}" : "Kết nối bởi {user}", 10 | "Invalid access token" : "Mã thông báo truy cập không hợp lệ", 11 | "Mark as read" : "Đánh dấu đã đọc", 12 | "Unknown error" : "Lỗi không xác định", 13 | "Owner" : "Chủ" 14 | }, 15 | "nplurals=1; plural=0;"); 16 | -------------------------------------------------------------------------------- /l10n/vi.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Comment" : "Bình luận", 3 | "Bad HTTP method" : "Phương thức HTTP không hợp lệ", 4 | "Bad credentials" : "Thông tin đăng nhập không hợp lệ.", 5 | "Connected accounts" : "Đã kết nối tài khoản", 6 | "Client ID" : "ID khách hàng", 7 | "Connected as {user}" : "Kết nối bởi {user}", 8 | "Invalid access token" : "Mã thông báo truy cập không hợp lệ", 9 | "Mark as read" : "Đánh dấu đã đọc", 10 | "Unknown error" : "Lỗi không xác định", 11 | "Owner" : "Chủ" 12 | },"pluralForm" :"nplurals=1; plural=0;" 13 | } -------------------------------------------------------------------------------- /lib/AppInfo/Application.php: -------------------------------------------------------------------------------- 1 | container = $this->getContainer(); 45 | $this->config = $this->container->get(IConfig::class); 46 | } 47 | 48 | public function register(IRegistrationContext $context): void { 49 | if ($this->config->getAppValue(self::APP_ID, 'dashboard_enabled', '1') === '1') { 50 | $context->registerDashboardWidget(GithubWidget::class); 51 | } 52 | 53 | if ($this->config->getAppValue(self::APP_ID, 'issue_notifications_enabled', '1') === '1') { 54 | $context->registerNotifierService(GitHubNotifier::class); 55 | } 56 | 57 | $context->registerSearchProvider(GithubSearchIssuesProvider::class); 58 | $context->registerSearchProvider(GithubSearchReposProvider::class); 59 | 60 | $context->registerReferenceProvider(GithubIssuePrReferenceProvider::class); 61 | $context->registerReferenceProvider(GithubCodeReferenceProvider::class); 62 | $context->registerEventListener(RenderReferenceEvent::class, GithubReferenceListener::class); 63 | $context->registerEventListener(AddContentSecurityPolicyEvent::class, ContentSecurityPolicyListener::class); 64 | } 65 | 66 | public function boot(IBootContext $context): void { 67 | $context->injectFn(\Closure::fromCallable([$this, 'registerNavigation'])); 68 | } 69 | 70 | public function registerNavigation(IUserSession $userSession): void { 71 | $user = $userSession->getUser(); 72 | if ($user !== null) { 73 | $userId = $user->getUID(); 74 | $container = $this->container; 75 | 76 | if ($this->config->getUserValue($userId, self::APP_ID, 'navigation_enabled', '0') === '1') { 77 | $container->get(INavigationManager::class)->add(static function () use ($container) { 78 | $urlGenerator = $container->get(IURLGenerator::class); 79 | $l10n = $container->get(IL10N::class); 80 | return [ 81 | 'id' => self::APP_ID, 82 | 'order' => 10, 83 | 'href' => 'https://github.com', 84 | 'target' => '_blank', 85 | 'icon' => $urlGenerator->imagePath(self::APP_ID, 'app.svg'), 86 | 'name' => $l10n->t('GitHub'), 87 | ]; 88 | }); 89 | } 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /lib/BackgroundJob/CheckGithubNotificationsJob.php: -------------------------------------------------------------------------------- 1 | setInterval(60 * 15); // Every 15 minutes 26 | } 27 | 28 | protected function run($argument): void { 29 | $this->githubAPIService->checkNewNotifications(); 30 | $this->logger->info('Checked if users have new unread GitHub notification.'); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /lib/Dashboard/GithubWidget.php: -------------------------------------------------------------------------------- 1 | l10n->t('GitHub notifications'); 49 | } 50 | 51 | /** 52 | * @inheritDoc 53 | */ 54 | public function getOrder(): int { 55 | return 10; 56 | } 57 | 58 | /** 59 | * @inheritDoc 60 | */ 61 | public function getIconClass(): string { 62 | return 'icon-github'; 63 | } 64 | 65 | /** 66 | * @inheritDoc 67 | */ 68 | public function getIconUrl(): string { 69 | return $this->urlGenerator->getAbsoluteURL( 70 | $this->urlGenerator->imagePath(Application::APP_ID, 'app-dark.svg') 71 | ); 72 | } 73 | 74 | /** 75 | * @inheritDoc 76 | */ 77 | public function getUrl(): ?string { 78 | return $this->urlGenerator->linkToRouteAbsolute('settings.PersonalSettings.index', ['section' => 'connected-accounts']); 79 | } 80 | 81 | /** 82 | * @inheritDoc 83 | */ 84 | public function load(): void { 85 | $clientID = $this->config->getAppValue(Application::APP_ID, 'client_id'); 86 | $clientSecret = $this->config->getAppValue(Application::APP_ID, 'client_secret'); 87 | $oauthPossible = $clientID !== '' && $clientSecret !== ''; 88 | $usePopup = $this->config->getAppValue(Application::APP_ID, 'use_popup', '0'); 89 | 90 | $userConfig = [ 91 | 'oauth_is_possible' => $oauthPossible, 92 | 'client_id' => $clientID, 93 | 'use_popup' => ($usePopup === '1'), 94 | ]; 95 | $this->initialStateService->provideInitialState('user-config', $userConfig); 96 | Util::addScript(Application::APP_ID, 'integration_github-dashboard'); 97 | Util::addStyle(Application::APP_ID, 'dashboard'); 98 | } 99 | 100 | /** 101 | * @inheritDoc 102 | */ 103 | public function getItems(string $userId, ?string $since = null, int $limit = 7): array { 104 | $notifications = $this->githubAPIService->getNotifications($this->userId, null, $since, $limit); 105 | if (isset($notifications['error'])) { 106 | return []; 107 | } 108 | $that = $this; 109 | return array_values(array_map(static function (array $notification) use ($that) { 110 | return $that->githubAPIService->getWidgetFromNotification($notification); 111 | }, $notifications)); 112 | } 113 | 114 | /** 115 | * @inheritDoc 116 | */ 117 | public function getWidgetButtons(string $userId): array { 118 | return [ 119 | new WidgetButton( 120 | WidgetButton::TYPE_MORE, 121 | 'https://github.com/notifications', 122 | $this->l10n->t('More notifications') 123 | ), 124 | ]; 125 | } 126 | 127 | /** 128 | * @inheritDoc 129 | */ 130 | public function getWidgetOptions(): WidgetOptions { 131 | return new WidgetOptions(true); 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /lib/Listener/ContentSecurityPolicyListener.php: -------------------------------------------------------------------------------- 1 | 17 | */ 18 | class ContentSecurityPolicyListener implements IEventListener { 19 | 20 | public function __construct() { 21 | } 22 | 23 | /** 24 | * @inheritDoc 25 | */ 26 | public function handle(Event $event): void { 27 | if (!$event instanceof AddContentSecurityPolicyEvent) { 28 | return; 29 | } 30 | 31 | $policy = new ContentSecurityPolicy(); 32 | $policy->addAllowedImageDomain('https://user-images.githubusercontent.com'); 33 | $event->addPolicy($policy); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /lib/Listener/GithubReferenceListener.php: -------------------------------------------------------------------------------- 1 | 18 | */ 19 | class GithubReferenceListener implements IEventListener { 20 | public function handle(Event $event): void { 21 | if (!$event instanceof RenderReferenceEvent) { 22 | return; 23 | } 24 | 25 | Util::addScript(Application::APP_ID, Application::APP_ID . '-reference'); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /lib/Migration/Version030010Date20241002015812.php: -------------------------------------------------------------------------------- 1 | config->getAppValue(Application::APP_ID, $key); 38 | if ($value !== '') { 39 | $encryptedValue = $this->crypto->encrypt($value); 40 | $this->config->setAppValue(Application::APP_ID, $key, $encryptedValue); 41 | } 42 | } 43 | 44 | // user tokens 45 | $qbUpdate = $this->connection->getQueryBuilder(); 46 | $qbUpdate->update('preferences') 47 | ->set('configvalue', $qbUpdate->createParameter('updateValue')) 48 | ->where( 49 | $qbUpdate->expr()->eq('appid', $qbUpdate->createNamedParameter(Application::APP_ID, IQueryBuilder::PARAM_STR)) 50 | ) 51 | ->andWhere( 52 | $qbUpdate->expr()->eq('userid', $qbUpdate->createParameter('updateUserId')) 53 | ) 54 | ->andWhere( 55 | $qbUpdate->expr()->eq('configkey', $qbUpdate->createNamedParameter('token', IQueryBuilder::PARAM_STR)) 56 | ); 57 | 58 | $qbSelect = $this->connection->getQueryBuilder(); 59 | $qbSelect->select('userid', 'configvalue') 60 | ->from('preferences') 61 | ->where( 62 | $qbSelect->expr()->eq('appid', $qbSelect->createNamedParameter(Application::APP_ID, IQueryBuilder::PARAM_STR)) 63 | ) 64 | ->andWhere( 65 | $qbSelect->expr()->eq('configkey', $qbSelect->createNamedParameter('token', IQueryBuilder::PARAM_STR)) 66 | ) 67 | ->andWhere( 68 | $qbSelect->expr()->nonEmptyString('configvalue') 69 | ) 70 | ->andWhere( 71 | $qbSelect->expr()->isNotNull('configvalue') 72 | ); 73 | $req = $qbSelect->executeQuery(); 74 | while ($row = $req->fetch()) { 75 | $userId = $row['userid']; 76 | $storedClearToken = $row['configvalue']; 77 | $encryptedToken = $this->crypto->encrypt($storedClearToken); 78 | $qbUpdate->setParameter('updateValue', $encryptedToken, IQueryBuilder::PARAM_STR); 79 | $qbUpdate->setParameter('updateUserId', $userId, IQueryBuilder::PARAM_STR); 80 | $qbUpdate->executeStatement(); 81 | } 82 | $req->closeCursor(); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /lib/Notification/GitHubNotifier.php: -------------------------------------------------------------------------------- 1 | factory->get('integration_github')->t('GitHub'); 32 | } 33 | 34 | public function prepare(INotification $notification, string $languageCode): INotification { 35 | if ($notification->getApp() !== Application::APP_ID) { 36 | throw new InvalidArgumentException(); 37 | } 38 | 39 | $l = $this->factory->get(Application::APP_ID, $languageCode); 40 | 41 | switch ($notification->getSubject()) { 42 | case 'new-github-notification': 43 | $p = $notification->getSubjectParameters(); 44 | $newNotifications = (int)($p['newNotifications'] ?? 0); 45 | $content = $l->n('You have %s new unread notification with recent activity on GitHub.', 'You have %s new unread notifications with recent activity on GitHub.', $newNotifications, [$newNotifications]); 46 | 47 | $notification->setParsedSubject($content) 48 | ->setLink('https://github.com/notifications') 49 | ->setIcon($this->urlGenerator->getAbsoluteURL($this->urlGenerator->imagePath(Application::APP_ID, 'app-dark.svg'))); 50 | return $notification; 51 | 52 | default: 53 | throw new InvalidArgumentException(); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /lib/Search/GithubSearchReposProvider.php: -------------------------------------------------------------------------------- 1 | l10n->t('GitHub repositories'); 48 | } 49 | 50 | /** 51 | * @inheritDoc 52 | */ 53 | public function getOrder(string $route, array $routeParameters): int { 54 | if (strpos($route, Application::APP_ID . '.') === 0) { 55 | // Active app, prefer Github results 56 | return -1; 57 | } 58 | 59 | return 20; 60 | } 61 | 62 | /** 63 | * @inheritDoc 64 | */ 65 | public function search(IUser $user, ISearchQuery $query): SearchResult { 66 | if (!$this->appManager->isEnabledForUser(Application::APP_ID, $user)) { 67 | return SearchResult::complete($this->getName(), []); 68 | } 69 | 70 | $limit = $query->getLimit(); 71 | $term = $query->getTerm(); 72 | $offset = $query->getCursor(); 73 | $offset = $offset ? intval($offset) : 0; 74 | 75 | $routeFrom = $query->getRoute(); 76 | $requestedFromSmartPicker = $routeFrom === '' || $routeFrom === 'smart-picker'; 77 | 78 | $searchReposEnabled = $this->config->getUserValue($user->getUID(), Application::APP_ID, 'search_repos_enabled', '0') === '1'; 79 | if (!$requestedFromSmartPicker && !$searchReposEnabled) { 80 | return SearchResult::paginated($this->getName(), [], 0); 81 | } 82 | 83 | $accessToken = $this->secretService->getAccessToken($user->getUID()); 84 | if ($accessToken === '') { 85 | return SearchResult::paginated($this->getName(), [], 0); 86 | } 87 | 88 | $searchResult = $this->service->searchRepositories($user->getUID(), $term, $offset, $limit); 89 | if (isset($searchResult['error'])) { 90 | $repos = []; 91 | } else { 92 | $repos = $searchResult['items']; 93 | } 94 | 95 | $formattedResults = array_map(function (array $entry): SearchResultEntry { 96 | return new SearchResultEntry( 97 | $this->getThumbnailUrl($entry), 98 | $this->getMainText($entry), 99 | $this->getSubline($entry), 100 | $this->getLinkToGithub($entry), 101 | '', 102 | true 103 | ); 104 | }, $repos); 105 | 106 | return SearchResult::paginated( 107 | $this->getName(), 108 | $formattedResults, 109 | $offset + $limit 110 | ); 111 | } 112 | 113 | /** 114 | * @param array $entry 115 | * @return string 116 | */ 117 | protected function getMainText(array $entry): string { 118 | return $entry['full_name'] . ' [' . ($entry['stargazers_count'] ?? 0) . '⭐]'; 119 | } 120 | 121 | /** 122 | * @param array $entry 123 | * @return string 124 | */ 125 | protected function getSubline(array $entry): string { 126 | return $entry['description'] ?? ''; 127 | } 128 | 129 | /** 130 | * @param array $entry 131 | * @return string 132 | */ 133 | protected function getLinkToGithub(array $entry): string { 134 | return $entry['html_url'] ?? ''; 135 | } 136 | 137 | /** 138 | * @param array $entry 139 | * @return string 140 | */ 141 | protected function getThumbnailUrl(array $entry): string { 142 | $userName = $entry['owner']['login'] ?? ''; 143 | return $this->urlGenerator->linkToRoute('integration_github.githubAPI.getAvatar', ['githubLogin' => $userName]); 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /lib/Service/SecretService.php: -------------------------------------------------------------------------------- 1 | config->setUserValue($userId, Application::APP_ID, $key, ''); 39 | return; 40 | } 41 | $encryptedValue = $this->crypto->encrypt($value); 42 | $this->config->setUserValue($userId, Application::APP_ID, $key, $encryptedValue); 43 | } 44 | 45 | /** 46 | * @param string $userId 47 | * @param string $key 48 | * @return string 49 | * @throws Exception 50 | */ 51 | public function getEncryptedUserValue(string $userId, string $key): string { 52 | $storedValue = $this->config->getUserValue($userId, Application::APP_ID, $key); 53 | if ($storedValue === '') { 54 | return ''; 55 | } 56 | return $this->crypto->decrypt($storedValue); 57 | } 58 | 59 | /** 60 | * @param string $key 61 | * @param string $value 62 | * @return void 63 | */ 64 | public function setEncryptedAppValue(string $key, string $value): void { 65 | if ($value === '') { 66 | $this->config->setAppValue(Application::APP_ID, $key, ''); 67 | return; 68 | } 69 | $encryptedValue = $this->crypto->encrypt($value); 70 | $this->config->setAppValue(Application::APP_ID, $key, $encryptedValue); 71 | } 72 | 73 | /** 74 | * @param string $key 75 | * @return string 76 | * @throws Exception 77 | */ 78 | public function getEncryptedAppValue(string $key): string { 79 | $storedValue = $this->config->getAppValue(Application::APP_ID, $key); 80 | if ($storedValue === '') { 81 | return ''; 82 | } 83 | return $this->crypto->decrypt($storedValue); 84 | } 85 | 86 | /** 87 | * Get the user access token 88 | * If there is none, get the default one, check: 89 | * - if we use it for this endpoint 90 | * - if user is anonymous 91 | * - if user is a guest 92 | * 93 | * @param string|null $userId 94 | * @param bool $endpointUsesDefaultToken 95 | * @return string 96 | * @throws Exception 97 | */ 98 | public function getAccessToken(?string $userId, bool $endpointUsesDefaultToken = false): string { 99 | // use user access token in priority 100 | $accessToken = ''; 101 | // for logged in users 102 | if ($userId !== null) { 103 | $accessToken = $this->getEncryptedUserValue($userId, 'token'); 104 | // fallback to admin default token if $useDefaultToken 105 | if ($accessToken === '' && $endpointUsesDefaultToken) { 106 | $user = $this->userManager->get($userId); 107 | $isGuestUser = $user->getBackendClassName() === 'Guests'; 108 | $allowDefaultTokenToGuests = $this->config->getAppValue(Application::APP_ID, 'allow_default_link_token_to_guests', '0') === '1'; 109 | 110 | if ((!$isGuestUser) || $allowDefaultTokenToGuests) { 111 | $accessToken = $this->getEncryptedAppValue('default_link_token'); 112 | } 113 | } 114 | } elseif ($endpointUsesDefaultToken) { 115 | // anonymous users 116 | $allowDefaultTokenToAnonymous = $this->config->getAppValue(Application::APP_ID, 'allow_default_link_token_to_anonymous', '0') === '1'; 117 | if ($allowDefaultTokenToAnonymous) { 118 | $accessToken = $this->getEncryptedAppValue('default_link_token'); 119 | } 120 | } 121 | 122 | return $accessToken; 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /lib/Settings/Admin.php: -------------------------------------------------------------------------------- 1 | secretService->getEncryptedAppValue('client_id'); 32 | $clientSecret = $this->secretService->getEncryptedAppValue('client_secret'); 33 | $usePopup = $this->config->getAppValue(Application::APP_ID, 'use_popup', '0'); 34 | $adminDashboardEnabled = $this->config->getAppValue(Application::APP_ID, 'dashboard_enabled', '1') === '1'; 35 | $adminLinkPreviewEnabled = $this->config->getAppValue(Application::APP_ID, 'link_preview_enabled', '1') === '1'; 36 | $defaultLinkToken = $this->secretService->getEncryptedAppValue('default_link_token'); 37 | $userName = $this->config->getAppValue(Application::APP_ID, 'user_name'); 38 | $userDisplayName = $this->config->getAppValue(Application::APP_ID, 'user_displayname'); 39 | $allowDefaultTokenToAnonymous = $this->config->getAppValue(Application::APP_ID, 'allow_default_link_token_to_anonymous', '0') === '1'; 40 | $allowDefaultTokenToGuests = $this->config->getAppValue(Application::APP_ID, 'allow_default_link_token_to_guests', '0') === '1'; 41 | $issueNotificationsEnabled = $this->config->getAppValue(Application::APP_ID, 'issue_notifications_enabled', '1') === '1'; 42 | 43 | if ($defaultLinkToken !== '' && ($userName === '' || $userDisplayName === '')) { 44 | $userInfo = $this->githubAPIService->updateLinkTokenUserInfo($defaultLinkToken); 45 | if (isset($userInfo['user_name'], $userInfo['user_displayname'])) { 46 | $userName = $userInfo['user_name']; 47 | $userDisplayName = $userInfo['user_displayname']; 48 | } 49 | } 50 | 51 | $adminConfig = [ 52 | 'client_id' => $clientID, 53 | 'client_secret' => $clientSecret === '' ? '' : 'dummyClientSecret', 54 | 'use_popup' => ($usePopup === '1'), 55 | 'dashboard_enabled' => $adminDashboardEnabled, 56 | 'link_preview_enabled' => $adminLinkPreviewEnabled, 57 | 'default_link_token' => $defaultLinkToken === '' ? '' : 'dummyToken', 58 | 'allow_default_link_token_to_anonymous' => $allowDefaultTokenToAnonymous, 59 | 'allow_default_link_token_to_guests' => $allowDefaultTokenToGuests, 60 | 'user_name' => $userName, 61 | 'user_displayname' => $userDisplayName, 62 | 'issue_notifications_enabled' => $issueNotificationsEnabled, 63 | ]; 64 | $this->initialStateService->provideInitialState('admin-config', $adminConfig); 65 | return new TemplateResponse(Application::APP_ID, 'adminSettings'); 66 | } 67 | 68 | public function getSection(): string { 69 | return 'connected-accounts'; 70 | } 71 | 72 | public function getPriority(): int { 73 | return 10; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /lib/Settings/AdminSection.php: -------------------------------------------------------------------------------- 1 | l->t('Connected accounts'); 38 | } 39 | 40 | /** 41 | * @return int whether the form should be rather on the top or bottom of 42 | * the settings navigation. The sections are arranged in ascending order of 43 | * the priority values. It is required to return a value between 0 and 99. 44 | */ 45 | public function getPriority(): int { 46 | return 80; 47 | } 48 | 49 | /** 50 | * @return string The relative path to a an icon describing the section 51 | */ 52 | public function getIcon(): string { 53 | return $this->urlGenerator->imagePath('core', 'categories/integration.svg'); 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /lib/Settings/Personal.php: -------------------------------------------------------------------------------- 1 | secretService->getEncryptedUserValue($this->userId, 'token'); 31 | $searchIssuesEnabled = $this->config->getUserValue($this->userId, Application::APP_ID, 'search_issues_enabled', '0'); 32 | $searchReposEnabled = $this->config->getUserValue($this->userId, Application::APP_ID, 'search_repos_enabled', '0'); 33 | $navigationEnabled = $this->config->getUserValue($this->userId, Application::APP_ID, 'navigation_enabled', '0'); 34 | $linkPreviewEnabled = $this->config->getUserValue($this->userId, Application::APP_ID, 'link_preview_enabled', '1'); 35 | $userName = $this->config->getUserValue($this->userId, Application::APP_ID, 'user_name'); 36 | $userDisplayName = $this->config->getUserValue($this->userId, Application::APP_ID, 'user_displayname'); 37 | $notificationsEnabled = $this->config->getUserValue($this->userId, Application::APP_ID, 'issue_notifications_enabled', '0'); 38 | $adminNotificationsEnabled = $this->config->getAppValue(Application::APP_ID, 'issue_notifications_enabled', '1'); 39 | 40 | // for OAuth 41 | $clientID = $this->secretService->getEncryptedAppValue('client_id'); 42 | $clientSecret = $this->secretService->getEncryptedAppValue('client_secret'); 43 | $usePopup = $this->config->getAppValue(Application::APP_ID, 'use_popup', '0'); 44 | 45 | $userConfig = [ 46 | 'token' => $token === '' ? '' : 'dummyToken', 47 | 'client_id' => $clientID, 48 | 'client_secret' => $clientSecret !== '', 49 | 'use_popup' => ($usePopup === '1'), 50 | 'search_issues_enabled' => ($searchIssuesEnabled === '1'), 51 | 'search_repos_enabled' => ($searchReposEnabled === '1'), 52 | 'navigation_enabled' => ($navigationEnabled === '1'), 53 | 'link_preview_enabled' => ($linkPreviewEnabled === '1'), 54 | 'user_name' => $userName, 55 | 'user_displayname' => $userDisplayName, 56 | 'issue_notifications_enabled' => ($notificationsEnabled === '1'), 57 | 'admin_issue_notifications_enabled' => ($adminNotificationsEnabled === '1'), 58 | ]; 59 | $this->initialStateService->provideInitialState('user-config', $userConfig); 60 | return new TemplateResponse(Application::APP_ID, 'personalSettings'); 61 | } 62 | 63 | public function getSection(): string { 64 | return 'connected-accounts'; 65 | } 66 | 67 | public function getPriority(): int { 68 | return 10; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /lib/Settings/PersonalSection.php: -------------------------------------------------------------------------------- 1 | l->t('Connected accounts'); 38 | } 39 | 40 | /** 41 | * @return int whether the form should be rather on the top or bottom of 42 | * the settings navigation. The sections are arranged in ascending order of 43 | * the priority values. It is required to return a value between 0 and 99. 44 | */ 45 | public function getPriority(): int { 46 | return 80; 47 | } 48 | 49 | /** 50 | * @return string The relative path to a an icon describing the section 51 | */ 52 | public function getIcon(): string { 53 | return $this->urlGenerator->imagePath('core', 'categories/integration.svg'); 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors 2 | # SPDX-License-Identifier: AGPL-3.0-or-later 3 | app_name=integration_github 4 | app_version=$(version) 5 | project_dir=. 6 | build_dir=/tmp/build 7 | sign_dir=/tmp/sign 8 | cert_dir=$(HOME)/.nextcloud/certificates 9 | webserveruser ?= www-data 10 | occ_dir ?= /var/www/html/dev/server 11 | 12 | build_tools_directory=$(CURDIR)/build/tools 13 | npm=$(shell which npm 2> /dev/null) 14 | composer=$(shell which composer 2> /dev/null) 15 | 16 | all: build 17 | 18 | .PHONY: build 19 | build: 20 | ifneq (,$(wildcard $(CURDIR)/composer.json)) 21 | make composer 22 | endif 23 | ifneq (,$(wildcard $(CURDIR)/package.json)) 24 | make npm 25 | endif 26 | 27 | .PHONY: dev 28 | dev: 29 | ifneq (,$(wildcard $(CURDIR)/composer.json)) 30 | make composer 31 | endif 32 | ifneq (,$(wildcard $(CURDIR)/package.json)) 33 | make npm-dev 34 | endif 35 | 36 | # Installs and updates the composer dependencies. If composer is not installed 37 | # a copy is fetched from the web 38 | .PHONY: composer 39 | composer: 40 | ifeq (, $(composer)) 41 | @echo "No composer command available, downloading a copy from the web" 42 | mkdir -p $(build_tools_directory) 43 | curl -sS https://getcomposer.org/installer | php 44 | mv composer.phar $(build_tools_directory) 45 | php $(build_tools_directory)/composer.phar install --prefer-dist 46 | else 47 | composer install --prefer-dist 48 | endif 49 | 50 | .PHONY: npm 51 | npm: 52 | $(npm) ci 53 | $(npm) run build 54 | 55 | .PHONY: npm-dev 56 | npm-dev: 57 | $(npm) ci 58 | $(npm) run dev 59 | 60 | clean: 61 | sudo rm -rf $(build_dir) 62 | sudo rm -rf $(sign_dir) 63 | 64 | appstore: clean 65 | mkdir -p $(sign_dir) 66 | mkdir -p $(build_dir) 67 | @rsync -a \ 68 | --exclude=.git \ 69 | --exclude=appinfo/signature.json \ 70 | --exclude=*.swp \ 71 | --exclude=build \ 72 | --exclude=.gitignore \ 73 | --exclude=.travis.yml \ 74 | --exclude=.scrutinizer.yml \ 75 | --exclude=CONTRIBUTING.md \ 76 | --exclude=composer.json \ 77 | --exclude=composer.lock \ 78 | --exclude=composer.phar \ 79 | --exclude=package.json \ 80 | --exclude=package-lock.json \ 81 | --exclude=js/node_modules \ 82 | --exclude=node_modules \ 83 | --exclude=/src \ 84 | --exclude=translationfiles \ 85 | --exclude=webpack.* \ 86 | --exclude=stylelint.config.js \ 87 | --exclude=.eslintrc.js \ 88 | --exclude=.github \ 89 | --exclude=.gitlab-ci.yml \ 90 | --exclude=crowdin.yml \ 91 | --exclude=tools \ 92 | --exclude=l10n/.tx \ 93 | --exclude=.tx \ 94 | --exclude=.l10nignore \ 95 | --exclude=l10n/l10n.pl \ 96 | --exclude=l10n/templates \ 97 | --exclude=l10n/*.sh \ 98 | --exclude=l10n/[a-z][a-z] \ 99 | --exclude=l10n/[a-z][a-z]_[A-Z][A-Z] \ 100 | --exclude=l10n/no-php \ 101 | --exclude=makefile \ 102 | --exclude=screenshots \ 103 | --exclude=phpunit*xml \ 104 | --exclude=tests \ 105 | --exclude=ci \ 106 | --exclude=vendor/bin \ 107 | $(project_dir) $(sign_dir)/$(app_name) 108 | @if [ -f $(cert_dir)/$(app_name).key ]; then \ 109 | sudo chown $(webserveruser) $(sign_dir)/$(app_name)/appinfo ;\ 110 | sudo -u $(webserveruser) php $(occ_dir)/occ integrity:sign-app --privateKey=$(cert_dir)/$(app_name).key --certificate=$(cert_dir)/$(app_name).crt --path=$(sign_dir)/$(app_name)/ ;\ 111 | sudo chown -R $(USER) $(sign_dir)/$(app_name)/appinfo ;\ 112 | else \ 113 | echo "!!! WARNING signature key not found" ;\ 114 | fi 115 | tar -czf $(build_dir)/$(app_name)-$(app_version).tar.gz \ 116 | -C $(sign_dir) $(app_name) 117 | @if [ -f $(cert_dir)/$(app_name).key ]; then \ 118 | echo NEXTCLOUD------------------------------------------ ;\ 119 | openssl dgst -sha512 -sign $(cert_dir)/$(app_name).key $(build_dir)/$(app_name)-$(app_version).tar.gz | openssl base64 | tee $(build_dir)/sign.txt ;\ 120 | fi 121 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "integration_github", 3 | "version": "0.0.1", 4 | "description": "GitHub integration", 5 | "main": "index.js", 6 | "directories": { 7 | "test": "tests" 8 | }, 9 | "type": "module", 10 | "scripts": { 11 | "build": "NODE_ENV=production vite --mode production build", 12 | "dev": "NODE_ENV=development vite --mode development build", 13 | "watch": "NODE_ENV=development vite --mode development build --watch", 14 | "lint": "eslint --ext .js,.vue src", 15 | "lint:fix": "eslint --ext .js,.vue src --fix", 16 | "stylelint": "stylelint src/**/*.vue src/**/*.scss src/**/*.css", 17 | "stylelint:fix": "stylelint src/**/*.vue src/**/*.scss src/**/*.css --fix" 18 | }, 19 | "repository": { 20 | "type": "git", 21 | "url": "https://github.com/nextcloud/integration_github" 22 | }, 23 | "keywords": [ 24 | "github" 25 | ], 26 | "author": "Julien Veyssier", 27 | "license": "AGPL-3.0", 28 | "bugs": { 29 | "url": "https://github.com/nextcloud/integration_github/issues" 30 | }, 31 | "homepage": "https://github.com/nextcloud/integration_github", 32 | "browserslist": [ 33 | "extends @nextcloud/browserslist-config" 34 | ], 35 | "engines": { 36 | "node": "^20.0.0", 37 | "npm": "^9.0.0 || ^10.0.0" 38 | }, 39 | "dependencies": { 40 | "@alchemyalcove/rgb-to-hsl": "^1.0.5", 41 | "@nextcloud/auth": "^2.4.0", 42 | "@nextcloud/axios": "^2.5.1", 43 | "@nextcloud/dialogs": "^5.1.2", 44 | "@nextcloud/initial-state": "^2.2.0", 45 | "@nextcloud/l10n": "^3.2.0", 46 | "@nextcloud/moment": "^1.3.2", 47 | "@nextcloud/password-confirmation": "^5.3.1", 48 | "@nextcloud/router": "^3.0.1", 49 | "@nextcloud/vue": "^8.24.0", 50 | "highlight.js": "^11.11.1", 51 | "vue": "^2.7.16", 52 | "vue-highlightjs": "^1.3.3", 53 | "vue-material-design-icons": "^5.3.1" 54 | }, 55 | "devDependencies": { 56 | "@nextcloud/babel-config": "^1.2.0", 57 | "@nextcloud/browserslist-config": "^3.0.1", 58 | "@nextcloud/eslint-config": "^8.4.2", 59 | "@nextcloud/stylelint-config": "^3.0.1", 60 | "@nextcloud/vite-config": "^1.4.2", 61 | "vite-plugin-eslint": "^1.8.1", 62 | "vite-plugin-stylelint": "^5.3.1" 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /psalm.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /src/adminSettings.js: -------------------------------------------------------------------------------- 1 | /** 2 | * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors 3 | * SPDX-License-Identifier: AGPL-3.0-or-later 4 | */ 5 | 6 | import Vue from 'vue' 7 | import './bootstrap.js' 8 | import AdminSettings from './components/AdminSettings.vue' 9 | 10 | const View = Vue.extend(AdminSettings) 11 | new View().$mount('#github_prefs') 12 | -------------------------------------------------------------------------------- /src/bootstrap.js: -------------------------------------------------------------------------------- 1 | /** 2 | * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors 3 | * SPDX-License-Identifier: AGPL-3.0-or-later 4 | */ 5 | import Vue from 'vue' 6 | import { translate, translatePlural } from '@nextcloud/l10n' 7 | 8 | Vue.prototype.t = translate 9 | Vue.prototype.n = translatePlural 10 | Vue.prototype.OC = window.OC 11 | Vue.prototype.OCA = window.OCA 12 | -------------------------------------------------------------------------------- /src/components/CommentReactions.vue: -------------------------------------------------------------------------------- 1 | 5 | 18 | 19 | 96 | 97 | 119 | -------------------------------------------------------------------------------- /src/components/icons/CommentIcon.vue: -------------------------------------------------------------------------------- 1 | 5 | 25 | 26 | 45 | -------------------------------------------------------------------------------- /src/components/icons/CommitIcon.vue: -------------------------------------------------------------------------------- 1 | 5 | 25 | 26 | 45 | -------------------------------------------------------------------------------- /src/components/icons/GithubIcon.vue: -------------------------------------------------------------------------------- 1 | 5 | 25 | 26 | 45 | -------------------------------------------------------------------------------- /src/components/icons/IssueClosedIcon.vue: -------------------------------------------------------------------------------- 1 | 5 | 26 | 27 | 46 | -------------------------------------------------------------------------------- /src/components/icons/IssueClosedNotPlannedIcon.vue: -------------------------------------------------------------------------------- 1 | 5 | 25 | 26 | 45 | -------------------------------------------------------------------------------- /src/components/icons/IssueOpenIcon.vue: -------------------------------------------------------------------------------- 1 | 5 | 26 | 27 | 46 | -------------------------------------------------------------------------------- /src/components/icons/LocationIcon.vue: -------------------------------------------------------------------------------- 1 | 5 | 25 | 26 | 45 | -------------------------------------------------------------------------------- /src/components/icons/MilestoneIcon.vue: -------------------------------------------------------------------------------- 1 | 5 | 25 | 26 | 45 | -------------------------------------------------------------------------------- /src/components/icons/PrClosedIcon.vue: -------------------------------------------------------------------------------- 1 | 5 | 25 | 26 | 45 | -------------------------------------------------------------------------------- /src/components/icons/PrMergedIcon.vue: -------------------------------------------------------------------------------- 1 | 5 | 25 | 26 | 45 | -------------------------------------------------------------------------------- /src/components/icons/PrOpenDraftIcon.vue: -------------------------------------------------------------------------------- 1 | 5 | 26 | 27 | 46 | -------------------------------------------------------------------------------- /src/components/icons/PrOpenIcon.vue: -------------------------------------------------------------------------------- 1 | 5 | 25 | 26 | 45 | -------------------------------------------------------------------------------- /src/components/icons/RepositoryIcon.vue: -------------------------------------------------------------------------------- 1 | 5 | 25 | 26 | 45 | -------------------------------------------------------------------------------- /src/components/icons/RocketIcon.vue: -------------------------------------------------------------------------------- 1 | 5 | 25 | 26 | 45 | -------------------------------------------------------------------------------- /src/dashboard.js: -------------------------------------------------------------------------------- 1 | /** 2 | * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors 3 | * SPDX-License-Identifier: AGPL-3.0-or-later 4 | */ 5 | 6 | document.addEventListener('DOMContentLoaded', () => { 7 | OCA.Dashboard.register('github_notifications', async (el, { widget }) => { 8 | const { default: Vue } = await import('vue') 9 | const { default: Dashboard } = await import('./views/Dashboard.vue') 10 | Vue.mixin({ methods: { t, n } }) 11 | const View = Vue.extend(Dashboard) 12 | new View({ 13 | propsData: { title: widget.title }, 14 | }).$mount(el) 15 | }) 16 | }) 17 | -------------------------------------------------------------------------------- /src/personalSettings.js: -------------------------------------------------------------------------------- 1 | /** 2 | * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors 3 | * SPDX-License-Identifier: AGPL-3.0-or-later 4 | */ 5 | 6 | import Vue from 'vue' 7 | import './bootstrap.js' 8 | import PersonalSettings from './components/PersonalSettings.vue' 9 | 10 | const View = Vue.extend(PersonalSettings) 11 | new View().$mount('#github_prefs') 12 | -------------------------------------------------------------------------------- /src/popupSuccess.js: -------------------------------------------------------------------------------- 1 | /** 2 | * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors 3 | * SPDX-License-Identifier: AGPL-3.0-or-later 4 | */ 5 | import { loadState } from '@nextcloud/initial-state' 6 | 7 | const state = loadState('integration_github', 'popup-data') 8 | const userName = state.user_name 9 | const userDisplayName = state.user_displayname 10 | 11 | if (window.opener) { 12 | window.opener.postMessage({ userName, userDisplayName }) 13 | window.close() 14 | } 15 | -------------------------------------------------------------------------------- /src/reference.js: -------------------------------------------------------------------------------- 1 | /** 2 | * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors 3 | * SPDX-License-Identifier: AGPL-3.0-or-later 4 | */ 5 | 6 | import { registerWidget } from '@nextcloud/vue/dist/Components/NcRichText.js' 7 | 8 | registerWidget('integration_github_issue_pr', async (el, { richObjectType, richObject, accessible }) => { 9 | const { default: Vue } = await import('vue') 10 | const { default: GithubIssuePrReferenceWidget } = await import('./views/GithubIssuePrReferenceWidget.vue') 11 | Vue.mixin({ methods: { t, n } }) 12 | const Widget = Vue.extend(GithubIssuePrReferenceWidget) 13 | new Widget({ 14 | propsData: { 15 | richObjectType, 16 | richObject, 17 | accessible, 18 | }, 19 | }).$mount(el) 20 | }, () => {}, { hasInteractiveView: false }) 21 | 22 | registerWidget('integration_github_code_permalink', async (el, { richObjectType, richObject, accessible }) => { 23 | const { default: Vue } = await import(/* webpackChunkName: "reference-permalink-lazy" */'vue') 24 | const { default: GithubCodePermalinkReferenceWidget } = await import('./views/GithubCodePermalinkReferenceWidget.vue') 25 | Vue.mixin({ methods: { t, n } }) 26 | const Widget = Vue.extend(GithubCodePermalinkReferenceWidget) 27 | new Widget({ 28 | propsData: { 29 | richObjectType, 30 | richObject, 31 | accessible, 32 | }, 33 | }).$mount(el) 34 | }, () => {}, { hasInteractiveView: false }) 35 | -------------------------------------------------------------------------------- /src/utils.js: -------------------------------------------------------------------------------- 1 | /** 2 | * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors 3 | * SPDX-License-Identifier: AGPL-3.0-or-later 4 | */ 5 | import { generateUrl } from '@nextcloud/router' 6 | import axios from '@nextcloud/axios' 7 | import { showError } from '@nextcloud/dialogs' 8 | 9 | let mytimer = 0 10 | export function delay(callback, ms) { 11 | return function() { 12 | const context = this 13 | const args = arguments 14 | clearTimeout(mytimer) 15 | mytimer = setTimeout(function() { 16 | callback.apply(context, args) 17 | }, ms || 0) 18 | } 19 | } 20 | 21 | export function oauthConnect(clientId, oauthOrigin, usePopup = false) { 22 | const redirectUri = window.location.protocol + '//' + window.location.host + generateUrl('/apps/integration_github/oauth-redirect') 23 | 24 | const oauthState = Math.random().toString(36).substring(3) 25 | const requestUrl = 'https://github.com/login/oauth/authorize' 26 | + '?client_id=' + encodeURIComponent(clientId) 27 | + '&redirect_uri=' + encodeURIComponent(redirectUri) 28 | + '&state=' + encodeURIComponent(oauthState) 29 | + '&scope=' + encodeURIComponent('read:user user:email repo notifications') 30 | 31 | const req = { 32 | values: { 33 | oauth_state: oauthState, 34 | redirect_uri: redirectUri, 35 | oauth_origin: usePopup ? undefined : oauthOrigin, 36 | }, 37 | } 38 | const url = generateUrl('/apps/integration_github/config') 39 | return new Promise((resolve, reject) => { 40 | axios.put(url, req).then((response) => { 41 | if (usePopup) { 42 | const ssoWindow = window.open( 43 | requestUrl, 44 | t('integration_github', 'Connect to GitHub'), 45 | 'toolbar=no, menubar=no, width=600, height=700') 46 | ssoWindow.focus() 47 | window.addEventListener('message', (event) => { 48 | console.debug('Child window message received', event) 49 | resolve(event.data) 50 | }) 51 | } else { 52 | window.location.replace(requestUrl) 53 | } 54 | }).catch((error) => { 55 | showError( 56 | t('integration_github', 'Failed to save GitHub OAuth state') 57 | + ': ' + (error.response?.request?.responseText ?? ''), 58 | ) 59 | console.error(error) 60 | }) 61 | }) 62 | } 63 | 64 | export function hexToRgb(hex) { 65 | const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex) 66 | return result 67 | ? { 68 | r: parseInt(result[1], 16), 69 | g: parseInt(result[2], 16), 70 | b: parseInt(result[3], 16), 71 | } 72 | : null 73 | } 74 | 75 | export function isDarkMode() { 76 | const bodyDataTheme = document.body.getAttribute('data-themes') 77 | return bodyDataTheme.startsWith('light') 78 | ? false 79 | : bodyDataTheme.startsWith('dark') 80 | ? true 81 | : (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) 82 | } 83 | -------------------------------------------------------------------------------- /stylelint.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: 'stylelint-config-recommended-vue', 3 | rules: { 4 | 'selector-type-no-unknown': null, 5 | 'rule-empty-line-before': [ 6 | 'always', 7 | { 8 | ignore: ['after-comment', 'inside-block'], 9 | }, 10 | ], 11 | 'declaration-empty-line-before': [ 12 | 'never', 13 | { 14 | ignore: ['after-declaration'], 15 | }, 16 | ], 17 | 'comment-empty-line-before': null, 18 | 'selector-type-case': null, 19 | 'no-descending-specificity': null, 20 | 'selector-pseudo-element-no-unknown': [ 21 | true, 22 | { 23 | ignorePseudoElements: ['v-deep'], 24 | }, 25 | ], 26 | }, 27 | plugins: ['stylelint-scss'], 28 | } 29 | -------------------------------------------------------------------------------- /templates/adminSettings.php: -------------------------------------------------------------------------------- 1 | 9 | 10 |
11 | -------------------------------------------------------------------------------- /templates/personalSettings.php: -------------------------------------------------------------------------------- 1 | 9 | 10 |
11 | -------------------------------------------------------------------------------- /templates/popupSuccess.php: -------------------------------------------------------------------------------- 1 | 9 | 10 |
11 | -------------------------------------------------------------------------------- /tests/bootstrap.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | ../appinfo 9 | ../lib 10 | 11 | 12 | 13 | . 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /tests/psalm-baseline.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /tests/unit/Controller/data/avatar.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nextcloud/integration_github/15249ea1ec9ac375e0d4074c59c74311f981249c/tests/unit/Controller/data/avatar.jpg -------------------------------------------------------------------------------- /tests/unit/Controller/data/issue_comment.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 1, 3 | "node_id": "MDEyOklzc3VlQ29tbWVudDE=", 4 | "url": "https://api.github.com/repos/octocat/Hello-World/issues/comments/1", 5 | "html_url": "https://github.com/octocat/Hello-World/issues/1347#issuecomment-1", 6 | "body": "Me too", 7 | "user": { 8 | "login": "octocat", 9 | "id": 1, 10 | "node_id": "MDQ6VXNlcjE=", 11 | "avatar_url": "https://github.com/images/error/octocat_happy.gif", 12 | "gravatar_id": "", 13 | "url": "https://api.github.com/users/octocat", 14 | "html_url": "https://github.com/octocat", 15 | "followers_url": "https://api.github.com/users/octocat/followers", 16 | "following_url": "https://api.github.com/users/octocat/following{/other_user}", 17 | "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", 18 | "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", 19 | "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", 20 | "organizations_url": "https://api.github.com/users/octocat/orgs", 21 | "repos_url": "https://api.github.com/users/octocat/repos", 22 | "events_url": "https://api.github.com/users/octocat/events{/privacy}", 23 | "received_events_url": "https://api.github.com/users/octocat/received_events", 24 | "type": "User", 25 | "site_admin": false 26 | }, 27 | "created_at": "2011-04-14T16:00:49Z", 28 | "updated_at": "2011-04-14T16:00:49Z", 29 | "issue_url": "https://api.github.com/repos/octocat/Hello-World/issues/1347", 30 | "author_association": "COLLABORATOR" 31 | } -------------------------------------------------------------------------------- /tests/unit/Controller/data/issue_comment_reactions.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": 1, 4 | "node_id": "MDg6UmVhY3Rpb24x", 5 | "user": { 6 | "login": "octocat", 7 | "id": 1, 8 | "node_id": "MDQ6VXNlcjE=", 9 | "avatar_url": "https://github.com/images/error/octocat_happy.gif", 10 | "gravatar_id": "", 11 | "url": "https://api.github.com/users/octocat", 12 | "html_url": "https://github.com/octocat", 13 | "followers_url": "https://api.github.com/users/octocat/followers", 14 | "following_url": "https://api.github.com/users/octocat/following{/other_user}", 15 | "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", 16 | "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", 17 | "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", 18 | "organizations_url": "https://api.github.com/users/octocat/orgs", 19 | "repos_url": "https://api.github.com/users/octocat/repos", 20 | "events_url": "https://api.github.com/users/octocat/events{/privacy}", 21 | "received_events_url": "https://api.github.com/users/octocat/received_events", 22 | "type": "User", 23 | "site_admin": false 24 | }, 25 | "content": "heart", 26 | "created_at": "2016-05-20T20:09:31Z" 27 | } 28 | ] -------------------------------------------------------------------------------- /tests/unit/Controller/data/issue_reactions.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": 1, 4 | "node_id": "MDg6UmVhY3Rpb24x", 5 | "user": { 6 | "login": "octocat", 7 | "id": 1, 8 | "node_id": "MDQ6VXNlcjE=", 9 | "avatar_url": "https://github.com/images/error/octocat_happy.gif", 10 | "gravatar_id": "", 11 | "url": "https://api.github.com/users/octocat", 12 | "html_url": "https://github.com/octocat", 13 | "followers_url": "https://api.github.com/users/octocat/followers", 14 | "following_url": "https://api.github.com/users/octocat/following{/other_user}", 15 | "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", 16 | "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", 17 | "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", 18 | "organizations_url": "https://api.github.com/users/octocat/orgs", 19 | "repos_url": "https://api.github.com/users/octocat/repos", 20 | "events_url": "https://api.github.com/users/octocat/events{/privacy}", 21 | "received_events_url": "https://api.github.com/users/octocat/received_events", 22 | "type": "User", 23 | "site_admin": false 24 | }, 25 | "content": "heart", 26 | "created_at": "2016-05-20T20:09:31Z" 27 | } 28 | ] -------------------------------------------------------------------------------- /tests/unit/Controller/data/users.json: -------------------------------------------------------------------------------- 1 | { 2 | "login": "octocat", 3 | "id": 1, 4 | "node_id": "MDQ6VXNlcjE=", 5 | "avatar_url": "https://avatars.githubusercontent.com/u/12345?v=4", 6 | "gravatar_id": "", 7 | "url": "https://api.github.com/users/octocat", 8 | "html_url": "https://github.com/octocat", 9 | "followers_url": "https://api.github.com/users/octocat/followers", 10 | "following_url": "https://api.github.com/users/octocat/following{/other_user}", 11 | "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", 12 | "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", 13 | "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", 14 | "organizations_url": "https://api.github.com/users/octocat/orgs", 15 | "repos_url": "https://api.github.com/users/octocat/repos", 16 | "events_url": "https://api.github.com/users/octocat/events{/privacy}", 17 | "received_events_url": "https://api.github.com/users/octocat/received_events", 18 | "type": "User", 19 | "site_admin": false, 20 | "name": "monalisa octocat", 21 | "company": "GitHub", 22 | "blog": "https://github.com/blog", 23 | "location": "San Francisco", 24 | "email": "octocat@github.com", 25 | "hireable": false, 26 | "bio": "There once was...", 27 | "twitter_username": "monatheoctocat", 28 | "public_repos": 2, 29 | "public_gists": 1, 30 | "followers": 20, 31 | "following": 0, 32 | "created_at": "2008-01-14T04:33:35Z", 33 | "updated_at": "2008-01-14T04:33:35Z" 34 | } -------------------------------------------------------------------------------- /tests/unit/Controller/data/users_contextual.json: -------------------------------------------------------------------------------- 1 | { 2 | "contexts": [ 3 | { 4 | "message": "Owns this repository", 5 | "octicon": "repo" 6 | } 7 | ] 8 | } -------------------------------------------------------------------------------- /tests/unit/Service/GithubAPIServiceTest.php: -------------------------------------------------------------------------------- 1 | assertEquals('integration_github', $app::APP_ID); 14 | } 15 | 16 | public function testPaginationConversion() { 17 | $expecteds = [ 18 | // offset, limit => perPage, page, leftPadding 19 | [[0, 5], [5, 1, 0]], 20 | [[0, 10], [10, 1, 0]], 21 | [[2, 5], [7, 1, 2]], 22 | [[2, 10], [12, 1, 2]], 23 | 24 | [[12, 2], [2, 7, 0]], 25 | [[12, 3], [3, 5, 0]], 26 | [[12, 4], [4, 4, 0]], 27 | [[12, 5], [6, 3, 0]], 28 | [[12, 6], [6, 3, 0]], 29 | [[12, 7], [10, 2, 2]], 30 | ]; 31 | 32 | foreach ($expecteds as $expected) { 33 | $params = $expected[0]; 34 | $offset = $params[0]; 35 | $limit = $params[1]; 36 | 37 | $expectedResults = $expected[1]; 38 | $results = GithubAPIService::getGitHubPaginationValues($offset, $limit); 39 | $this->assertEquals($expectedResults, $results); 40 | } 41 | 42 | foreach (range(0, 100) as $offset) { 43 | foreach (range(1, 100) as $limit) { 44 | [$perPage, $page, $leftPadding] = GithubAPIService::getGitHubPaginationValues($offset, $limit); 45 | // what do we want? 46 | $firstRequestedIndex = $offset; 47 | $lastRequestedIndex = $offset + $limit - 1; 48 | 49 | // what do we get? 50 | // page number start at 1 51 | $firstObtainedIndex = ($page - 1) * $perPage; 52 | $lastObtainedIndex = $firstObtainedIndex + ($perPage - 1); 53 | 54 | // check requested indexes are in the obtained page 55 | $this->assertTrue($firstRequestedIndex >= $firstObtainedIndex); 56 | $this->assertTrue($lastRequestedIndex <= $lastObtainedIndex); 57 | 58 | // page size can't be smaller than the number of elements we want 59 | $this->assertTrue($perPage >= $limit); 60 | // no negative padding 61 | $this->assertTrue($leftPadding >= 0); 62 | // padding can't be bigger than the number of extra elements we got 63 | $this->assertTrue($leftPadding <= $perPage - $limit); 64 | } 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /vendor-bin/php-cs-fixer/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "require-dev": { 3 | "nextcloud/coding-standard": "^1.2" 4 | }, 5 | "config": { 6 | "platform": { 7 | "php": "8.0" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /vendor-bin/phpunit/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "require-dev": { 3 | "phpunit/phpunit": "^9.6" 4 | }, 5 | "config": { 6 | "platform": { 7 | "php": "8.0" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /vendor-bin/psalm/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "require-dev": { 3 | "psalm/phar": "^5.22" 4 | }, 5 | "config": { 6 | "platform": { 7 | "php": "8.0" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /vendor-bin/psalm/composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", 5 | "This file is @generated automatically" 6 | ], 7 | "content-hash": "3495ee8f47f7d906767ccc17bf8f2358", 8 | "packages": [], 9 | "packages-dev": [ 10 | { 11 | "name": "psalm/phar", 12 | "version": "5.26.1", 13 | "source": { 14 | "type": "git", 15 | "url": "https://github.com/psalm/phar.git", 16 | "reference": "8a38e7ad04499a0ccd2c506fd1da6fc01fff4547" 17 | }, 18 | "dist": { 19 | "type": "zip", 20 | "url": "https://api.github.com/repos/psalm/phar/zipball/8a38e7ad04499a0ccd2c506fd1da6fc01fff4547", 21 | "reference": "8a38e7ad04499a0ccd2c506fd1da6fc01fff4547", 22 | "shasum": "" 23 | }, 24 | "require": { 25 | "php": "^7.1 || ^8.0" 26 | }, 27 | "conflict": { 28 | "vimeo/psalm": "*" 29 | }, 30 | "bin": [ 31 | "psalm.phar" 32 | ], 33 | "type": "library", 34 | "notification-url": "https://packagist.org/downloads/", 35 | "license": [ 36 | "MIT" 37 | ], 38 | "description": "Composer-based Psalm Phar", 39 | "support": { 40 | "issues": "https://github.com/psalm/phar/issues", 41 | "source": "https://github.com/psalm/phar/tree/5.26.1" 42 | }, 43 | "time": "2024-09-09T16:22:43+00:00" 44 | } 45 | ], 46 | "aliases": [], 47 | "minimum-stability": "stable", 48 | "stability-flags": [], 49 | "prefer-stable": false, 50 | "prefer-lowest": false, 51 | "platform": [], 52 | "platform-dev": [], 53 | "platform-overrides": { 54 | "php": "8.0" 55 | }, 56 | "plugin-api-version": "2.6.0" 57 | } 58 | -------------------------------------------------------------------------------- /vite.config.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors 3 | * SPDX-License-Identifier: AGPL-3.0-or-later 4 | */ 5 | import { createAppConfig } from '@nextcloud/vite-config' 6 | import eslint from 'vite-plugin-eslint' 7 | import stylelint from 'vite-plugin-stylelint' 8 | 9 | const isProduction = process.env.NODE_ENV === 'production' 10 | 11 | export default createAppConfig({ 12 | personalSettings: 'src/personalSettings.js', 13 | adminSettings: 'src/adminSettings.js', 14 | dashboard: 'src/dashboard.js', 15 | popupSuccess: 'src/popupSuccess.js', 16 | reference: 'src/reference.js', 17 | }, { 18 | config: { 19 | css: { 20 | modules: { 21 | localsConvention: 'camelCase', 22 | }, 23 | preprocessorOptions: { 24 | scss: { 25 | api: 'modern-compiler', 26 | }, 27 | }, 28 | }, 29 | plugins: [eslint(), stylelint()], 30 | }, 31 | inlineCSS: { relativeCSSInjection: true }, 32 | minify: isProduction, 33 | }) 34 | -------------------------------------------------------------------------------- /webpack.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const webpackConfig = require('@nextcloud/webpack-vue-config') 3 | const ESLintPlugin = require('eslint-webpack-plugin') 4 | const StyleLintPlugin = require('stylelint-webpack-plugin') 5 | 6 | const buildMode = process.env.NODE_ENV 7 | const isDev = buildMode === 'development' 8 | webpackConfig.devtool = isDev ? 'cheap-source-map' : 'source-map' 9 | // webpackConfig.bail = false 10 | 11 | webpackConfig.stats = { 12 | colors: true, 13 | modules: false, 14 | } 15 | 16 | const appId = 'integration_github' 17 | webpackConfig.entry = { 18 | personalSettings: { import: path.join(__dirname, 'src', 'personalSettings.js'), filename: appId + '-personalSettings.js' }, 19 | adminSettings: { import: path.join(__dirname, 'src', 'adminSettings.js'), filename: appId + '-adminSettings.js' }, 20 | dashboard: { import: path.join(__dirname, 'src', 'dashboard.js'), filename: appId + '-dashboard.js' }, 21 | popupSuccess: { import: path.join(__dirname, 'src', 'popupSuccess.js'), filename: appId + '-popupSuccess.js' }, 22 | reference: { import: path.join(__dirname, 'src', 'reference.js'), filename: appId + '-reference.js' }, 23 | } 24 | 25 | webpackConfig.plugins.push( 26 | new ESLintPlugin({ 27 | extensions: ['js', 'vue'], 28 | files: 'src', 29 | failOnError: !isDev, 30 | }) 31 | ) 32 | webpackConfig.plugins.push( 33 | new StyleLintPlugin({ 34 | files: 'src/**/*.{css,scss,vue}', 35 | failOnError: !isDev, 36 | }), 37 | ) 38 | 39 | module.exports = webpackConfig 40 | --------------------------------------------------------------------------------