Nothing Special   »   [go: up one dir, main page]

2022-11 Developing On DSpace 7.4 Webinar

Download as pptx, pdf, or txt
Download as pptx, pdf, or txt
You are on page 1of 96

Developing on

DSpace 7.4

Art Lowel, Atmire


Andrea Bollini, 4Science
DSpace 7.4 Workshop series: November 17, 2022
Workshop Schedule
• 15:00-15:05 UTC : Intro (Natalie Baur, LYRASIS)

• 15:05-15:25 UTC : Understanding the REST API


(Andrea Bollini, 4Science)

• 15:25-16:00 UTC : Customizing/Developing with


the DSpace UI (Art Lowel, Atmire)

• 16:00-16:30 UTC : Questions & Answers


Your Support Works to Sustain
DSpace!
• Membership
– https://tinyurl.com/dspace-membership
• Registered Service Providers
– https://dspace.lyrasis.org/rsp/
• DSpace Development Fund and SCOSS
Pledge
– https://dspace.lyrasis.org/fundraising/
Presenter Introductions
Questions during Workshop

DSpace 7 Q&A Public Doc


https://tinyurl.com/dspace7-4-questions
Understanding the
REST API
Why a new REST API?
Covers only a Not based on current
4.x - 6.x
subset of DSpace REST best practices
functionality or standards
No search
No submit / workflows
Limited admin operations
Limited write / delete
(4.x was read only)
Handcrafted in Jersey,
while most DSpace code uses
Spring technologies
Why a new REST API?
All features MUST
be in REST API
(for Angular UI) 7.x Defined REST Contract.
following an HATEOAS, HAL format
API first
approach
→better third-party app
integration!*

Built using Spring technologies


(Spring Boot, MVC, HATEOAS)
* are you interested in something unusual, take a look to my presentation at
OR2019 where DSpace was integrated with Alexa -
https://lecture2go.uni-hamburg.de/l2go/-/get/v/24830 around minute 19
Interacting with the REST API
• Observing what the angular UI does via the
developer webtools of your browser
• via the integrated HAL Browser
https://api7.dspace.org/server
• via the command line…
curl "https://api7.dspace.org/server/api"

• using Postman
github:DSpace-Labs/DSpace7RestTutorial postman-config
• via a programming language… we haven’t yet a
client SDK: maybe is a side project that you want to
start?
The
developer
webtools of
your
browser is
the best
way to
understand
the REST
API!
Accessing the home page
Accessing the home page
Several
REST
requests
are sent to
the
backend.
Use the
The status Fetch/XHR
(/server/api/authn/status) request
is used to discover if there is a
filter to
loggedin user to setup the easily focus
corresponding menu
on them
Accessing the
home page

No requests to retrieve the top


communities…? why?
SSR - Server Side Rendering

The first access to DSpace will trigger the creation


of a “plain HTML” page generated by
angular/nodejs on the server side. This page
include javascript that once download will turn the
html page in a SPA (single page application).
To optimize the loading time angular try to reuse
as much as possible what has been already done
on the server side so some “requests” are passed
to the browser state via the NgRX state
rehydratation - state transfer
Accessing the home page
Using another page as entry point (i.e. /search or
a specific item) and navigate to the home page
Here our request to retrieve the top
communities
(/server/api/core/communities/sear
ch/top)
The information in the JSON
response are used to fill the top
communities widget in the home
page
Hypermedia as the Engine of Application
State - HATEAOS

HAL Format
Links are expressed in a
standard/well-known way in the
json response (it is also suitable for
xml but DSpace7 will focus only on
JSON)

→ enable the interactive navigation


→ abstract routing (URL can change
without break the client)
→ support documentation (not yet
used)
Response Body
RAW JSON Response

The HAL Browser will parse the key


elements:
_links
_embedded
Everything else
Pagination
https://github.com/DSpace/RestContract#pagination

Resource Collections are always paginated


→ pagination information are returned in a
consistent way across all the endpoints
→ pagination parameters are expected in the
same form in all the endpoints
→ common JAVA API to deal with page jump
and offset
Links - A generic approach to
paginated results
Projection
https://github.com/DSpace/RestContract/blob/main/projections.md

→ Allow the client to decide which details are included in the response
→ Save HTTP round-trip
→ Respect the security
Specified via the projection param
default: no embeds
full: include everything up to a default depth (2)
level: allow the client to set the depth via the embedLevelDepth
parameter

or embedding specific “paths” via one or more embed


params (
i.e. embed=owningCollection/logo&embed=submitter, etc.)
REST Authentication

• The existing DSpace


authentication methods are
supported
• The REST API returns an
authentication token
• This token is passed to
subsequent REST requests as
a header
JWT Token

A JWT Token contains user data “signed”


by the Server so that they cannot be
modified

https://jwt.io/
eid → EPerson uuid

sg → Special group

exp → Expiration
time
CSRF / XSRF

Authentication information in DSpace are sent over


Header but for some Authentication provider such as
Shibboleth a temporary cookie is also required, this
open to XSRF attack
DSpace implements the Double Submit Cookie
protection technique (as we are stateless)
https://owasp.org/www-community/attacks/csrf
a POST request against the
workspaceitems REST collection
(/server/api/submission/workspaceite
ms) has been performed to create the
empty workspace that we are going to
fill resulting in a 201 CREATED

Several GET requests are used to


retrieve the submission configuration
that apply to our new workspaceitem
How to deal with PATCH

JSON Patch specification RFC6902


Express change to a JSON Object in JSON
Array of Operations executed in an atomic
transaction
Each successful Patch operation will return a
HTTP 200 CODE with the new state of the
patched resource as body similar to what is
returned for a GET request.
How to deal with PATCH

ADD / REMOVE / REPLACE / MOVE


[
{ "op": "test", "path": "/a/b/c", "value": "foo" },
{ "op": "remove", "path": "/a/b/c" },
{ "op": "add", "path": "/a/b/c", "value": [ "foo", "bar" ] },
{ "op": "replace", "path": "/a/b/c", "value": 42 },
{ "op": "move", "from": "/a/b/c", "path": "/a/b/d" },
{ "op": "copy", "from": "/a/b/d", "path": "/a/b/e" }
]

TEST & COPY (no plan to support them)


curl
It is a HTTP PATCH request
'https://api7.dspace.org/server/api/submission/workspaceitems/27286' \
-X 'PATCH' \
-H 'Accept: application/json, text/plain, */*' \ XSRF Protection via header / cookie
… check
-H 'Content-Type: application/json; charset=UTF-8' \
-H 'Cookie: DSPACE-XSRF-COOKIE=dbe62bdd-ddf5-4f14-943d-
A correlation ID header helpful to
020444ac36a9' \
related backend logs to all the http

request coming from a single browser
-H 'X-CORRELATION-ID: 269319bb-1244-42f2-8ec6-ff2ef47c4bfc' \
-H 'X-REFERRER: /workspaceitems/27286/edit' \
-H 'X-XSRF-TOKEN: dbe62bdd-ddf5-4f14-943d-020444ac36a9' \
-H 'authorization: Bearer The authentication details - JWT Token
eyJhbGciOiJIUzI1NiJ9.eyJlaWQiOiIzMzU2NDdiNi04YTUyLTRlY2ItYT
hjMS03ZWJhYmIxOTliZGEiLCJzZyI6W10sImF1dGhlbnRpY2F0aW9u
TWV0aG9kIjoicGFzc3dvcmQiLCJleHAiOjE2Njg2MjI5MTF9.3G7vaKiB
7NeIwo90PptAiBb-EZS0F6BfOF44k0iF9hM' \
--data-raw The JSON Patch
'[{"op":"add","path":"/sections/traditionalpageone/dc.contributo
r.author","value":[{"value":"Bollini,
Andrea","language":null,"authority":null,"display":"Bollini,
Andrea","confidence":-1,"place":0,"otherInformation":null}]}]' \
Postman - A development client for
REST API’s
https://www.getpostman.com/downloads/
DSpace Postman Configuration:
https://github.com/DSpace-Labs/DSpace7RestTut
orial/tree/master/postman-config

Many sample requests for


common endpoint, variables to
easily between different
environments & users

If you are a postman user


please contribute via a GitHub
PR adding more sample
requests!!!
The REST contract

• https://github.com/DSpace/RestContract
– Aims to be the source of truth for all the
implemented endpoints
– Use GitHub issues/pull requests to
suggest changes, missing or wrong
information
REST cheat sheet
Stateless (no session) HTTP methods
GET (read), HEAD (read headers only)
Specifications POST (create)
JSON web tokens (JWT)
PUT (replace), PATCH (partial update)

• Cross-Origin Resource Sharing ( DELETE (remove)
CORS) Headers OPTIONS (verify access, e.g. via CORS)
• Cross-Site Request Forgery
Prevention (CSRF Token) HTTP return codes
2xx (Success)
HTTP Resources
3xx (Redirect)
● URIs reference individual
resources or collections (of 4xx (Client error)
resources) 5xx (Server error)
● /items/{uuid} and /items
Formats: JSON
Customizing the
DSpace 7 UI
What is Angular?
How does it work?
What is Angular?

• Framework for building dynamic


applications in the browser

• Data comes from the server (REST API)

• HTML is generated via Javascript


(Typescript)
https://angular.io
DSpace + Angular Back End

Architecture
Front End
Web Browser 1 Initial Request

2 Return first page, JS Database

3 Request data via REST Assetstor


e

4 Return JSON

HTML logo: https://freeiconshop.com/icon/html-icon-outline/


JSON logo: http://www.flaticon.com/free-icon/json-file_136443
DSpace + Angular Back End

Architecture
Front End
Web Browser 1 Initial Request

2 Return first page Database


Javascript e
e x t pag
n
e q ues t
3 R
Assetstor
ge
t pa e
rn nex
u
Ret
4

Via Angular Universal


Angular: Components

• The building blocks of an Angular app


• Allow you to create new HTML tags that
come with their own code and styling
Everything’s a
Component
● <ds-app>

● <ds-header>

● <ds-breadcrumbs>

● <ds-item-page>

● <ds-thumbnail>

● <ds-item-page-
field>
Angular: Components
• Each component has
– a ts file that contains the logic.
e.g. header.component.ts
– an html file that contains the markup.
e.g. header.component.html
– an scss file that contains the style.
e.g. header.component.scss
Angular: Components
@Component({
selector: 'ds-header',
styleUrls: ['./header.component.scss'],
templateUrl: './header.component.html'
})
export class HeaderComponent {}
Sass

• The DSpace UI is built using Bootstrap, a


framework with utilities and components for
building websites
• Bootstrap makes use of Sass: a CSS
preprocessor
• Sass adds the ability to nest css rules, and to
have variables and functions
Sass variables

• Bootstrap uses these variables to configure


everything about its components: colors,
fonts, spacing, etc.

• Downside: Sass variables are resolved at


build time. You can’t change their value on
the fly
CSS variables

• Native CSS has support for variables too


• They can be changed on the fly
• We use them to support themes that can be
swapped dynamically
• All of Bootstrap’s sass variables are mapped
to native css ones
Variable mapping

Sass =>
CSS

$primary =>
var(--bs-primary);
$success =>
var(--bs-success);
$spacer =>
var(--bs-spacer);
CSS variables

• Both still work everywhere


• But Sass variables won’t update when you
switch themes at runtime
• So inside a theme, feel free to still use Sass
variables
• When you contribute a component, always
use CSS variables
Custom theme folder

• The folder src/themes/custom is a template


theme to start from
• It contains boilerplate code for all themeable
components
Custom theme folder

• It doesn’t change the look of anything yet


• It refers back to the HTML and SCSS of the base
component
• Everything is plain bootstrap with a few tweaks
for accessibility
Custom theme folder
@Component({
selector: 'ds-home-page',
// styleUrls: ['./home-page.component.scss'],
styleUrls: ['/app/+home-page/home-page.component.scss'],
// templateUrl: './home-page.component.html'
templateUrl: '/app/+home-page/home-page.component.html'
})
export class HomePageComponent extends BaseComponent {}
DSpace theme folder
• The folder src/themes/dspace contains an
example theme
• It started from the custom folder
• Changes some colors, fonts, the news and the
header
• If you prefer it, you can start from it, instead of
the custom folder.
Create a new theme
• Copy the folder src/themes/custom to
src/themes/workshop
• In angular.json add the theme to the styles list
• In config.yml add the theme to the themes list
• In eager-themes.module.ts import the theme’s
EagerThemeModule
• Restart the server
Theming a component
• Inspect the element you want to override in the
browser’s dev tools
• Find the closest parent that starts with ‘ds-’
e.g. ds-home-news
• Search your theme folder for that selector to
find the component
e.g. HomeNewsComponent
Theming a component
• Swap the commented templateUrl and styleUrls
properties with the uncommented ones
• Either copy the HTML from the original and
replace the text
• or write your own HTML from scratch
Logo
• copy the logo to the assets/images folder in
your theme folder
• open app/header/header.component.ts in your
theme folder
• swap the comments on the templateUrl
properties
Logo
@Component({
selector: 'ds-header',
// styleUrls: ['header.component.scss'],
styleUrls: ['../../../../app/header/header.component.scss'],
templateUrl: 'header.component.html',
// templateUrl:
'../../../../app/header/header.component.html',
})
export class HeaderComponent extends BaseComponent
Logo
• Open the base
app/header/header.component.html file
• Copy the contents to your theme’s version
• Replace the logo url with your own
• Theme assets are deployed in assets/${theme-
name}
Logo

<a class="navbar-brand my-2" routerLink="/home">


<img src="assets/workshop/images/logo.svg"/>
</a>
Colors
• Override Bootstrap variables in the file
styles/_theme_sass_variable_overrides.scss in your
theme folder
• It contains a few frequently used variables as
comments
• Look for other variables you can change in
node_modules/bootstrap/scss/_variables.scss
Colors

• Let’s change these:

$blue: #2B3A67;

$cyan: #207698;

$red: #FF325D;

primary: $yellow,
Colors
• Override css variables in the file
styles/_theme_css_variable_overrides.scss in your
theme folder
• It also contains a few example variables as
comments
• Look for other variables you can change in
src/styles/_custom_variables.scss
Colors

• Let’s use it to change the navbar link and icon colors:


--ds-navbar-link-color: #{$link-color};

--ds-navbar-link-color-hover: #{darken($link-color, 15%)};

--ds-header-icon-color: #{$blue};

--ds-header-icon-color-hover: #{darken($blue, 15%)};


Font
• Import a new font
• Modify $font-family-sans-serif to use it.

@import url('https://fonts.googleapis.com/css?
family=Source+Sans+Pro');
$font-family-sans-serif: 'Source Sans Pro', -apple-system, …
Footer
• Open app/footer/footer.component.ts in your
theme folder
• swap the templateUrl and styleUrls comments
• Open the base
app/footer/footer.component.html file
• Copy the contents to your theme’s version
Footer
• Open footer.component.scss in your theme
folder
• Set the color to $light and the background to
$dark
Footer

footer {
color: $light;
background: $dark;
}
Footer
• In the html file, add margins to the footer-info
links using Bootstrap classes:
<a class="text-white mr-2" routerLink="info/privacy">
• mr-2 is short for margin-right 2
• See the Bootstrap docs for more of these:
https://getbootstrap.com/docs
Footer
• Enable the top footer in footer.component.ts

export class FooterComponent extends BaseComponent {


showTopFooter = true;
}
Footer
• In the scss file, give both footers different colors
.top-footer {
background: $dark;
}
.bottom-footer {
background: $black;
}
Home page news
• Open home-news.component.ts in app/+home-
page/home-news inside your theme folder
• swap the templateUrl and styleUrls comments
• Add a div with class banner to the template:
<div class="banner"></div>
Home page news

• copy the banner to the assets/images folder in


your theme folder
• In home-news.component.scss, add the image
and style it
Home page news

.banner {
background-image:
url('/assets/workshop/images/pexels-will-mu-
3802667.jpg');
background-size: cover;
}
Home page news
• Compensate for the padding of <main> and add
margin below

margin-top: calc(-1 * var(--ds-content-spacing));


margin-bottom: var(--ds-content-spacing);
Home page news
• Add some content inside the banner div
<div class="container">
<div>
<img src="assets/workshop/images/logo-text-only.svg"/>
<p>Lorem ipsum dolor … at venenatis.</p>
</div>
</div>
Theming dynamic components

• Components with a custom decorator are


dynamically rendered
e.g. @listableObjectComponent or
@metadataRepresentationComponent
• Theming them works the same way, but there
are 2 additional requirements
Theming dynamic components

• Add the theme name to the end of the


decorator. e.g.
@listableObjectComponent (…, 'workshop')

• This makes the component selection algorithm


take the theme into account
Theming dynamic components

• Add the component to ENTRY_COMPONENTS in


EagerThemeModule
• This ensures that decorator gets registered
when the app starts
Community list element

• Open community-list-element.component.ts in
app/shared/object-list/community-list-element
inside your theme folder
• swap the templateUrl and styleUrls properties
Community list element
• Add the theme name to the
@listableObjectComponent decorator:
@listableObjectComponent(Community,
ViewMode.ListElement, Context.Any, 'workshop')
• Add the component to ENTRY_COMPONENTS in
EagerThemeModule
Community list element
• Open the base community-list-
element.component.html file
• Copy the contents to your theme’s version
• Add the ds-thumbnail to the HTML using
object.logo as the image
Community list element
<div class="d-flex justify-content-start">
<div class="thumbnail mr-3">
<ds-thumbnail [thumbnail]="(object.logo | async)?.payload">
</ds-thumbnail>
</div>
<div>

</div>
Community list element
• Get the code to retrieve the logo from
community-grid-element.component.ts
@Input() set object(object: Community) {
this._object = object;
if (hasValue(this._object) && hasNoValue(this._object.logo)) {
this.linkService.resolveLink<Community>(this._object,
followLink('logo'));
}
}
Get the code
https://tinyurl.com/webinar-2022-11
Wrap-Up
Learn & help at the same time!

● Fix “good first issue” tickets for


frontend or backend
○ Also see tickets labeled “help wanted”

● Test new PRs from 7.5 project board


(see “Needs Reviewers Assigned” or “Under
Review” columns)
How can I contribute?
Join DSpace 7 Working Group (Dev Team)
➢ Meets every Thursday at 15:00UTC
➢ Help review / test Pull Requests!

Join DSpace Community Advisory Team (DCAT)


➢ Repository manager interest group
➢ Meets monthly: Tues, Dec 13 at 17:00UTC
➢ Provide feedback to developers & governance
Time for your questions!
Questions?
Workshop Slides
https://tinyurl.com/dspace7-4-develop

DSpace 7 Q&A Public Doc


https://tinyurl.com/dspace7-4-questions

You might also like