### Clone and Install DSpace-Angular
Source: https://github.com/4science/dspace-angular/blob/main-cris/README.md
Clone the repository, navigate into the project directory, install dependencies, and start the development server. Ensure you have the correct Node.js and npm versions installed.
```bash
git clone https://github.com/4Science/dspace-angular.git
cd dspace-angular
npm install
npm start
```
--------------------------------
### Install Project Dependencies
Source: https://github.com/4science/dspace-angular/blob/main-cris/README.md
Run these commands to clean, install, and start the project locally. This is useful for testing pull requests without a local DSpace backend.
```bash
npm run clean
npm install
npm start
```
--------------------------------
### Starting DSpace Angular in Development Mode
Source: https://context7.com/4science/dspace-angular/llms.txt
Install dependencies and start the application with live-reloading. The default address is http://localhost:4000.
```bash
# Install dependencies
npm install
# Start with live-reload (default: http://localhost:4000)
npm run start:dev
```
--------------------------------
### Build and Start SSR Server
Source: https://context7.com/4science/dspace-angular/llms.txt
Build the production application and then start the SSR server. Verify SSR functionality by checking the response for rendered HTML.
```bash
# Build and start the SSR server
npm run build:prod
npm run serve:ssr
# Verify SSR is working (page should contain rendered HTML, not just )
curl -s http://localhost:4000/ | grep '
DSPACE_CACHE_MSTOLIVE_DEFAULT
```
```bash
auth.ui.timeUntilIdle => DSPACE_AUTH_UI_TIMEUNTILIDLE
```
--------------------------------
### DSpace Angular List Example Component
Source: https://context7.com/4science/dspace-angular/llms.txt
Demonstrates constructing `FindListOptions` for paginated, sorted, and searched lists, including embedding HAL links for related resources. Ensure `ItemDataService` and related models are imported.
```typescript
import { Component, OnInit } from '@angular/core';
import { ItemDataService } from '../core/data/item-data.service';
import { FindListOptions } from '../core/data/find-list-options.model';
import { RequestParam } from '../core/cache/models/request-param.model';
import { SortOptions, SortDirection } from '../core/cache/models/sort-options.model';
import { followLink } from '../shared/utils/follow-link-config.model';
@Component({ selector: 'ds-list-example', template: '' })
export class ListExampleComponent implements OnInit {
constructor(private itemService: ItemDataService) {}
ngOnInit() {
// ── Paginated & sorted list ───────────────────────────────────────────
const opts: FindListOptions = {
currentPage: 2,
elementsPerPage: 25,
sort: new SortOptions('dc.date.issued', SortDirection.DESC),
};
// Resulting URL: .../items?page=1&size=25&sort=dc.date.issued,DESC
// ── StartsWith for browse indices ─────────────────────────────────────
const browseOpts: FindListOptions = {
startsWith: 'Smith',
currentPage: 1,
elementsPerPage: 10,
};
// Resulting URL: .../items?startsWith=Smith&page=0&size=10
// ── Custom search params ──────────────────────────────────────────────
const searchOpts: FindListOptions = {
searchParams: [
new RequestParam('query', 'climate change'),
new RequestParam('scope', 'community-uuid'),
],
currentPage: 1,
elementsPerPage: 10,
};
// ── With embedded HAL links (avoids extra round-trips) ────────────────
this.itemService.findAll(opts,
followLink('bundles'), // embed bundles
followLink('owningCollection'), // embed owning collection
followLink('thumbnail'), // embed thumbnail bitstream
).subscribe(rd => {
if (rd.hasSucceeded) {
rd.payload.page.forEach(item => {
console.log(item.uuid, item.name);
// item.bundles is already resolved — no extra HTTP call needed
});
const { currentPage, totalPages, totalElements } = rd.payload.pageInfo;
console.log(`Page ${currentPage} of ${totalPages} (${totalElements} total)`);
}
});
}
}
```
--------------------------------
### Add New Dependency with npm
Source: https://github.com/4science/dspace-angular/blob/main-cris/README.md
Use this command to install and add a new third-party library to your project's dependencies. Ensure you use the correct flag for development dependencies.
```bash
npm install some-lib
```
```bash
npm install some-lib --save--dev
```
--------------------------------
### Angular AuthService Example
Source: https://context7.com/4science/dspace-angular/llms.txt
Demonstrates various functionalities of the AuthService, including checking authentication status, logging in, retrieving user information, refreshing tokens, setting redirect URLs, handling external authentication, managing user idle state, and logging out.
```typescript
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { AuthService } from '../core/auth/auth.service';
import { EPerson } from '../core/eperson/models/eperson.model';
@Component({ selector: 'ds-login-example', template: '' })
export class LoginExampleComponent implements OnInit {
constructor(
private authService: AuthService,
private router: Router,
) {}
ngOnInit() {
// ── Check if user is currently authenticated ──────────────────────────
this.authService.isAuthenticated().subscribe(authenticated => {
console.log('Authenticated:', authenticated);
});
// ── Login with username and password ──────────────────────────────────
this.authService.authenticate('admin@example.org', 's3cr3t').subscribe({
next: (status) => {
console.log('Login successful, token:', status.token?.accessToken);
this.router.navigate(['/home']);
},
error: (err) => {
console.error('Login failed:', err.message);
// err.message === 'auth.errors.invalid-user' for bad credentials
},
});
// ── Get the authenticated EPerson from the store ───────────────────────
this.authService.getAuthenticatedUserFromStore().subscribe((user: EPerson) => {
if (user) console.log('Logged in as:', user.email);
});
// ── Refresh the current JWT token ─────────────────────────────────────
this.authService.refreshAuthenticationToken(null).subscribe(token => {
console.log('New token expiry:', token?.expires);
});
// ── Set a redirect URL before sending user to login ───────────────────
this.authService.setRedirectUrl('/protected-page');
// ── Retrieve the stored redirect URL ─────────────────────────────────
this.authService.getRedirectUrl().subscribe(url => {
console.log('Will redirect to:', url);
});
// ── Check for external (Shibboleth/OIDC) authentication ───────────────
this.authService.isExternalAuthentication().subscribe(external => {
console.log('Using external auth:', external);
});
// ── Mark user as idle / not idle ─────────────────────────────────────
this.authService.setIdle(true);
this.authService.isUserIdle().subscribe(idle => console.log('Idle:', idle));
// ── Logout ────────────────────────────────────────────────────────────
this.authService.logout().subscribe(() => {
this.router.navigate(['/home']);
});
}
}
```
--------------------------------
### Run End-to-End Tests
Source: https://github.com/4science/dspace-angular/blob/main-cris/README.md
Execute end-to-end tests using the 'ng e2e' command. This requires a locally running DSpace backend and specific test data setup. The tests will run against the backend configured in `config.prod.yml` by default.
```bash
ng e2e
```
--------------------------------
### Browse Community Hierarchy with CommunityDataService
Source: https://context7.com/4science/dspace-angular/llms.txt
Demonstrates fetching top-level communities, authorized communities, and sub-communities using CommunityDataService. Includes examples for finding communities by parent ID and accessing the community endpoint.
```typescript
import { Component, OnInit } from '@angular/core';
import { CommunityDataService } from '../core/data/community-data.service';
import { Community } from '../core/shared/community.model';
import { RemoteData } from '../core/data/remote-data';
import { PaginatedList } from '../core/data/paginated-list.model';
import { FindListOptions } from '../core/data/find-list-options.model';
import { followLink } from '../shared/utils/follow-link-config.model';
@Component({ selector: 'ds-community-example', template: '' })
export class CommunityExampleComponent implements OnInit {
constructor(private communityService: CommunityDataService) {}
ngOnInit() {
const opts: FindListOptions = { currentPage: 1, elementsPerPage: 10 };
// ── Top-level communities ─────────────────────────────────────────────
this.communityService.findTop(opts, followLink('logo'))
.subscribe((rd: RemoteData>) => {
if (rd.hasSucceeded) {
rd.payload.page.forEach(c => console.log(c.name, c.archivedItemsCount));
}
});
// ── All communities the current user administers ───────────────────────
this.communityService.getAuthorizedCommunity('', opts)
.subscribe((rd: RemoteData>) => {
if (rd.hasSucceeded) rd.payload.page.forEach(c => console.log(c.uuid));
});
// ── Sub-communities of a parent community ─────────────────────────────
const parentId = 'parent-community-uuid';
this.communityService.findByParent(parentId, opts)
.subscribe((rd: RemoteData>) => {
if (rd.hasSucceeded) {
console.log(`Sub-communities: ${rd.payload.page.length}`);
console.log('Total:', rd.payload.pageInfo.totalElements);
}
});
// ── Direct endpoint access (community is public) ──────────────────────
this.communityService.getEndpoint()
.subscribe(href => console.log('Communities endpoint:', href));
}
}
```
--------------------------------
### Invalid: Sort multiple imports alphabetically
Source: https://github.com/4science/dspace-angular/blob/main-cris/docs/lint/ts/rules/sort-standalone-imports.md
Shows an example of unsorted multiple imports that will trigger the ESLint rule and require fixing.
```typescript
@Component({
selector: 'ds-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
imports: [
RootComponent,
AsyncPipe,
],
})
export class AppComponent {}
```
--------------------------------
### DSpace Angular Docker Quick-start
Source: https://context7.com/4science/dspace-angular/llms.txt
Launch the Angular UI and REST backend simultaneously using Docker Compose for testing purposes. Access the UI at http://localhost:4000.
```bash
# Spin up Angular UI + REST backend for testing
docker compose -f docker/docker-compose.yml -f docker/docker-compose-rest.yml up
# Access the UI
open http://localhost:4000
```
--------------------------------
### Invalid: Multiple imports on the same line
Source: https://github.com/4science/dspace-angular/blob/main-cris/docs/lint/ts/rules/sort-standalone-imports.md
An example where multiple imports are placed on the same line, violating the sorting rule.
```typescript
@Component({
selector: 'ds-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
imports: [AsyncPipe, RootComponent],
})
export class AppComponent {}
```
--------------------------------
### Invalid: Singular import not on one line when maxItems is 0
Source: https://github.com/4science/dspace-angular/blob/main-cris/docs/lint/ts/rules/sort-standalone-imports.md
An example where a singular import is not on its own line, violating the `maxItems: 0` configuration.
```typescript
@Component({
selector: 'ds-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
imports: [RootComponent],
})
export class AppComponent {}
```
--------------------------------
### Run DSpace-CRIS Angular Dist Build with Demo Backend
Source: https://github.com/4science/dspace-angular/blob/main-cris/docker/README.md
Sets up and runs the Angular UI in production mode, connecting to a demo or sandbox DSpace-CRIS REST backend.
```bash
docker compose -f docker/docker-compose-dist.yml pull
docker compose -f docker/docker-compose-dist.yml build
docker compose -p dcris25 -f docker/docker-compose-dist.yml up -d
```
--------------------------------
### Runtime Configuration via config.yml
Source: https://context7.com/4science/dspace-angular/llms.txt
Configure UI, REST API, caching, authentication, theming, languages, and submission settings. Ensure correct paths and values for your DSpace instance.
```yaml
# config/config.prod.yml
ui:
ssl: false
host: localhost
port: 4000
nameSpace: /
# Server-side rendering cache for anonymous users (120 seconds)
cache:
anonymousMax: 120
anonymousMaxAge: 120
rest:
ssl: true
host: sandbox.dspace.org
port: 443
nameSpace: /server
cache:
msToLive:
default: 900000 # 15 minutes default cache TTL
serverSide:
debug: false
botCache:
enabled: true # cache responses for bots
max: 1000
timeToLive: 86400000 # 24 hours
auth:
ui:
timeUntilIdle: 900 # seconds until idle logout warning
idleGracePeriod: 300 # seconds of grace before forced logout
themes:
- name: dspace
# Optionally scope to a handle: handle: '10673/1'
languages:
- code: en
label: English
active: true
- code: de
label: Deutsch
active: true
- code: fr
label: Français
active: true
submission:
autosave:
metadata: [] # auto-save on these metadata field changes
timer: 5 # auto-save interval in minutes
icons:
metadata:
- name: dc.author
style: fas fa-user
```
--------------------------------
### Displaying Other Information for List Entries
Source: https://github.com/4science/dspace-angular/blob/main-cris/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.html
Iterates through additional information associated with a list entry, filtering out keys that start with 'data-' and displaying the translated key and its value.
```html
* {{entry.value}}
```
```html
@for (item of entry.otherInformation | dsObjNgFor; track item) { @if (!item.key.startsWith('data-')) {* {{ 'form.other-information.' + item.key | translate }} : {{item.value}}
} }
```
--------------------------------
### Building for Production
Source: https://github.com/4science/dspace-angular/blob/main-cris/README.md
Command to only build the application for production, placing the compiled output in the 'dist' folder. This output can then be deployed or served separately.
```bash
npm run build:prod
```
--------------------------------
### Configure Node.js Server UI Options
Source: https://github.com/4science/dspace-angular/blob/main-cris/docs/Configuration.md
Define UI settings for the Node.js server, such as SSL, host, and port, in a configuration file.
```yaml
ui:
ssl: false
host: localhost
port: 4000
nameSpace: /
```
--------------------------------
### Run Unit Tests
Source: https://github.com/4science/dspace-angular/blob/main-cris/README.md
Execute unit tests using the command below. Ensure tests are placed in files ending with '*.component.spec.ts'.
```bash
npm test
```
--------------------------------
### Iterate and Display Bitstreams
Source: https://github.com/4science/dspace-angular/blob/main-cris/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.html
Iterates over bitstreams and their updates, displaying details like name, description, and format. Includes logic for handling pagination options.
```html
@if ((bitstreamsRD$ | async)?.payload; as bitstreamsList) { @if ((updates$ | async); as updates) { @for (entry of (tableEntries$ | async); track entry) { @if (updates[entry.id]; as update) { } } }
```
```html
@for (size of paginationOptions.pageSizeOptions; track size) {* {{size}}
}
```
--------------------------------
### Set DSPACE_APP_CONFIG_PATH Environment Variable
Source: https://github.com/4science/dspace-angular/blob/main-cris/docs/Configuration.md
Specify an external configuration file path using the DSPACE_APP_CONFIG_PATH environment variable.
```bash
DSPACE_APP_CONFIG_PATH=/usr/local/dspace/config/config.yml
```
--------------------------------
### Allow Wrapper Class Usages
Source: https://github.com/4science/dspace-angular/blob/main-cris/docs/lint/ts/rules/themed-component-usages.md
Demonstrates correct usage of `ThemedComponent` wrappers in configuration objects.
```typescript
import { ThemedTestThemeableComponent } from './app/test/themed-test-themeable.component';
const config = {
a: ThemedTestThemeableComponent,
b: ChipsComponent,
}
```
--------------------------------
### Build Production DSpace-CRIS Angular Image
Source: https://github.com/4science/dspace-angular/blob/main-cris/docker/README.md
Builds a production-ready image for DSpace-CRIS Angular using Dockerfile.dist. A default demo version is built automatically.
```bash
docker build -f Dockerfile.dist -t 4science/dspace-cris-angular:dspace-cris-2025_02_x-dist .
```
--------------------------------
### Cleaning Project Files
Source: https://github.com/4science/dspace-angular/blob/main-cris/README.md
Provides commands for cleaning various parts of the project. Use `npm run clean` to remove everything including node_modules, `npm run clean:prod` for production build artifacts, and `npm run clean:dist` for the distribution directory.
```bash
# clean everything, including node_modules. You'll need to run npm install again afterwards.
npm run clean
```
```bash
# clean files generated by the production build (.ngfactory files, css files, etc)
npm run clean:prod
```
```bash
# cleans the distribution directory
npm run clean:dist
```
--------------------------------
### Configure DSpace-Angular Environment Variables
Source: https://github.com/4science/dspace-angular/blob/main-cris/README.md
Override default configuration values by creating a .env file in the project root. Non-convention settings like host, port, namespace, and SSL can be set directly. Other settings follow a DSPACE_ prefix convention.
```bash
DSPACE_HOST # The host name of the angular application
DSPACE_PORT # The port number of the angular application
DSPACE_NAMESPACE # The namespace of the angular application
DSPACE_SSL # Whether the angular application uses SSL [true/false]
```
```bash
# The host name of the REST application
rest.host => DSPACE_REST_HOST
# The port number of the REST application
rest.port => DSPACE_REST_PORT
# The namespace of the REST application
rest.nameSpace => DSPACE_REST_NAMESPACE
```
--------------------------------
### Environment Variable Overrides for Configuration
Source: https://context7.com/4science/dspace-angular/llms.txt
Override configuration settings at runtime using DSPACE-prefixed environment variables. Dots in keys are converted to underscores, and all variables are uppercased.
```bash
# Override REST host and port
export DSPACE_REST_HOST=repo.example.org
export DSPACE_REST_PORT=8080
export DSPACE_REST_SSL=true
export DSPACE_REST_NAMESPACE=/server
# Override UI binding
export DSPACE_HOST=0.0.0.0
export DSPACE_PORT=4000
```
--------------------------------
### Displaying Login Record Details
Source: https://github.com/4science/dspace-angular/blob/main-cris/src/app/statistics-page/login-statistics-page/login-statistics-page.component.html
Displays details for a single login record within a loop. This includes the index, user name, email, and login count.
```html
{{ i + 1 }}
```
```html
{{login.name}}
```
```html
{{login.email}}
```
```html
{{login.count}}
```
--------------------------------
### Display Bitstream Properties
Source: https://github.com/4science/dspace-angular/blob/main-cris/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.html
Displays the name, description, and format of a bitstream entry. The format's short description is fetched asynchronously.
```html
{{ entry.name }}
```
```html
{{ entry.description }}
```
```html
{{ (entry.format | async)?.shortDescription }}
```
--------------------------------
### Show More Button Logic
Source: https://github.com/4science/dspace-angular/blob/main-cris/src/app/community-list-page/community-list/community-list.component.html
Renders a 'Show More' button when the data source is not actively loading.
```html
@if ((dataSource.loading$ | async) !== true) { {{ 'communityList.showMore' | translate }} }
```
--------------------------------
### Environment Variable Overrides
Source: https://github.com/4science/dspace-angular/blob/main-cris/README.md
Demonstrates how environment variables can override legacy settings and variables in a .env file. These settings are collected at run time and written to a configuration file.
```bash
DSPACE_UI_HOST => DSPACE_HOST
DSPACE_UI_PORT => DSPACE_PORT
DSPACE_UI_NAMESPACE => DSPACE_NAMESPACE
DSPACE_UI_SSL => DSPACE_SSL
```
```bash
export DSPACE_HOST=demo.dspace.org
export DSPACE_UI_PORT=4000
```
--------------------------------
### Injecting App Configuration in TypeScript
Source: https://github.com/4science/dspace-angular/blob/main-cris/README.md
Shows how to inject the application configuration into a UI component using dependency injection in TypeScript. Ensure the AppConfig interface and APP_CONFIG provider are correctly imported.
```typescript
import { AppConfig, APP_CONFIG } from 'src/config/app-config.interface';
...
constructor(@Inject(APP_CONFIG) private appConfig: AppConfig) {}
...
```
--------------------------------
### Run DSpace Angular Tests
Source: https://context7.com/4science/dspace-angular/llms.txt
Execute unit tests using Karma/Jasmine, generate coverage reports, run ESLint for linting, check for circular dependencies, and run end-to-end tests with Cypress. Ensure the DSpace backend is running and configured correctly for E2E tests.
```bash
# ── Unit tests (all) ──────────────────────────────────────────────────────
npm test
# ── Unit tests with coverage report ─────────────────────────────────────
npm run coverage
# Coverage report available at http://localhost:9876/
# ── Lint (ESLint) ────────────────────────────────────────────────────────
npm run lint
# ── Check for circular dependencies ─────────────────────────────────────
npm run check-circ-deps
# ── E2E tests (requires running DSpace backend with test data) ───────────
# 1. Configure your local backend in config/config.dev.yml:
# rest: { host: localhost, port: 8080, ssl: false }
# 2. Ingest the DSpace Entities test data set
# 3. Run Cypress:
NODE_ENV=development ng e2e
```
--------------------------------
### Importing Environment Variables in TypeScript
Source: https://github.com/4science/dspace-angular/blob/main-cris/README.md
Demonstrates a common way to import environment-specific variables directly into your TypeScript code. This is useful for accessing build-time configurations.
```typescript
import { environment } from '../environment.ts';
```
--------------------------------
### Valid Themed Component Usage in HTML Templates
Source: https://github.com/4science/dspace-angular/blob/main-cris/docs/lint/html/rules/themed-component-usages.md
Demonstrates correct usage of themeable components using their `ds-test-themeable` selector in HTML templates, including with attributes.
```html
```
--------------------------------
### Handling No Results and Loading States
Source: https://github.com/4science/dspace-angular/blob/main-cris/src/app/shared/form/builder/ds-dynamic-form-ui/models/lookup/dynamic-lookup.component.html
Displays messages for 'no results' when the options list is empty and a 'loading' indicator while data is being fetched. It also iterates over the options list to display entries.
```html
@if (optionsList && optionsList.length === 0) { {{ 'form.no-results' | translate }} }
```
```html
@for (listEntry of optionsList; track listEntry) { }
```
```html
@if (loading) {
{{'form.loading' | translate}}
}
```
--------------------------------
### Override Node.js Server UI Configuration with Environment Variables
Source: https://github.com/4science/dspace-angular/blob/main-cris/docs/Configuration.md
Override Node.js server UI configuration using environment variables. These variables take precedence over configuration files.
```bash
DSPACE_SSL=true
DSPACE_HOST=localhost
DSPACE_PORT=4000
DSPACE_NAMESPACE=/
```
```bash
DSPACE_UI_SSL=true
DSPACE_UI_HOST=localhost
DSPACE_UI_PORT=4000
DSPACE_UI_NAMESPACE=/
```
--------------------------------
### Build DSpace-CRIS Images from Local Branch
Source: https://github.com/4science/dspace-angular/blob/main-cris/docker/README.md
Builds DSpace-CRIS images using the Docker Compose file and the code from your current local branch.
```bash
docker compose -f docker/docker-compose.yml build
```
--------------------------------
### Iterating and Displaying Dropdown Options
Source: https://github.com/4science/dspace-angular/blob/main-cris/src/app/shared/form/builder/ds-dynamic-form-ui/models/scrollable-dropdown/dynamic-scrollable-dropdown.component.html
This Angular template syntax iterates over the 'optionsList' to display each entry. It uses 'track listEntry' for efficient change detection and 'let i = $index' to access the item's index. The 'inputFormatter' function is used to format how each option is displayed.
```html
@for (listEntry of optionsList; track listEntry; let i = $index) { {{inputFormatter(listEntry)}} }
```
--------------------------------
### Create DSpace-CRIS Administrator
Source: https://github.com/4science/dspace-angular/blob/main-cris/docker/README.md
Creates a new administrator user for the DSpace-CRIS instance using the CLI container. Ensure the DSpace-CRIS REST container is running.
```bash
docker compose -p dcris25 -f docker/cli.yml run --rm dspace-cli create-administrator -e test@test.edu -f admin -l user -p admin -c en
```
--------------------------------
### Iterating and Rendering Suggestion Options
Source: https://github.com/4science/dspace-angular/blob/main-cris/src/app/shared/input-suggestions/validation-suggestions/validation-suggestions.component.html
This code iterates over a list of suggestions and renders them as clickable links. It uses an Angular structural directive for iteration and a JavaScript void link as a placeholder.
```html
@for (suggestionOption of suggestions; track suggestionOption) {
[](javascript:void(0);
}
```
--------------------------------
### Display Timestamp with Date Formatting
Source: https://github.com/4science/dspace-angular/blob/main-cris/src/app/admin/admin-notify-dashboard/admin-notify-search-result/admin-notify-search-result.component.html
Conditionally displays the 'queueLastStartTime' if it exists, formatted as 'yyyy/MM/d hh:mm:ss'. Shows 'n/a' if the timestamp is not available.
```html
@if (message.queueLastStartTime) {
{{ message.queueLastStartTime | date:"yyyy/MM/d hh:mm:ss" }}
} @if (!message.queueLastStartTime) {
n/a
}
```
--------------------------------
### Allow Wrapper Selectors in Test Queries
Source: https://github.com/4science/dspace-angular/blob/main-cris/docs/lint/ts/rules/themed-component-usages.md
Shows valid CSS selectors for themeable components in test files.
```typescript
By.css('ds-themeable');
By.css('#test > ds-themeable > #nest');
```
--------------------------------
### Load Assetstore Content and Re-index
Source: https://github.com/4science/dspace-angular/blob/main-cris/docker/README.md
This command loads assetstore content and triggers a re-index of the repository. It utilizes specific Docker compose files for CLI operations.
```bash
docker compose -p dcris25 -f docker/cli.yml -f docker/cli.assetstore.yml run --rm dspace-cli
```
--------------------------------
### Upgrade Existing Dependency with npm
Source: https://github.com/4science/dspace-angular/blob/main-cris/README.md
Use this command to upgrade existing dependencies to their latest versions or a specific version. This helps in keeping your project up-to-date with the latest features and security patches.
```bash
npm update some-lib
```
```bash
npm update some-lib@version
```
--------------------------------
### Generate Unit Test Coverage Report
Source: https://github.com/4science/dspace-angular/blob/main-cris/README.md
This command generates a coverage report for unit tests, accessible at http://localhost:9876/. Ensure Karma's 'autoWatch' and 'singleRun' options are configured appropriately if needed.
```bash
npm run coverage
```
--------------------------------
### Iterating and Displaying Entities in Dropdown
Source: https://github.com/4science/dspace-angular/blob/main-cris/src/app/shared/entity-dropdown/entity-dropdown.component.html
Renders a list of entities, sorted by their translated labels. Uses the dsSort pipe for sorting.
```html
@for (listItem of searchListEntity | dsSort: 'translatedLabel'; track listItem) {
* * {{ listItem.translatedLabel }}
}
```
--------------------------------
### Configure DSpace REST Endpoint
Source: https://github.com/4science/dspace-angular/blob/main-cris/docs/Configuration.md
Set DSpace REST endpoint configuration, including SSL, host, port, and namespace, in a configuration file.
```yaml
rest:
ssl: true
host: demo.dspace.org
port: 443
nameSpace: /server
}
```
--------------------------------
### Iterate and Display Scripts
Source: https://github.com/4science/dspace-angular/blob/main-cris/src/app/process-page/form/scripts-select/scripts-select.component.html
Iterates over a list of scripts and displays their names. Also includes a conditional check for loading state.
```HTML
@for (script of scripts; track script) { {{ script.name }} } @if ((isLoading$ | async)) { }
```
--------------------------------
### Iterate and Render Content with Links
Source: https://github.com/4science/dspace-angular/blob/main-cris/src/app/shared/context-help-wrapper/context-help-wrapper.component.html
Iterates over parsed content, rendering each item as a link if an href is present, otherwise as plain text. This is useful for displaying dynamic lists of information.
```html
@for (elem of (parsedContent$ | async); track elem) { @if (elem.href) { [{{elem.text}}]({{elem.href}}) } @else { {{ elem.text }} } }
```
--------------------------------
### Displaying Individual EPerson Data
Source: https://github.com/4science/dspace-angular/blob/main-cris/src/app/access-control/epeople-registry/epeople-registry.component.html
Renders the details for a single ePerson within the registry table, including their ID, name, and email. It also includes a conditional check for the ability to delete the ePerson.
```html
{{epersonDto.eperson.id}}
{{ dsoNameService.getName(epersonDto.eperson) }}
{{epersonDto.eperson.email}}
@if (epersonDto.ableToDelete) { }
```
--------------------------------
### Configure DSpace REST API via Environment Variables
Source: https://github.com/4science/dspace-angular/blob/main-cris/README.md
These environment variables can be used to configure the DSpace REST API endpoint for end-to-end tests, offering an alternative to modifying configuration files.
```bash
DSPACE_REST_SSL = false
DSPACE_REST_HOST = localhost
DSPACE_REST_PORT = 8080
```
--------------------------------
### Iterate and Display Top Objects with Columns
Source: https://github.com/4science/dspace-angular/blob/main-cris/src/app/shared/explore/section-component/multi-column-top-section/multi-column-top-section.component.html
Iterates over a list of top objects (likely fetched asynchronously) and for each object, iterates over columns to display their corresponding values. This is useful for rendering data rows in a table or list format.
```html
@for (topObject of ( topObjects | async ); track topObject; let last = $last) {
@for (column of getColumns(); track column) {
{{getColumnValue(topObject,column)}}
}
}
```
--------------------------------
### Conditional Rendering for Loading State
Source: https://github.com/4science/dspace-angular/blob/main-cris/src/app/access-control/group-registry/groups-registry.component.html
Uses the async pipe to conditionally render content based on the loading state. An empty block indicates no content is shown while loading.
```html
@if (loading$ | async) { }
```
--------------------------------
### Allow Inheriting from Base Class
Source: https://github.com/4science/dspace-angular/blob/main-cris/docs/lint/ts/rules/themed-component-usages.md
Illustrates extending a base themeable component class.
```typescript
import { TestThemeableComponent } from './app/test/test-themeable.component';
export class ThemedAdminSidebarComponent extends ThemedComponent {
}
```
--------------------------------
### Valid Themed Component Usage in TypeScript Templates
Source: https://github.com/4science/dspace-angular/blob/main-cris/docs/lint/html/rules/themed-component-usages.md
Shows the correct way to use themeable components within TypeScript templates.
```html
```
--------------------------------
### Find and List Items with ItemDataService
Source: https://context7.com/4science/dspace-angular/llms.txt
Demonstrates how to find a single item by its UUID and list items with pagination and sorting options. Ensure the `ItemDataService` is injected into your component.
```typescript
import { Component, OnInit } from '@angular/core';
import { ItemDataService } from '../core/data/item-data.service';
import { Item } from '../core/shared/item.model';
import { RemoteData } from '../core/data/remote-data';
import { PaginatedList } from '../core/data/paginated-list.model';
import { FindListOptions } from '../core/data/find-list-options.model';
import { SortDirection } from '../core/cache/models/sort-options.model';
import { followLink } from '../shared/utils/follow-link-config.model';
@Component({ selector: 'ds-item-example', template: '' })
export class ItemExampleComponent implements OnInit {
constructor(private itemService: ItemDataService) {}
ngOnInit() {
const itemId = 'a1b2c3d4-0000-0000-0000-000000000001';
// ── Find a single Item by UUID ────────────────────────────────────────
this.itemService.findById(itemId, true, true, followLink('bundles'))
.subscribe((rd: RemoteData- ) => {
if (rd.hasSucceeded) console.log('Item name:', rd.payload.name);
});
// ── List Items with pagination and sorting ────────────────────────────
const opts: FindListOptions = {
currentPage: 1,
elementsPerPage: 10,
sort: { field: 'dc.date.issued', direction: SortDirection.DESC },
};
this.itemService.findAll(opts).subscribe((rd: RemoteData>) => {
if (rd.hasSucceeded) {
rd.payload.page.forEach(item => console.log(item.uuid, item.name));
}
});
}
}
```
--------------------------------
### Handle Array Replacements Correctly
Source: https://github.com/4science/dspace-angular/blob/main-cris/docs/lint/ts/rules/themed-component-usages.md
Shows how the linter automatically corrects themeable component usages within arrays.
```typescript
const DECLARATIONS = [
Something,
TestThemeableComponent,
Something,
ThemedTestThemeableComponent,
];
Will produce the following error(s):
```
Themeable components should be used via their ThemedComponent wrapper
```
Result of `yarn lint --fix`:
```typescript
const DECLARATIONS = [
Something,
Something,
ThemedTestThemeableComponent,
];
```
```
--------------------------------
### Display Metric Icon and Label
Source: https://github.com/4science/dspace-angular/blob/main-cris/src/app/shared/metric/metric-default/metric-default.component.html
Conditionally displays the metric's icon if available. Translates the metric label using the 'translate' pipe.
```html
@if (metric && metric.icon) {
}
```
```html
{{ "item.page.metric.label." + metric.metricType | translate }}
```
--------------------------------
### Server-Side Rendering (SSR) with Express
Source: https://context7.com/4science/dspace-angular/llms.txt
The Express server handles SSR, serving cached HTML for bots and using transfer state to prevent duplicate API calls between server and browser. Configure the engine with bootstrap module, document path, URL, public path, and providers.
```typescript
// server.ts (simplified)
import 'zone.js/node';
import { APP_BASE_HREF } from '@angular/common';
import { CommonEngine } from '@angular/ssr';
import express from 'express';
import { AppServerModule } from './src/main.server';
const server = express();
const engine = new CommonEngine();
server.get('*', (req, res) => {
engine.render({
bootstrap: AppServerModule,
documentFilePath: 'dist/browser/index.html',
url: req.url,
publicPath: 'dist/browser',
providers: [{ provide: APP_BASE_HREF, useValue: req.baseUrl }],
}).then(html => res.send(html))
.catch(err => {
console.error('SSR render error:', err);
res.sendFile('dist/browser/index.html', { root: '.' });
});
});
server.listen(4000, () => console.log('SSR server running on port 4000'));
```
--------------------------------
### Display Metric Acquisition Date
Source: https://github.com/4science/dspace-angular/blob/main-cris/src/app/shared/metric/metric-default/metric-default.component.html
Displays the metric's acquisition date, formatted using the 'date' pipe for localization.
```html
{{ "item.page.metric.acquisition-date" | translate }}
{{ metric.acquisitionDate | date }}
```
--------------------------------
### Translate and Display Bundle Name
Source: https://github.com/4science/dspace-angular/blob/main-cris/src/app/item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.html
Translates and displays the bundle name using the provided 'bundleName' variable.
```html
{{'item.edit.bitstreams.bundle.name' | translate:{ name: bundleName } }}
```
--------------------------------
### Conditional Rendering of Metadata Group
Source: https://github.com/4science/dspace-angular/blob/main-cris/src/app/cris-layout/cris-layout-matrix/cris-layout-box-container/boxes/metadata/rendering-types/metadataGroup/table/table.component.html
This snippet demonstrates conditional rendering based on an asynchronous initialization status. It iterates over metadata groups and components to be rendered.
```html
@if ((initialized | async)) {
@for (field of metadataGroup; track field) { } @for (index of componentsToBeRenderedMap.keys(); track index) { @for (mdg of componentsToBeRenderedMap.get(index); track mdg) { } }
}
```
--------------------------------
### Display Collections and Loading State in Angular Template
Source: https://github.com/4science/dspace-angular/blob/main-cris/src/app/item-page/field-components/collections/collections.component.html
Iterates over collections, displays their names, and handles loading and 'load more' states using Angular's template syntax and async pipe.
```html
@for (collection of (this.collections$ | async); track collection; let last = $last) { {{ dsoNameService.getName(collection) }}@if (!last) { } }
@if (isLoading$ | async) {
{{'item.page.collections.loading' | translate}}
} @if ((isLoading$ | async) !== true && (hasMore$ | async)) { [{{'item.page.collections.load-more' | translate}}](javascript:void(0);) }
```
--------------------------------
### Run End-to-End Tests with Development Configuration
Source: https://github.com/4science/dspace-angular/blob/main-cris/README.md
To run end-to-end tests against the development configuration, set the NODE_ENV environment variable to 'development' before executing the 'ng e2e' command.
```bash
NODE_ENV=development ng e2e
```
--------------------------------
### Configure Lazy-Loaded Application Routes
Source: https://context7.com/4science/dspace-angular/llms.txt
Define application routes in `app-routes.ts` for lazy loading modules. Use guards like `AuthenticatedGuard` and `SiteAdministratorGuard` to protect routes.
```typescript
// src/app/app-routes.ts
import { Route } from '@angular/router';
import { AuthenticatedGuard } from './core/auth/authenticated.guard';
import { SiteAdministratorGuard } from './core/data/feature-authorization/feature-authorization-guard/site-administrator.guard';
export const APP_ROUTES: Route[] = [
// Public routes
{ path: '', pathMatch: 'full', redirectTo: '/home' },
{ path: 'home',
loadChildren: () => import('./home-page/home-page-routes').then(m => m.HOME_PAGE_ROUTES) },
{ path: 'communities/:id',
loadChildren: () => import('./community-page/community-page-routes').then(m => m.COMMUNITY_PAGE_ROUTES) },
{ path: 'collections/:id',
loadChildren: () => import('./collection-page/collection-page-routes').then(m => m.COLLECTION_PAGE_ROUTES) },
{ path: 'items/:id',
loadChildren: () => import('./item-page/item-page-routes').then(m => m.ITEM_PAGE_ROUTES) },
{ path: 'search',
loadChildren: () => import('./search-page/search-page-routes').then(m => m.SEARCH_PAGE_ROUTES) },
// Authenticated routes
{ path: 'mydspace',
canActivate: [AuthenticatedGuard],
loadChildren: () => import('./my-dspace-page/my-dspace-page-routes').then(m => m.MY_DSPACE_PAGE_ROUTES) },
{ path: 'submit',
canActivate: [AuthenticatedGuard],
loadChildren: () => import('./submit-page/submit-page-routes').then(m => m.SUBMIT_PAGE_ROUTES) },
{ path: 'workspaceitems/:id/edit',
canActivate: [AuthenticatedGuard],
loadChildren: () => import('./submission/submission-edit-routes').then(m => m.SUBMISSION_EDIT_ROUTES) },
// Admin routes
{ path: 'admin',
canActivate: [SiteAdministratorGuard],
loadChildren: () => import('./admin/admin-routes').then(m => m.ADMIN_ROUTES) },
];
```
--------------------------------
### Load Content from AIP Files
Source: https://github.com/4science/dspace-angular/blob/main-cris/docker/README.md
Loads content from AIP files into the DSpace-CRIS instance using the CLI container. This command requires the 'cli.ingest.yml' configuration file.
```bash
docker compose -p dcris25 -f docker/cli.yml -f ./docker/cli.ingest.yml run --rm dspace-cli
```
--------------------------------
### Display View Detail Button
Source: https://github.com/4science/dspace-angular/blob/main-cris/src/app/shared/metric/metric-default/metric-default.component.html
Conditionally displays a 'View Detail' button if a URL is provided. The button's label is translated.
```html
@if (url) {
{{ "item.page.metric.label.view-detail-btn" | translate }}
}
```
--------------------------------
### Angular Iteration and Conditional Rendering
Source: https://github.com/4science/dspace-angular/blob/main-cris/src/app/social/social.component.html
Demonstrates Angular's @for and @if directives for iterating over a list of buttons and conditionally displaying a share button.
```html
@for (button of buttonList; track button) { }
@if (showPlusButton) { [](https://www.addtoany.com/share)}
```
--------------------------------
### Valid Component Declarations
Source: https://github.com/4science/dspace-angular/blob/main-cris/docs/lint/ts/rules/no-default-standalone-value.md
Demonstrates valid ways to declare Angular components. Not setting the `standalone` value or explicitly setting it to `false` are both acceptable.
```typescript
@Component({
selector: 'ds-test',
})
class TestComponent {}
```
```typescript
@Component({
selector: 'ds-test',
standalone: false,
})
class TestComponent {}
```
--------------------------------
### Display Page Size Options in Angular Template
Source: https://github.com/4science/dspace-angular/blob/main-cris/src/app/shared/page-size-selector/page-size-selector.component.html
Iterates over available page size options from an observable and displays them. Ensure paginationOptions$ is properly defined and emits an object with pageSizeOptions.
```html
@for (pageSizeOption of (paginationOptions$ | async).pageSizeOptions; track pageSizeOption) { {{pageSizeOption}} }
```
--------------------------------
### Displaying Item Thumbnail and Title
Source: https://github.com/4science/dspace-angular/blob/main-cris/src/app/shared/metadata-link-view/metadata-link-view-popover/metadata-link-view-popover.component.html
Conditionally displays the item's thumbnail if available, and then shows the first metadata value for 'dc.title'.
```html
@if (item.thumbnail | async) { } {{item.firstMetadataValue('dc.title')}}
```
--------------------------------
### Display Notification Detail and Reprocess Action
Source: https://github.com/4science/dspace-angular/blob/main-cris/src/app/admin/admin-notify-dashboard/admin-notify-search-result/admin-notify-search-result.component.html
Displays a 'detail' translation and conditionally renders a 'reprocess' translation if the 'queueStatusLabel' is not 'reprocessStatus' and is included in 'validStatusesForReprocess'.
```html
{{ 'notify-message-result.detail' | translate }} @if (message.queueStatusLabel !== reprocessStatus && validStatusesForReprocess.includes(message.queueStatusLabel)) { {{ 'notify-message-result.reprocess' | translate }} }
```
--------------------------------
### Display Item Metadata or Placeholder
Source: https://github.com/4science/dspace-angular/blob/main-cris/src/app/shared/object-detail/my-dspace-result-detail-element/item-detail-preview/item-detail-preview-field/item-detail-preview-field.component.html
Conditionally renders item metadata values if they exist, otherwise displays a translated placeholder. This is useful for showing field information in a user-friendly way.
```html
@if (item.hasMetadata(metadata)) { @for (mdValue of allMetadataValues(metadata); track mdValue; let last = $last) { {{mdValue}}@if (!last) { } } } @if (!item.hasMetadata(metadata)) { {{(placeholder | translate)}} }
```
--------------------------------
### Override DSpace REST Endpoint Configuration with Environment Variables
Source: https://github.com/4science/dspace-angular/blob/main-cris/docs/Configuration.md
Override DSpace REST endpoint configuration using environment variables. These variables take precedence over configuration files.
```bash
DSPACE_REST_SSL=true
DSPACE_REST_HOST=demo.dspace.org
DSPACE_REST_PORT=443
DSPACE_REST_NAMESPACE=/server
```
--------------------------------
### Valid Regular Component Selector
Source: https://github.com/4science/dspace-angular/blob/main-cris/docs/lint/ts/rules/themed-component-selectors.md
Demonstrates a valid selector for a regular, non-themeable component.
```typescript
@Component({
selector: 'ds-something',
})
class Something {
}
```
--------------------------------
### Loading State Indicator
Source: https://github.com/4science/dspace-angular/blob/main-cris/src/app/shared/form/builder/ds-dynamic-form-ui/models/list/dynamic-list.component.html
Conditionally render content while data is being loaded, typically used to show a spinner or placeholder.
```html
@if ((isLoading$ | async)) {
}
```
--------------------------------
### Valid Themeable Component Selectors
Source: https://github.com/4science/dspace-angular/blob/main-cris/docs/lint/ts/rules/themed-component-selectors.md
Shows the correct selector pattern for themeable components, including base, wrapper, and override classes.
```typescript
@Component({
selector: 'ds-base-something',
})
class Something {
}
@Component({
selector: 'ds-something',
})
class ThemedSomething extends ThemedComponent {
}
@Component({
selector: 'ds-themed-something',
})
class OverrideSomething extends Something {
}
```
--------------------------------
### Expand/Collapse Button Logic
Source: https://github.com/4science/dspace-angular/blob/main-cris/src/app/community-list-page/community-list/community-list.component.html
Conditionally displays 'expand' or 'collapse' text based on the node's expansion state and whether it has children. Requires an asynchronous check for child existence.
```html
@if (hasChild(null, node) | async) { {{ (node.isExpanded ? 'communityList.collapse' : 'communityList.expand') | translate:{ name: dsoNameService.getName(node.payload) } }} }
```
--------------------------------
### Loading Indicator
Source: https://github.com/4science/dspace-angular/blob/main-cris/src/app/shared/search/search-results/search-results.component.html
Displays a loading indicator when the isLoading function returns true.
```html
@if (isLoading()) { }
```
--------------------------------
### Iterate and Display Item Representations
Source: https://github.com/4science/dspace-angular/blob/main-cris/src/app/item-page/simple/metadata-representation-list/metadata-representation-list.component.html
Iterates over a list of objects and their associated representations. Includes conditional logic for displaying pagination controls.
```html
@for (objectPage of objects; track objectPage; let i = $index) {
@for (rep of representations; track rep) {
}
@if ((i + 1) === objects.length && (i > 0) && (!representations || representations?.length === 0)) {
}
@if ((i + 1) === objects.length && representations?.length > 0) {
}
}
```
--------------------------------
### Conditional 'Show More' Link
Source: https://github.com/4science/dspace-angular/blob/main-cris/src/app/shared/search/search-filters/search-filter/search-text-filter/search-text-filter.component.html
Conditionally display a 'show more' link if the current page is not the last page. The link navigates to a javascript:void(0) placeholder.
```html
@if ((isLastPage$ | async) !== true) { [{{"search.filters.filter.show-more" | translate}}](javascript:void(0);) }
```
--------------------------------
### Displaying 'More Info' Label
Source: https://github.com/4science/dspace-angular/blob/main-cris/src/app/shared/metadata-link-view/metadata-link-view-popover/metadata-link-view-popover.component.html
Displays a translated label for 'more info' at the end of the metadata list.
```html
{{ "metadata-link-view.popover.label.more-info" | translate }}
```
--------------------------------
### Dynamic API Endpoint Resolution with HALEndpointService
Source: https://context7.com/4science/dspace-angular/llms.txt
Utilize HALEndpointService to dynamically discover API URLs at runtime by traversing the HAL link graph. This avoids hardcoding URLs and ensures adaptability to API changes.
```typescript
import { Component, OnInit } from '@angular/core';
import { HALEndpointService } from '../core/shared/hal-endpoint.service';
@Component({ selector: 'ds-example', template: '' })
export class ExampleComponent implements OnInit {
constructor(private halService: HALEndpointService) {}
ngOnInit() {
// Resolve a top-level endpoint by its HAL link name
this.halService.getEndpoint('items').subscribe(href => {
console.log(href); // https://sandbox.dspace.org/server/api/core/items
});
// Resolve a nested endpoint (traverses link chain)
this.halService.getEndpoint('communities/subcommunities').subscribe(href => {
console.log(href); // resolved subcommunities href
});
// Check if an endpoint exists on the REST API
this.halService.isEnabledOnRestApi('ldn').subscribe(enabled => {
if (enabled) { console.log('LDN notifications are available'); }
});
// Get the root REST URL directly
const rootHref = this.halService.getRootHref();
// e.g. https://sandbox.dspace.org/server
}
}
```
--------------------------------
### Correctly Aliased Import
Source: https://github.com/4science/dspace-angular/blob/main-cris/docs/lint/ts/rules/alias-imports.md
Demonstrates a correctly aliased import for 'rxjs/of' using the 'observableOf' alias. This is used when the alias is explicitly defined in the configuration.
```typescript
import { of as observableOf } from 'rxjs';
```
```json
{
"aliases": [
{
"package": "rxjs",
"imported": "of",
"local": "observableOf"
}
]
}
```