no message

This commit is contained in:
Ioannis Kalyvas 2018-03-21 15:15:06 +02:00
parent f1586bfef1
commit bdf4a76a21
56 changed files with 833 additions and 229 deletions

View File

@ -0,0 +1,58 @@
package eu.eudat.data.query;
import eu.eudat.data.query.definition.TableQuery;
import eu.eudat.data.query.definition.helpers.ColumnOrderings;
import eu.eudat.data.query.definition.helpers.Ordering;
import eu.eudat.queryable.QueryableList;
import eu.eudat.queryable.queryableentity.DataEntity;
import java.util.Arrays;
import java.util.Collection;
/**
* Created by ikalyvas on 3/21/2018.
*/
public class PaginationService {
public static <T extends DataEntity> QueryableList<T> applyPaging(QueryableList<T> items, TableQuery tableRequest) throws Exception {
if (tableRequest.getOrderings() != null) applyOrder(items, tableRequest);
if (tableRequest.getLength() != null) items.take(tableRequest.getLength());
if (tableRequest.getOffset() != null) items.skip(tableRequest.getOffset());
if (tableRequest.getSelection() != null && tableRequest.getSelection().getFields() != null && tableRequest.getSelection().getFields().length > 0)
items.withFields(Arrays.asList(tableRequest.getSelection().getFields()));
return items;
}
public static <T extends DataEntity> void applyOrder(QueryableList<T> items, TableQuery tableRequest) throws Exception {
ColumnOrderings columnOrderings = tableRequest.getOrderings();
for (Ordering ordering : columnOrderings.getFieldOrderings()) {
if (ordering.getOrderByType() == Ordering.OrderByType.ASC)
applyAscOrder(items, ordering);
if (ordering.getOrderByType() == Ordering.OrderByType.DESC) {
applyDescOrder(items, ordering);
}
}
return;
}
private static <T extends DataEntity> void applyAscOrder(QueryableList<T> items, Ordering ordering) {
if (ordering.getColumnType() == Ordering.ColumnType.COUNT) {
items.orderBy((builder, root) -> builder.asc(builder.size(root.<Collection>get(ordering.getFieldName()))));
} else if (ordering.getColumnType() == Ordering.ColumnType.JOIN_COLUMN) {
String[] fields = ordering.getFieldName().split(":");
items.orderBy((builder, root) -> builder.asc(root.get(fields[0]).get(fields[1])));
} else {
items.orderBy((builder, root) -> builder.asc(root.get(ordering.getFieldName())));
}
}
private static <T extends DataEntity> void applyDescOrder(QueryableList<T> items, Ordering ordering) {
if (ordering.getColumnType() == Ordering.ColumnType.COUNT) {
items.orderBy((builder, root) -> builder.desc(builder.size(root.<Collection>get(ordering.getFieldName()))));
} else if (ordering.getColumnType() == Ordering.ColumnType.JOIN_COLUMN) {
String[] fields = ordering.getFieldName().split(":");
items.orderBy((builder, root) -> builder.desc(root.get(fields[0]).get(fields[1])));
} else {
items.orderBy((builder, root) -> builder.desc(root.get(ordering.getFieldName())));
}
}
}

View File

@ -6,6 +6,9 @@ import eu.eudat.queryable.queryableentity.DataEntity;
/**
* Created by ikalyvas on 3/21/2018.
*/
public interface Collector<T extends DataEntity<T, K>, K> {
QueryableList<T> collect();
public interface Collector<T extends DataEntity> {
QueryableList<T> collect() throws Exception;
QueryableList<T> collect(QueryableList<T> repo) throws Exception;
}

View File

@ -7,7 +7,7 @@ import eu.eudat.queryable.queryableentity.DataEntity;
/**
* Created by ikalyvas on 3/21/2018.
*/
public interface CriteriaQuery<C extends Criteria<T>, T extends DataEntity<T, K>, K> extends Collector<T, K> {
public interface CriteriaQuery<C extends Criteria<T>, T extends DataEntity> extends Collector<T> {
QueryableList<T> applyCriteria();
}

View File

@ -4,10 +4,32 @@ import eu.eudat.data.dao.criteria.Criteria;
import eu.eudat.queryable.QueryableList;
import eu.eudat.queryable.queryableentity.DataEntity;
public abstract class Query<C extends Criteria<T>, T extends DataEntity<T, K>, K> implements CriteriaQuery<C, T, K> {
public abstract class Query<C extends Criteria<T>, T extends DataEntity> implements CriteriaQuery<C, T> {
private C criteria;
private QueryableList<T> query;
public static class QueryBuilder<C extends Criteria<T>, T extends DataEntity, Q extends Query<C, T>> {
private C criteria;
private QueryableList<T> query;
public QueryBuilder<C, T, Q> criteria(C criteria) {
this.criteria = criteria;
return this;
}
public QueryBuilder<C, T, Q> query(QueryableList<T> query) {
this.query = query;
return this;
}
public Q build(Class<Q> qClass) throws IllegalAccessException, InstantiationException {
Q q = qClass.newInstance();
q.setCriteria(criteria);
q.setQuery(query);
return q;
}
}
public QueryableList<T> getQuery() {
return query;
}
@ -25,7 +47,13 @@ public abstract class Query<C extends Criteria<T>, T extends DataEntity<T, K>, K
}
@Override
public QueryableList<T> collect() {
public QueryableList<T> collect() throws Exception {
return this.applyCriteria();
}
@Override
public QueryableList<T> collect(QueryableList<T> repo) throws Exception {
this.query = repo;
return this.applyCriteria();
}
}

View File

@ -7,6 +7,6 @@ import eu.eudat.queryable.queryableentity.DataEntity;
/**
* Created by ikalyvas on 3/21/2018.
*/
public interface TableCriteriaQuery<C extends Criteria<T>, T extends DataEntity<T, K>, K> extends CriteriaQuery<C, T, K> {
QueryableList<T> applyPaging(QueryableList<T> items);
public interface TableCriteriaQuery<C extends Criteria<T>, T extends DataEntity> extends CriteriaQuery<C, T> {
QueryableList<T> applyPaging(QueryableList<T> items) throws Exception;
}

View File

@ -8,7 +8,7 @@ import eu.eudat.queryable.QueryableList;
import eu.eudat.queryable.queryableentity.DataEntity;
public abstract class TableQuery<C extends Criteria<T>, T extends DataEntity<T, K>, K> extends Query<C, T, K> implements TableCriteriaQuery<C, T, K> {
public abstract class TableQuery<C extends Criteria<T>, T extends DataEntity<T, K>, K> extends Query<C, T> implements TableCriteriaQuery<C, T> {
private ColumnOrderings orderings;
private SelectionFields selection;
private Integer length;
@ -47,7 +47,12 @@ public abstract class TableQuery<C extends Criteria<T>, T extends DataEntity<T,
}
@Override
public QueryableList<T> collect() {
public QueryableList<T> collect() throws Exception {
return this.applyPaging(super.collect());
}
@Override
public QueryableList<T> collect(QueryableList<T> repo) throws Exception {
return this.applyPaging(super.collect(repo));
}
}

View File

@ -8,7 +8,7 @@ import eu.eudat.queryable.QueryableList;
import java.util.UUID;
public class DatasetWizardAutocompleteRequest extends Query<DatasetWizardUserDmpCriteria, DMP, UUID> {
public class DatasetWizardAutocompleteRequest extends Query<DatasetWizardUserDmpCriteria, DMP> {
@Override
public QueryableList<DMP> applyCriteria() {
QueryableList<DMP> query = this.getQuery().where((builder, root) -> builder.or(builder.equal(root.get("creator"), this.getCriteria().getUserInfo()), builder.isMember(this.getCriteria().getUserInfo(), root.get("users"))));

View File

@ -7,7 +7,7 @@ import eu.eudat.queryable.QueryableList;
import java.util.UUID;
public class DatasetProfileAutocompleteRequest extends Query<DatasetProfileCriteria,DatasetProfile,UUID> {
public class DatasetProfileAutocompleteRequest extends Query<DatasetProfileCriteria,DatasetProfile> {
@Override
public QueryableList<DatasetProfile> applyCriteria() {
QueryableList<DatasetProfile> query = this.getQuery();

View File

@ -7,7 +7,7 @@ import eu.eudat.queryable.QueryableList;
import java.util.UUID;
public class DatasetProfileWizardAutocompleteRequest extends Query<DatasetProfileWizardCriteria,DatasetProfile,UUID> {
public class DatasetProfileWizardAutocompleteRequest extends Query<DatasetProfileWizardCriteria,DatasetProfile> {
@Override
public QueryableList<DatasetProfile> applyCriteria() {
return null;

View File

@ -11,7 +11,7 @@ import java.util.Arrays;
import java.util.UUID;
public class DataManagementPlanCriteriaRequest extends Query<DataManagementPlanCriteria, DMP, UUID> {
public class DataManagementPlanCriteriaRequest extends Query<DataManagementPlanCriteria, DMP> {
@Override
public QueryableList<DMP> applyCriteria() {
QueryableList<DMP> query = this.getQuery();

View File

@ -7,7 +7,10 @@ import eu.eudat.queryable.QueryableList;
import java.util.UUID;
public class ProjectCriteriaRequest extends Query<ProjectCriteria,Project,UUID> {
public class ProjectCriteriaRequest extends Query<ProjectCriteria,Project> {
private ProjectCriteriaRequest() {
}
@Override
public QueryableList<Project> applyCriteria() {
QueryableList<Project> query = this.getQuery();

View File

@ -10,7 +10,7 @@ import java.util.UUID;
/**
* Created by ikalyvas on 3/6/2018.
*/
public class ResearcherCriteriaRequest extends Query<ResearcherCriteria,Researcher,UUID> {
public class ResearcherCriteriaRequest extends Query<ResearcherCriteria,Researcher> {
@Override
public QueryableList<Researcher> applyCriteria() {
QueryableList<Researcher> query = this.getQuery();

View File

@ -5,10 +5,8 @@ import eu.eudat.data.entities.UserInfo;
import eu.eudat.data.query.definition.Query;
import eu.eudat.queryable.QueryableList;
import java.util.UUID;
public class UserInfoRequestItem extends Query<UserInfoCriteria, UserInfo, UUID> {
public class UserInfoRequestItem extends Query<UserInfoCriteria, UserInfo> {
@Override
public QueryableList<UserInfo> applyCriteria() {
QueryableList<UserInfo> users = this.getQuery();

View File

@ -2,7 +2,7 @@ package eu.eudat.data.query.items.table.dmp;
import eu.eudat.data.dao.criteria.DataManagementPlanCriteria;
import eu.eudat.data.entities.DMP;
import eu.eudat.data.query.definition.Query;
import eu.eudat.data.query.PaginationService;
import eu.eudat.data.query.definition.TableQuery;
import eu.eudat.queryable.QueryableList;
import eu.eudat.queryable.types.FieldSelectionType;
@ -11,14 +11,9 @@ import eu.eudat.queryable.types.SelectionField;
import java.util.Arrays;
import java.util.UUID;
public class DataManagementPlanTableRequest extends TableQuery<DataManagementPlanCriteria,DMP,UUID> {
public class DataManagementPlanTableRequest extends TableQuery<DataManagementPlanCriteria, DMP, UUID> {
@Override
public QueryableList<DMP> applyCriteria() {
return null;
}
@Override
public QueryableList<DMP> applyPaging(QueryableList<DMP> items) {
QueryableList<DMP> query = this.getQuery();
if (this.getCriteria().getLike() != null && !this.getCriteria().getLike().isEmpty())
query.where((builder, root) -> builder.like(root.get("label"), "%" + this.getCriteria().getLike() + "%"));
@ -35,4 +30,9 @@ public class DataManagementPlanTableRequest extends TableQuery<DataManagementPla
query.where((builder, root) -> builder.notEqual(root.get("status"), DMP.DMPStatus.DELETED.getValue()));
return query;
}
@Override
public QueryableList<DMP> applyPaging(QueryableList<DMP> items) throws Exception {
return PaginationService.applyPaging(items, this);
}
}

View File

@ -129,7 +129,7 @@ public class DataManagementPlanManager {
ResearcherCriteria criteria = new ResearcherCriteria();
criteria.setLike(researcher.getReference());
List<eu.eudat.data.entities.Researcher> entries = researcherRepository.getWithCriteria(criteria).toList();
if (entries != null && !entries.isEmpty()) researcher.setId(entries.get(0).getId());
if (entries != null && !entries.isEmpty()) researcher.setId(entries.get(0).getId ());
else researcher = researcherRepository.createOrUpdate(researcher);
}
}

View File

@ -34,12 +34,14 @@ import { WelcomepageComponent } from '@app/welcomepage/welcomepage.component';
import { HelpContentService } from './services/help-content/help-content.service';
import { HelpContentComponent } from './help-content/help-content.component';
import { B2AccessLoginComponent } from './user-management/login/b2access/b2access-login.component';
import { RecentActivityComponent } from '@app/users/activity/recent-activity.component';
@NgModule({
declarations: [
AppComponent,
PageNotFoundComponent,
HomepageComponent,
RecentActivityComponent,
WelcomepageComponent,
HelpContentComponent,
B2AccessLoginComponent
@ -53,7 +55,6 @@ import { B2AccessLoginComponent } from './user-management/login/b2access/b2acces
loginProviders: [
LoginOptions.facebookOauth,
LoginOptions.googleOauth,
LoginOptions.nativeLogin,
LoginOptions.linkedInOauth,
LoginOptions.twitterOauth,
LoginOptions.b2Access

View File

@ -67,11 +67,9 @@
<!-- Column Definition: Submission Time -->
<ng-container cdkColumnDef="actions">
<mat-header-cell *matHeaderCellDef>{{'DATASET-LISTING.COLUMNS.ACTIONS' | translate}}</mat-header-cell>
<mat-cell *matCellDef="let row">
<mat-cell *matCellDef="let row" (click)="$event.stopPropagation()">
<mat-menu #actionsMenu="matMenu">
<button *ngIf="row.status==0" mat-menu-item (click)="rowClick(row.id)"><mat-icon>mode_edit</mat-icon>{{'DATASET-LISTING.ACTIONS.EDIT' | translate}}</button>
<button *ngIf="row.status==1" mat-menu-item (click)="rowClick(row.id)"><mat-icon>visibility</mat-icon>{{'DATASET-LISTING.ACTIONS.VIEW' | translate}}</button>
<button *ngIf="row.status==1" mat-menu-item (click)="makeItPublic(row.id)"><mat-icon>people_outline</mat-icon>{{'DATASET-LISTING.ACTIONS.MAKE-IT-PUBLIC' | translate}}</button>
<button *ngIf="row.status == 0" mat-menu-item ><mat-icon>mode_edit</mat-icon>{{'DATASET-LISTING.ACTIONS.EDIT' | translate}}</button>
</mat-menu>
<button mat-icon-button [matMenuTriggerFor]="actionsMenu">
<mat-icon>more_vert</mat-icon>
@ -80,7 +78,7 @@
</ng-container>
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
<mat-row *matRowDef="let row; columns: displayedColumns"></mat-row>
<mat-row *matRowDef="let row; columns: displayedColumns" (click)="rowClick(row.id)"></mat-row>
<!-- (click)="rowClick(row.id)" -->
</mat-table>

View File

@ -8,6 +8,7 @@ import { InvitationAcceptedComponent } from '../invitation-accepted/invitation-a
const routes: Routes = [
{ path: '', component: DataManagementPlanListingComponent },
{ path: 'viewversions/:groupId', component: DataManagementPlanListingComponent },
{ path: 'project/:projectId', component: DataManagementPlanListingComponent },
{ path: 'edit/:id', component: DataManagementPlanEditorComponent },
{ path: 'new', component: DataManagementPlanEditorComponent },
{ path: 'new_version/:id', component: DataManagementPlanWizardComponent, data: { clone: false } },

View File

@ -1,7 +1,7 @@
<div class="container-fluid">
<h3>{{'DMP-LISTING.TITLE' | translate}}</h3>
<app-dmp-criteria-component></app-dmp-criteria-component>
<app-dmp-criteria-component [showProject]="showProject"></app-dmp-criteria-component>
<mat-card class="mat-card">
<mat-card-header>
<mat-progress-bar *ngIf="dataSource?.isLoadingResults" mode="query"></mat-progress-bar>
@ -53,9 +53,8 @@
<ng-container cdkColumnDef="actions">
<mat-header-cell *matHeaderCellDef>{{'DMP-LISTING.COLUMNS.ACTIONS' | translate}}</mat-header-cell>
<mat-cell *matCellDef="let row">
<mat-menu #actionsMenu="matMenu">
<button mat-menu-item (click)="rowClick(row.id)"><mat-icon>mode_edit</mat-icon>{{'DMP-LISTING.ACTIONS.EDIT' | translate}}</button>
<mat-cell *matCellDef="let row" (click)="$event.stopPropagation()">
<mat-menu #actionsMenu="matMenu" >
<button mat-menu-item (click)="openShareDialog(row.id,row.label)"><mat-icon>share</mat-icon>{{'DMP-LISTING.ACTIONS.INVITE' | translate}}</button>
<button mat-menu-item (click)="addDataset(row.id)"><mat-icon>add</mat-icon>{{'DMP-LISTING.ACTIONS.ADD-DATASET' | translate}}</button>
<button mat-menu-item (click)="showDatasets(row.id, row.label)"><mat-icon>list</mat-icon>{{'DMP-LISTING.ACTIONS.DATASETS' | translate}}</button>
@ -70,7 +69,7 @@
</ng-container>
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
<mat-row *matRowDef="let row; columns: displayedColumns"></mat-row>
<mat-row *matRowDef="let row; columns: displayedColumns" (click)="rowClick(row.id);"></mat-row>
</mat-table>
<mat-paginator #paginator [length]="dataSource?.totalCount" [pageSizeOptions]="[10, 25, 100]">

View File

@ -14,6 +14,7 @@ import { DataSource } from "@angular/cdk/table";
import { Observable } from "rxjs/Observable";
import { DataManagementPlanRoutes } from '@app/dmps/dmps.routes';
import { DatasetRoutes } from '@app/datasets/dataset.routes';
import { ProjectModel } from '@app/models/projects/ProjectModel';
@ -33,7 +34,8 @@ export class DataManagementPlanListingComponent implements OnInit {
dataSource: DataManagementPlanDataSource | null;
displayedColumns: String[] = ['name', 'project', 'creationTime', 'organisations', 'version', 'numOfDatasets', 'actions'];
itemId: string;
projectId: string;
showProject: boolean;
constructor(
private dataManagementPlanService: DataManagementPlanService,
private router: Router,
@ -47,10 +49,20 @@ export class DataManagementPlanListingComponent implements OnInit {
ngOnInit() {
this.route.params.subscribe(params => {
this.itemId = params['groupId'];
this.criteria.setCriteria(this.getDefaultCriteria());
this.refresh();
this.criteria.setRefreshCallback(() => this.refresh());
if (params["projectId"]) {
this.projectId = params["projectId"];
this.showProject = false;
let project = new ProjectModel();
project.id = this.projectId;
this.criteria.setCriteria({ like: null, projects: [project], groupIds: null, allVersions: false })
this.refresh();
this.criteria.setRefreshCallback(() => this.refresh());
} else {
this.itemId = params['groupId'];
this.criteria.setCriteria(this.getDefaultCriteria());
this.refresh();
this.criteria.setRefreshCallback(() => this.refresh());
}
})
}
@ -67,12 +79,12 @@ export class DataManagementPlanListingComponent implements OnInit {
this.router.navigate(['/datasets/new/' + rowId]);
}
showDatasets(rowId: String, rowLabel:String) {
this.router.navigate(['/datasets/dmp/' + rowId, {dmpLabel:rowLabel}]);
showDatasets(rowId: String, rowLabel: String) {
this.router.navigate(['/datasets/dmp/' + rowId, { dmpLabel: rowLabel }]);
}
newVersion(rowId: String, rowLabel:String) {
this.router.navigate(['/dmps/new_version/' + rowId, {dmpLabel:rowLabel}]);
newVersion(rowId: String, rowLabel: String) {
this.router.navigate(['/dmps/new_version/' + rowId, { dmpLabel: rowLabel }]);
}
viewVersions(rowId: String) {

View File

@ -1,99 +1,29 @@
<div class="main-panel" id="main-panel">
<div class="container">
<div class="row" style="margin-top: 30px">
<div class="col-lg-3 col-md-3 col-sm-6 col-xs-12 col-md-offset-1">
<app-figurecard
title={{dashboardStatisticsData.totalProjectCount}}
headerIcon="list"
category="Projects"
[hasFootContent]="this.isAuthenticated()"
footContent="Open Projects"
routelLink= '/projects'
footerIcon="open_in_new"
linearColor="linear-gradient(60deg, #ffa726, #fb8c00)"
boxShadow="0 4px 20px 0 rgba(0, 0, 0, 0.14), 0 7px 10px -5px rgba(255, 152, 0, 0.4)">
</app-figurecard>
</div>
<div class="col-lg-3 col-md-3 col-sm-6 col-xs-12">
<app-figurecard
title={{dashboardStatisticsData.totalDataManagementPlanCount}}
headerIcon="mode_edit"
category="DMPs"
[hasFootContent]="this.isAuthenticated()"
footContent="Open DMPs"
routelLink= '/dmps'
footerIcon="open_in_new"
linearColor="linear-gradient(60deg, #ef5350, #e53935)"
boxShadow="0 4px 20px 0px rgba(0, 0, 0, 0.14), 0 7px 10px -5px rgba(244, 67, 54, 0.4)">
</app-figurecard>
</div>
<div class="col-lg-3 col-md-3 col-sm-6 col-xs-12">
<app-figurecard
title={{dashboardStatisticsData.totalDataSetCount}}
headerIcon="subject"
category="Datasets"
[hasFootContent]="this.isAuthenticated()"
footContent="Open Datasets"
routelLink= '/datasets'
footerIcon="open_in_new"
linearColor="linear-gradient(60deg, #26c6da, #00acc1)"
boxShadow="0 4px 20px 0px rgba(0, 0, 0, 0.14), 0 7px 10px -5px rgba(0, 188, 212, 0.4)">
</app-figurecard>
</div>
</div>
<div class="container">
<div class="row" style="margin-top: 30px">
<div class="col-lg-3 col-md-3 col-sm-6 col-xs-12 col-md-offset-1">
<app-figurecard title={{dashboardStatisticsData.totalProjectCount}} headerIcon="list" [category]="this.isAuthenticated() ? 'My Projects' : 'Projects'"
[hasFootContent]="this.isAuthenticated()" [footContent]="this.isAuthenticated() ? 'Open My Projects' : 'Open Projects'"
routelLink='/projects' footerIcon="open_in_new" linearColor="linear-gradient(60deg, #ffa726, #fb8c00)" boxShadow="0 4px 20px 0 rgba(0, 0, 0, 0.14), 0 7px 10px -5px rgba(255, 152, 0, 0.4)">
</app-figurecard>
</div>
<!-- <div class="container">
<div class="row page-title">
<div class="col-md-8 col-md-offset-2">
<div class="row">
<div class="col-md-4 page-title">
<div class="card card-raised">
<h6>Projects</h6>
<div class="icon">
<i class="material-icons">list</i>
</div>
<h3 class="card-title">{{dashboardStatisticsData.totalProjectCount}}</h3>
<p class="card-description text-center">
OpenAIRE projects
</p>
<button md-raised-button class="btn btn-rose btn-round" [routerLink]=" ['/projects'] ">OPEN PROJECTS</button>
</div>
</div>
<div class="col-md-4 page-title">
<div class="card card-raised">
<h6>DMPs</h6>
<div class="icon">
<i class="material-icons">mode_edit</i>
</div>
<h3 class="card-title">{{dashboardStatisticsData.totalDataManagementPlanCount}}</h3>
<p class="card-description text-center">
My DMPs
</p>
<button md-raised-button class="btn btn-rose btn-round" [routerLink]=" ['/dmps'] ">OPEN DMPs</button>
</div>
</div>
<div class="col-md-4 page-title">
<div class="card card-raised">
<h6>Datasets</h6>
<div class="icon">
<i class="material-icons">subject</i>
</div>
<h3 class="card-title">{{dashboardStatisticsData.totalDataSetCount}}</h3>
<p class="card-description text-center">
My Datasets
</p>
<button md-raised-button class="btn btn-rose btn-round" [routerLink]=" ['/datasets'] ">OPEN DATASETS</button>
</div>
</div>
</div>
<div class="col-lg-3 col-md-3 col-sm-6 col-xs-12">
<app-figurecard title={{dashboardStatisticsData.totalDataManagementPlanCount}} headerIcon="mode_edit" [category]="this.isAuthenticated() ? 'My DMPs' : 'DMPs'"
[hasFootContent]="this.isAuthenticated()" [footContent]="this.isAuthenticated() ? 'Open My DMPs' : 'Open DMPs'"
routelLink='/dmps' footerIcon="open_in_new" linearColor="linear-gradient(60deg, #ef5350, #e53935)" boxShadow="0 4px 20px 0px rgba(0, 0, 0, 0.14), 0 7px 10px -5px rgba(244, 67, 54, 0.4)">
</app-figurecard>
</div>
<div class="col-lg-3 col-md-3 col-sm-6 col-xs-12">
<app-figurecard title={{dashboardStatisticsData.totalDataSetCount}} headerIcon="subject" [category]="this.isAuthenticated() ? 'My Datasets' : 'Datasets'"
[hasFootContent]="this.isAuthenticated()" [footContent]="this.isAuthenticated() ? 'Open My Datasets' : 'Open Datasets'"
routelLink='/datasets' footerIcon="open_in_new" linearColor="linear-gradient(60deg, #26c6da, #00acc1)" boxShadow="0 4px 20px 0px rgba(0, 0, 0, 0.14), 0 7px 10px -5px rgba(0, 188, 212, 0.4)">
</app-figurecard>
</div>
</div>
</div> -->
<!-- <app-dataset-listing-component></app-dataset-listing-component> -->
<div *ngIf="this.isAuthenticated()" class="row" style="margin-top: 30px">
<div class="col-lg-9 col-md-12 col-sm-12 col-xs-12 col-md-offset-1">
<app-recent-activity></app-recent-activity>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,16 @@
import { Serializable } from "@app/models/Serializable";
export class ContentFile implements Serializable<ContentFile>{
private filename: string;
private id: string;
private location: string;
private type: string;
fromJSONObject(item: any): ContentFile {
this.filename = item.filename;
this.id = item.id;
this.location = item.location
this.type = item.type
return this;
}
}

View File

@ -1,4 +1,8 @@
import { Serializable } from "../Serializable";
import { ContentFile } from "@app/models/files/ContentFile";
import { JsonSerializer } from "@app/utilities/JsonSerializer";
import { UrlListingComponent } from "@app/shared/components/url-listing/url-listing.component";
import { UrlListingItem } from "@app/shared/components/url-listing/UrlListingItem";
export class ProjectListingModel implements Serializable<ProjectListingModel> {
public id: String;
@ -10,18 +14,21 @@ export class ProjectListingModel implements Serializable<ProjectListingModel> {
public startDate: Date;
public endDate: Date;
public description: String;
public files: ContentFile[] = new Array();
public dmps: UrlListingItem[] = new Array();
fromJSONObject(item: any): ProjectListingModel {
this.id = item.id;
this.label = item.label;
this.abbreviation = item.abbreviation;
this.reference = item.reference;
this.uri = item.uri;
this.status = item.status;
this.startDate = new Date(item.startdate);
this.endDate = new Date(item.enddate);
this.description = item.description;
this.abbreviation = item.abbreviation;
this.reference = item.reference;
this.uri = item.uri;
this.status = item.status;
this.startDate = new Date(item.startdate);
this.endDate = new Date(item.enddate);
this.description = item.description;
this.files = JsonSerializer.fromJSONArray(item.files, ContentFile)
this.dmps = JsonSerializer.fromJSONArray(item.dmps,UrlListingItem)
return this;
}
}

View File

@ -4,6 +4,8 @@ import { FormGroup, FormBuilder, FormControl, Validators } from "@angular/forms"
import { BackendErrorValidator } from "../../utilities/validators/BackendErrorValidator";
import { BaseErrorModel } from "../error/BaseErrorModel";
import { Status } from "../Status";
import { ContentFile } from "@app/models/files/ContentFile";
import { JsonSerializer } from "@app/utilities/JsonSerializer";
export class ProjectModel implements Serializable<ProjectModel> {
public id: String;
@ -15,7 +17,8 @@ export class ProjectModel implements Serializable<ProjectModel> {
public startDate: Date;
public endDate: Date;
public description: String;
public contentUrl: string;
public files: ContentFile[] = new Array();
public errorModel: BaseErrorModel = new BaseErrorModel();
fromJSONObject(item: any): ProjectModel {
@ -28,7 +31,8 @@ export class ProjectModel implements Serializable<ProjectModel> {
this.startDate = new Date(item.startDate);
this.endDate = new Date(item.endDate);
this.description = item.description;
this.contentUrl = item.contentUrl;
this.files = JsonSerializer.fromJSONArray(item.files,ContentFile)
return this;
}
@ -43,7 +47,8 @@ export class ProjectModel implements Serializable<ProjectModel> {
status: [{ value: this.status, disabled: disabled }, context.getValidation('status').validators],
description: [{ value: this.description, disabled: disabled }, context.getValidation('description').validators],
startDate: [{ value: this.startDate, disabled: disabled }, context.getValidation('startDate').validators],
endDate: [{ value: this.endDate, disabled: disabled }, context.getValidation('endDate').validators]
endDate: [{ value: this.endDate, disabled: disabled }, context.getValidation('endDate').validators],
files: [{ value: this.files, disabled: disabled }, context.getValidation('files').validators]
});
return formGroup;
@ -59,6 +64,7 @@ export class ProjectModel implements Serializable<ProjectModel> {
baseContext.validation.push({ key: 'description', validators: [Validators.required, BackendErrorValidator(this.errorModel, 'description')] });
baseContext.validation.push({ key: 'startDate', validators: [Validators.required, BackendErrorValidator(this.errorModel, 'startDate')] });
baseContext.validation.push({ key: 'endDate', validators: [Validators.required, BackendErrorValidator(this.errorModel, 'endDate')] });
baseContext.validation.push({ key: 'files', validators: [Validators.required, BackendErrorValidator(this.errorModel, 'files')] });
return baseContext;
}

View File

@ -1,8 +1,11 @@
<div class="project-editor">
<form *ngIf="formGroup" (ngSubmit)="formSubmit()" [formGroup]="formGroup">
<mat-card>
<mat-card-title *ngIf="isNew">{{'PROJECT-EDITOR.TITLE.NEW' | translate}}</mat-card-title>
<mat-card-title *ngIf="!isNew">{{formGroup.get('label').value}}</mat-card-title>
<mat-card-header>
<mat-card-title *ngIf="isNew">{{'PROJECT-EDITOR.TITLE.NEW' | translate}}</mat-card-title>
<mat-card-title *ngIf="!isNew">{{formGroup.get('label').value}}</mat-card-title>
</mat-card-header>
<mat-card-content>
<mat-form-field>
@ -56,7 +59,18 @@
<mat-error *ngIf="formGroup.get('description').errors?.backendError">{{errorModel.description}}</mat-error>
<mat-error *ngIf="formGroup.get('description').errors?.required">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
</mat-form-field>
<p>{{'PROJECT-EDITOR.FIELDS.LOGO' | translate}}</p>
<table class="logo-table full-width">
<tr>
<td>
<img mat-card-avatar [src]="host+'files/'+formGroup.get('files').value[0].id+'?location='+formGroup.get('files').value[0].location+'&type='+formGroup.get('files').value[0].type">
</td>
<td>
<app-fileuploader-component [form]="formGroup.get('files')" [label]="'FILE-UPLOADER.PROJECT'" [fileUploader]="uploaderService"></app-fileuploader-component>
</td>
</tr>
</table>
<div layout="row" class="full-width text-right" align="end">
<button mat-raised-button color="primary" (click)="cancel()" type="button">{{'PROJECT-EDITOR.ACTIONS.CANCEL' | translate}}</button>
<button mat-raised-button color="primary" type="submit">{{'PROJECT-EDITOR.ACTIONS.SAVE' | translate}}</button>

View File

@ -6,6 +6,15 @@
table-layout: fixed;
}
.logo-table {
table-layout: fixed;
display: inline-block;
td{
padding: 3px;
}
}
.table-card .mat-grid-tile {
background: rgba(0, 0, 0, 0.32);
}

View File

@ -12,6 +12,8 @@ import { FormGroup, AbstractControl, FormControl, FormArray } from "@angular/for
import { SnackBarNotificationComponent } from "../../shared/components/notificaiton/snack-bar-notification.component";
import { BaseErrorModel } from "../../models/error/BaseErrorModel";
import { TdDialogService } from "@covalent/core";
import { ProjectFileUploaderService } from "@app/services/files/project-file-uploader.service";
import { HostConfiguration } from "@app/app.constants";
@ -19,7 +21,7 @@ import { TdDialogService } from "@covalent/core";
selector: 'app-project-editor-component',
templateUrl: 'project-editor.component.html',
styleUrls: ['./project-editor.component.scss'],
providers: [ProjectService],
providers: [ProjectService, ProjectFileUploaderService],
encapsulation: ViewEncapsulation.None
})
export class ProjectEditorComponent implements AfterViewInit {
@ -27,14 +29,15 @@ export class ProjectEditorComponent implements AfterViewInit {
isNew = true;
project: ProjectModel;
formGroup: FormGroup = null;
host = HostConfiguration.Server;
constructor(
private projectService: ProjectService,
private route: ActivatedRoute,
public snackBar: MatSnackBar,
public router: Router,
public language: TranslateService,
private dialogService: TdDialogService
private dialogService: TdDialogService,
private uploaderService: ProjectFileUploaderService
) {
}
@ -135,18 +138,18 @@ export class ProjectEditorComponent implements AfterViewInit {
}
public validateAllFormFields(formControl: AbstractControl) {
if (formControl instanceof FormControl) {
formControl.updateValueAndValidity({ emitEvent: false })
} else if (formControl instanceof FormGroup) {
Object.keys(formControl.controls).forEach(item => {
const control = formControl.get(item);
this.validateAllFormFields(control);
})
}
else if (formControl instanceof FormArray) {
formControl.controls.forEach(item => {
this.validateAllFormFields(item);
})
}
}
if (formControl instanceof FormControl) {
formControl.updateValueAndValidity({ emitEvent: false })
} else if (formControl instanceof FormGroup) {
Object.keys(formControl.controls).forEach(item => {
const control = formControl.get(item);
this.validateAllFormFields(control);
})
}
else if (formControl instanceof FormArray) {
formControl.controls.forEach(item => {
this.validateAllFormFields(item);
})
}
}
}

View File

@ -9,6 +9,13 @@
<mat-table [dataSource]="dataSource" matSort (matSortChange)="refresh()">
<ng-container cdkColumnDef="avatar">
<mat-header-cell *matHeaderCellDef mat-sort-header="avatar">{{'PROJECT-LISTING.COLUMNS.AVATAR' | translate}}</mat-header-cell>
<mat-cell *matCellDef="let row">
<img mat-card-avatar [src]="host+'files/'+row.files[0].id+'?location='+row.files[0].location+'&type='+row.files[0].type">
</mat-cell>
</ng-container>
<!-- Column Definition: Name -->
<ng-container cdkColumnDef="name">
<mat-header-cell *matHeaderCellDef mat-sort-header="label">{{'PROJECT-LISTING.COLUMNS.NAME' | translate}}</mat-header-cell>
@ -33,6 +40,15 @@
<mat-cell *matCellDef="let row"> {{row.endDate | date:'shortDate'}} </mat-cell>
</ng-container>
<!-- Column Definition: End -->
<ng-container cdkColumnDef="dmps">
<mat-header-cell *matHeaderCellDef mat-sort-header="dmps">{{'PROJECT-LISTING.COLUMNS.DMPS' | translate}}</mat-header-cell>
<mat-cell *matCellDef="let row" (click)="$event.stopPropagation()">
<app-url-listing [items]="row.dmps" [urlLimit]="5"></app-url-listing>
</mat-cell>
</ng-container>
<!-- Column Definition: Submission Time -->
<!-- <ng-container cdkColumnDef="actions">
<mat-header-cell *matHeaderCellDef>{{'PROJECT-LISTING.COLUMNS.ACTIONS' | translate}}</mat-header-cell>

View File

@ -9,6 +9,7 @@ import { TranslateService } from "@ngx-translate/core";
import { DataSource } from "@angular/cdk/table";
import { Observable } from "rxjs/Observable";
import { ProjectCriteriaComponent } from '@app/shared/components/criteria/projects/projects-criteria.component';
import { HostConfiguration } from '@app/app.constants';
@Component({
selector: 'app-project-listing-component',
@ -23,8 +24,9 @@ export class ProjectListingComponent implements OnInit {
@ViewChild(MatSort) sort: MatSort;
@ViewChild(ProjectCriteriaComponent) criteria: ProjectCriteriaComponent;
host = HostConfiguration.Server;
dataSource: ProjectDataSource | null;
displayedColumns: String[] = ['name', 'abbreviation', 'start', 'end'];
displayedColumns: String[] = ['avatar', 'name', 'abbreviation', 'start', 'end', "dmps"];
constructor(
private projectService: ProjectService,
@ -117,7 +119,14 @@ export class ProjectDataSource extends DataSource<ProjectListingModel> {
.map(result => {
if (!result) { return []; }
if (this._paginator.pageIndex === 0) { this.totalCount = result.totalCount; }
return result.data;
return result.data.map(item => {
item.dmps.map(dmp => {
dmp.url = "dmps/edit/" + dmp.url;
dmp.all = "dmps/project/" + item.id
return dmp;
})
return item;
});
});
}

View File

@ -7,7 +7,7 @@ import { AutocompleteLookupItem } from '@app/models/autocomplete/AutocompleteLoo
import { Observable } from 'rxjs/Observable';
@Injectable()
export class DatasetProfileService implements OnInit {
export class DatasetProfileService {
private actionUrl: string;
private headers: HttpHeaders;

View File

@ -0,0 +1,34 @@
import 'rxjs/add/operator/map';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { HostConfiguration } from './../../app.constants';
import { BaseHttpService } from '../../utilities/cite-http-service-module/base-http.service';
import { Observable } from 'rxjs/Observable';
import { ExternalSourcesItemModel } from '../../models/external-sources/ExternalSourcesItemModel';
import { BaseCriteria } from '@app/models/criteria/BaseCriteria';
import { RequestItem } from '@app/models/criteria/RequestItem';
import { ResearcherCriteria } from '@app/models/criteria/researchers/ResearcherCriteria';
import { FileUploader } from '@app/shared/components/file-uploader/FileUploader';
import { ContentFile } from '@app/models/files/ContentFile';
@Injectable()
export class ProjectFileUploaderService implements FileUploader {
private actionUrl: string;
private headers: HttpHeaders;
constructor(private http: BaseHttpService) {
this.actionUrl = HostConfiguration.Server + 'files/';
this.headers = new HttpHeaders();
this.headers = this.headers.set('Content-Type', 'application/json');
this.headers = this.headers.set('Accept', 'application/json');
}
uploadFile(formData: FormData): Observable<ContentFile> {
return this.http.post(this.actionUrl + "upload", formData, this.headers);
}
}

View File

@ -43,4 +43,8 @@ export class UserReferenceService {
delete(id: String): Observable<any> {
return this.http.delete<any>(this.actionUrl + id, { headers: this.headers });
}
getRecentActivity(): Observable<any[]> {
return this.http.get<any[]>(this.actionUrl + "recentActivity", { headers: this.headers });
}
}

View File

@ -8,7 +8,7 @@
<mat-error *ngIf="baseErrorModel?.like">{{baseErrorModel['Criteria.like']}}</mat-error>
</mat-form-field>
</div>
<div class="col-md-6">
<div *ngIf="showProject" class="col-md-6">
<td-chips color="accent" [items]="filteredProjects" [(ngModel)]="criteria.projects" (ngModelChange)="controlModified()" placeholder="{{'CRITERIA.DMP.PROJECTS' | translate}}"
(inputChange)="filterProjects($event)" requireMatch>
<ng-template td-chip let-chip="chip">

View File

@ -1,5 +1,5 @@
import { TranslateService } from '@ngx-translate/core';
import { Component, OnInit } from '@angular/core';
import { Component, OnInit, Input } from '@angular/core';
import { FormControl, FormGroup, FormBuilder, Validators } from '@angular/forms';
import { BaseCriteriaComponent } from '../base/base-criteria.component';
import { ValidationContext, Validation } from '../../../../utilities/validators/ValidationContext';
@ -21,6 +21,8 @@ import { create } from 'domain';
export class DataManagementPlanCriteriaComponent extends BaseCriteriaComponent implements OnInit {
@Input()
showProject: boolean;
public criteria: DataManagementPlanCriteria = new DataManagementPlanCriteria();
filteringProjectsAsync: boolean = false;
filteredProjects: ProjectModel[];
@ -56,24 +58,24 @@ export class DataManagementPlanCriteriaComponent extends BaseCriteriaComponent i
}
filterProjects(value: string): void {
this.filteredProjects = undefined;
if (value) {
this.filteringProjectsAsync = true;
let requestItem: RequestItem<ProjectCriteria> = new RequestItem();
let criteria: ProjectCriteria = new ProjectCriteria();
criteria.like = value;
requestItem.criteria = criteria;
this.projectService.get(requestItem).subscribe(items => {
this.filteredProjects = items;
this.filteringProjectsAsync = false;
// this.filteredProjects = items.filter((filteredObj: any) => {
// return this.objectsModel ? this.objectsModel.indexOf(filteredObj) < 0 : true;
// });
});
this.filteringProjectsAsync = true;
let requestItem: RequestItem<ProjectCriteria> = new RequestItem();
let criteria: ProjectCriteria = new ProjectCriteria();
criteria.like = value;
requestItem.criteria = criteria;
this.projectService.get(requestItem).subscribe(items => {
this.filteredProjects = items;
this.filteringProjectsAsync = false;
// this.filteredProjects = items.filter((filteredObj: any) => {
// return this.objectsModel ? this.objectsModel.indexOf(filteredObj) < 0 : true;
// });
});
}
}
}
}

View File

@ -0,0 +1,6 @@
import { Observable } from "rxjs";
import { ContentFile } from "@app/models/files/ContentFile";
export interface FileUploader {
uploadFile(formData: FormData): Observable<ContentFile>;
}

View File

@ -0,0 +1,11 @@
<td-file-upload #fileUpload defaultColor="primary" activeColor="primary" cancelColor="primary" (select)="selectEvent($event)"
(upload)="uploadEvent($event)" (cancel)="cancelEvent()" accept=".jpg,.png" [disabled]="disabled" multiple>
<mat-icon>file_upload</mat-icon>
<span>{{ files?.name }}</span>
<ng-template td-file-input-label>
<mat-icon>attach_file</mat-icon>
<span>
{{label | translate}}
</span>
</ng-template>
</td-file-upload>

View File

@ -0,0 +1,57 @@
import { Component, Input, OnInit } from "@angular/core";
import { FileUploader } from "@app/shared/components/file-uploader/FileUploader";
import { FormControl } from "@angular/forms";
@Component({
selector: 'app-fileuploader-component',
templateUrl: './file-uploader.component.html'
})
export class FileUploaderComponent implements OnInit {
files: File | FileList;
disabled: boolean = false;
fileSelectMultipleMsg: string = 'No file(s) selected yet.';
@Input()
public label: string = 'FILE-UPLOADER.DEFAULT';
@Input()
public fileUploader: FileUploader;
@Input()
form: FormControl;
ngOnInit(): void {
console.log(this.form)
}
selectEvent(files: FileList | File): void {
this.label = 'FILE-UPLOADER.UPLOAD'
if (files instanceof FileList) {
let names: string[] = [];
for (let i: number = 0; i < files.length; i++) {
names.push(files[i].name);
}
this.fileSelectMultipleMsg = names.join(',');
} else {
this.fileSelectMultipleMsg = files.name;
}
}
uploadEvent(files: FileList | File): void {
let formdata: FormData = new FormData();
if (files instanceof FileList) {
for (let i: number = 0; i < files.length; i++) {
formdata.append('file', files[i]);
}
} else {
formdata.append('file', files);
}
this.fileUploader.uploadFile(formdata).subscribe(files => this.form.patchValue(files));
}
cancelEvent(): void {
}
}

View File

@ -0,0 +1,14 @@
import { Serializable } from "@app/models/Serializable";
export class UrlListingItem implements Serializable<UrlListingItem>{
public label: string;
public url: string;
public all: string;
fromJSONObject(item: any): UrlListingItem {
this.label = item.label;
this.url = item.url;
return this;
}
}

View File

@ -0,0 +1,4 @@
<div *ngFor="let item of items | limitTo:urlLimit">
<a [href]="item.url">{{item.label}}</a>
</div>
<a *ngIf="this.items.length > this.urlLimit" [href]="items[0].all">{{'URL-LISTING-COMPONENT.SHOW-MORE'|translate}}</a>

View File

@ -0,0 +1,19 @@
import { Component, Input } from "@angular/core";
import { UrlListingItem } from "@app/shared/components/url-listing/UrlListingItem";
@Component({
selector: 'app-url-listing',
templateUrl: './url-listing.component.html'
})
export class UrlListingComponent {
@Input()
items: UrlListingItem[];
@Input()
urlLimit: number = 3;
ngOnInit() {
console.log(this.items.length > this.urlLimit)
}
}

View File

@ -32,7 +32,7 @@ import {
} from '@angular/material';
import { CdkTableModule } from '@angular/cdk/table';
import { SnackBarNotificationComponent } from '../components/notificaiton/snack-bar-notification.component';
import { CovalentLayoutModule, CovalentChipsModule, CovalentDialogsModule } from '@covalent/core';
import { CovalentLayoutModule, CovalentChipsModule, CovalentDialogsModule, CovalentFileModule } from '@covalent/core';
@NgModule({
imports: [
@ -66,6 +66,7 @@ import { CovalentLayoutModule, CovalentChipsModule, CovalentDialogsModule } from
CovalentLayoutModule,
CovalentChipsModule,
CovalentDialogsModule,
CovalentFileModule,
MatStepperModule,
MatRadioModule,
MatMenuModule,

View File

@ -0,0 +1,10 @@
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({ name: 'limitTo' })
export class NgForLimitPipe implements PipeTransform {
transform(items: any[], limit: number) {
if (items.length > limit) {
return items.slice(0, limit);
} else return items;
}
}

View File

@ -13,6 +13,9 @@ import { DatasetCriteriaComponent } from './components/criteria/datasets/dataset
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { DataManagementPlanCriteriaComponent } from './components/criteria/data-management-plan/dmp-criteria.component';
import { AutocompleteChipComponent } from '@app/shared/components/autocompleteChips/autocompleteChips.component';
import { FileUploaderComponent } from '@app/shared/components/file-uploader/file-uploader.component';
import { UrlListingComponent } from '@app/shared/components/url-listing/url-listing.component';
import { NgForLimitPipe } from '@app/shared/pipes/ngforlimit/NgForLimit.pipe';
@NgModule({
imports: [
@ -33,7 +36,10 @@ import { AutocompleteChipComponent } from '@app/shared/components/autocompleteCh
AutocompleteComponent,
FigurecardComponent,
BaseCriteriaComponent,
AutocompleteChipComponent
FileUploaderComponent,
AutocompleteChipComponent,
UrlListingComponent,
NgForLimitPipe
],
exports: [
@ -46,7 +52,10 @@ import { AutocompleteChipComponent } from '@app/shared/components/autocompleteCh
AutocompleteComponent,
FigurecardComponent,
BaseCriteriaComponent,
AutocompleteChipComponent
FileUploaderComponent,
AutocompleteChipComponent,
UrlListingComponent,
NgForLimitPipe
],
entryComponents: [
]

View File

@ -0,0 +1,34 @@
<div class="container">
<div class="container">
<div class="row">
<div class="row col-md-6 col-sm-6 col-md-offset-3 col-sm-offset-3">
<div class="card col-md-8 col-md-offset-2">
<div class="card-header">
<h4>Login</h4>
<div class="social-btns">
<div>
<div class="card-form">
<div class="form-row">
<i class="material-icons">email</i>
<mat-input-container color="accent">
<input type="text" [(ngModel)]="credential.username" matInput placeholder="Email address" />
</mat-input-container>
</div>
<div class="form-row">
<i class="material-icons">lock_outline</i>
<mat-input-container color="accent">
<input type="password" [(ngModel)]="credential.secret" matInput placeholder="Password" />
</mat-input-container>
</div>
</div>
<div class="card-footer">
<button mat-button (click)="nativeLogin()">LOGIN</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,139 @@
.container{
padding: 15px 30px;
}
.card{
box-shadow: 0 1px 4px 0 rgba(0, 0, 0, 0.14);
border-radius: 6px;
color: rgba(0,0,0, 0.87);
background: #fff;
}
.card-raised{
box-shadow: 0 10px 30px -12px rgba(0, 0, 0, 0.42), 0 4px 25px 0px rgba(0, 0, 0, 0.12), 0 8px 10px -5px rgba(0, 0, 0, 0.2);
}
.page-title{
margin-top: 40px;
}
@media (min-width: 1200px) {
.container {
width: 100%;
}
}
@media (min-width: 992px) {
.container {
width: 100%;
}
}
@media (min-width: 768px) {
.container {
width: 100%;
}
}
.container{
height: 100%;
position: relative;
z-index: 1;
}
.card{
position: relative;
padding: 20px;
display: flex;
flex-direction: column;
align-items: center;
margin-top: 90px;
top: -90px;
-webkit-animation-name: card;
-moz-animation-name: card;
-o-animation-name: card;
animation-name: card;
-webkit-animation-duration: 600ms;
-moz-animation-duration: 600ms;
-o-animation-duration: 600ms;
animation-duration: 600ms;
-webkit-animation-fill-mode: forwards;
-moz-animation-fill-mode: forwards;
-o-animation-fill-mode: forwards;
animation-fill-mode: forwards;
}
@-webkit-keyframes card {
from {top: -40px;}
to {top: 0;}
}
@keyframes card {
from {top: -40px;}
to {top: 0;}
}
.card-header{
position: relative;
overflow: hidden;
top: -40px;
width: 100%;
padding: 25px;
border-radius: 3px;
background: linear-gradient(60deg, #ec407a, #d81b60);
box-shadow: 0 4px 20px 0px rgba(0, 0, 0, 0.14), 0 7px 10px -5px rgba(233, 30, 99, 0.4);
display: flex;
flex-direction: column;
align-items: center;
}
.card-header h4{
font-weight: 400;
color: #fff;
margin-bottom: 25px;
margin-top: 5px;
}
.social-btns i{
font-size: 21px;
color: #fff;
}
.social-btns button{
margin: 0 8px;
}
.tip{
margin-top: -20px;
}
.form-row, .card-form, .mat-input-container{
width: 100%;
}
.card-form{
padding: 5px;
}
.form-row{
position: relative;
display: flex;
align-items: center;
margin-top: 13px;
}
.form-row i{
position: relative;
top: -5px;
margin-right: 15px;
color: #555;
}
.card-footer{
margin: 10px;
}
.card-footer button{
color: #e91e63;
}

View File

@ -0,0 +1,36 @@
import { Credential } from '../../models/login/Credential';
import { LoginOptions } from '../utilties/LoginOptions';
import { LoginService } from '../utilties/login-service';
import { HttpClient } from '@angular/common/http';
import { Component, OnInit, ElementRef, AfterViewInit, VERSION, Injectable, NgZone } from '@angular/core';
import { Router, ActivatedRoute, Params } from "@angular/router";
import { MatPaginator, MatSort, MatSnackBar } from "@angular/material";
import { TranslateService } from "@ngx-translate/core";
@Component({
selector: 'admin-login',
templateUrl: './admin-login.component.html',
styleUrls: ['./admin-login.component.scss']
})
export class AdminLoginComponent implements OnInit {
public auth2: any;
public credential: Credential = new Credential()
constructor(
private loginService: LoginService
) {
}
ngOnInit() {
}
public nativeLogin() {
this.loginService.nativeLogin(this.credential);
}
}

View File

@ -10,6 +10,7 @@ import { LoginService } from './utilties/login-service';
import { LoginComponent } from './login/login.component';
import { ModuleWithProviders, NgModule } from "@angular/core";
import { CommonModule } from '@angular/common';
import { AdminLoginComponent } from '@app/user-management/admin-login/admin-login.component';
@NgModule({
imports: [
@ -21,12 +22,14 @@ import { CommonModule } from '@angular/common';
declarations: [
LoginComponent,
LinkedInLoginComponent,
TwitterLoginComponent
TwitterLoginComponent,
AdminLoginComponent
],
exports: [
LoginComponent,
LinkedInLoginComponent,
TwitterLoginComponent
TwitterLoginComponent,
AdminLoginComponent
],
providers: [LoginService]
})

View File

@ -2,9 +2,11 @@ import { TwitterLoginComponent } from './login/twitter-login/twitter-login.compo
import { LinkedInLoginComponent } from './login/linkedin-login/linkedin-login.component';
import { LoginComponent } from './login/login.component';
import { RouterModule, Routes } from '@angular/router';
import { AdminLoginComponent } from '@app/user-management/admin-login/admin-login.component';
const routes: Routes = [
{ path: 'login', component: LoginComponent },
{ path: 'login/admin', component: AdminLoginComponent },
{ path: 'login/linkedin', component: LinkedInLoginComponent },
{ path: 'login/twitter', component: TwitterLoginComponent }
];

View File

@ -41,6 +41,7 @@
<button mat-button (click)="nativeLogin()">LOGIN</button>
</div>
</div>
<p>You dont need to have a registered account for OpenDMPs</p>
</div>
</div>
</div>

View File

@ -0,0 +1,5 @@
export enum RecentActivityTypes {
PROJECT = 0,
DATASET = 1,
DMP = 2
}

View File

@ -0,0 +1,21 @@
<div *ngIf="activities!=null">
<mat-card class="example-card">
<mat-card-header>
<mat-card-title>
{{'RECENT-ACTIVITY.TITLE' | translate}}
</mat-card-title>
</mat-card-header>
<mat-card-content>
<mat-nav-list>
<mat-list-item (click)="redirect(activity.id,activity.type)" *ngFor="let activity of activities">
<p mat-line>
{{activity.label}}
</p>
<p mat-line>
{{activity.timestamp | date:'shortDate'}}
</p>
</mat-list-item>
</mat-nav-list>
</mat-card-content>
</mat-card>
</div>

View File

@ -0,0 +1,60 @@
import { DataTableRequest } from '../../models/data-table/DataTableRequest';
import { UserErrorModel } from '../../models/users/UserErrorModel';
import { UserReferenceService } from '../../services/user-reference/user-reference-data.service';
import { UserListingModel } from '../../models/users/UserListingModel';
import { SnackBarNotificationComponent } from '../../shared/components/notificaiton/snack-bar-notification.component';
import { UserCriteria } from '../../models/criteria/users/UserCriteria';
import { UserCriteriaErrorModel } from '../../models/criteria/users/UserCriteriaErrorModel';
import { Observable } from 'rxjs/Rx';
import { Component, OnInit, AfterViewInit, ViewChild } from '@angular/core';
import { UsersCriteriaComponent } from '../../shared/components/criteria/users/users-criteria.component';
import { Router } from '@angular/router';
import { Principal } from '../../models/login/Principal';
import { MatPaginator, MatSort, MatSnackBar } from '@angular/material';
import { TranslateService } from '@ngx-translate/core';
import { DataSource } from '@angular/cdk/table';
import { RecentActivityTypes } from '@app/users/activity/RecentActivityTypes';
@Component({
selector: 'app-recent-activity',
templateUrl: './recent-activity.component.html',
styleUrls: ['./recent-activity.component.scss'],
providers: [
UserReferenceService
]
})
export class RecentActivityComponent implements OnInit {
activities: any[];
constructor(
private router: Router,
private userReferenceService: UserReferenceService
) { }
ngOnInit() {
this.userReferenceService.getRecentActivity().subscribe(response => {
this.activities = response["recentActivities"];
})
}
redirect(id: string, type: RecentActivityTypes) {
switch (type) {
case RecentActivityTypes.PROJECT: {
this.router.navigate(["projects/edit/" + id]);
return;
}
case RecentActivityTypes.DATASET: {
this.router.navigate(["datasets/edit/" + id]);
return;
}
case RecentActivityTypes.DMP: {
this.router.navigate(["dmps/edit/" + id]);
return;
}
default: throw new Error("Unsupported Activity Type ")
}
}
}

View File

@ -11,6 +11,7 @@ import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { UsersComponent } from './components/users.component';
import { UsersRoutes } from './users.routes';
import { UserRoleEditorComponent } from './components/roles/user-role-editor.component';
import { RecentActivityComponent } from '@app/users/activity/recent-activity.component';
@NgModule({
imports: [
@ -25,13 +26,15 @@ import { UserRoleEditorComponent } from './components/roles/user-role-editor.com
}
}),
ReactiveFormsModule,
MaterialModule
MaterialModule,
RecentActivityComponent
],
declarations: [
UsersComponent,
UsersCriteriaComponent,
UserRoleEditorComponent
UserRoleEditorComponent,
RecentActivityComponent
],
exports: [

View File

@ -1,8 +1,8 @@
import { Serializable } from '../models/interfaces/Serializable';
export class JsonSerializer{
export class JsonSerializer {
public static fromJSONArray<T extends Serializable<T>>(items: any[], type: { new(): T; }): T[] {
if(!items)return new Array<T>();
if (!items) return new Array<T>();
const objectList: T[] = new Array<T>();
for (let i = 0; i < items.length; i++) {
objectList.push(new type().fromJSONObject(items[i]))
@ -11,7 +11,7 @@ export class JsonSerializer{
}
public static fromJSONObject<T extends Serializable<T>>(item: any, type: { new(): T; }): T {
if(!item)return null;
if (!item) return null;
return new type().fromJSONObject(item);
}
}

View File

@ -17,8 +17,8 @@
"UNSUCCESSFUL-LOGOUT": "Unsuccessful Logout",
"UNSUCCESSFUL-LOGIN": "Unsuccessful Login"
},
"ERRORS":{
"HTTP-REQUEST-ERROR":"An Unexpected Error Has Occured"
"ERRORS": {
"HTTP-REQUEST-ERROR": "An Unexpected Error Has Occured"
}
},
"NAV-BAR": {
@ -27,17 +27,18 @@
"DMPS": "Plans",
"DATASETS": "Datasets",
"USERS": "Users",
"DATASETS(ADMIN)":"Dataset Profiles"
"DATASETS(ADMIN)": "Dataset Profiles"
},
"PROJECT-LISTING": {
"TITLE": "Projects",
"COLUMNS": {
"AVATAR": "Image",
"NAME": "Name",
"ABBREVIATION": "Abbreviation",
"START": "Start",
"END": "End",
"ACTIONS": "Actions"
"ACTIONS": "Actions",
"DMPS": "Dmps"
}
},
"DMP-LISTING": {
@ -50,7 +51,7 @@
"ORGANISATIONS": "Organisations",
"LATEST_VERSION": "Latest Version",
"ACTIONS": "Actions",
"DATASETS":"Datasets"
"DATASETS": "Datasets"
},
"ACTIONS": {
"EDIT": "Edit",
@ -59,7 +60,7 @@
"DATASETS": "Datasets",
"NEW-VERSION": "New Version",
"VIEW-VERSION": "All Versions",
"CLONE" : "Clone"
"CLONE": "Clone"
}
},
"DATASET-WIZARD": {
@ -112,7 +113,8 @@
"URI": "URL",
"START": "Start",
"END": "End",
"DESCRIPTION": "Description"
"DESCRIPTION": "Description",
"LOGO": "Project Logo"
},
"ACTIONS": {
"SAVE": "Save",
@ -156,9 +158,9 @@
"PROJECTS": "Projects"
},
"USERS": {
"LABEL": "Label",
"ROLE": "Role"
}
"LABEL": "Label",
"ROLE": "Role"
}
},
"DATASET-EDITOR": {
"TITLE": {
@ -189,21 +191,21 @@
"CANCEL": "Cancel"
}
},
"USERS": {
"LISTING": {
"USERS": {
"LISTING": {
"TITLE": "Users",
"EMAIL": "Email",
"LAST-LOGGED-IN": "Last Logged In",
"LABEL": "Label",
"ROLES": "Roles"
}
},
"TYPES": {
"APP-ROLE": {
"ADMIN": "Admin",
"USER": "User",
"MANAGER": "Manager"
}
"LABEL": "Label",
"ROLES": "Roles"
}
},
"TYPES": {
"APP-ROLE": {
"ADMIN": "Admin",
"USER": "User",
"MANAGER": "Manager"
}
},
"ADDRESEARCHERS-EDITOR": {
"TITLE": "Add a Researcher",
@ -214,15 +216,26 @@
"CANCEL": "Cancel"
}
},
"DMP-WIZARD":{
"FIRST-STEP":{
"DMP":"DMP Editor",
"DATASETS":"Datasets"
"DMP-WIZARD": {
"FIRST-STEP": {
"DMP": "DMP Editor",
"DATASETS": "Datasets"
},
"ACTIONS": {
"NEXT": "Next",
"BACK": "Back",
"SAVE": "Save"
}
},
"RECENT-ACTIVITY": {
"TITLE": "Recent Activity"
},
"FILE-UPLOADER": {
"DEFAULT": "Choose a file",
"PROJECT": "",
"UPLOAD": "Upload"
},
"URL-LISTING-COMPONENT": {
"SHOW-MORE": "Show more"
}
}