develop #2
108
README.md
108
README.md
|
@ -1,32 +1,110 @@
|
||||||
# UOA Repository Manager UI
|
# UOA Repository Manager UI
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Building
|
||||||
|
|
||||||
This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 6.0.8 (Angular version 6.1.10).
|
This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 6.0.8 (Angular version 6.1.10).
|
||||||
|
|
||||||
## Minimum requirements for installing and building the project
|
#### Minimum requirements for installing and building the project
|
||||||
|
|
||||||
[Node.js](https://nodejs.org/en/) version 8.x or 10.x.<br>
|
[Node.js](https://nodejs.org/en/) version 8.x or 10.x.<br>
|
||||||
[npm client](https://docs.npmjs.com/cli/install) command line interface (it is installed with Node.js by default).
|
[npm client](https://docs.npmjs.com/cli/install) command line interface (it is installed with Node.js by default).
|
||||||
|
- [Node.js version 16](https://nodejs.org/en/blog/release/v16.16.0)
|
||||||
|
|
||||||
## Installing the project
|
###### Build Instructions:
|
||||||
|
Follow the instructions below to download the source code and build the application.
|
||||||
|
For more information about building an Angular app you can refer to the official documentation: [Building and serving Angular apps](https://angular.io/guide/build#building-and-serving-angular-apps).
|
||||||
|
|
||||||
After checking out (or updating) the repository enter the created folder and run `npm ci`.
|
1. Clone the repository and move inside the directory
|
||||||
This will install the exact versions of the dependencies as mentioned in the `package-lock.json` file (inside the root folder).
|
<br> `git clone https://code-repo.d4science.org/MaDgIK/uoa-repository-manager-ui.git && cd uoa-repository-manager-ui`
|
||||||
|
2. Install Angular dependencies
|
||||||
|
<br> `npm install`
|
||||||
|
3. Build Angular app
|
||||||
|
<br> `ng build --configuration production`
|
||||||
|
<br> Produces the directory "dist/**uoa-repository-manager-ui**" which contains the compiled files.
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
|
||||||
## Build for production
|
## Deployment
|
||||||
|
|
||||||
Run `npm run build` (equivalent of `ng build --prod`) to build the project. The build artifacts will be stored in the `dist/uoa-repository-manager-ui` directory.
|
### Prerequisites
|
||||||
|
- Nginx
|
||||||
|
|
||||||
## Deploy project to nginx server
|
### Instructions
|
||||||
|
To deploy the Frontend app:
|
||||||
|
1. Make sure that you have successfully built and installed the application on Nginx (or another Web Server).
|
||||||
|
2. _Start_ or _reload_ the Web Server service.
|
||||||
|
<br>e.g. `systemctl start nginx` or `systemctl reload nginx`
|
||||||
|
|
||||||
Run `tar -czvf dist.tar.gz dist/` to generate a compressed `.gz` file containing the built angular folder<br>
|
## Installation
|
||||||
Run `scp dist.tar.gz path/to/server/` to copy the compressed file to the server.<br>
|
|
||||||
Connect to server (`ssh user@server.ip.address`).<br>
|
|
||||||
Uncompress `dist.tar.gz` file.<br>
|
|
||||||
Navigate to the root folder of the server.
|
|
||||||
Copy the contents of the uncompressed dist/uoa-repository-manager-ui folder
|
|
||||||
into the `uoa-repository-manager-dashboard` folder (superuser privileges are normally required for this action).<br>
|
|
||||||
|
|
||||||
## Other topics
|
### Prerequisites
|
||||||
|
- [Nginx](https://www.nginx.com/) (or another Web Server like [Apache HTTP Server](https://httpd.apache.org/))
|
||||||
|
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
|
||||||
|
|
||||||
|
### Installation
|
||||||
|
|
||||||
|
#### Nginx Configuration
|
||||||
|
You have to create a [Server Block configuration](https://www.nginx.com/resources/wiki/start/topics/examples/server_blocks/) that will point to the directory "dist/**uoa-repository-manager-ui**" created by [building manually](./building.md#manual-build) the webapp.
|
||||||
|
It must also be configured as a reverse proxy for the Backend Application (to serve it under the path '/api') and for the list of [Dependencies](#dependencies) of the project.
|
||||||
|
|
||||||
|
See the example below:
|
||||||
|
```nginx
|
||||||
|
server {
|
||||||
|
server_name ...
|
||||||
|
access_log ...
|
||||||
|
root /path/to/uoa-repository-manager-ui; # the directory of the application
|
||||||
|
|
||||||
|
location / {
|
||||||
|
try_files $uri$args $uri$args/ /index.html /index.php;
|
||||||
|
}
|
||||||
|
|
||||||
|
location ~* \.(eot|ttf|woff)$ {
|
||||||
|
add_header Access-Control-Allow-Origin *;
|
||||||
|
}
|
||||||
|
|
||||||
|
# reverse proxy configuration for the backend application
|
||||||
|
location /api {
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
proxy_pass <?>;
|
||||||
|
proxy_read_timeout 3600;
|
||||||
|
proxy_send_timeout 3600;
|
||||||
|
}
|
||||||
|
|
||||||
|
[...]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Lastly, we would advice to validate the configuration of the Nginx to make sure it does not contain errors.
|
||||||
|
<br>Execute `nginx -t` with elevated permissions to perform a validation. If the test is successful you can move on to [deploying](./deployment.md#frontend) the application.
|
||||||
|
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Security
|
||||||
|
## Maintenance
|
||||||
|
## Recovery
|
||||||
|
## References
|
||||||
|
|
||||||
|
|
||||||
|
## Other topics
|
||||||
### Development server
|
### Development server
|
||||||
|
|
||||||
Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files.<br>
|
Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files.<br>
|
||||||
|
|
|
@ -678,11 +678,12 @@ export class Typology {
|
||||||
}
|
}
|
||||||
|
|
||||||
export class AggregationDetails implements IsSerializable {
|
export class AggregationDetails implements IsSerializable {
|
||||||
aggregationStage: string;
|
|
||||||
date: Date;
|
date: Date;
|
||||||
numberOfRecords: number;
|
aggregationStage: string; // is present when aggregationStage==='COLLECT'
|
||||||
collectionMode: string;
|
collectionMode: string;
|
||||||
|
numberOfRecords: number;
|
||||||
indexedVersion: boolean;
|
indexedVersion: boolean;
|
||||||
|
completedSuccessfully: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Aggregations implements IsSerializable {
|
export class Aggregations implements IsSerializable {
|
||||||
|
|
|
@ -53,7 +53,7 @@ export class HomeComponent implements OnInit {
|
||||||
if (this.authService.getIsUserLoggedIn()) {
|
if (this.authService.getIsUserLoggedIn()) {
|
||||||
this.router.navigate([pageUrl]);
|
this.router.navigate([pageUrl]);
|
||||||
} else {
|
} else {
|
||||||
this.authService.redirectUrl = pageUrl;
|
// this.authService.redirectUrl = pageUrl;
|
||||||
this.login();
|
this.login();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,8 +51,8 @@
|
||||||
<!--<td class="uk-text-center"><img class="md-user-image dense-image dense-ready" src="assets/img/avatars/avatar_01_tn@2x.png" alt="" data-dense-cap="2"></td>-->
|
<!--<td class="uk-text-center"><img class="md-user-image dense-image dense-ready" src="assets/img/avatars/avatar_01_tn@2x.png" alt="" data-dense-cap="2"></td>-->
|
||||||
<td><span *ngIf="aggr.date">{{ aggr.date | date : "yyyy-MM-dd" }}</span></td>
|
<td><span *ngIf="aggr.date">{{ aggr.date | date : "yyyy-MM-dd" }}</span></td>
|
||||||
<td class=""><span *ngIf="aggr.aggregationStage">{{ aggr.aggregationStage }}</span></td>
|
<td class=""><span *ngIf="aggr.aggregationStage">{{ aggr.aggregationStage }}</span></td>
|
||||||
<td class=""><span *ngIf="aggr.collectionMode">{{ aggr.collectionMode }}</span></td>
|
<td class=""><span>{{ aggr.collectionMode ? aggr.collectionMode : '-'}}</span></td>
|
||||||
<td class="uk-text-center"><span *ngIf="aggr.numberOfRecords">{{ aggr.numberOfRecords }}</span></td>
|
<td class="uk-text-center"><span *ngIf="aggr.numberOfRecords !== null">{{ aggr.numberOfRecords }}</span></td>
|
||||||
<td class="uk-text-center"><span *ngIf="aggr.indexedVersion !== null && (aggr.indexedVersion === true)" class="uk-badge">Indexed version</span></td>
|
<td class="uk-text-center"><span *ngIf="aggr.indexedVersion !== null && (aggr.indexedVersion === true)" class="uk-badge">Indexed version</span></td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|
|
@ -74,7 +74,7 @@
|
||||||
<span class="uk-text-small uk-text-muted">{{ aggr.collectionMode }}</span>
|
<span class="uk-text-small uk-text-muted">{{ aggr.collectionMode }}</span>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li *ngIf="aggr.numberOfRecords">
|
<li>
|
||||||
<!--<div class="md-list-addon-element">-->
|
<!--<div class="md-list-addon-element">-->
|
||||||
<!--<span class="md-user-image md-list-addon-avatar dense-image dense-ready">-->
|
<!--<span class="md-user-image md-list-addon-avatar dense-image dense-ready">-->
|
||||||
<!--<i class="material-icons">list</i>-->
|
<!--<i class="material-icons">list</i>-->
|
||||||
|
@ -82,7 +82,13 @@
|
||||||
<!--</div>-->
|
<!--</div>-->
|
||||||
<div class="md-list-content">
|
<div class="md-list-content">
|
||||||
<span class="md-list-heading">Number of records</span>
|
<span class="md-list-heading">Number of records</span>
|
||||||
<span class="uk-text-small uk-text-muted">{{ aggr.numberOfRecords }}</span>
|
<span class="uk-text-small uk-text-muted">{{ aggr?.numberOfRecords>=0 ? aggr.numberOfRecords : 'NA' }}</span>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<div class="md-list-content">
|
||||||
|
<span class="md-list-heading">Completed Successfully</span>
|
||||||
|
<span class="uk-text-small uk-text-muted">{{ aggr.completedSuccessfully }}</span>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
|
@ -144,7 +144,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div *ngIf="aggr.numberOfRecords" class="uk-margin-small-bottom">
|
<div class="uk-margin-small-bottom">
|
||||||
<!--<div class="inline-block" style="vertical-align: top">-->
|
<!--<div class="inline-block" style="vertical-align: top">-->
|
||||||
<!--<span class="md-user-image md-list-addon-avatar dense-image dense-ready">-->
|
<!--<span class="md-user-image md-list-addon-avatar dense-image dense-ready">-->
|
||||||
<!--<i class="material-icons">list</i>-->
|
<!--<i class="material-icons">list</i>-->
|
||||||
|
@ -153,7 +153,14 @@
|
||||||
|
|
||||||
<div class="">
|
<div class="">
|
||||||
<div class="md-list-heading">Number of records</div>
|
<div class="md-list-heading">Number of records</div>
|
||||||
<div class="uk-text-small uk-text-muted">{{ aggr.numberOfRecords | number }}</div>
|
<div class="uk-text-small uk-text-muted">{{ aggr?.numberOfRecords>=0 ? aggr.numberOfRecords : 'NA' }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="uk-margin-small-bottom">
|
||||||
|
<div class="">
|
||||||
|
<div class="md-list-heading">Completed Successfully</div>
|
||||||
|
<div class="uk-text-small uk-text-muted">{{ aggr.completedSuccessfully }}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -12,12 +12,17 @@ export class AuthGuardService implements CanActivate, CanLoad {
|
||||||
canActivate (route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
canActivate (route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
||||||
if ( this.authenticationService.getIsUserLoggedIn() ) { return true; }
|
if ( this.authenticationService.getIsUserLoggedIn() ) { return true; }
|
||||||
|
|
||||||
/* If no cookie was found, clear the app's session.
|
|
||||||
The user may have logged out using another OpenAIRE portal */
|
|
||||||
sessionStorage.clear();
|
|
||||||
|
|
||||||
// Store the attempted URL for redirecting
|
// Store the attempted URL for redirecting
|
||||||
sessionStorage.setItem('state.location', state.url);
|
if (state.url !== '/join') {
|
||||||
|
/* If no cookie was found, clear the app's session.
|
||||||
|
The user may have logged out using another OpenAIRE portal */
|
||||||
|
sessionStorage.clear();
|
||||||
|
this.authenticationService.redirectUrl = state.url;
|
||||||
|
sessionStorage.setItem('state.location', state.url);
|
||||||
|
}
|
||||||
|
console.log('redirect state: ' + sessionStorage.getItem('state.location'));
|
||||||
|
|
||||||
// If we decide that in this case we will send the user back to the aai
|
// If we decide that in this case we will send the user back to the aai
|
||||||
// this.authenticationService.redirectUrl = state.url;
|
// this.authenticationService.redirectUrl = state.url;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { ActivatedRoute, Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
import { HttpClient } from '@angular/common/http';
|
import { HttpClient } from '@angular/common/http';
|
||||||
import { environment } from '../../environments/environment';
|
import { environment } from '../../environments/environment';
|
||||||
import { deleteCookie, getCookie } from '../domain/utils';
|
import { deleteCookie, getCookie } from '../domain/utils';
|
||||||
|
@ -8,8 +8,7 @@ import { BehaviorSubject } from 'rxjs';
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class AuthenticationService {
|
export class AuthenticationService {
|
||||||
|
|
||||||
constructor(private route: ActivatedRoute,
|
constructor(private router: Router,
|
||||||
private router: Router,
|
|
||||||
private http: HttpClient) {}
|
private http: HttpClient) {}
|
||||||
|
|
||||||
private apiUrl: string = environment.API_ENDPOINT;
|
private apiUrl: string = environment.API_ENDPOINT;
|
||||||
|
@ -18,8 +17,6 @@ export class AuthenticationService {
|
||||||
// store the URL so we can redirect after logging in
|
// store the URL so we can redirect after logging in
|
||||||
public redirectUrl: string;
|
public redirectUrl: string;
|
||||||
|
|
||||||
private _storage: Storage = sessionStorage;
|
|
||||||
|
|
||||||
private cookie: string = null;
|
private cookie: string = null;
|
||||||
|
|
||||||
public isLoggedIn_ = new BehaviorSubject(false);
|
public isLoggedIn_ = new BehaviorSubject(false);
|
||||||
|
@ -33,7 +30,6 @@ export class AuthenticationService {
|
||||||
if (this.redirectUrl) {
|
if (this.redirectUrl) {
|
||||||
const url = this.redirectUrl;
|
const url = this.redirectUrl;
|
||||||
this.redirectUrl = null;
|
this.redirectUrl = null;
|
||||||
console.log('stored location', url);
|
|
||||||
sessionStorage.setItem('state.location', url);
|
sessionStorage.setItem('state.location', url);
|
||||||
} else {
|
} else {
|
||||||
/*sessionStorage.setItem("state.location", this.router.url);*/
|
/*sessionStorage.setItem("state.location", this.router.url);*/
|
||||||
|
@ -108,7 +104,7 @@ export class AuthenticationService {
|
||||||
sessionStorage.removeItem('state.location');
|
sessionStorage.removeItem('state.location');
|
||||||
console.log(`tried to login - returning to state: ${state}`);
|
console.log(`tried to login - returning to state: ${state}`);
|
||||||
if ( !this.getIsUserLoggedIn() ) {
|
if ( !this.getIsUserLoggedIn() ) {
|
||||||
// console.log('user hasn\'t logged in yet -- going to home');
|
// console.log('user hasn't logged in yet -- redirecting to home');
|
||||||
this.router.navigate(['/home']);
|
this.router.navigate(['/home']);
|
||||||
} else {
|
} else {
|
||||||
this.router.navigate([state]);
|
this.router.navigate([state]);
|
||||||
|
|
|
@ -23,7 +23,7 @@ export class UsagestatsService {
|
||||||
|
|
||||||
getReportResponse(page: String, pageSize: String, params: URLSearchParams): Observable<ReportResponseWrapper> {
|
getReportResponse(page: String, pageSize: String, params: URLSearchParams): Observable<ReportResponseWrapper> {
|
||||||
const url = `${this.apiUrl}/sushilite/getReportResults/${page}/${pageSize}?${params}`;
|
const url = `${this.apiUrl}/sushilite/getReportResults/${page}/${pageSize}?${params}`;
|
||||||
console.log(`knocking on: ${url}`);
|
// console.log(`knocking on: ${url}`);
|
||||||
|
|
||||||
return this.httpClient.get<ReportResponseWrapper>(url, headerOptions);
|
return this.httpClient.get<ReportResponseWrapper>(url, headerOptions);
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,7 +61,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div *ngIf="reposOfUser && reposOfUser.length>0" class="menu_section border_top">
|
<div *ngIf="reposOfUser && reposOfUser.length>0" class="menu_section border_top">
|
||||||
<div class="sidebar_heading">REPOSITORIES</div>
|
<div class="sidebar_heading">DATASOURCES</div>
|
||||||
<ul>
|
<ul>
|
||||||
|
|
||||||
<li *ngFor="let repo of visibleReposOfUser" [routerLinkActive]="['current_section']" class="">
|
<li *ngFor="let repo of visibleReposOfUser" [routerLinkActive]="['current_section']" class="">
|
||||||
|
|
Loading…
Reference in New Issue