diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index be15b0a507..e50105b879 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,7 +1,7 @@ ## References _Add references/links to any related issues or PRs. These may include:_ -* Fixes #[issue-number] -* Requires DSpace/DSpace#[pr-number] (if a REST API PR is required to test this) +* Fixes #`issue-number` (if this fixes an issue ticket) +* Requires DSpace/DSpace#`pr-number` (if a REST API PR is required to test this) ## Description Short summary of changes (1-2 sentences). @@ -19,8 +19,10 @@ List of changes in this PR: _This checklist provides a reminder of what we are going to look for when reviewing your PR. You need not complete this checklist prior to creating your PR (draft PRs are always welcome). If you are unsure about an item in the checklist, don't hesitate to ask. We're here to help!_ - [ ] My PR is small in size (e.g. less than 1,000 lines of code, not including comments & specs/tests), or I have provided reasons as to why that's not possible. -- [ ] My PR passes [TSLint](https://palantir.github.io/tslint/) validation using `yarn run lint` -- [ ] My PR doesn't introduce circular dependencies +- [ ] My PR passes [ESLint](https://eslint.org/) validation using `yarn lint` +- [ ] My PR doesn't introduce circular dependencies (verified via `yarn check-circ-deps`) - [ ] My PR includes [TypeDoc](https://typedoc.org/) comments for _all new (or modified) public methods and classes_. It also includes TypeDoc for large or complex private methods. - [ ] My PR passes all specs/tests and includes new/updated specs or tests based on the [Code Testing Guide](https://wiki.lyrasis.org/display/DSPACE/Code+Testing+Guide). -- [ ] If my PR includes new, third-party dependencies (in `package.json`), I've made sure their licenses align with the [DSpace BSD License](https://github.com/DSpace/DSpace/blob/main/LICENSE) based on the [Licensing of Contributions](https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines#CodeContributionGuidelines-LicensingofContributions) documentation. +- [ ] If my PR includes new libraries/dependencies (in `package.json`), I've made sure their licenses align with the [DSpace BSD License](https://github.com/DSpace/DSpace/blob/main/LICENSE) based on the [Licensing of Contributions](https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines#CodeContributionGuidelines-LicensingofContributions) documentation. +- [ ] If my PR includes new features or configurations, I've provided basic technical documentation in the PR itself. +- [ ] If my PR fixes an issue ticket, I've [linked them together](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue). diff --git a/.github/workflows/codescan.yml b/.github/workflows/codescan.yml new file mode 100644 index 0000000000..35a2e2d24a --- /dev/null +++ b/.github/workflows/codescan.yml @@ -0,0 +1,49 @@ +# DSpace CodeQL code scanning configuration for GitHub +# https://docs.github.com/en/code-security/code-scanning +# +# NOTE: Code scanning must be run separate from our default build.yml +# because CodeQL requires a fresh build with all tests *disabled*. +name: "Code Scanning" + +# Run this code scan for all pushes / PRs to main branch. Also run once a week. +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + # Don't run if PR is only updating static documentation + paths-ignore: + - '**/*.md' + - '**/*.txt' + schedule: + - cron: "37 0 * * 1" + +jobs: + analyze: + name: Analyze Code + runs-on: ubuntu-latest + # Limit permissions of this GitHub action. Can only write to security-events + permissions: + actions: read + contents: read + security-events: write + + steps: + # https://github.com/actions/checkout + - name: Checkout repository + uses: actions/checkout@v3 + + # Initializes the CodeQL tools for scanning. + # https://github.com/github/codeql-action + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + with: + languages: javascript + + # Autobuild attempts to build any compiled languages + - name: Autobuild + uses: github/codeql-action/autobuild@v2 + + # Perform GitHub Code Scanning. + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000000..4e732302f4 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,46 @@ +# How to Contribute + +DSpace is a community built and supported project. We do not have a centralized development or support team, but have a dedicated group of volunteers who help us improve the software, documentation, resources, etc. + +* [Contribute new code via a Pull Request](#contribute-new-code-via-a-pull-request) +* [Contribute documentation](#contribute-documentation) +* [Help others on mailing lists or Slack](#help-others-on-mailing-lists-or-slack) +* [Join a working or interest group](#join-a-working-or-interest-group) + +## Contribute new code via a Pull Request + +We accept [GitHub Pull Requests (PRs)](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request-from-a-fork) at any time from anyone. +Contributors to each release are recognized in our [Release Notes](https://wiki.lyrasis.org/display/DSDOC7x/Release+Notes). + +Code Contribution Checklist +- [ ] PRs _should_ be smaller in size (ideally less than 1,000 lines of code, not including comments & tests) +- [ ] PRs **must** pass [ESLint](https://eslint.org/) validation using `yarn lint` +- [ ] PRs **must** not introduce circular dependencies (verified via `yarn check-circ-deps`) +- [ ] PRs **must** include [TypeDoc](https://typedoc.org/) comments for _all new (or modified) public methods and classes_. Large or complex private methods should also have TypeDoc. +- [ ] PRs **must** pass all automated pecs/tests and includes new/updated specs or tests based on the [Code Testing Guide](https://wiki.lyrasis.org/display/DSPACE/Code+Testing+Guide). +- [ ] If a PR includes new libraries/dependencies (in `package.json`), then their software licenses **must** align with the [DSpace BSD License](https://github.com/DSpace/dspace-angular/blob/main/LICENSE) based on the [Licensing of Contributions](https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines#CodeContributionGuidelines-LicensingofContributions) documentation. +- [ ] Basic technical documentation _should_ be provided for any new features or configuration, either in the PR itself or in the DSpace Wiki documentation. +- [ ] If a PR fixes an issue ticket, please [link them together](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue). + +Additional details on the code contribution process can be found in our [Code Contribution Guidelines](https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines) + +## Contribute documentation + +DSpace Documentation is a collaborative effort in a shared Wiki. The latest documentation is at https://wiki.lyrasis.org/display/DSDOC7x + +If you find areas of the DSpace Documentation which you wish to improve, please request a Wiki account by emailing wikihelp@lyrasis.org. +Once you have an account setup, contact @tdonohue (via [Slack](https://wiki.lyrasis.org/display/DSPACE/Slack) or email) for access to edit our Documentation. + +## Help others on mailing lists or Slack + +DSpace has our own [Slack](https://wiki.lyrasis.org/display/DSPACE/Slack) community and [Mailing Lists](https://wiki.lyrasis.org/display/DSPACE/Mailing+Lists) where discussions take place and questions are answered. +Anyone is welcome to join and help others. We just ask you to follow our [Code of Conduct](https://www.lyrasis.org/about/Pages/Code-of-Conduct.aspx) (adopted via LYRASIS). + +## Join a working or interest group + +Most of the work in building/improving DSpace comes via [Working Groups](https://wiki.lyrasis.org/display/DSPACE/DSpace+Working+Groups) or [Interest Groups](https://wiki.lyrasis.org/display/DSPACE/DSpace+Interest+Groups). + +All working/interest groups are open to anyone to join and participate. A few key groups to be aware of include: + +* [DSpace 7 Working Group](https://wiki.lyrasis.org/display/DSPACE/DSpace+7+Working+Group) - This is the main (mostly volunteer) development team. We meet weekly to review our current development [project board](https://github.com/orgs/DSpace/projects), assigning tickets and/or PRs. +* [DSpace Community Advisory Team (DCAT)](https://wiki.lyrasis.org/display/cmtygp/DSpace+Community+Advisory+Team) - This is an interest group for repository managers/administrators. We meet monthly to discuss DSpace, share tips & provide feedback back to developers. \ No newline at end of file diff --git a/README.md b/README.md index 0ede4d4d19..3867759ab7 100644 --- a/README.md +++ b/README.md @@ -379,10 +379,10 @@ To get the most out of TypeScript, you'll need a TypeScript-aware editor. We've - [Sublime Text](http://www.sublimetext.com/3) - [Typescript-Sublime-Plugin](https://github.com/Microsoft/Typescript-Sublime-plugin#installation) -Collaborating +Contributing ------------- -See [the guide on the wiki](https://wiki.lyrasis.org/display/DSPACE/DSpace+7+-+Angular+UI+Development#DSpace7-AngularUIDevelopment-Howtocontribute) +See [Contributing documentation](CONTRIBUTING.md) File Structure -------------- diff --git a/config/config.example.yml b/config/config.example.yml index 7bc96b8e4a..dab599ccc7 100644 --- a/config/config.example.yml +++ b/config/config.example.yml @@ -170,6 +170,9 @@ languages: - code: el label: Ελληνικά active: true + - code: uk + label: Yкраї́нська + active: true # Browse-By Pages browseBy: @@ -207,6 +210,11 @@ item: undoTimeout: 10000 # 10 seconds # Show the item access status label in items lists showAccessStatuses: false + bitstream: + # Number of entries in the bitstream list in the item view page. + # Rounded to the nearest size in the list of selectable sizes on the + # settings menu. See pageSizeOptions in 'pagination-component-options.model.ts'. + pageSize: 5 # Collection Page Config collection: diff --git a/src/app/item-page/full/field-components/file-section/full-file-section.component.spec.ts b/src/app/item-page/full/field-components/file-section/full-file-section.component.spec.ts index 1059ed12da..6f0e97513f 100644 --- a/src/app/item-page/full/field-components/file-section/full-file-section.component.spec.ts +++ b/src/app/item-page/full/field-components/file-section/full-file-section.component.spec.ts @@ -18,6 +18,8 @@ import { NotificationsService } from '../../../../shared/notifications/notificat import { NotificationsServiceStub } from '../../../../shared/testing/notifications-service.stub'; import { PaginationService } from '../../../../core/pagination/pagination.service'; import { PaginationServiceStub } from '../../../../shared/testing/pagination-service.stub'; +import { APP_CONFIG } from 'src/config/app-config.interface'; +import { environment } from 'src/environments/environment'; describe('FullFileSectionComponent', () => { let comp: FullFileSectionComponent; @@ -69,7 +71,8 @@ describe('FullFileSectionComponent', () => { providers: [ { provide: BitstreamDataService, useValue: bitstreamDataService }, { provide: NotificationsService, useValue: new NotificationsServiceStub() }, - { provide: PaginationService, useValue: paginationService } + { provide: PaginationService, useValue: paginationService }, + { provide: APP_CONFIG, useValue: environment }, ], schemas: [NO_ERRORS_SCHEMA] diff --git a/src/app/item-page/full/field-components/file-section/full-file-section.component.ts b/src/app/item-page/full/field-components/file-section/full-file-section.component.ts index e21c1a32eb..3be0d58c81 100644 --- a/src/app/item-page/full/field-components/file-section/full-file-section.component.ts +++ b/src/app/item-page/full/field-components/file-section/full-file-section.component.ts @@ -1,4 +1,4 @@ -import { Component, Input, OnInit } from '@angular/core'; +import { Component, Inject, Input, OnInit } from '@angular/core'; import { Observable } from 'rxjs'; import { BitstreamDataService } from '../../../../core/data/bitstream-data.service'; @@ -14,6 +14,7 @@ import { NotificationsService } from '../../../../shared/notifications/notificat import { TranslateService } from '@ngx-translate/core'; import { hasValue, isEmpty } from '../../../../shared/empty.util'; import { PaginationService } from '../../../../core/pagination/pagination.service'; +import { AppConfig, APP_CONFIG } from 'src/config/app-config.interface'; /** * This component renders the file section of the item @@ -34,26 +35,26 @@ export class FullFileSectionComponent extends FileSectionComponent implements On originals$: Observable>>; licenses$: Observable>>; - pageSize = 5; originalOptions = Object.assign(new PaginationComponentOptions(), { id: 'obo', currentPage: 1, - pageSize: this.pageSize + pageSize: this.appConfig.item.bitstream.pageSize }); licenseOptions = Object.assign(new PaginationComponentOptions(), { id: 'lbo', currentPage: 1, - pageSize: this.pageSize + pageSize: this.appConfig.item.bitstream.pageSize }); constructor( bitstreamDataService: BitstreamDataService, protected notificationsService: NotificationsService, protected translateService: TranslateService, - protected paginationService: PaginationService + protected paginationService: PaginationService, + @Inject(APP_CONFIG) protected appConfig: AppConfig ) { - super(bitstreamDataService, notificationsService, translateService); + super(bitstreamDataService, notificationsService, translateService, appConfig); } ngOnInit(): void { diff --git a/src/app/item-page/simple/field-components/file-section/file-section.component.spec.ts b/src/app/item-page/simple/field-components/file-section/file-section.component.spec.ts index 2d185aef9c..83f92d5af8 100644 --- a/src/app/item-page/simple/field-components/file-section/file-section.component.spec.ts +++ b/src/app/item-page/simple/field-components/file-section/file-section.component.spec.ts @@ -17,6 +17,8 @@ import { MetadataFieldWrapperComponent } from '../../../field-components/metadat import { createPaginatedList } from '../../../../shared/testing/utils.test'; import { NotificationsService } from '../../../../shared/notifications/notifications.service'; import { NotificationsServiceStub } from '../../../../shared/testing/notifications-service.stub'; +import { APP_CONFIG } from 'src/config/app-config.interface'; +import { environment } from 'src/environments/environment'; describe('FileSectionComponent', () => { let comp: FileSectionComponent; @@ -65,7 +67,8 @@ describe('FileSectionComponent', () => { declarations: [FileSectionComponent, VarDirective, FileSizePipe, MetadataFieldWrapperComponent], providers: [ { provide: BitstreamDataService, useValue: bitstreamDataService }, - { provide: NotificationsService, useValue: new NotificationsServiceStub() } + { provide: NotificationsService, useValue: new NotificationsServiceStub() }, + { provide: APP_CONFIG, useValue: environment } ], schemas: [NO_ERRORS_SCHEMA] diff --git a/src/app/item-page/simple/field-components/file-section/file-section.component.ts b/src/app/item-page/simple/field-components/file-section/file-section.component.ts index d28b579996..08e792fc8b 100644 --- a/src/app/item-page/simple/field-components/file-section/file-section.component.ts +++ b/src/app/item-page/simple/field-components/file-section/file-section.component.ts @@ -1,4 +1,4 @@ -import { Component, Input, OnInit } from '@angular/core'; +import { Component, Inject, Input, OnInit } from '@angular/core'; import { BehaviorSubject } from 'rxjs'; import { BitstreamDataService } from '../../../../core/data/bitstream-data.service'; @@ -10,6 +10,7 @@ import { PaginatedList } from '../../../../core/data/paginated-list.model'; import { NotificationsService } from '../../../../shared/notifications/notifications.service'; import { TranslateService } from '@ngx-translate/core'; import { getFirstCompletedRemoteData } from '../../../../core/shared/operators'; +import { AppConfig, APP_CONFIG } from 'src/config/app-config.interface'; /** * This component renders the file section of the item @@ -35,13 +36,15 @@ export class FileSectionComponent implements OnInit { isLastPage: boolean; - pageSize = 5; + pageSize: number; constructor( protected bitstreamDataService: BitstreamDataService, protected notificationsService: NotificationsService, - protected translateService: TranslateService + protected translateService: TranslateService, + @Inject(APP_CONFIG) protected appConfig: AppConfig ) { + this.pageSize = this.appConfig.item.bitstream.pageSize; } ngOnInit(): void { diff --git a/src/app/navbar/navbar.module.ts b/src/app/navbar/navbar.module.ts index af2bf036bd..de3244099d 100644 --- a/src/app/navbar/navbar.module.ts +++ b/src/app/navbar/navbar.module.ts @@ -21,6 +21,7 @@ const effects = [ const ENTRY_COMPONENTS = [ // put only entry components that use custom decorator NavbarSectionComponent, + ExpandableNavbarSectionComponent, ThemedExpandableNavbarSectionComponent, ]; @@ -34,11 +35,9 @@ const ENTRY_COMPONENTS = [ CoreModule.forRoot() ], declarations: [ + ...ENTRY_COMPONENTS, NavbarComponent, ThemedNavbarComponent, - NavbarSectionComponent, - ExpandableNavbarSectionComponent, - ThemedExpandableNavbarSectionComponent, ], providers: [], exports: [ diff --git a/src/app/shared/dso-selector/dso-selector/authorized-collection-selector/authorized-collection-selector.component.ts b/src/app/shared/dso-selector/dso-selector/authorized-collection-selector/authorized-collection-selector.component.ts index ab48d058ca..cc1f9822d6 100644 --- a/src/app/shared/dso-selector/dso-selector/authorized-collection-selector/authorized-collection-selector.component.ts +++ b/src/app/shared/dso-selector/dso-selector/authorized-collection-selector/authorized-collection-selector.component.ts @@ -53,8 +53,9 @@ export class AuthorizedCollectionSelectorComponent extends DSOSelectorComponent * Perform a search for authorized collections with the current query and page * @param query Query to search objects for * @param page Page to retrieve + * @param useCache Whether or not to use the cache */ - search(query: string, page: number): Observable>>> { + search(query: string, page: number, useCache: boolean = true): Observable>>> { let searchListService$: Observable>> = null; const findOptions: FindListOptions = { currentPage: page, @@ -69,7 +70,7 @@ export class AuthorizedCollectionSelectorComponent extends DSOSelectorComponent findOptions); } else { searchListService$ = this.collectionDataService - .getAuthorizedCollection(query, findOptions, true, false, followLink('parentCommunity')); + .getAuthorizedCollection(query, findOptions, useCache, false, followLink('parentCommunity')); } return searchListService$.pipe( getFirstCompletedRemoteData(), diff --git a/src/app/shared/dso-selector/dso-selector/dso-selector.component.html b/src/app/shared/dso-selector/dso-selector/dso-selector.component.html index 8abb8ad558..c4f5dbc4cd 100644 --- a/src/app/shared/dso-selector/dso-selector/dso-selector.component.html +++ b/src/app/shared/dso-selector/dso-selector/dso-selector.component.html @@ -21,12 +21,12 @@