diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000000..682f67294b --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,28 @@ +## References +_Add references/links to any related tickets or PRs. These may include:_ +* Link to [Angular issue or PR](https://github.com/DSpace/dspace-angular/issues) related to this PR, if any +* Link to [JIRA](https://jira.lyrasis.org/projects/DS/summary) ticket(s), if any + +## Description +Short summary of changes (1-2 sentences). + +## Instructions for Reviewers +Please add a more detailed description of the changes made by your PR. At a minimum, providing a bulleted list of changes in your PR is helpful to reviewers. + +List of changes in this PR: +* First, ... +* Second, ... + +**Include guidance for how to test or review your PR.** This may include: steps to reproduce a bug, screenshots or description of a new feature, or reasons behind specific changes. + +## Checklist +_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 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 for any bug fixes, improvements or new features. A few reminders about what constitutes good tests: + * Include tests for different user types (if behavior differs), including: (1) Anonymous user, (2) Logged in user (non-admin), and (3) Administrator. + * Include tests for error scenarios, e.g. when errors/warnings should appear (or buttons should be disabled). + * For bug fixes, include a test that reproduces the bug and proves it is fixed. For clarity, it may be useful to provide the test in a separate commit from the bug fix. +- [ ] 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/master/LICENSE) based on the [Licensing of Contributions](https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines#CodeContributionGuidelines-LicensingofContributions) documentation. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000000..b7cb98fe83 --- /dev/null +++ b/LICENSE @@ -0,0 +1,39 @@ +DSpace source code BSD License: + +Copyright (c) 2002-2020, LYRASIS. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +- Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +- Neither the name DuraSpace nor the name of the DSpace Foundation +nor the names of its contributors may be used to endorse or promote +products derived from this software without specific prior written +permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR +TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. + + +DSpace uses third-party libraries which may be distributed under +different licenses to the above. Information about these licenses +is detailed in the LICENSES_THIRD_PARTY file at the root of the source +tree. You must agree to the terms of these licenses, in addition to +the above DSpace source code license, in order to use this software. diff --git a/LICENSES_THIRD_PARTY b/LICENSES_THIRD_PARTY new file mode 100644 index 0000000000..c42cc0b255 --- /dev/null +++ b/LICENSES_THIRD_PARTY @@ -0,0 +1,15 @@ + +DSpace uses third-party libraries which may be distributed under different licenses. +A summary of all third-party, production dependencies used by this user interface may be found by running: + + npx license-checker --production --summary + +(Additional license-checker options may be found in its documentation: https://github.com/davglass/license-checker) + +You must agree to the terms of these licenses, in addition to the DSpace source code license, in order to use this +software. + +PLEASE NOTE: Some third-party dependencies may be listed under multiple licenses if they are dual-licensed. +This is especially true of anything listed as GPL (or similar), as DSpace does NOT allow for the inclusion of +any dependencies that are solely released under GPL (or similar) terms. For more info see: +https://wiki.lyrasis.org/display/DSPACE/Code+Contribution+Guidelines#CodeContributionGuidelines-LicensingofContributions diff --git a/resources/i18n/en.json5 b/resources/i18n/en.json5 index 20c7b05ec6..064698bf76 100644 --- a/resources/i18n/en.json5 +++ b/resources/i18n/en.json5 @@ -38,7 +38,7 @@ "admin.registries.bitstream-formats.edit.extensions.label": "File extensions", - "admin.registries.bitstream-formats.edit.extensions.placeholder": "Enter a file extenstion without the dot", + "admin.registries.bitstream-formats.edit.extensions.placeholder": "Enter a file extension without the dot", "admin.registries.bitstream-formats.edit.failure.content": "An error occurred while editing the bitstream format.", @@ -176,12 +176,12 @@ "admin.access-control.epeople.search.head": "Search", - "admin.access-control.epeople.search.scope.name": "Name", - - "admin.access-control.epeople.search.scope.email": "E-mail (exact)", + "admin.access-control.epeople.button.see-all": "Browse All", "admin.access-control.epeople.search.scope.metadata": "Metadata", + "admin.access-control.epeople.search.scope.email": "E-mail (exact)", + "admin.access-control.epeople.search.button": "Search", "admin.access-control.epeople.button.add": "Add EPerson", @@ -190,13 +190,13 @@ "admin.access-control.epeople.table.name": "Name", - "admin.access-control.epeople.table.email": "E-mail", + "admin.access-control.epeople.table.email": "E-mail (exact)", "admin.access-control.epeople.table.edit": "Edit", - "item.access-control.epeople.table.edit.buttons.edit": "Edit", + "admin.access-control.epeople.table.edit.buttons.edit": "Edit \"{{name}}\"", - "item.access-control.epeople.table.edit.buttons.remove": "Remove", + "admin.access-control.epeople.table.edit.buttons.remove": "Delete \"{{name}}\"", "admin.access-control.epeople.no-items": "No EPeople to show.", @@ -228,12 +228,149 @@ "admin.access-control.epeople.form.notification.edited.failure": "Failed to edit EPerson \"{{name}}\"", + "admin.access-control.epeople.form.groupsEPersonIsMemberOf": "Member of these groups:", + + "admin.access-control.epeople.form.table.id": "ID", + + "admin.access-control.epeople.form.table.name": "Name", + + "admin.access-control.epeople.form.memberOfNoGroups": "This EPerson is not a member of any groups", + + "admin.access-control.epeople.form.goToGroups": "Add to groups", + "admin.access-control.epeople.notification.deleted.failure": "Failed to delete EPerson: \"{{name}}\"", "admin.access-control.epeople.notification.deleted.success": "Successfully deleted EPerson: \"{{name}}\"", + "admin.access-control.groups.title": "DSpace Angular :: Groups", + + "admin.access-control.groups.head": "Groups", + + "admin.access-control.groups.button.add": "Add group", + + "admin.access-control.groups.search.head": "Search groups", + + "admin.access-control.groups.button.see-all": "Browse all", + + "admin.access-control.groups.search.button": "Search", + + "admin.access-control.groups.table.id": "ID", + + "admin.access-control.groups.table.name": "Name", + + "admin.access-control.groups.table.members": "Members", + + "admin.access-control.groups.table.comcol": "Community / Collection", + + "admin.access-control.groups.table.edit": "Edit", + + "admin.access-control.groups.table.edit.buttons.edit": "Edit \"{{name}}\"", + + "admin.access-control.groups.table.edit.buttons.remove": "Delete \"{{name}}\"", + + "admin.access-control.groups.no-items": "No groups found with this in their name or this as UUID", + + "admin.access-control.groups.notification.deleted.success": "Successfully deleted group \"{{name}}\"", + + "admin.access-control.groups.notification.deleted.failure": "Failed to delete group \"{{name}}\"", + + + "admin.access-control.groups.form.head.create": "Create group", + + "admin.access-control.groups.form.head.edit": "Edit group", + + "admin.access-control.groups.form.groupName": "Group name", + + "admin.access-control.groups.form.groupDescription": "Description", + + "admin.access-control.groups.form.notification.created.success": "Successfully created Group \"{{name}}\"", + + "admin.access-control.groups.form.notification.created.failure": "Failed to create Group \"{{name}}\"", + + "admin.access-control.groups.form.notification.created.failure.groupNameInUse": "Failed to create Group with name: \"{{name}}\", make sure the name is not already in use.", + + "admin.access-control.groups.form.members-list.head": "EPeople", + + "admin.access-control.groups.form.members-list.search.head": "Add EPeople", + + "admin.access-control.groups.form.members-list.button.see-all": "Browse All", + + "admin.access-control.groups.form.members-list.headMembers": "Current Members", + + "admin.access-control.groups.form.members-list.search.scope.metadata": "Metadata", + + "admin.access-control.groups.form.members-list.search.scope.email": "E-mail (exact)", + + "admin.access-control.groups.form.members-list.search.button": "Search", + + "admin.access-control.groups.form.members-list.table.id": "ID", + + "admin.access-control.groups.form.members-list.table.name": "Name", + + "admin.access-control.groups.form.members-list.table.edit": "Remove / Add", + + "admin.access-control.groups.form.members-list.table.edit.buttons.remove": "Remove member with name \"{{name}}\"", + + "admin.access-control.groups.form.members-list.notification.success.addMember": "Successfully added member: \"{{name}}\"", + + "admin.access-control.groups.form.members-list.notification.failure.addMember": "Failed to add member: \"{{name}}\"", + + "admin.access-control.groups.form.members-list.notification.success.deleteMember": "Successfully deleted member: \"{{name}}\"", + + "admin.access-control.groups.form.members-list.notification.failure.deleteMember": "Failed to delete member: \"{{name}}\"", + + "admin.access-control.groups.form.members-list.table.edit.buttons.add": "Add member with name \"{{name}}\"", + + "admin.access-control.groups.form.members-list.notification.failure.noActiveGroup": "No current active group, submit a name first.", + + "admin.access-control.groups.form.members-list.no-members-yet": "No members in group yet, search and add.", + + "admin.access-control.groups.form.members-list.no-items": "No EPeople found in that search", + + "admin.access-control.groups.form.subgroups-list.head": "Groups", + + "admin.access-control.groups.form.subgroups-list.search.head": "Add Subgroup", + + "admin.access-control.groups.form.subgroups-list.button.see-all": "Browse All", + + "admin.access-control.groups.form.subgroups-list.headSubgroups": "Current Subgroups", + + "admin.access-control.groups.form.subgroups-list.search.button": "Search", + + "admin.access-control.groups.form.subgroups-list.table.id": "ID", + + "admin.access-control.groups.form.subgroups-list.table.name": "Name", + + "admin.access-control.groups.form.subgroups-list.table.edit": "Remove / Add", + + "admin.access-control.groups.form.subgroups-list.table.edit.buttons.remove": "Remove subgroup with name \"{{name}}\"", + + "admin.access-control.groups.form.subgroups-list.table.edit.buttons.add": "Add subgroup with name \"{{name}}\"", + + "admin.access-control.groups.form.subgroups-list.table.edit.currentGroup": "Current group", + + "admin.access-control.groups.form.subgroups-list.notification.success.addSubgroup": "Successfully added subgroup: \"{{name}}\"", + + "admin.access-control.groups.form.subgroups-list.notification.failure.addSubgroup": "Failed to add subgroup: \"{{name}}\"", + + "admin.access-control.groups.form.subgroups-list.notification.success.deleteSubgroup": "Successfully deleted subgroup: \"{{name}}\"", + + "admin.access-control.groups.form.subgroups-list.notification.failure.deleteSubgroup": "Failed to delete subgroup: \"{{name}}\"", + + "admin.access-control.groups.form.subgroups-list.notification.failure.noActiveGroup": "No current active group, submit a name first.", + + "admin.access-control.groups.form.subgroups-list.notification.failure.subgroupToAddIsActiveGroup": "This is the current group, can't be added.", + + "admin.access-control.groups.form.subgroups-list.no-items": "No groups found with this in their name or this as UUID", + + "admin.access-control.groups.form.subgroups-list.no-subgroups-yet": "No subgroups in group yet.", + + "admin.access-control.groups.form.return": "Return to groups", + + + "admin.search.breadcrumbs": "Administrative Search", "admin.search.collection.edit": "Edit", @@ -282,6 +419,42 @@ + "bitstream.edit.bitstream": "Bitstream: ", + + "bitstream.edit.form.description.hint": "Optionally, provide a brief description of the file, for example \"Main article\" or \"Experiment data readings\".", + + "bitstream.edit.form.description.label": "Description", + + "bitstream.edit.form.embargo.hint": "The first day from which access is allowed. This date cannot be modified on this form. To set an embargo date for a bitstream, go to the Item Status tab, click Authorizations..., create or edit the bitstream's READ policy, and set the Start Date as desired.", + + "bitstream.edit.form.embargo.label": "Embargo until specific date", + + "bitstream.edit.form.fileName.hint": "Change the filename for the bitstream. Note that this will change the display bitstream URL, but old links will still resolve as long as the sequence ID does not change.", + + "bitstream.edit.form.fileName.label": "Filename", + + "bitstream.edit.form.newFormat.label": "Describe new format", + + "bitstream.edit.form.newFormat.hint": "The application you used to create the file, and the version number (for example, \"ACMESoft SuperApp version 1.5\").", + + "bitstream.edit.form.primaryBitstream.label": "Primary bitstream", + + "bitstream.edit.form.selectedFormat.hint": "If the format is not in the above list, select \"format not in list\" above and describe it under \"Describe new format\".", + + "bitstream.edit.form.selectedFormat.label": "Selected Format", + + "bitstream.edit.form.selectedFormat.unknown": "Format not in list", + + "bitstream.edit.notifications.error.format.title": "An error occurred saving the bitstream's format", + + "bitstream.edit.notifications.saved.content": "Your changes to this bitstream were saved.", + + "bitstream.edit.notifications.saved.title": "Bitstream saved", + + "bitstream.edit.title": "Edit bitstream", + + + "browse.comcol.by.author": "By Author", "browse.comcol.by.dateissued": "By Issue Date", @@ -652,6 +825,8 @@ + "error.bitstream": "Error fetching bitstream", + "error.browse-by": "Error fetching items", "error.collection": "Error fetching collection", @@ -759,6 +934,93 @@ + + "item.bitstreams.upload.bundle": "Bundle", + + "item.bitstreams.upload.bundle.placeholder": "Select a bundle", + + "item.bitstreams.upload.bundle.new": "Create bundle", + + "item.bitstreams.upload.bundles.empty": "This item doesn\'t contain any bundles to upload a bitstream to.", + + "item.bitstreams.upload.cancel": "Cancel", + + "item.bitstreams.upload.drop-message": "Drop a file to upload", + + "item.bitstreams.upload.item": "Item: ", + + "item.bitstreams.upload.notifications.bundle.created.content": "Successfully created new bundle.", + + "item.bitstreams.upload.notifications.bundle.created.title": "Created bundle", + + "item.bitstreams.upload.notifications.upload.failed": "Upload failed. Please verify the content before retrying.", + + "item.bitstreams.upload.title": "Upload bitstream", + + + + "item.edit.bitstreams.bundle.edit.buttons.upload": "Upload", + + "item.edit.bitstreams.bundle.displaying": "Currently displaying {{ amount }} bitstreams of {{ total }}.", + + "item.edit.bitstreams.bundle.load.all": "Load all ({{ total }})", + + "item.edit.bitstreams.bundle.load.more": "Load more", + + "item.edit.bitstreams.bundle.name": "BUNDLE: {{ name }}", + + "item.edit.bitstreams.discard-button": "Discard", + + "item.edit.bitstreams.edit.buttons.download": "Download", + + "item.edit.bitstreams.edit.buttons.drag": "Drag", + + "item.edit.bitstreams.edit.buttons.edit": "Edit", + + "item.edit.bitstreams.edit.buttons.remove": "Remove", + + "item.edit.bitstreams.edit.buttons.undo": "Undo changes", + + "item.edit.bitstreams.empty": "This item doesn't contain any bitstreams. Click the upload button to create one.", + + "item.edit.bitstreams.headers.actions": "Actions", + + "item.edit.bitstreams.headers.bundle": "Bundle", + + "item.edit.bitstreams.headers.description": "Description", + + "item.edit.bitstreams.headers.format": "Format", + + "item.edit.bitstreams.headers.name": "Name", + + "item.edit.bitstreams.notifications.discarded.content": "Your changes were discarded. To reinstate your changes click the 'Undo' button", + + "item.edit.bitstreams.notifications.discarded.title": "Changes discarded", + + "item.edit.bitstreams.notifications.move.failed.title": "Error moving bitstreams", + + "item.edit.bitstreams.notifications.move.saved.content": "Your move changes to this item's bitstreams and bundles have been saved.", + + "item.edit.bitstreams.notifications.move.saved.title": "Move changes saved", + + "item.edit.bitstreams.notifications.outdated.content": "The item you're currently working on has been changed by another user. Your current changes are discarded to prevent conflicts", + + "item.edit.bitstreams.notifications.outdated.title": "Changes outdated", + + "item.edit.bitstreams.notifications.remove.failed.title": "Error deleting bitstream", + + "item.edit.bitstreams.notifications.remove.saved.content": "Your removal changes to this item's bitstreams have been saved.", + + "item.edit.bitstreams.notifications.remove.saved.title": "Removal changes saved", + + "item.edit.bitstreams.reinstate-button": "Undo", + + "item.edit.bitstreams.save-button": "Save", + + "item.edit.bitstreams.upload-button": "Upload", + + + "item.edit.delete.cancel": "Cancel", "item.edit.delete.confirm": "Delete", @@ -957,7 +1219,7 @@ - "item.edit.tabs.bitstreams.head": "Item Bitstreams", + "item.edit.tabs.bitstreams.head": "Bitstreams", "item.edit.tabs.bitstreams.title": "Item Edit - Bitstreams", @@ -965,11 +1227,11 @@ "item.edit.tabs.curate.title": "Item Edit - Curate", - "item.edit.tabs.metadata.head": "Item Metadata", + "item.edit.tabs.metadata.head": "Metadata", "item.edit.tabs.metadata.title": "Item Edit - Metadata", - "item.edit.tabs.relationships.head": "Item Relationships", + "item.edit.tabs.relationships.head": "Relationships", "item.edit.tabs.relationships.title": "Item Edit - Relationships", @@ -1007,7 +1269,7 @@ "item.edit.tabs.status.description": "Welcome to the item management page. From here you can withdraw, reinstate, move or delete the item. You may also update or add new metadata / bitstreams on the other tabs.", - "item.edit.tabs.status.head": "Item Status", + "item.edit.tabs.status.head": "Status", "item.edit.tabs.status.labels.handle": "Handle", @@ -1176,6 +1438,10 @@ + "loading.bitstream": "Loading bitstream...", + + "loading.bitstreams": "Loading bitstreams...", + "loading.browse-by": "Loading items...", "loading.browse-by-page": "Loading page...", @@ -2213,6 +2479,9 @@ "administrativeView.search.results.head": "Administrative Search", + "menu.section.admin_search": "Admin Search", + + "uploader.browse": "browse", diff --git a/resources/i18n/lv.json5 b/resources/i18n/lv.json5 new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/resources/i18n/lv.json5 @@ -0,0 +1 @@ + diff --git a/src/app/+admin/admin-access-control/admin-access-control-routing.module.ts b/src/app/+admin/admin-access-control/admin-access-control-routing.module.ts index 83f67a770e..93e65708bc 100644 --- a/src/app/+admin/admin-access-control/admin-access-control-routing.module.ts +++ b/src/app/+admin/admin-access-control/admin-access-control-routing.module.ts @@ -1,11 +1,24 @@ import { NgModule } from '@angular/core'; import { RouterModule } from '@angular/router'; import { EPeopleRegistryComponent } from './epeople-registry/epeople-registry.component'; +import { GroupFormComponent } from './group-registry/group-form/group-form.component'; +import { GroupsRegistryComponent } from './group-registry/groups-registry.component'; @NgModule({ imports: [ RouterModule.forChild([ { path: 'epeople', component: EPeopleRegistryComponent, data: { title: 'admin.access-control.epeople.title' } }, + { path: 'groups', component: GroupsRegistryComponent, data: { title: 'admin.access-control.groups.title' } }, + { + path: 'groups/:groupId', + component: GroupFormComponent, + data: {title: 'admin.registries.schema.title'} + }, + { + path: 'groups/newGroup', + component: GroupFormComponent, + data: {title: 'admin.registries.schema.title'} + }, ]) ] }) diff --git a/src/app/+admin/admin-access-control/admin-access-control.module.ts b/src/app/+admin/admin-access-control/admin-access-control.module.ts index 0c8573e135..8b8ad2a420 100644 --- a/src/app/+admin/admin-access-control/admin-access-control.module.ts +++ b/src/app/+admin/admin-access-control/admin-access-control.module.ts @@ -6,6 +6,10 @@ import { SharedModule } from '../../shared/shared.module'; import { AdminAccessControlRoutingModule } from './admin-access-control-routing.module'; import { EPeopleRegistryComponent } from './epeople-registry/epeople-registry.component'; import { EPersonFormComponent } from './epeople-registry/eperson-form/eperson-form.component'; +import { GroupFormComponent } from './group-registry/group-form/group-form.component'; +import { MembersListComponent } from './group-registry/group-form/members-list/members-list.component'; +import { SubgroupsListComponent } from './group-registry/group-form/subgroup-list/subgroups-list.component'; +import { GroupsRegistryComponent } from './group-registry/groups-registry.component'; @NgModule({ imports: [ @@ -17,7 +21,11 @@ import { EPersonFormComponent } from './epeople-registry/eperson-form/eperson-fo ], declarations: [ EPeopleRegistryComponent, - EPersonFormComponent + EPersonFormComponent, + GroupsRegistryComponent, + GroupFormComponent, + SubgroupsListComponent, + MembersListComponent ], entryComponents: [] }) diff --git a/src/app/+admin/admin-access-control/epeople-registry/epeople-registry.component.html b/src/app/+admin/admin-access-control/epeople-registry/epeople-registry.component.html index dd1e8bb62c..20593756c1 100644 --- a/src/app/+admin/admin-access-control/epeople-registry/epeople-registry.component.html +++ b/src/app/+admin/admin-access-control/epeople-registry/epeople-registry.component.html @@ -15,7 +15,10 @@ -