diff --git a/sample-components/sampleComponent-2/.editorconfig b/sample-components/sampleComponent-2/.editorconfig new file mode 100644 index 00000000..f1cc3ad3 --- /dev/null +++ b/sample-components/sampleComponent-2/.editorconfig @@ -0,0 +1,15 @@ +# http://editorconfig.org + +root = true + +[*] +charset = utf-8 +indent_style = space +indent_size = 2 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true + +[*.md] +insert_final_newline = false +trim_trailing_whitespace = false diff --git a/sample-components/sampleComponent-2/.gitignore b/sample-components/sampleComponent-2/.gitignore new file mode 100644 index 00000000..9e17510b --- /dev/null +++ b/sample-components/sampleComponent-2/.gitignore @@ -0,0 +1,12 @@ +/__build__ +/__server_build__ +/node_modules +/typings +/tsd_typings/ +npm-debug.log + +/dist/ + +.idea + +.DS_Store diff --git a/sample-components/sampleComponent-2/README.md b/sample-components/sampleComponent-2/README.md new file mode 100644 index 00000000..b1c84a93 --- /dev/null +++ b/sample-components/sampleComponent-2/README.md @@ -0,0 +1,23 @@ +# Angular 2 Universal Starter [![Universal Angular 2](https://img.shields.io/badge/universal-angular2-brightgreen.svg?style=flat)](https://github.com/angular/universal) +> Server-Side Rendering for Angular 2 + +A minimal Angular 2 starter for Universal JavaScript using TypeScript 2 and Webpack 2 + +> If you're looking for the Angular Universal repo go to [angular/universal](https://github.com/angular/universal) + +[![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy) + +## Installation + +* `npm install` + +## Serve + +* `npm start` to build your client app and start a web server +* `npm run build` to prepare a distributable bundle + +## Development +* run `npm start` and `npm run watch` in two separate terminals to build your client app, start a web server, and allow file changes to update in realtime + +## Watch files +* `npm run watch` to build your client app and start a web server diff --git a/sample-components/sampleComponent-2/app.json b/sample-components/sampleComponent-2/app.json new file mode 100644 index 00000000..1762bb6b --- /dev/null +++ b/sample-components/sampleComponent-2/app.json @@ -0,0 +1,12 @@ +{ + "name": "Angular 2 Universal Starter", + "description": "Angular 2 Universal starter kit by @AngularClass", + "repository": "https://github.com/angular/universal-starter", + "logo": "https://cloud.githubusercontent.com/assets/1016365/10639063/138338bc-7806-11e5-8057-d34c75f3cafc.png", + "env": { + "NPM_CONFIG_PRODUCTION": { + "description": "Install `webpack` and other development modules when deploying to allow full builds.", + "value": "false" + } + } +} diff --git a/sample-components/sampleComponent-2/nodemon.json b/sample-components/sampleComponent-2/nodemon.json new file mode 100644 index 00000000..97a836fb --- /dev/null +++ b/sample-components/sampleComponent-2/nodemon.json @@ -0,0 +1,7 @@ +{ + "watch": [ + "dist", + "src/index.html" + ], + "ext" : "js ts json html" +} diff --git a/sample-components/sampleComponent-2/package.json b/sample-components/sampleComponent-2/package.json new file mode 100644 index 00000000..ee0e39d5 --- /dev/null +++ b/sample-components/sampleComponent-2/package.json @@ -0,0 +1,73 @@ +{ + "name": "universal-starter", + "version": "2.0.0", + "description": "Angular 2 Universal starter kit by @AngularClass", + "repository": { + "type": "git", + "url": "https://github.com/angular/universal-starter.git" + }, + "scripts": { + "watch": "webpack --watch", + "prebuild": "rimraf dist", + "build": "webpack", + "build:prod": "webpack --progress -p", + "prestart": "npm run build", + "server": "nodemon dist/server/index.js", + "start": "npm run server", + "predebug": "npm run build", + "debug:build": "node-nightly --inspect --debug-brk node_modules/webpack/bin/webpack.js", + "debug": "node --debug-brk dist/server/index.js" + }, + "license": "MIT", + "contributors": [ + "AngularClass ", + "PatrickJS ", + "Jeff Whelpley ", + "Jeff Cross ", + "Mark Pieszak " + ], + "dependencies": { + "@angular/common": "2.0.0", + "@angular/compiler": "2.0.0", + "@angular/core": "2.0.0", + "@angular/forms": "2.0.0", + "@angular/http": "2.0.0", + "@angular/platform-browser": "2.0.0", + "@angular/platform-browser-dynamic": "2.0.0", + "@angular/platform-server": "2.0.0", + "@angular/router": "3.0.0", + "angular2-platform-node": "~2.0.4", + "angular2-universal": "~2.0.4", + "angular2-universal-polyfills": "~2.0.4", + "angular2-express-engine": "~2.0.4", + "body-parser": "^1.15.2", + "express": "^4.14.0", + "methods": "~1.1.2", + "rxjs": "5.0.0-beta.12", + "zone.js": "~0.6.21" + }, + "devDependencies": { + "@angularclass/resolve-angular-routes": "^1.0.9", + "@types/body-parser": "0.0.29", + "@types/compression": "0.0.29", + "@types/cookie-parser": "^1.3.29", + "@types/express": "^4.0.32", + "@types/express-serve-static-core": "^4.0.33", + "@types/mime": "0.0.28", + "@types/node": "^6.0.38", + "@types/serve-static": "^1.7.27", + "angular2-template-loader": "^0.4.0", + "cookie-parser": "^1.4.3", + "json-loader": "^0.5.4", + "nodemon": "^1.10.0", + "raw-loader": "^0.5.1", + "rimraf": "^2.5.4", + "ts-loader": "^0.8.2", + "ts-node": "^1.3.0", + "typescript": "2.0.0", + "webpack": "^2.1.0-beta.22", + "webpack-dev-middleware": "^1.6.1", + "webpack-dev-server": "^2.1.0-beta.0", + "webpack-merge": "^0.13.0" + } +} diff --git a/sample-components/sampleComponent-2/src/app/app.routing.ts b/sample-components/sampleComponent-2/src/app/app.routing.ts new file mode 100644 index 00000000..36ac3ad0 --- /dev/null +++ b/sample-components/sampleComponent-2/src/app/app.routing.ts @@ -0,0 +1,27 @@ +import { ModuleWithProviders } from '@angular/core'; +import { Routes, RouterModule } from '@angular/router'; +import {ClaimsAdminComponent} from './claimPages/claims/claimsAdmin.component'; +import {HomeComponent} from './home/home.component'; +const appRoutes: Routes = [ + { path: '', component: HomeComponent, pathMatch: 'full' }, + { path: 'claims', component: ClaimsAdminComponent }, + { path: 'home', component: HomeComponent } + +]; + + +// , +// { +// path: 'heroes', +// component: HeroListComponent, +// data: { +// title: 'Heroes List' +// } +// }, +// { path: 'hero/:id', component: HeroDetailComponent }, +// { path: '**', component: PageNotFoundComponent } +// export const appRoutingProviders: any[] = [ +// +// ]; + +export const routing: ModuleWithProviders = RouterModule.forRoot(appRoutes); diff --git a/sample-components/sampleComponent-2/src/app/app.ts b/sample-components/sampleComponent-2/src/app/app.ts new file mode 100644 index 00000000..cccc2bdc --- /dev/null +++ b/sample-components/sampleComponent-2/src/app/app.ts @@ -0,0 +1,41 @@ +import { Component } from '@angular/core'; + +import 'rxjs/Rx'; +@Component({ + selector: 'app', + template: ` +
+ + +
+ +
+ +
` + +}) +export class App { + +} diff --git a/sample-components/sampleComponent-2/src/app/claimPages/claims/claims.component.html b/sample-components/sampleComponent-2/src/app/claimPages/claims/claims.component.html new file mode 100644 index 00000000..4518b03f --- /dev/null +++ b/sample-components/sampleComponent-2/src/app/claimPages/claims/claims.component.html @@ -0,0 +1,107 @@ +
+
+
+
+ +
Claims related to
+ +
+

+ +

+

+ +

+

+ +

+

+ +

+

+ +

+
+
+
+ + +
+ + + diff --git a/sample-components/sampleComponent-2/src/app/claimPages/claims/claims.component.ts b/sample-components/sampleComponent-2/src/app/claimPages/claims/claims.component.ts new file mode 100644 index 00000000..b8151b44 --- /dev/null +++ b/sample-components/sampleComponent-2/src/app/claimPages/claims/claims.component.ts @@ -0,0 +1,490 @@ +import {Component, ViewChild, Input} from '@angular/core'; +import {Location} from '@angular/common'; +import {Observable} from 'rxjs/Observable'; +import {ActivatedRoute, Router} from '@angular/router'; +import {ClaimsService} from '../../services/claims.service'; +import {Loading} from '../../common/modal/loading.component'; +import {Alert} from '../../common/modal/alert'; + + +@Component({ + selector: 'claims', + templateUrl: 'claims.component.html', + providers:[ ClaimsService] + +}) +export class ClaimsComponent { + constructor (private _claimService: ClaimsService, private route: ActivatedRoute, private _router:Router, private location: Location) { + } + + ngOnInit() { + // this.sub = this.route.queryParams.subscribe(params => { + + var params = []; + if( this.myClaims == 'true' ){ + this.fetchBy = "User"; + }else{ + + this.fetchBy = params['fetchBy']; + this.fetchBy = (this.types.indexOf(this.fetchBy) != -1)? this.fetchBy:'All'; + this.fetchId = params['fetchId']; + this.fetchId=this.fetchId?this.fetchId:''; + + } + + let page = (params['page']=== undefined)?1:+params['page']; + let size = (params['size']=== undefined)?10:+params['size']; + + this.keyword = (params['keyword']?params['keyword']:""); + this.inputkeyword = this.keyword; + this.page = ( page <= 0 ) ? 1 : page; + this.size = ( size <= 0 ) ? 10 : size; + this.entityTypes = []//(params['types']?params['types']:[]); + this.setTypes(params['types']); // check the appropriate checkboxes + // this.setSortby(params['sort']); + this.getClaims(); + + // }); + // this.sub = this.route.params.subscribe(params => { + // console.info(this.isAdmin+" "+this.myClaims+" Fetch by: "+this.fetchBy+" Fetch id: "+this.fetchId); + // if( this.myClaims == 'true' ){ + // console.info("Is myclaims"); + // this.fetchBy = "User"; + // }else{ + // console.info("Is admin"); + // + // console.info(this.isAdmin); + // + // this.fetchBy = params['fetchBy']; + // this.fetchBy = (this.types.indexOf(this.fetchBy) != -1)? this.fetchBy:'All'; + // this.fetchId = params['fetchId']; + // console.info("Fetch by:"+this.fetchBy+"Fetch id:"+this.fetchId); + // this.fetchId=this.fetchId?this.fetchId:''; + // + // } + // + // console.info(this.isAdmin+" "+this.myClaims+" Fetch by: "+this.fetchBy+" Fetch id: "+this.fetchId); + // let page = (params['page']=== undefined)?1:+params['page']; + // let size = (params['size']=== undefined)?10:+params['size']; + // + // this.keyword = (params['keyword']?params['keyword']:""); + // this.inputkeyword = this.keyword; + // this.page = ( page <= 0 ) ? 1 : page; + // this.size = ( size <= 0 ) ? 10 : size; + // this.entityTypes = []//(params['types']?params['types']:[]); + // this.setTypes(params['types']); // check the appropriate checkboxes + // this.setSortby(params['sort']); + // this.getClaims(); + // console.info("params: "+params['page']+" page "+page +" this.page: "+this.page ); + // }); + } + ngOnDestroy() { + this.sub.unsubscribe(); + } + sub: any; + //string because comes as input from component directive + @Input() enableDelete: string = 'false'; + @Input() myClaims: string= 'false' ; + @Input() isAdmin:string = 'false'; + page : number; + size:number; + keyword:string; // the keyword string to give to the request as parameter + inputkeyword:string; // the string written in the input field (keyword=inputkeyword when its length is bigger than 3 and the user stops typing) + lengths = [10,20,30,50]; + types = ["All","Project","Context","Result","User"]; + @Input() fetchBy:string; + @Input() fetchId:string; + + navigateTo: string = "Claims"; + resultsNum: number ; + claims: string[]; + + @ViewChild (Loading) loading : Loading ; + + //checkboxes: + publicationCB = false; + datasetCB = false; + contextCB = false; + projectCB = false; + entityTypes : string[] =[] ; + + descending = true; + sortby = "date"; + + selected=[]; + deleteMessage:string = ""; + showErrorMessage:boolean = false; + + //params for pagingFormatter to use when navigate to page + params; + @ViewChild(Alert) alert; + + claimsDeleted:number = 0; + + getClaims () { + this.selected=[]; + var types = ''; + this.showErrorMessage = false; + for (var type of this.entityTypes){ + types+=(types.length>0?'&':'')+"types="+type; + } + if(this.fetchBy =="Project" ){ + this._claimService.getClaimsByProject(this.size,this.page,this.fetchId,this.keyword,this.sortby,this.descending, types).subscribe( + data => { + this.claims = data.data; + this.resultsNum= data.total; + }, + err => { + console.error(err); + this.showErrorMessage = true; + } + ); + }else if(this.fetchBy =="User"){ + this._claimService.getClaimsByUser(this.size,this.page,this.fetchId,this.keyword,this.sortby,this.descending, types).subscribe( + data => { + this.claims = data.data; + this.resultsNum= data.total; + }, + err => { + console.error(err); + this.showErrorMessage = true; + } + ); + }else if(this.fetchBy =="Result"){ + this._claimService.getClaimsByResult(this.size,this.page,this.fetchId,this.keyword,this.sortby,this.descending, types).subscribe( + data => { + this.claims = data.data; + this.resultsNum= data.total; + }, + err => { + console.error(err); + this.showErrorMessage = true; + } + ); + }else if(this.fetchBy =="Context"){ + this._claimService.getClaimsBycontext(this.size,this.page,this.fetchId,this.keyword,this.sortby,this.descending, types).subscribe( + data => { + this.claims = data.data; + this.resultsNum= null; + this.resultsNum= data.total;//data.length; //TODO get the total results num + }, + err => { + console.error(err); + this.showErrorMessage = true; + } + ); + }else{ + this._claimService.getClaims(this.size,this.page,this.keyword,this.sortby,this.descending, types).subscribe( + data => { + this.claims = data.data; + this.resultsNum = null; + this.resultsNum= data.total;//data.length; //TODO get the total results num + }, + err => { + console.error(err); + this.showErrorMessage = true; + } + ); + } + } + + goToClaim(claimId: number){ + this._router.navigate( ['Claim', { id: claimId}] ); + } + goTo(page:number = 1){ + + this.page = page; + + this.location.go(location.pathname,this.getParametersString()); + this.getClaims(); + } + getParameters(){ + let params={ page: this.page, size: this.size, types: this.entityTypes, fetchBy: this.fetchBy, fetchId:this.fetchId, keyword : this.keyword, sort: this.getSortby() }; + return params; + } + getParametersString(){ + var params=''; + params+=(this.page==1?"":(params.length>0?'&':'')+"page="+this.page); + params+=(this.size==10?"":(params.length>0?'&':'')+"size="+this.size); + // params+=(this.entityTypes==''?"":(params.length>0?'&':'')+"types="+this.entityTypes); + var types=""; + for (var type of this.entityTypes){ + types+=(types.length>0?',':'')+type; + } + params+=(types.length>0)?"types="+types:""; + + if(this.isAdmin === 'true'){ + params+=(this.fetchBy=='All'?"":(params.length>0?'&':'')+"fetchBy="+this.fetchBy); + params+=(this.fetchId==''?"":(params.length>0?'&':'')+"fetchId="+this.fetchId); + } + params+=(this. getSortby()=='datedesc'?"":(params.length>0?'&':'')+"sort="+this. getSortby()); + params+=(this.keyword==''?"":(params.length>0?'&':'')+"keyword="+this.keyword); + return params; + } + changeLength(){ + this.goTo(); + } + clearFilters(){ + this.keyword = ''; + this.inputkeyword = ''; + this.publicationCB = false; + this.projectCB = false; + this.datasetCB = false; + this.contextCB = false; + this.entityTypes = []; + this.goTo(); + } + changeOrderby(sortby:string){ + if(sortby==this.sortby){ + this.descending = !this.descending; + }else{ + this.sortby = sortby; + this.descending = false; + } + this.goTo(); + } + setSortby(sortby:string){ + if(!sortby|| sortby == "datedesc"){ + this.descending = true; + this.sortby = "date"; + }else if(sortby == "dateasc"){ + this.descending = false; + this.sortby = "date"; + }else if(sortby == "userasc"){ + this.descending = false; + this.sortby = "user"; + }else if(sortby == "userdesc"){ + this.descending = true; + this.sortby = "user"; + }if(sortby =="sourceasc"){ + this.descending = false; + this.sortby = "source"; + }else if(sortby == "sourcedesc"){ + this.descending = true; + this.sortby = "source"; + }else if(sortby == "targetasc"){ + this.descending = false; + this.sortby = "target"; + }else if(sortby == "targetdesc"){ + this.descending = true; + this.sortby = "target"; + } + } + getSortby():string{ + if(this.descending){ + return this.sortby+"desc"; + }else{ + return this.sortby+"asc"; + } + + } + changeType(){ + this.entityTypes = []; + if(this.publicationCB){ + this.entityTypes.push('publication'); + } + if(this.datasetCB){ + this.entityTypes.push('dataset'); + } + if(this.projectCB){ + this.entityTypes.push('project'); + } + if(this.contextCB){ + this.entityTypes.push('context'); + } + + // if(this.publicationCB == true && this.datasetCB == true && this.contextCB == true && this.projectCB == true ){ + // this.entityTypes=""; + // }else{ + // this.entityTypes = ""; + // if(this.publicationCB == true){ + // this.entityTypes = "publication"; + // } + // if(this.datasetCB == true){ + // this.entityTypes += (this.entityTypes.length > 0?",":"")+"dataset"; + // } + // if(this.contextCB == true){ + // this.entityTypes += (this.entityTypes.length > 0?",":"")+"context"; + // } + // if(this.projectCB == true){ + // this.entityTypes += (this.entityTypes.length > 0?",":"")+"project"; + // } + // } + // console.debug("Type changed: "+this.entityTypes+" "+this.publicationCB+ this.datasetCB + this.contextCB + this.projectCB); + this.goTo(); + } + setTypes(types:string){ + if(!types){ + return; + } + if(types.length > 0){ + this.entityTypes = []; + if(types.indexOf("publication")!=-1){ + this.publicationCB = true; + this.entityTypes.push("publication"); + } + if(types.indexOf("dataset")!=-1){ + this.datasetCB = true; + this.entityTypes.push("dataset"); + } + if(types.indexOf("project")!=-1){ + this.projectCB = true; + this.entityTypes.push("project"); + } + if(types.indexOf("context")!=-1){ + this.contextCB = true; + this.entityTypes.push("context"); + } + } + if(this.publicationCB && this.datasetCB && this.contextCB && this.projectCB){ + this.entityTypes=[]; + } + } + changekeyword(){ + + if(this.inputkeyword.length >= 3 || this.inputkeyword.length == 0 ){ + this.keyword = this.inputkeyword; + this.page = 1; + this.goTo(); + } + + } + select(item:any,event){ + this.deleteMessage=""; + var value = event.currentTarget.checked; + if(value){ + this.selected.push(item); + }else{ + for (var _i = 0; _i < this.selected.length; _i++) { + let claim = this.selected[_i]; + if(claim['id'] == item.id){ + this.selected.splice(_i, 1); + } + } + + + } + } + selectAll(){ + this.selected = []; + for (var _i = 0; _i < this.claims.length; _i++) { + let claim = this.claims[_i]; + this.selected.push(claim); + } + this.deleteMessage = ""; + } + deselectAll(){ + this.selected = []; + this.deleteMessage=""; + } + isSelected(id:string){ + for (var _i = 0; _i < this.selected.length; _i++) { + let claim = this.selected[_i]; + if(claim['id'] == id){ + return true; + } + } + return false; + } + + + confirmOpen(){ + if(this.selected.length <= 0){ + + }else{ + this.alert.cancelButton = true; + this.alert.okButton = true; + this.alert.alertTitle = "Delete "+this.selected.length+" claim(s)"; + this.alert.message = this.selected.length+" claims will be deleted. Do you want to proceed? "; + this.alert.okButtonText = "Yes"; + this.alert.cancelButtonText = "No"; + this.alert.open(); + } + } + confirmClose(data){ + this.delete(); + } + delete(){ + this.deleteMessage=""; + this.loading.open(); + this.claimsDeleted = 0; + var ids = []; + for (var i = 0; i < this.selected.length; i++){ + var id =this.selected[i].id; + ids.push(id); + // var selected =this.selected[i].id; + // console.warn("Deleting claim with id:"+id); + // this.deleteById(id); + //TODO for multiple concurrent + } + this.batchDeleteById(ids); + } + + deleteById(id:string){ + + console.warn("Deleting claim with id:"+id); + // this._claimService.deleteClaimById(id); + this._claimService.deleteClaimById(id).subscribe( + res => { + console.info('Delete response'+res.code ); + console.warn("Deleted claim with id:"+ id); + //remove this claim from the + let newClaims=this.claims; + for (var _i = 0; _i < this.claims.length; _i++) { + let claim = this.claims[_i]; + if(claim['id'] == id){ + newClaims.splice(_i, 1); + } + } + //TODO should call getClaims??? + this.claimsDeleted++; + this.claims = newClaims; + if(this.claimsDeleted == this.selected.length){ + this.resultsNum = this.resultsNum - this.selected.length; + this.loading.close(); + this.selected = []; + } + + + }); + } + batchDeleteById(ids:string[]){ + + console.warn("Deleting claim with ids:"+ids); + this._claimService.deleteBulk(ids).subscribe( + res => { + console.info('Delete response'+res.code ); + console.warn("Deleted ids:"+ res.deletedIds); + console.warn("Not found ids:"+ res.notFoundIds); + //remove this claim from the + let newClaims=this.claims; + for(var id of res.deletedIds){ + for (var _i = 0; _i < this.claims.length; _i++) { + let claim = this.claims[_i]; + if(claim['id'] == id){ + newClaims.splice(_i, 1); + } + } + for (var _i = 0; _i < this.selected.length; _i++) { + let claim = this.selected[_i]; + if(claim['id'] == id){ + this.selected.splice(_i, 1); + } + } + } + this.claims = newClaims; + this.resultsNum = this.resultsNum - res.deletedIds.length; + this.loading.close(); + if(res.deletedIds.length>0){ + this.deleteMessage=this.deleteMessage+'
'+res.deletedIds.length+' claim(s) successfully deleted.
'; + } + if(res.notFoundIds.length>0){ + this.deleteMessage=this.deleteMessage+'
'+res.notFoundIds.length+' claim(s) couldn\'t be deleted.
'; + } + }); + } + pageChange($event) { + var page:number = +$event.value + this.goTo(page); + } +} diff --git a/sample-components/sampleComponent-2/src/app/claimPages/claims/claimsAdmin.component.ts b/sample-components/sampleComponent-2/src/app/claimPages/claims/claimsAdmin.component.ts new file mode 100644 index 00000000..a602bdc9 --- /dev/null +++ b/sample-components/sampleComponent-2/src/app/claimPages/claims/claimsAdmin.component.ts @@ -0,0 +1,36 @@ +import {Component, ViewChild, Input} from '@angular/core'; +import {Location} from '@angular/common'; +import {Observable} from 'rxjs/Observable'; + +@Component({ + selector: 'claims-admin', + template: ` +
+ + +
+ + +
+ TODO login +
+ `, + +}) +export class ClaimsAdminComponent { + constructor ( ) { + + } +user:string="argirok@di.uoa.gr"; + ngOnInit() { + + + } + + +} diff --git a/sample-components/sampleComponent-2/src/app/common/claimEntityFormatter.component.ts b/sample-components/sampleComponent-2/src/app/common/claimEntityFormatter.component.ts new file mode 100644 index 00000000..093b1cd5 --- /dev/null +++ b/sample-components/sampleComponent-2/src/app/common/claimEntityFormatter.component.ts @@ -0,0 +1,38 @@ +import {Component, Input} from '@angular/core'; +// import {PublicationTitleFormatter} from './publicationTitleFormatter.component'; +// import {ProjectTitleFormatter} from './projectTitleFormatter.component'; + +//Usage Example " " + +//externalUrl +@Component({ + selector: 'claim-entity', + template: ` + +
+ ({{type}}) + +
+
+ (Project) + +
+
+ (Context) +
{{entity.title}}
+
+ ` +}) + +export class ClaimEntityFormatter { + @Input() entity: string[]; + @Input() type: string; + + constructor () {} + + ngOnInit() { + + } + + +} diff --git a/sample-components/sampleComponent-2/src/app/common/modal/alert.ts b/sample-components/sampleComponent-2/src/app/common/modal/alert.ts new file mode 100644 index 00000000..bf5d1f60 --- /dev/null +++ b/sample-components/sampleComponent-2/src/app/common/modal/alert.ts @@ -0,0 +1,110 @@ +import {Component, ViewEncapsulation, ComponentRef, ElementRef, Input, EventEmitter, Output} from '@angular/core'; +// import { DynamicComponentLoader} from '@angular/core'; + +import {Open} from './open.component'; + +@Component({ + selector: 'alert', + template: ` + + `, + encapsulation: ViewEncapsulation.None, +}) +/** + * API to an open alert window. + */ +export class Alert{ + /** + * Caption for the title. + */ + public alertTitle:string; + /** + * Describes if the alert contains Ok Button. + * The default Ok button will close the alert and emit the callback. + * Defaults to true. + */ + public okButton:boolean = true; + /** + * Caption for the OK button. + * Default: Ok + */ + public okButtonText:string= 'Ok'; + /** + * Describes if the alert contains cancel Button. + * The default Cancelbutton will close the alert. + * Defaults to true. + */ + public cancelButton:boolean = true; + /** + * Caption for the Cancel button. + * Default: Cancel + */ + public cancelButtonText:string = 'Cancel'; + /** + * if the alertMessage is true it will show the contentString inside alert body. + */ + public alertMessage:boolean = true; + /** + * Some message/content can be set in message which will be shown in alert body. + */ + public message:string; + /** + * if the value is true alert footer will be visible or else it will be hidden. + */ + public alertFooter:boolean= true; + /** + * shows alert header if the value is true. + */ + public alertHeader:boolean = true; + /** + * if the value is true alert will be visible or else it will be hidden. + */ + public isOpen:boolean=false; + /** + * Emitted when a ok button was clicked + * or when Ok method is called. + */ + @Output() public alertOutput:EventEmitter = new EventEmitter(); + constructor( public _elementRef: ElementRef){} + /** + * Opens a alert window creating backdrop. + */ + open(){ + this.isOpen= true; + } + /** + * ok method closes the modal and emits modalOutput. + */ + ok(){ + this.isOpen = false; + this.alertOutput.emit(true); + } + /** + * cancel method closes the moda. + */ + cancel(){ + this.isOpen = false; + } +} diff --git a/sample-components/sampleComponent-2/src/app/common/modal/loading.component.ts b/sample-components/sampleComponent-2/src/app/common/modal/loading.component.ts new file mode 100644 index 00000000..c046feae --- /dev/null +++ b/sample-components/sampleComponent-2/src/app/common/modal/loading.component.ts @@ -0,0 +1,49 @@ +import {Component, ViewEncapsulation, ComponentRef, ElementRef, Input, EventEmitter, Output} from '@angular/core'; + +@Component({ + selector: 'loading', + template: ` + + `, + encapsulation: ViewEncapsulation.None, +}) +/** + * API to an open alert window. + */ +export class Loading{ + +@Input() public message:string ="Loading"; + + /** + * if the value is true alert will be visible or else it will be hidden. + */ + public isOpen:boolean=false; + /** + * Emitted when a ok button was clicked + * or when Ok method is called. + */ + @Output() public alertOutput:EventEmitter = new EventEmitter(); + constructor( public _elementRef: ElementRef){} + /** + * Opens a alert window creating backdrop. + */ + open(){ + this.isOpen= true; + } + + close(){ + this.isOpen = false; + } +} diff --git a/sample-components/sampleComponent-2/src/app/common/modal/open.component.ts b/sample-components/sampleComponent-2/src/app/common/modal/open.component.ts new file mode 100644 index 00000000..95add08d --- /dev/null +++ b/sample-components/sampleComponent-2/src/app/common/modal/open.component.ts @@ -0,0 +1,55 @@ +import {Directive, Input, HostBinding} from '@angular/core'; + +// todo: add animate +// todo: add init and on change +@Directive({selector: '[open]'}) +export class Open { + @HostBinding('style.display') + private display:string; + @HostBinding('class.in') + @HostBinding('attr.aria-expanded') + private isExpanded:boolean = true; + + @Input() + private set open(value:boolean) { + this.isExpanded = value; + this.toggle(); + } + + private get open():boolean { + return this.isExpanded; + } + + constructor() { + } + init() { + this.isExpanded = false; + this.display = 'none'; + } + toggle() { + if (this.isExpanded) { + this.hide(); + } else { + this.show(); + } + } + + hide() { + this.isExpanded = false; + this.display = 'none'; + if (typeof document !== 'undefined') { + let backDrop = document.getElementsByClassName("modal-backdrop"); + if(backDrop.length>0){ + document.body.removeChild(backDrop[0]); + } + } + } + + show() { + let backDrop = document.createElement('div'); + backDrop.className="modal-backdrop fade in"; + document.body.appendChild(backDrop); + this.isExpanded = true; + this.display = 'block'; + } +} diff --git a/sample-components/sampleComponent-2/src/app/common/pagingFormatterNoLoad.component.ts b/sample-components/sampleComponent-2/src/app/common/pagingFormatterNoLoad.component.ts new file mode 100644 index 00000000..42534afd --- /dev/null +++ b/sample-components/sampleComponent-2/src/app/common/pagingFormatterNoLoad.component.ts @@ -0,0 +1,75 @@ +import {Component, Input, Output, EventEmitter} from '@angular/core'; + + +//Usage Example + +@Component({ + selector: 'paging-no-load', + template: ` + + ` +}) + +export class pagingFormatterNoLoad { + @Input() currentPage: number = 1; + @Input() navigateTo: string; + @Input() term: string=''; + @Input() size: number=10; + @Input() totalResults: number = 10; + @Input() params; + + @Output() pageChange = new EventEmitter(); + + constructor () { + } + + ngOnInit() { + console.info("In paging -- CurrentPage:"+this.currentPage+" "+"total Pages = "+this.getTotalPages() +" Results num:"+this.totalResults); + } + getTotalPages(){ + var i= this.totalResults/this.size; + var integerI=parseInt(''+i); + return parseInt(''+((i==integerI)?i:i+1)); + } + onPrev(){ + this.currentPage=this.currentPage-1; + this.pageChange.emit({ + value: this.currentPage + }); + + } + + onNext(){ + + this.currentPage=this.currentPage+1; + this.pageChange.emit({ + value: this.currentPage + }); + } + onPage(pageNum: number){ + + this.currentPage=pageNum; + this.pageChange.emit({ + value: this.currentPage + }); + } +} diff --git a/sample-components/sampleComponent-2/src/app/common/projectTitleFormatter.component.ts b/sample-components/sampleComponent-2/src/app/common/projectTitleFormatter.component.ts new file mode 100644 index 00000000..5917768e --- /dev/null +++ b/sample-components/sampleComponent-2/src/app/common/projectTitleFormatter.component.ts @@ -0,0 +1,23 @@ +import {Component, Input} from '@angular/core'; +import {OpenaireProperties} from '../openaireProperties'; + +//Usage Example " " + +@Component({ + selector: 'project-title', + template: ` + + ` +}) + +export class ProjectTitleFormatter { + @Input() project: string[]; + private url:string; + constructor () {} + + ngOnInit() { + this.url = OpenaireProperties.getsearchLinkToProject() + "?projectId=" + this.project["openaireId"]; + } +} diff --git a/sample-components/sampleComponent-2/src/app/common/publicationTitleFormatter.component.ts b/sample-components/sampleComponent-2/src/app/common/publicationTitleFormatter.component.ts new file mode 100644 index 00000000..2c87c50a --- /dev/null +++ b/sample-components/sampleComponent-2/src/app/common/publicationTitleFormatter.component.ts @@ -0,0 +1,26 @@ +import {Component, Input} from '@angular/core'; + +//Usage Example " " + +@Component({ + selector: 'publication-title', + template: ` +
+
{{title}}
+
{{title}}
+
+ ` +}) + +export class PublicationTitleFormatter { + @Input() title: string[]; + @Input() url: string[]; + + constructor () {} + + ngOnInit() { + + } + + +} diff --git a/sample-components/sampleComponent-2/src/app/entities/claim.ts b/sample-components/sampleComponent-2/src/app/entities/claim.ts new file mode 100644 index 00000000..b5378c5f --- /dev/null +++ b/sample-components/sampleComponent-2/src/app/entities/claim.ts @@ -0,0 +1,15 @@ +export class Claim { + id: string; + sourceType: string; + targetType: string; + sourceId: string; + targetId: string; + date: string; + DOI: string; + project: Project + userMail: string; + +} +export class Project{ + +} diff --git a/sample-components/sampleComponent-2/src/app/home/home.component.html b/sample-components/sampleComponent-2/src/app/home/home.component.html new file mode 100644 index 00000000..fa7f4167 --- /dev/null +++ b/sample-components/sampleComponent-2/src/app/home/home.component.html @@ -0,0 +1,15 @@ + +
+
+
+
+
+ + + + +
+
+
+
+
diff --git a/sample-components/sampleComponent-2/src/app/home/home.component.ts b/sample-components/sampleComponent-2/src/app/home/home.component.ts new file mode 100644 index 00000000..03253360 --- /dev/null +++ b/sample-components/sampleComponent-2/src/app/home/home.component.ts @@ -0,0 +1,15 @@ +import {Component} from '@angular/core'; +import {Router} from '@angular/router'; +import {Observable} from 'rxjs/Observable'; +import {Location} from '@angular/common'; + +@Component({ + selector: 'home', + templateUrl: 'home.component.html', + }) + +export class HomeComponent { + constructor ( private _router: Router, private location: Location) {} + + +} diff --git a/sample-components/sampleComponent-2/src/app/openaireProperties.ts b/sample-components/sampleComponent-2/src/app/openaireProperties.ts new file mode 100644 index 00000000..796973ae --- /dev/null +++ b/sample-components/sampleComponent-2/src/app/openaireProperties.ts @@ -0,0 +1,89 @@ +export class OpenaireProperties { + //landing Pages + private static baseSearchLink="/" + private static searchLinkToPublication = "publication?articleId="; + private static searchLinkToProject = "project?projectId="; + private static searchLinkToPerson = "person?personId="; + private static searchLinkToDataProvider = "https://beta.openaire.eu/search/dataprovider?datasourceId="; + private static searchLinkToDataset = "dataset?datasetId="; + private static searchLinkToOrganization = "organization?organizationId="; + + // Services - APIs + + // public claimsAPIURL = "http://rudie.di.uoa.gr:8080/dnet-openaire-connector-service-1.0.0-SNAPSHOT/rest/claimsService/" + private static claimsAPIURL = "http://scoobydoo.di.uoa.gr:8181/dnet-openaire-connector-service-1.0.0-SNAPSHOT/rest/claimsService/"; + + private static searchAPIURL = "http://astero.di.uoa.gr:8080/dnet-functionality-services-2.0.0-SNAPSHOT/rest/v2.0/api/"; + // private searchAPIURL = "http://rudie.di.uoa.gr:8080/dnet-functionality-services-2.0.0-SNAPSHOT/rest/v2.0/api/"; + // private searchAPIURL = "http://scoobydoo.di.uoa.gr:8181/dnet-functionality-services-2.0.0-SNAPSHOT/rest/v2.0/api/"; + + private static searchServiveURL = "http://astero.di.uoa.gr:8080/dnet-functionality-services-2.0.0-SNAPSHOT/"; + // private static searchServiveURL = "http://scoobydoo.di.uoa.gr:8181/dnet-functionality-services-2.0.0-SNAPSHOT/"; + // private static searchServiveURL = "http://services.openaire.eu:8380/search/"; + //private static searchServiveURL = "http://rudie.di.uoa.gr:8080/dnet-functionality-services-2.0.0-SNAPSHOT/"; + + private static searchCrossrefAPIURL = "http://api.crossref.org/works"; + private static searchDataciteAPIURL = "http://search.datacite.org/api"; + private static searchOrcidURL = "https://pub.orcid.org/"; + + // Identifiers + private static pmidURL = "http://www.ncbi.nlm.nih.gov/pubmed/"; + private static doiURL = "http://dx.doi.org/"; + private static cordisURL = "http://cordis.europa.eu/projects/"; + private static pmcURL = "http://europepmc.org/articles/"; + + + //landing Pages' getters + public static getsearchLinkToPublication():string{ + return this.baseSearchLink + this.searchLinkToPublication; + } + public static getsearchLinkToDataset():string{ + return this.baseSearchLink + this.searchLinkToDataset; + } + public static getsearchLinkToProject():string{ + return this.baseSearchLink + this.searchLinkToProject; + } + public static getsearchLinkToPerson():string{ + return this.baseSearchLink + this.searchLinkToPerson; + } + public static getsearchLinkToOrganization():string{ + return this.searchLinkToOrganization; + } + public static getsearchLinkToDataProvider():string{ + return this.searchLinkToDataProvider; + } + + // Services - APIs' getters + public static getSearchAPIURL():string{ + return this.searchAPIURL; + } + public static getSearchServiceURL():string{ + return this.searchServiveURL; + } + public static getClaimsAPIURL():string{ + return this.claimsAPIURL; + } + public static getSearchCrossrefAPIURL():string{ + return this.searchCrossrefAPIURL; + } + public static getSearchDataciteAPIURL():string{ + return this.searchDataciteAPIURL; + } + public static getSearchOrcidURL():string{ + return this.searchOrcidURL; + } + + // Identifiers' getters + public static getPmidURL():string{ + return this.pmidURL; + } + public static getDoiURL():string{ + return this.doiURL; + } + public static getCordisURL():string{ + return this.cordisURL; + } + public static getPmcURL():string{ + return this.pmcURL; + } +} diff --git a/sample-components/sampleComponent-2/src/app/services/claims.service.ts b/sample-components/sampleComponent-2/src/app/services/claims.service.ts new file mode 100644 index 00000000..43c6abce --- /dev/null +++ b/sample-components/sampleComponent-2/src/app/services/claims.service.ts @@ -0,0 +1,131 @@ +import {Injectable} from '@angular/core'; +import {Jsonp, URLSearchParams,ResponseOptions, RequestOptions, Headers} from '@angular/http'; +import {Http, Response} from '@angular/http'; +import {Observable} from 'rxjs/Observable'; +import {Claim} from '../entities/claim'; +import {OpenaireProperties} from '../openaireProperties'; + +@Injectable() +export class ClaimsService { + private baseUrl; + constructor(private jsonp: Jsonp, private http: Http) { + this.baseUrl = OpenaireProperties.getClaimsAPIURL(); + } + + private getClaimRequest(size : number, page : number, url :string):any { + console.info('ClaimsService: Claims request: '+url); + return this.http.get( url) + .map(request => request.json()) + .do(request => console.info("Get claims: offset = "+(size*(page-1)) + " limit ="+size )) + .catch(this.handleError); + } + getClaims( size : number, page : number, keyword:string, sortby: string, descending: boolean, types: string):any { + console.info('ClaimsService: getClaims ' ); + console.info('ClaimsService: Types : '+types ); + let url = this.baseUrl +"claims"+"?offset="+(size*(page-1) + "&limit="+size)+"&keyword="+keyword+"&sortby="+sortby+"&descending="+descending+""+types; + return this.getClaimRequest(size,page,url); + + } + getClaimsByUser( size : number, page : number, user:string, keyword:string, sortby: string, descending: boolean, types: string):any { + console.info('ClaimsService: getClaims for user : '+user); + let url = this.baseUrl +"users/"+user+"/claims"+"?offset="+(size*(page-1) + "&limit="+size)+"&keyword="+keyword+"&sortby="+sortby+"&descending="+descending+""+types; + return this.getClaimRequest(size,page,url); + + } + getClaimsBycontext( size : number, page : number, contextId:string, keyword:string, sortby: string, descending: boolean, types: string):any { + console.info('ClaimsService: getClaims for context : '+contextId); + let url = this.baseUrl +"contexts/"+contextId+"/claims"+"?offset="+(size*(page-1) + "&limit="+size)+"&keyword="+keyword+"&sortby="+sortby+"&descending="+descending+""+types; + return this.getClaimRequest(size,page,url); + + } + getClaimsByResult( size : number, page : number, resultId:string, keyword:string, sortby: string, descending: boolean, types: string):any { + console.info('ClaimsService: getClaims for result : '+resultId); + let url = this.baseUrl +"results/"+resultId+"/claims"+"?offset="+(size*(page-1) + "&limit="+size)+"&keyword="+keyword+"&sortby="+sortby+"&descending="+descending+""+types; + return this.getClaimRequest(size,page,url); + + } + getClaimsByProject( size : number, page : number, projectId:string, keyword:string, sortby: string, descending: boolean, types: string):any { + console.info('ClaimsService: getClaims for project : '+projectId); + let url = this.baseUrl +"projects/"+projectId+"/claims"+"?offset="+(size*(page-1) + "&limit="+size)+"&keyword="+keyword+"&sortby="+sortby+"&descending="+descending+""+types; + return this.getClaimRequest(size,page,url); + } + + deleteClaimById(claimId:string):any{ + console.warn('Trying to delete claim with id : '+claimId); + let url = this.baseUrl +"claims/"+claimId; + console.warn('Delete url: '+url); + let headers = new Headers({ 'Content-Type': 'application/json' }); + let options = new RequestOptions({ headers: headers }); + return this.http.delete( url, options).map(request => request.json()) + .do(request => console.info("After delete" )) + .catch(this.handleError); + + } + deleteBulk(claimIds:string[]):any{ + + console.warn('Trying to delete claims with ids : '+claimIds); + var url = ""; + + for(var claimId of claimIds){ + url=url+(url.length >0 ?"&":"")+"claimId="+claimId; + } + url= this.baseUrl +"claims/bulk?"+url; + console.warn('Delete url: '+url); + let headers = new Headers({ 'Content-Type': 'application/json' }); + let options = new RequestOptions({ headers: headers }); + return this.http.delete( url, options).map(request => request.json()) + .do(request => console.info("After delete" )) + .catch(this.handleError); + + } + insertBulkClaims(claims):any{ + console.warn('Trying toinsert claims : '+claims); + let url = this.baseUrl +"claims/bulk"; + let body = JSON.stringify( claims ); + console.warn('Json body: : '+body); + let headers = new Headers({ 'Content-Type': 'application/json' }); + let options = new RequestOptions({ headers: headers }); + return this.http.post(url, body, options) + .map(res => res.json()) + .do(request => console.info("Insert Response:"+request.status) ) + .catch(this.handleError); + + } + insertClaim(claim):any{ + console.warn('Trying toinsert claim : '+claim); + let url = this.baseUrl +"claims"; + let body = JSON.stringify( claim ); + let headers = new Headers({ 'Content-Type': 'application/json' }); + let options = new RequestOptions({ headers: headers }); + return this.http.post(url, body, options) + .map(res => res.json()) + .do(request => console.info("Insert Response:"+request.status) ) + .catch(this.handleError); + + } + + private handleError (error: Response) { + // in a real world app, we may send the error to some remote logging infrastructure + // instead of just logging it to the console + console.error(error); + return Observable.throw(error || 'Server error'); + } + + getClaim(id:string):any { + let url = this.baseUrl+"claims/"+id; + return new Promise((resolve, reject) => { + this.http.get(url) + .map(res => res.json()) + .subscribe( + data => { + resolve(data.data); + }, + err => { + reject(err); + } + ) + ; + }); + } + +} diff --git a/sample-components/sampleComponent-2/src/assets/logo.png b/sample-components/sampleComponent-2/src/assets/logo.png new file mode 100644 index 00000000..afea237f Binary files /dev/null and b/sample-components/sampleComponent-2/src/assets/logo.png differ diff --git a/sample-components/sampleComponent-2/src/backend/api.ts b/sample-components/sampleComponent-2/src/backend/api.ts new file mode 100644 index 00000000..d8f4f517 --- /dev/null +++ b/sample-components/sampleComponent-2/src/backend/api.ts @@ -0,0 +1,24 @@ +// Our API for demos only +import {fakeDataBase} from './db'; +import {fakeDemoRedisCache} from './cache'; + +// you would use cookies/token etc +var USER_ID = 'f9d98cf1-1b96-464e-8755-bcc2a5c09077'; // hardcoded as an example + +// Our API for demos only +export function serverApi(req, res) { + let key = USER_ID + '/data.json'; + let cache = fakeDemoRedisCache.get(key); + if (cache !== undefined) { + console.log('/data.json Cache Hit'); + return res.json(cache); + } + console.log('/data.json Cache Miss'); + + fakeDataBase.get() + .then(data => { + fakeDemoRedisCache.set(key, data); + return data; + }) + .then(data => res.json(data)); +} diff --git a/sample-components/sampleComponent-2/src/backend/cache.ts b/sample-components/sampleComponent-2/src/backend/cache.ts new file mode 100644 index 00000000..490a3561 --- /dev/null +++ b/sample-components/sampleComponent-2/src/backend/cache.ts @@ -0,0 +1,17 @@ + + +var _fakeLRUcount = 0; +export const fakeDemoRedisCache = { + _cache: {}, + get: (key) => { + let cache = fakeDemoRedisCache._cache[key]; + _fakeLRUcount++; + if (_fakeLRUcount >= 10) { + fakeDemoRedisCache.clear(); + _fakeLRUcount = 0; + } + return cache; + }, + set: (key, data) => fakeDemoRedisCache._cache[key] = data, + clear: () => fakeDemoRedisCache._cache = {} +}; diff --git a/sample-components/sampleComponent-2/src/backend/db.ts b/sample-components/sampleComponent-2/src/backend/db.ts new file mode 100644 index 00000000..3ba8ea3d --- /dev/null +++ b/sample-components/sampleComponent-2/src/backend/db.ts @@ -0,0 +1,7 @@ +// Our API for demos only +export const fakeDataBase = { + get() { + let res = { data: 'This fake data came from the db on the server.' }; + return Promise.resolve(res); + } +}; diff --git a/sample-components/sampleComponent-2/src/client.ts b/sample-components/sampleComponent-2/src/client.ts new file mode 100644 index 00000000..4b89d28d --- /dev/null +++ b/sample-components/sampleComponent-2/src/client.ts @@ -0,0 +1,20 @@ +// the polyfills must be the first thing imported +import 'angular2-universal-polyfills'; + +// Angular 2 +import { enableProdMode} from '@angular/core'; +import { platformUniversalDynamic } from 'angular2-universal'; + +// enable prod for faster renders +enableProdMode(); + +import { MainModule } from './main.browser'; + +const platformRef = platformUniversalDynamic(); + +// on document ready bootstrap Angular 2 +document.addEventListener('DOMContentLoaded', () => { + + platformRef.bootstrapModule(MainModule); + +}); diff --git a/sample-components/sampleComponent-2/src/index.html b/sample-components/sampleComponent-2/src/index.html new file mode 100644 index 00000000..3c3c2067 --- /dev/null +++ b/sample-components/sampleComponent-2/src/index.html @@ -0,0 +1,31 @@ + + + + OpenAIRE + + + + + + + + + + + + + + + + + + + Loading Universal ... + + + + + diff --git a/sample-components/sampleComponent-2/src/main.browser.ts b/sample-components/sampleComponent-2/src/main.browser.ts new file mode 100644 index 00000000..074b673b --- /dev/null +++ b/sample-components/sampleComponent-2/src/main.browser.ts @@ -0,0 +1,38 @@ +import { NgModule } from '@angular/core'; +import { FormsModule } from '@angular/forms'; + +import { UniversalModule } from 'angular2-universal'; + +import { App } from './app/app'; +//for routing: +import {ClaimsAdminComponent} from './app/claimPages/claims/claimsAdmin.component'; +import { routing } from './app/app.routing'; +import {Routes, RouterModule} from "@angular/router"; + +import {Open} from './app/common/modal/open.component'; + +import {Alert} from './app/common/modal/alert'; +import {Loading} from './app/common/modal/loading.component'; +import {ClaimsComponent} from './app/claimPages/claims/claims.component'; +import {ClaimsService} from './app/services/claims.service'; +import {Claim} from './app/entities/claim'; +import {pagingFormatterNoLoad} from './app/common/pagingFormatterNoLoad.component'; + +import {ClaimEntityFormatter} from './app/common/claimEntityFormatter.component'; +import {PublicationTitleFormatter} from './app/common/publicationTitleFormatter.component'; +import {ProjectTitleFormatter} from './app/common/projectTitleFormatter.component'; +import {HomeComponent} from './app/home/home.component'; + +@NgModule({ + bootstrap: [ App ], + declarations: [ App, ClaimsAdminComponent, ClaimsComponent, ClaimEntityFormatter,pagingFormatterNoLoad, Open, ProjectTitleFormatter, PublicationTitleFormatter,HomeComponent, Loading, Alert], + imports: [ + UniversalModule, // BrowserModule, HttpModule, and JsonpModule are included + FormsModule, + routing + ], + providers: [ ClaimsService ] +}) +export class MainModule { + +} diff --git a/sample-components/sampleComponent-2/src/main.node.ts b/sample-components/sampleComponent-2/src/main.node.ts new file mode 100644 index 00000000..e635b031 --- /dev/null +++ b/sample-components/sampleComponent-2/src/main.node.ts @@ -0,0 +1,21 @@ +import { NgModule } from '@angular/core'; +import { FormsModule } from '@angular/forms'; +import { RouterModule } from '@angular/router'; +import { UniversalModule } from 'angular2-universal'; +import { HomeComponent } from './app/home/home.component'; +import { App } from './app/app'; + +@NgModule({ + bootstrap: [ App ], + declarations: [ App, HomeComponent ], + imports: [ + UniversalModule, // NodeModule, NodeHttpModule, and NodeJsonpModule are included + FormsModule, + RouterModule.forRoot([ + { path: '', component: HomeComponent, pathMatch: 'full' } + ]) + ] +}) +export class MainModule { + +} diff --git a/sample-components/sampleComponent-2/src/server.ts b/sample-components/sampleComponent-2/src/server.ts new file mode 100644 index 00000000..21f61053 --- /dev/null +++ b/sample-components/sampleComponent-2/src/server.ts @@ -0,0 +1,70 @@ +// the polyfills must be the first thing imported in node.js +import 'angular2-universal-polyfills'; + +import * as path from 'path'; +import * as express from 'express'; +import * as bodyParser from 'body-parser'; +import * as cookieParser from 'cookie-parser'; + +// Angular 2 +import { enableProdMode } from '@angular/core'; +// Angular 2 Universal +import { createEngine } from 'angular2-express-engine'; + +// App +import { MainModule } from './main.node'; + +// enable prod for faster renders +enableProdMode(); + +const app = express(); +const ROOT = path.join(path.resolve(__dirname, '..')); + +// Express View +app.engine('.html', createEngine({})); +app.set('views', __dirname); +app.set('view engine', 'html'); + +app.use(cookieParser('Angular 2 Universal')); +app.use(bodyParser.json()); + +// Serve static files +app.use('/assets', express.static(path.join(__dirname, 'assets'), {maxAge: 30})); +app.use(express.static(path.join(ROOT, 'dist/client'), {index: false})); +/* **AK** Add this path so that index.html can see files from node_modules folder (e.g. bootstrap files)*/ +app.use(express.static(path.join(ROOT, 'node_modules'), {index: false})); +// app.get('/bootstrap.css', express.static(path.join(ROOT, 'node_modules/bootstrap/dist/css/bootstrap.min.css'))); + +import { serverApi } from './backend/api'; +// Our API for demos only +app.get('/data.json', serverApi); + +function ngApp(req, res) { + res.render('index', { + req, + res, + ngModule: MainModule, + preboot: false, + baseUrl: '/', + requestUrl: req.originalUrl, + originUrl: req.hostname + }); +} +// Routes with html5pushstate +// ensure routes match client-side-app +app.get('/', ngApp); +app.get('/claims', ngApp); +app.get('/home', ngApp); + + +app.get('*', function(req, res) { + res.setHeader('Content-Type', 'application/json'); + var pojo = { status: 404, message: 'No Content' }; + var json = JSON.stringify(pojo, null, 2); + res.status(404).send(json); +}); + +// Server +let server = app.listen(process.env.PORT || 3000, () => { + console.log(`Listening on: http://localhost:${server.address().port}`); +}); diff --git a/sample-components/sampleComponent-2/src/typings.d.ts b/sample-components/sampleComponent-2/src/typings.d.ts new file mode 100644 index 00000000..89020e14 --- /dev/null +++ b/sample-components/sampleComponent-2/src/typings.d.ts @@ -0,0 +1,56 @@ +/* + * Custom Type Definitions + * When including 3rd party modules you also need to include the type definition for the module + * if they don't provide one within the module. You can try to install it with typings +typings install node --save + * If you can't find the type definition in the registry we can make an ambient definition in + * this file for now. For example +declare module "my-module" { + export function doesSomething(value: string): string; +} + * + * If you're prototying and you will fix the types later you can also declare it as type any + * +declare var assert: any; + * + * If you're importing a module that uses Node.js modules which are CommonJS you need to import as + * +import * as _ from 'lodash' + * You can include your type definitions in this file until you create one for the typings registry + * see https://github.com/typings/registry + * + */ + + +// Extra variables that live on Global that will be replaced by webpack DefinePlugin +declare var ENV: string; +declare var HMR: boolean; +interface GlobalEnvironment { + ENV; + HMR; +} + +interface WebpackModule { + hot: { + data?: any, + idle: any, + accept(dependencies?: string | string[], callback?: (updatedDependencies?: any) => void): void; + decline(dependencies?: string | string[]): void; + dispose(callback?: (data?: any) => void): void; + addDisposeHandler(callback?: (data?: any) => void): void; + removeDisposeHandler(callback?: (data?: any) => void): void; + check(autoApply?: any, callback?: (err?: Error, outdatedModules?: any[]) => void): void; + apply(options?: any, callback?: (err?: Error, outdatedModules?: any[]) => void): void; + status(callback?: (status?: string) => void): void | string; + removeStatusHandler(callback?: (status?: string) => void): void; + }; +} + +interface WebpackRequire { + context(file: string, flag?: boolean, exp?: RegExp): any; +} + +// Extend typings +interface NodeRequire extends WebpackRequire {} +interface NodeModule extends WebpackModule {} +interface Global extends GlobalEnvironment {} diff --git a/sample-components/sampleComponent-2/tsconfig.json b/sample-components/sampleComponent-2/tsconfig.json new file mode 100644 index 00000000..02adde85 --- /dev/null +++ b/sample-components/sampleComponent-2/tsconfig.json @@ -0,0 +1,30 @@ +{ + "compilerOptions": { + "declaration": false, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "module": "commonjs", + "moduleResolution": "node", + "outDir": "dist", + "sourceMap": true, + "sourceRoot": "src", + "target": "es5", + "lib": ["es6", "dom"], + "types": [ + "body-parser", + "compression", + "cookie-parser", + "express", + "express-serve-static-core", + "mime", + "node", + "serve-static" + ] + }, + "exclude": [ + "node_modules" + ], + "compileOnSave": false, + "buildOnSave": false, + "atom": { "rewriteTsconfig": false } +} diff --git a/sample-components/sampleComponent-2/webpack.config.ts b/sample-components/sampleComponent-2/webpack.config.ts new file mode 100644 index 00000000..f70d9498 --- /dev/null +++ b/sample-components/sampleComponent-2/webpack.config.ts @@ -0,0 +1,102 @@ +var webpack = require('webpack'); +var path = require('path'); +var resolveNgRoute = require('@angularclass/resolve-angular-routes'); + + +var commonConfig = { + resolve: { + extensions: ['', '.ts', '.js', '.json'] + }, + module: { + preLoaders: [ + ], + loaders: [ + // TypeScript + { test: /\.ts$/, loaders: ['ts-loader', 'angular2-template-loader'] }, + { test: /\.html$/, loader: 'raw-loader' }, + { test: /\.css$/, loader: 'raw-loader' }, + { test: /\.json$/, loader: 'json-loader' } + ], + }, + plugins: [ + new webpack.ContextReplacementPlugin( + // The (\\|\/) piece accounts for path separators in *nix and Windows + /angular(\\|\/)core(\\|\/)src(\\|\/)linker/, + root('./src'), + resolveNgRoute(root('./src')) + ) + ] + +}; + + +var clientConfig = { + target: 'web', + entry: './src/client', + output: { + path: root('dist/client') + }, + node: { + global: true, + __dirname: true, + __filename: true, + process: true, + Buffer: false + } +}; + + +var serverConfig = { + target: 'node', + entry: './src/server', // use the entry file of the node server if everything is ts rather than es5 + output: { + path: root('dist/server'), + libraryTarget: 'commonjs2' + }, + externals: checkNodeImport, + node: { + global: true, + __dirname: true, + __filename: true, + process: true, + Buffer: true + } +}; + + + +// Default config +var defaultConfig = { + context: __dirname, + resolve: { + root: root('/src') + }, + output: { + publicPath: path.resolve(__dirname), + filename: 'index.js' + } +}; + + + +var webpackMerge = require('webpack-merge'); +module.exports = [ + // Client + webpackMerge({}, defaultConfig, commonConfig, clientConfig), + + // Server + webpackMerge({}, defaultConfig, commonConfig, serverConfig) +]; + +// Helpers +function checkNodeImport(context, request, cb) { + if (!path.isAbsolute(request) && request.charAt(0) !== '.') { + cb(null, 'commonjs ' + request); return; + } + cb(); +} + +function root(args) { + args = Array.prototype.slice.call(arguments, 0); + return path.join.apply(path, [__dirname].concat(args)); +} diff --git a/sample-components/sampleComponent-rc4/nodemon.json b/sample-components/sampleComponent-rc4/nodemon.json new file mode 100644 index 00000000..97a836fb --- /dev/null +++ b/sample-components/sampleComponent-rc4/nodemon.json @@ -0,0 +1,7 @@ +{ + "watch": [ + "dist", + "src/index.html" + ], + "ext" : "js ts json html" +} diff --git a/sample-components/sampleComponent-rc4/package.json b/sample-components/sampleComponent-rc4/package.json new file mode 100644 index 00000000..c9a9d2fb --- /dev/null +++ b/sample-components/sampleComponent-rc4/package.json @@ -0,0 +1,51 @@ +{ + "name": "test-portal", + "version": "1.0.0-rc4", + "description": "Open Access Infrastructure for Research in Europe ", + "scripts": { + "postinstall": "typings install", + "watch": "webpack --watch", + "prebuild": "rimraf dist", + "build": "webpack", + "build:prod": "webpack --progress -p", + "prestart": "npm run build", + "server": "nodemon dist/server/index.js", + "start": "npm run server", + "predebug": "npm run build", + "debug": "node --debug-brk dist/server/index.js" + }, + "license": "UOA", + "dependencies": { + "@angular/common": "2.0.0-rc.4", + "@angular/compiler": "2.0.0-rc.4", + "@angular/core": "2.0.0-rc.4", + "@angular/forms": "0.2.0", + "@angular/http": "2.0.0-rc.4", + "@angular/platform-browser": "2.0.0-rc.4", + "@angular/platform-browser-dynamic": "2.0.0-rc.4", + "@angular/platform-server": "2.0.0-rc.4", + "@angular/router": "3.0.0-beta.1", + "angular2-universal": "~0.104.5", + "body-parser": "^1.15.1", + "bootstrap": "^3.3.6", + "express": "^4.14.0", + "methods": "~1.1.2", + "parse5": "^1.5.0", + "preboot": "^2.1.2", + "rxjs": "5.0.0-beta.6" + }, + "devDependencies": { + "angular2-template-loader": "^0.4.0", + "cookie-parser": "^1.4.3", + "nodemon": "^1.9.2", + "raw-loader": "^0.5.1", + "rimraf": "^2.5.2", + "source-map-loader": "^0.1.5", + "ts-loader": "^0.8.2", + "typescript": "^1.8.9", + "typings": "~1.0.5", + "webpack": "^1.13.1", + "webpack-dev-server": "^1.14.0", + "webpack-merge": "^0.13.0" + } +} diff --git a/sample-components/sampleComponent-rc4/src/app/app.component.ts b/sample-components/sampleComponent-rc4/src/app/app.component.ts new file mode 100644 index 00000000..52b8e4db --- /dev/null +++ b/sample-components/sampleComponent-rc4/src/app/app.component.ts @@ -0,0 +1,116 @@ +import {Component, Directive, ElementRef, Renderer} from '@angular/core'; +import {RouterConfig, ROUTER_DIRECTIVES } from '@angular/router'; +import {Http} from '@angular/http'; +// import {SearchComponent} from './searchPages/search.component'; +// import {ClaimComponent} from './claimPages/claim/claim.component'; +import {ClaimsAdminComponent} from './claimPages/claims/claimsAdmin.component'; +import {HomeComponent} from './home/home.component'; +// import {LinkingComponent} from './claimPages/linking/linking.component'; +// import {LinkingHomeComponent} from './claimPages/linking/linkingHome.component'; +// import {MyClaimsComponent} from './claimPages/myClaims/myClaims.component'; +// import {ProjectComponent} from './landingPages/project/project.component'; +// import {DatasetComponent} from './landingPages/dataset/dataset.component'; +// import {PersonComponent} from './landingPages/person/person.component'; +// import {PublicationComponent} from './landingPages/publication/publication.component'; +// import {OrganizationComponent} from './landingPages/organization/organization.component'; +// import {MyClaimsDemoComponent} from './claimPages/myClaimsDemo.component'; +// import {SearchPublicationsComponent} from './searchPages/searchPublications.component'; +// import {AdvancedSearchPublicationsComponent} from './searchPages/advancedSearchPublications.component'; +// import {UploadComponent} from './upload.component'; +// import {BulkLinkingComponent} from './claimPages/linking/bulkLinking.component'; +// import {DepositComponent} from './deposit/deposit.component'; +import 'rxjs/Rx'; + + + +@Component({ + selector: 'app', + directives: [ + ...ROUTER_DIRECTIVES + ], + precompile: [ ClaimsAdminComponent, HomeComponent], + styles: [` + .router-link-active { + background-color: lightgray; + } + `], + template: ` +
+ + +
+ +
+ +
+ ` +}) + + + + +export class App { + name: string = 'Angular 2'; + data = {}; + server; + + constructor(public http: Http ) { + + } + + + ngOnInit() { + setTimeout(() => { + this.server = 'Rendered on the Server'; + }, 10); + + } + +} + +export const routes: RouterConfig = [ + { path: '', + pathMatch: 'full', + redirectTo: 'home' }, + { path: 'home', component: HomeComponent }, + { path: 'claims', component: ClaimsAdminComponent } ]; +// , +// { path: 'claim', component: ClaimComponent }, +// { path: 'search', component: SearchComponent }, +// { path: 'linking', component: LinkingComponent }, +// { path: 'my-claims', component: MyClaimsComponent }, +// { path: 'demo', component: MyClaimsDemoComponent }, +// { path: 'project', component: ProjectComponent}, +// { path: 'publication', component: PublicationComponent }, +// { path: 'dataset', component: DatasetComponent}, +// { path: 'person', component: PersonComponent }, +// { path: 'organization', component: OrganizationComponent }, +// { path: 'up', component: UploadComponent}, +// { path: 'bulk-linking', component: BulkLinkingComponent}, +// { path: 'search-publications', component: SearchPublicationsComponent }, +// { path: 'advanced-search-publications', component: AdvancedSearchPublicationsComponent }, +// { path: 'deposit', component: DepositComponent} +// +// ]; diff --git a/sample-components/sampleComponent-rc4/src/app/claimPages/claims/claims.component.html b/sample-components/sampleComponent-rc4/src/app/claimPages/claims/claims.component.html new file mode 100644 index 00000000..0ebd0692 --- /dev/null +++ b/sample-components/sampleComponent-rc4/src/app/claimPages/claims/claims.component.html @@ -0,0 +1,107 @@ +
+
+
+
+ +
Claims related to
+ +
+

+ +

+

+ +

+

+ +

+

+ +

+

+ +

+
+
+
+ + +
+ diff --git a/sample-components/sampleComponent-rc4/src/app/claimPages/claims/claims.component.ts b/sample-components/sampleComponent-rc4/src/app/claimPages/claims/claims.component.ts new file mode 100644 index 00000000..8532fc6d --- /dev/null +++ b/sample-components/sampleComponent-rc4/src/app/claimPages/claims/claims.component.ts @@ -0,0 +1,491 @@ +import {Component, ViewChild, Input} from '@angular/core'; +import {JSONP_PROVIDERS} from '@angular/http'; +import {Location} from '@angular/common'; +import {Observable} from 'rxjs/Observable'; +import {ROUTER_DIRECTIVES,ActivatedRoute, Router} from '@angular/router'; +import {ClaimsService} from '../../services/claims.service'; +import {Claim} from '../../entities/claim'; +import {pagingFormatterNoLoad} from '../../common/pagingFormatterNoLoad.component'; + +import {ClaimEntityFormatter} from '../../common/claimEntityFormatter.component'; + +@Component({ + selector: 'claims', + directives: [...ROUTER_DIRECTIVES,ClaimEntityFormatter,pagingFormatterNoLoad ], + templateUrl: 'claims.component.html', + providers:[ ClaimsService, JSONP_PROVIDERS] + +}) +export class ClaimsComponent { + constructor (private _claimService: ClaimsService, private route: ActivatedRoute, private _router:Router, private location: Location) { + } + + ngOnInit() { + this.sub = this._router.routerState.queryParams.subscribe(params => { + if( this.myClaims == 'true' ){ + this.fetchBy = "User"; + }else{ + + this.fetchBy = params['fetchBy']; + this.fetchBy = (this.types.indexOf(this.fetchBy) != -1)? this.fetchBy:'All'; + this.fetchId = params['fetchId']; + this.fetchId=this.fetchId?this.fetchId:''; + + } + + let page = (params['page']=== undefined)?1:+params['page']; + let size = (params['size']=== undefined)?10:+params['size']; + + this.keyword = (params['keyword']?params['keyword']:""); + this.inputkeyword = this.keyword; + this.page = ( page <= 0 ) ? 1 : page; + this.size = ( size <= 0 ) ? 10 : size; + this.entityTypes = []//(params['types']?params['types']:[]); + this.setTypes(params['types']); // check the appropriate checkboxes + this.setSortby(params['sort']); + this.getClaims(); + + }); + // this.sub = this.route.params.subscribe(params => { + // console.info(this.isAdmin+" "+this.myClaims+" Fetch by: "+this.fetchBy+" Fetch id: "+this.fetchId); + // if( this.myClaims == 'true' ){ + // console.info("Is myclaims"); + // this.fetchBy = "User"; + // }else{ + // console.info("Is admin"); + // + // console.info(this.isAdmin); + // + // this.fetchBy = params['fetchBy']; + // this.fetchBy = (this.types.indexOf(this.fetchBy) != -1)? this.fetchBy:'All'; + // this.fetchId = params['fetchId']; + // console.info("Fetch by:"+this.fetchBy+"Fetch id:"+this.fetchId); + // this.fetchId=this.fetchId?this.fetchId:''; + // + // } + // + // console.info(this.isAdmin+" "+this.myClaims+" Fetch by: "+this.fetchBy+" Fetch id: "+this.fetchId); + // let page = (params['page']=== undefined)?1:+params['page']; + // let size = (params['size']=== undefined)?10:+params['size']; + // + // this.keyword = (params['keyword']?params['keyword']:""); + // this.inputkeyword = this.keyword; + // this.page = ( page <= 0 ) ? 1 : page; + // this.size = ( size <= 0 ) ? 10 : size; + // this.entityTypes = []//(params['types']?params['types']:[]); + // this.setTypes(params['types']); // check the appropriate checkboxes + // this.setSortby(params['sort']); + // this.getClaims(); + // console.info("params: "+params['page']+" page "+page +" this.page: "+this.page ); + // }); + } + ngOnDestroy() { + this.sub.unsubscribe(); + } + sub: any; + //string because comes as input from component directive + @Input() enableDelete: string = 'false'; + @Input() myClaims: string= 'false' ; + @Input() isAdmin:string = 'false'; + page : number; + size:number; + keyword:string; // the keyword string to give to the request as parameter + inputkeyword:string; // the string written in the input field (keyword=inputkeyword when its length is bigger than 3 and the user stops typing) + lengths = [10,20,30,50]; + types = ["All","Project","Context","Result","User"]; + @Input() fetchBy:string; + @Input() fetchId:string; + + navigateTo: string = "Claims"; + resultsNum: number ; + claims: string[]; + + // @ViewChild (Loading) loading : Loading ; + + //checkboxes: + publicationCB = false; + datasetCB = false; + contextCB = false; + projectCB = false; + entityTypes : string[] =[] ; + + descending = true; + sortby = "date"; + + selected=[]; + deleteMessage:string = ""; + showErrorMessage:boolean = false; + + //params for pagingFormatter to use when navigate to page + params; + // @ViewChild(Alert) alert; + + claimsDeleted:number = 0; + + getClaims () { + this.selected=[]; + var types = ''; + this.showErrorMessage = false; + for (var type of this.entityTypes){ + types+=(types.length>0?'&':'')+"types="+type; + } + if(this.fetchBy =="Project" ){ + this._claimService.getClaimsByProject(this.size,this.page,this.fetchId,this.keyword,this.sortby,this.descending, types).subscribe( + data => { + this.claims = data.data; + this.resultsNum= data.total; + }, + err => { + console.error(err); + this.showErrorMessage = true; + } + ); + }else if(this.fetchBy =="User"){ + this._claimService.getClaimsByUser(this.size,this.page,this.fetchId,this.keyword,this.sortby,this.descending, types).subscribe( + data => { + this.claims = data.data; + this.resultsNum= data.total; + }, + err => { + console.error(err); + this.showErrorMessage = true; + } + ); + }else if(this.fetchBy =="Result"){ + this._claimService.getClaimsByResult(this.size,this.page,this.fetchId,this.keyword,this.sortby,this.descending, types).subscribe( + data => { + this.claims = data.data; + this.resultsNum= data.total; + }, + err => { + console.error(err); + this.showErrorMessage = true; + } + ); + }else if(this.fetchBy =="Context"){ + this._claimService.getClaimsBycontext(this.size,this.page,this.fetchId,this.keyword,this.sortby,this.descending, types).subscribe( + data => { + this.claims = data.data; + this.resultsNum= null; + this.resultsNum= data.total;//data.length; //TODO get the total results num + }, + err => { + console.error(err); + this.showErrorMessage = true; + } + ); + }else{ + this._claimService.getClaims(this.size,this.page,this.keyword,this.sortby,this.descending, types).subscribe( + data => { + this.claims = data.data; + this.resultsNum = null; + this.resultsNum= data.total;//data.length; //TODO get the total results num + }, + err => { + console.error(err); + this.showErrorMessage = true; + } + ); + } + } + + goToClaim(claimId: number){ + this._router.navigate( ['Claim', { id: claimId}] ); + } + goTo(page:number = 1){ + + this.page = page; + + this.location.go(location.pathname,this.getParametersString()); + this.getClaims(); + } + getParameters(){ + let params={ page: this.page, size: this.size, types: this.entityTypes, fetchBy: this.fetchBy, fetchId:this.fetchId, keyword : this.keyword, sort: this.getSortby() }; + return params; + } + getParametersString(){ + var params=''; + params+=(this.page==1?"":(params.length>0?'&':'')+"page="+this.page); + params+=(this.size==10?"":(params.length>0?'&':'')+"size="+this.size); + // params+=(this.entityTypes==''?"":(params.length>0?'&':'')+"types="+this.entityTypes); + var types=""; + for (var type of this.entityTypes){ + types+=(types.length>0?',':'')+type; + } + params+=(types.length>0)?"types="+types:""; + + if(this.isAdmin === 'true'){ + params+=(this.fetchBy=='All'?"":(params.length>0?'&':'')+"fetchBy="+this.fetchBy); + params+=(this.fetchId==''?"":(params.length>0?'&':'')+"fetchId="+this.fetchId); + } + params+=(this. getSortby()=='datedesc'?"":(params.length>0?'&':'')+"sort="+this. getSortby()); + params+=(this.keyword==''?"":(params.length>0?'&':'')+"keyword="+this.keyword); + return params; + } + changeLength(){ + this.goTo(); + } + clearFilters(){ + this.keyword = ''; + this.inputkeyword = ''; + this.publicationCB = false; + this.projectCB = false; + this.datasetCB = false; + this.contextCB = false; + this.entityTypes = []; + this.goTo(); + } + changeOrderby(sortby:string){ + if(sortby==this.sortby){ + this.descending = !this.descending; + }else{ + this.sortby = sortby; + this.descending = false; + } + this.goTo(); + } + setSortby(sortby:string){ + if(!sortby|| sortby == "datedesc"){ + this.descending = true; + this.sortby = "date"; + }else if(sortby == "dateasc"){ + this.descending = false; + this.sortby = "date"; + }else if(sortby == "userasc"){ + this.descending = false; + this.sortby = "user"; + }else if(sortby == "userdesc"){ + this.descending = true; + this.sortby = "user"; + }if(sortby =="sourceasc"){ + this.descending = false; + this.sortby = "source"; + }else if(sortby == "sourcedesc"){ + this.descending = true; + this.sortby = "source"; + }else if(sortby == "targetasc"){ + this.descending = false; + this.sortby = "target"; + }else if(sortby == "targetdesc"){ + this.descending = true; + this.sortby = "target"; + } + } + getSortby():string{ + if(this.descending){ + return this.sortby+"desc"; + }else{ + return this.sortby+"asc"; + } + + } + changeType(){ + this.entityTypes = []; + if(this.publicationCB){ + this.entityTypes.push('publication'); + } + if(this.datasetCB){ + this.entityTypes.push('dataset'); + } + if(this.projectCB){ + this.entityTypes.push('project'); + } + if(this.contextCB){ + this.entityTypes.push('context'); + } + + // if(this.publicationCB == true && this.datasetCB == true && this.contextCB == true && this.projectCB == true ){ + // this.entityTypes=""; + // }else{ + // this.entityTypes = ""; + // if(this.publicationCB == true){ + // this.entityTypes = "publication"; + // } + // if(this.datasetCB == true){ + // this.entityTypes += (this.entityTypes.length > 0?",":"")+"dataset"; + // } + // if(this.contextCB == true){ + // this.entityTypes += (this.entityTypes.length > 0?",":"")+"context"; + // } + // if(this.projectCB == true){ + // this.entityTypes += (this.entityTypes.length > 0?",":"")+"project"; + // } + // } + // console.debug("Type changed: "+this.entityTypes+" "+this.publicationCB+ this.datasetCB + this.contextCB + this.projectCB); + this.goTo(); + } + setTypes(types:string){ + if(!types){ + return; + } + if(types.length > 0){ + this.entityTypes = []; + if(types.indexOf("publication")!=-1){ + this.publicationCB = true; + this.entityTypes.push("publication"); + } + if(types.indexOf("dataset")!=-1){ + this.datasetCB = true; + this.entityTypes.push("dataset"); + } + if(types.indexOf("project")!=-1){ + this.projectCB = true; + this.entityTypes.push("project"); + } + if(types.indexOf("context")!=-1){ + this.contextCB = true; + this.entityTypes.push("context"); + } + } + if(this.publicationCB && this.datasetCB && this.contextCB && this.projectCB){ + this.entityTypes=[]; + } + } + changekeyword(){ + + if(this.inputkeyword.length >= 3 || this.inputkeyword.length == 0 ){ + this.keyword = this.inputkeyword; + this.page = 1; + this.goTo(); + } + + } + select(item:any,event){ + this.deleteMessage=""; + var value = event.currentTarget.checked; + if(value){ + this.selected.push(item); + }else{ + for (var _i = 0; _i < this.selected.length; _i++) { + let claim = this.selected[_i]; + if(claim['id'] == item.id){ + this.selected.splice(_i, 1); + } + } + + + } + } + selectAll(){ + this.selected = []; + for (var _i = 0; _i < this.claims.length; _i++) { + let claim = this.claims[_i]; + this.selected.push(claim); + } + this.deleteMessage = ""; + } + deselectAll(){ + this.selected = []; + this.deleteMessage=""; + } + isSelected(id:string){ + for (var _i = 0; _i < this.selected.length; _i++) { + let claim = this.selected[_i]; + if(claim['id'] == id){ + return true; + } + } + return false; + } + + + // confirmOpen(){ + // if(this.selected.length <= 0){ + // + // }else{ + // this.alert.cancelButton = true; + // this.alert.okButton = true; + // this.alert.alertTitle = "Delete "+this.selected.length+" claim(s)"; + // this.alert.message = this.selected.length+" claims will be deleted. Do you want to proceed? "; + // this.alert.okButtonText = "Yes"; + // this.alert.cancelButtonText = "No"; + // this.alert.open(); + // } + // } + // confirmClose(data){ + // this.delete(); + // } + // delete(){ + // this.deleteMessage=""; + // this.loading.open(); + // this.claimsDeleted = 0; + // var ids = []; + // for (var i = 0; i < this.selected.length; i++){ + // var id =this.selected[i].id; + // ids.push(id); + // // var selected =this.selected[i].id; + // // console.warn("Deleting claim with id:"+id); + // // this.deleteById(id); + // //TODO for multiple concurrent + // } + // this.batchDeleteById(ids); + // } + + // deleteById(id:string){ + // + // console.warn("Deleting claim with id:"+id); + // // this._claimService.deleteClaimById(id); + // this._claimService.deleteClaimById(id).subscribe( + // res => { + // console.info('Delete response'+res.code ); + // console.warn("Deleted claim with id:"+ id); + // //remove this claim from the + // let newClaims=this.claims; + // for (var _i = 0; _i < this.claims.length; _i++) { + // let claim = this.claims[_i]; + // if(claim['id'] == id){ + // newClaims.splice(_i, 1); + // } + // } + // //TODO should call getClaims??? + // this.claimsDeleted++; + // this.claims = newClaims; + // if(this.claimsDeleted == this.selected.length){ + // this.resultsNum = this.resultsNum - this.selected.length; + // this.loading.close(); + // this.selected = []; + // } + // + // + // }); + // } + // batchDeleteById(ids:string[]){ + // + // console.warn("Deleting claim with ids:"+ids); + // this._claimService.deleteBulk(ids).subscribe( + // res => { + // console.info('Delete response'+res.code ); + // console.warn("Deleted ids:"+ res.deletedIds); + // console.warn("Not found ids:"+ res.notFoundIds); + // //remove this claim from the + // let newClaims=this.claims; + // for(var id of res.deletedIds){ + // for (var _i = 0; _i < this.claims.length; _i++) { + // let claim = this.claims[_i]; + // if(claim['id'] == id){ + // newClaims.splice(_i, 1); + // } + // } + // for (var _i = 0; _i < this.selected.length; _i++) { + // let claim = this.selected[_i]; + // if(claim['id'] == id){ + // this.selected.splice(_i, 1); + // } + // } + // } + // this.claims = newClaims; + // this.resultsNum = this.resultsNum - res.deletedIds.length; + // this.loading.close(); + // if(res.deletedIds.length>0){ + // this.deleteMessage=this.deleteMessage+'
'+res.deletedIds.length+' claim(s) successfully deleted.
'; + // } + // if(res.notFoundIds.length>0){ + // this.deleteMessage=this.deleteMessage+'
'+res.notFoundIds.length+' claim(s) couldn\'t be deleted.
'; + // } + // }); + // } + pageChange($event) { + var page:number = +$event.value + this.goTo(page); + } +} diff --git a/sample-components/sampleComponent-rc4/src/app/claimPages/claims/claimsAdmin.component.ts b/sample-components/sampleComponent-rc4/src/app/claimPages/claims/claimsAdmin.component.ts new file mode 100644 index 00000000..19d231b3 --- /dev/null +++ b/sample-components/sampleComponent-rc4/src/app/claimPages/claims/claimsAdmin.component.ts @@ -0,0 +1,40 @@ +import {Component, ViewChild, Input} from '@angular/core'; +import {JSONP_PROVIDERS} from '@angular/http'; +import {Location} from '@angular/common'; +import {Observable} from 'rxjs/Observable'; +import {ROUTER_DIRECTIVES } from '@angular/router'; +import {ClaimsComponent} from './claims.component'; + +@Component({ + selector: 'claims', + directives: [...ROUTER_DIRECTIVES , ClaimsComponent], + template: ` +
+ + +
+ + +
+ TODO login +
+ `, + +}) +export class ClaimsAdminComponent { + constructor ( ) { + + } +user:string="argirok@di.uoa.gr"; + ngOnInit() { + + + } + + +} diff --git a/sample-components/sampleComponent-rc4/src/app/common/claimEntityFormatter.component.ts b/sample-components/sampleComponent-rc4/src/app/common/claimEntityFormatter.component.ts new file mode 100644 index 00000000..b38ea128 --- /dev/null +++ b/sample-components/sampleComponent-rc4/src/app/common/claimEntityFormatter.component.ts @@ -0,0 +1,39 @@ +import {Component, Input} from '@angular/core'; +import {PublicationTitleFormatter} from './publicationTitleFormatter.component'; +import {ProjectTitleFormatter} from './projectTitleFormatter.component'; + +//Usage Example " " + +//externalUrl +@Component({ + selector: 'claim-entity', + template: ` + +
+ ({{type}}) + +
+
+ (Project) + +
+
+ (Context) +
{{entity.title}}
+
+ `, + directives: [PublicationTitleFormatter,ProjectTitleFormatter] +}) + +export class ClaimEntityFormatter { + @Input() entity: string[]; + @Input() type: string; + + constructor () {} + + ngOnInit() { + + } + + +} diff --git a/sample-components/sampleComponent-rc4/src/app/common/modal/alert.ts b/sample-components/sampleComponent-rc4/src/app/common/modal/alert.ts new file mode 100644 index 00000000..d9f84fd2 --- /dev/null +++ b/sample-components/sampleComponent-rc4/src/app/common/modal/alert.ts @@ -0,0 +1,111 @@ +import {Component, ViewEncapsulation, ComponentRef, DynamicComponentLoader,ElementRef, Input, EventEmitter, Output} from '@angular/core'; +import {Open} from './open.component'; + +@Component({ + selector: 'alert', + template: ` + + `, + providers: [], + directives: [Open], + encapsulation: ViewEncapsulation.None, + pipes: [] +}) +/** + * API to an open alert window. + */ +export class Alert{ + /** + * Caption for the title. + */ + public alertTitle:string; + /** + * Describes if the alert contains Ok Button. + * The default Ok button will close the alert and emit the callback. + * Defaults to true. + */ + public okButton:boolean = true; + /** + * Caption for the OK button. + * Default: Ok + */ + public okButtonText:string= 'Ok'; + /** + * Describes if the alert contains cancel Button. + * The default Cancelbutton will close the alert. + * Defaults to true. + */ + public cancelButton:boolean = true; + /** + * Caption for the Cancel button. + * Default: Cancel + */ + public cancelButtonText:string = 'Cancel'; + /** + * if the alertMessage is true it will show the contentString inside alert body. + */ + public alertMessage:boolean = true; + /** + * Some message/content can be set in message which will be shown in alert body. + */ + public message:string; + /** + * if the value is true alert footer will be visible or else it will be hidden. + */ + public alertFooter:boolean= true; + /** + * shows alert header if the value is true. + */ + public alertHeader:boolean = true; + /** + * if the value is true alert will be visible or else it will be hidden. + */ + public isOpen:boolean=false; + /** + * Emitted when a ok button was clicked + * or when Ok method is called. + */ + @Output() public alertOutput:EventEmitter = new EventEmitter(); + constructor(public dcl:DynamicComponentLoader, public _elementRef: ElementRef){} + /** + * Opens a alert window creating backdrop. + */ + open(){ + this.isOpen= true; + } + /** + * ok method closes the modal and emits modalOutput. + */ + ok(){ + this.isOpen = false; + this.alertOutput.emit(true); + } + /** + * cancel method closes the moda. + */ + cancel(){ + this.isOpen = false; + } +} diff --git a/sample-components/sampleComponent-rc4/src/app/common/modal/loading.component.ts b/sample-components/sampleComponent-rc4/src/app/common/modal/loading.component.ts new file mode 100644 index 00000000..18722dbe --- /dev/null +++ b/sample-components/sampleComponent-rc4/src/app/common/modal/loading.component.ts @@ -0,0 +1,53 @@ +import {Component, ViewEncapsulation, ComponentRef, DynamicComponentLoader,ElementRef, Input, EventEmitter, Output} from '@angular/core'; +import {Open} from './open.component'; + +@Component({ + selector: 'loading', + template: ` + + `, + providers: [], + directives: [Open], + encapsulation: ViewEncapsulation.None, + pipes: [] +}) +/** + * API to an open alert window. + */ +export class Loading{ + +@Input() public message:string ="Loading"; + + /** + * if the value is true alert will be visible or else it will be hidden. + */ + public isOpen:boolean=false; + /** + * Emitted when a ok button was clicked + * or when Ok method is called. + */ + @Output() public alertOutput:EventEmitter = new EventEmitter(); + constructor(public dcl:DynamicComponentLoader, public _elementRef: ElementRef){} + /** + * Opens a alert window creating backdrop. + */ + open(){ + this.isOpen= true; + } + + close(){ + this.isOpen = false; + } +} diff --git a/sample-components/sampleComponent-rc4/src/app/common/modal/open.component.ts b/sample-components/sampleComponent-rc4/src/app/common/modal/open.component.ts new file mode 100644 index 00000000..95add08d --- /dev/null +++ b/sample-components/sampleComponent-rc4/src/app/common/modal/open.component.ts @@ -0,0 +1,55 @@ +import {Directive, Input, HostBinding} from '@angular/core'; + +// todo: add animate +// todo: add init and on change +@Directive({selector: '[open]'}) +export class Open { + @HostBinding('style.display') + private display:string; + @HostBinding('class.in') + @HostBinding('attr.aria-expanded') + private isExpanded:boolean = true; + + @Input() + private set open(value:boolean) { + this.isExpanded = value; + this.toggle(); + } + + private get open():boolean { + return this.isExpanded; + } + + constructor() { + } + init() { + this.isExpanded = false; + this.display = 'none'; + } + toggle() { + if (this.isExpanded) { + this.hide(); + } else { + this.show(); + } + } + + hide() { + this.isExpanded = false; + this.display = 'none'; + if (typeof document !== 'undefined') { + let backDrop = document.getElementsByClassName("modal-backdrop"); + if(backDrop.length>0){ + document.body.removeChild(backDrop[0]); + } + } + } + + show() { + let backDrop = document.createElement('div'); + backDrop.className="modal-backdrop fade in"; + document.body.appendChild(backDrop); + this.isExpanded = true; + this.display = 'block'; + } +} diff --git a/sample-components/sampleComponent-rc4/src/app/common/pagingFormatterNoLoad.component.ts b/sample-components/sampleComponent-rc4/src/app/common/pagingFormatterNoLoad.component.ts new file mode 100644 index 00000000..42534afd --- /dev/null +++ b/sample-components/sampleComponent-rc4/src/app/common/pagingFormatterNoLoad.component.ts @@ -0,0 +1,75 @@ +import {Component, Input, Output, EventEmitter} from '@angular/core'; + + +//Usage Example + +@Component({ + selector: 'paging-no-load', + template: ` + + ` +}) + +export class pagingFormatterNoLoad { + @Input() currentPage: number = 1; + @Input() navigateTo: string; + @Input() term: string=''; + @Input() size: number=10; + @Input() totalResults: number = 10; + @Input() params; + + @Output() pageChange = new EventEmitter(); + + constructor () { + } + + ngOnInit() { + console.info("In paging -- CurrentPage:"+this.currentPage+" "+"total Pages = "+this.getTotalPages() +" Results num:"+this.totalResults); + } + getTotalPages(){ + var i= this.totalResults/this.size; + var integerI=parseInt(''+i); + return parseInt(''+((i==integerI)?i:i+1)); + } + onPrev(){ + this.currentPage=this.currentPage-1; + this.pageChange.emit({ + value: this.currentPage + }); + + } + + onNext(){ + + this.currentPage=this.currentPage+1; + this.pageChange.emit({ + value: this.currentPage + }); + } + onPage(pageNum: number){ + + this.currentPage=pageNum; + this.pageChange.emit({ + value: this.currentPage + }); + } +} diff --git a/sample-components/sampleComponent-rc4/src/app/common/projectTitleFormatter.component.ts b/sample-components/sampleComponent-rc4/src/app/common/projectTitleFormatter.component.ts new file mode 100644 index 00000000..5917768e --- /dev/null +++ b/sample-components/sampleComponent-rc4/src/app/common/projectTitleFormatter.component.ts @@ -0,0 +1,23 @@ +import {Component, Input} from '@angular/core'; +import {OpenaireProperties} from '../openaireProperties'; + +//Usage Example " " + +@Component({ + selector: 'project-title', + template: ` + + ` +}) + +export class ProjectTitleFormatter { + @Input() project: string[]; + private url:string; + constructor () {} + + ngOnInit() { + this.url = OpenaireProperties.getsearchLinkToProject() + "?projectId=" + this.project["openaireId"]; + } +} diff --git a/sample-components/sampleComponent-rc4/src/app/common/publicationTitleFormatter.component.ts b/sample-components/sampleComponent-rc4/src/app/common/publicationTitleFormatter.component.ts new file mode 100644 index 00000000..2c87c50a --- /dev/null +++ b/sample-components/sampleComponent-rc4/src/app/common/publicationTitleFormatter.component.ts @@ -0,0 +1,26 @@ +import {Component, Input} from '@angular/core'; + +//Usage Example " " + +@Component({ + selector: 'publication-title', + template: ` +
+
{{title}}
+
{{title}}
+
+ ` +}) + +export class PublicationTitleFormatter { + @Input() title: string[]; + @Input() url: string[]; + + constructor () {} + + ngOnInit() { + + } + + +} diff --git a/sample-components/sampleComponent-rc4/src/app/entities/claim.ts b/sample-components/sampleComponent-rc4/src/app/entities/claim.ts new file mode 100644 index 00000000..b5378c5f --- /dev/null +++ b/sample-components/sampleComponent-rc4/src/app/entities/claim.ts @@ -0,0 +1,15 @@ +export class Claim { + id: string; + sourceType: string; + targetType: string; + sourceId: string; + targetId: string; + date: string; + DOI: string; + project: Project + userMail: string; + +} +export class Project{ + +} diff --git a/sample-components/sampleComponent-rc4/src/app/home/home.component.html b/sample-components/sampleComponent-rc4/src/app/home/home.component.html new file mode 100644 index 00000000..fa7f4167 --- /dev/null +++ b/sample-components/sampleComponent-rc4/src/app/home/home.component.html @@ -0,0 +1,15 @@ + +
+
+
+
+
+ + + + +
+
+
+
+
diff --git a/sample-components/sampleComponent-rc4/src/app/home/home.component.ts b/sample-components/sampleComponent-rc4/src/app/home/home.component.ts new file mode 100644 index 00000000..4d8cba35 --- /dev/null +++ b/sample-components/sampleComponent-rc4/src/app/home/home.component.ts @@ -0,0 +1,17 @@ +import {Component} from '@angular/core'; +import { ROUTER_DIRECTIVES, Router} from '@angular/router'; +import {JSONP_PROVIDERS} from '@angular/http'; +import {Observable} from 'rxjs/Observable'; +import {Location} from '@angular/common'; + +@Component({ + selector: 'home', + templateUrl: 'home.component.html', + directives: [ ...ROUTER_DIRECTIVES ], +}) + +export class HomeComponent { + constructor ( private _router: Router, private location: Location) {} + + +} diff --git a/sample-components/sampleComponent-rc4/src/app/openaireProperties.ts b/sample-components/sampleComponent-rc4/src/app/openaireProperties.ts new file mode 100644 index 00000000..796973ae --- /dev/null +++ b/sample-components/sampleComponent-rc4/src/app/openaireProperties.ts @@ -0,0 +1,89 @@ +export class OpenaireProperties { + //landing Pages + private static baseSearchLink="/" + private static searchLinkToPublication = "publication?articleId="; + private static searchLinkToProject = "project?projectId="; + private static searchLinkToPerson = "person?personId="; + private static searchLinkToDataProvider = "https://beta.openaire.eu/search/dataprovider?datasourceId="; + private static searchLinkToDataset = "dataset?datasetId="; + private static searchLinkToOrganization = "organization?organizationId="; + + // Services - APIs + + // public claimsAPIURL = "http://rudie.di.uoa.gr:8080/dnet-openaire-connector-service-1.0.0-SNAPSHOT/rest/claimsService/" + private static claimsAPIURL = "http://scoobydoo.di.uoa.gr:8181/dnet-openaire-connector-service-1.0.0-SNAPSHOT/rest/claimsService/"; + + private static searchAPIURL = "http://astero.di.uoa.gr:8080/dnet-functionality-services-2.0.0-SNAPSHOT/rest/v2.0/api/"; + // private searchAPIURL = "http://rudie.di.uoa.gr:8080/dnet-functionality-services-2.0.0-SNAPSHOT/rest/v2.0/api/"; + // private searchAPIURL = "http://scoobydoo.di.uoa.gr:8181/dnet-functionality-services-2.0.0-SNAPSHOT/rest/v2.0/api/"; + + private static searchServiveURL = "http://astero.di.uoa.gr:8080/dnet-functionality-services-2.0.0-SNAPSHOT/"; + // private static searchServiveURL = "http://scoobydoo.di.uoa.gr:8181/dnet-functionality-services-2.0.0-SNAPSHOT/"; + // private static searchServiveURL = "http://services.openaire.eu:8380/search/"; + //private static searchServiveURL = "http://rudie.di.uoa.gr:8080/dnet-functionality-services-2.0.0-SNAPSHOT/"; + + private static searchCrossrefAPIURL = "http://api.crossref.org/works"; + private static searchDataciteAPIURL = "http://search.datacite.org/api"; + private static searchOrcidURL = "https://pub.orcid.org/"; + + // Identifiers + private static pmidURL = "http://www.ncbi.nlm.nih.gov/pubmed/"; + private static doiURL = "http://dx.doi.org/"; + private static cordisURL = "http://cordis.europa.eu/projects/"; + private static pmcURL = "http://europepmc.org/articles/"; + + + //landing Pages' getters + public static getsearchLinkToPublication():string{ + return this.baseSearchLink + this.searchLinkToPublication; + } + public static getsearchLinkToDataset():string{ + return this.baseSearchLink + this.searchLinkToDataset; + } + public static getsearchLinkToProject():string{ + return this.baseSearchLink + this.searchLinkToProject; + } + public static getsearchLinkToPerson():string{ + return this.baseSearchLink + this.searchLinkToPerson; + } + public static getsearchLinkToOrganization():string{ + return this.searchLinkToOrganization; + } + public static getsearchLinkToDataProvider():string{ + return this.searchLinkToDataProvider; + } + + // Services - APIs' getters + public static getSearchAPIURL():string{ + return this.searchAPIURL; + } + public static getSearchServiceURL():string{ + return this.searchServiveURL; + } + public static getClaimsAPIURL():string{ + return this.claimsAPIURL; + } + public static getSearchCrossrefAPIURL():string{ + return this.searchCrossrefAPIURL; + } + public static getSearchDataciteAPIURL():string{ + return this.searchDataciteAPIURL; + } + public static getSearchOrcidURL():string{ + return this.searchOrcidURL; + } + + // Identifiers' getters + public static getPmidURL():string{ + return this.pmidURL; + } + public static getDoiURL():string{ + return this.doiURL; + } + public static getCordisURL():string{ + return this.cordisURL; + } + public static getPmcURL():string{ + return this.pmcURL; + } +} diff --git a/sample-components/sampleComponent-rc4/src/app/pipes/claimTextFilter.pipe.ts b/sample-components/sampleComponent-rc4/src/app/pipes/claimTextFilter.pipe.ts new file mode 100644 index 00000000..e1d402f0 --- /dev/null +++ b/sample-components/sampleComponent-rc4/src/app/pipes/claimTextFilter.pipe.ts @@ -0,0 +1,21 @@ +import {Pipe, PipeTransform} from '@angular/core'; + +@Pipe({ + name: 'claimTextFilter' +}) +export class ClaimTextFilterPipe implements PipeTransform { + + transform(value: any, filter: string): any { + console.info('ClaimTextFilterPipe word to filter : '+filter); + filter = filter?filter.toLocaleLowerCase():''; + return filter ? value.filter(claim=> ( + claim.sourceType.toLocaleLowerCase().indexOf(filter)!=-1|| //sourceType + claim.targetType.toLocaleLowerCase().indexOf(filter)!=-1|| //targetType + claim.userMail.toLocaleLowerCase().indexOf(filter)!=-1|| //mail + ((claim.source.title && claim.source.title.toLocaleLowerCase().indexOf(filter)!=-1)||(claim.source.name && claim.source.name.toLocaleLowerCase().indexOf(filter)!=-1))|| //source title + ((claim.target.title && claim.target.title.toLocaleLowerCase().indexOf(filter)!=-1)||(claim.target.name && claim.target.name.toLocaleLowerCase().indexOf(filter)!=-1))|| //target title + ((claim.source.funderName && claim.source.funderName.toLocaleLowerCase().indexOf(filter)!=-1)||(claim.source.funderName && claim.source.funderName.toLocaleLowerCase().indexOf(filter)!=-1))|| //source funder name + ((claim.target.funderName && claim.target.funderName.toLocaleLowerCase().indexOf(filter)!=-1)||(claim.target.funderName && claim.target.funderName.toLocaleLowerCase().indexOf(filter)!=-1)) //target funder name + )) : value; + } +} diff --git a/sample-components/sampleComponent-rc4/src/app/pipes/claimTypeFilter.pipe.ts b/sample-components/sampleComponent-rc4/src/app/pipes/claimTypeFilter.pipe.ts new file mode 100644 index 00000000..0c386c76 --- /dev/null +++ b/sample-components/sampleComponent-rc4/src/app/pipes/claimTypeFilter.pipe.ts @@ -0,0 +1,35 @@ + +import {Pipe, PipeTransform} from '@angular/core'; + +@Pipe({name: 'claimTypeFilter'}) +export class ClaimTypeFilterPipe implements PipeTransform { + transform(value: any, publication:boolean,dataset:boolean,project:boolean,context:boolean) : any { + let filter = publication; + console.info('ClaimTypeFilterPipe types to show : '+(publication?'publication ':' ')+(dataset?'dataset ':' ')+(project?'project ':' ')+(context?'context ':' ')); + return (value)?value.filter((claim) =>{ + let filter =publication; + if(publication||dataset||project||context) { + let filter = publication + if(filter && (claim.sourceType.toLocaleLowerCase().indexOf('publication')!=-1 || claim.targetType.toLocaleLowerCase().indexOf('publication')!=-1 )) { + return true; + } + filter = dataset; + if(filter && (claim.sourceType.toLocaleLowerCase().indexOf('dataset')!=-1 || claim.targetType.toLocaleLowerCase().indexOf('dataset')!=-1 )) { + return true; + } + filter = project; + if(filter && (claim.sourceType.toLocaleLowerCase().indexOf('project')!=-1 || claim.targetType.toLocaleLowerCase().indexOf('project')!=-1 )) { + return true; + } + filter = context; + if(filter && (claim.sourceType.toLocaleLowerCase().indexOf('context')!=-1 || claim.targetType.toLocaleLowerCase().indexOf('context')!=-1 )) { + return true; + } + return false; + }else{ + return true; + } + }):value; + } + +} diff --git a/sample-components/sampleComponent-rc4/src/app/services/claims.service.ts b/sample-components/sampleComponent-rc4/src/app/services/claims.service.ts new file mode 100644 index 00000000..43c6abce --- /dev/null +++ b/sample-components/sampleComponent-rc4/src/app/services/claims.service.ts @@ -0,0 +1,131 @@ +import {Injectable} from '@angular/core'; +import {Jsonp, URLSearchParams,ResponseOptions, RequestOptions, Headers} from '@angular/http'; +import {Http, Response} from '@angular/http'; +import {Observable} from 'rxjs/Observable'; +import {Claim} from '../entities/claim'; +import {OpenaireProperties} from '../openaireProperties'; + +@Injectable() +export class ClaimsService { + private baseUrl; + constructor(private jsonp: Jsonp, private http: Http) { + this.baseUrl = OpenaireProperties.getClaimsAPIURL(); + } + + private getClaimRequest(size : number, page : number, url :string):any { + console.info('ClaimsService: Claims request: '+url); + return this.http.get( url) + .map(request => request.json()) + .do(request => console.info("Get claims: offset = "+(size*(page-1)) + " limit ="+size )) + .catch(this.handleError); + } + getClaims( size : number, page : number, keyword:string, sortby: string, descending: boolean, types: string):any { + console.info('ClaimsService: getClaims ' ); + console.info('ClaimsService: Types : '+types ); + let url = this.baseUrl +"claims"+"?offset="+(size*(page-1) + "&limit="+size)+"&keyword="+keyword+"&sortby="+sortby+"&descending="+descending+""+types; + return this.getClaimRequest(size,page,url); + + } + getClaimsByUser( size : number, page : number, user:string, keyword:string, sortby: string, descending: boolean, types: string):any { + console.info('ClaimsService: getClaims for user : '+user); + let url = this.baseUrl +"users/"+user+"/claims"+"?offset="+(size*(page-1) + "&limit="+size)+"&keyword="+keyword+"&sortby="+sortby+"&descending="+descending+""+types; + return this.getClaimRequest(size,page,url); + + } + getClaimsBycontext( size : number, page : number, contextId:string, keyword:string, sortby: string, descending: boolean, types: string):any { + console.info('ClaimsService: getClaims for context : '+contextId); + let url = this.baseUrl +"contexts/"+contextId+"/claims"+"?offset="+(size*(page-1) + "&limit="+size)+"&keyword="+keyword+"&sortby="+sortby+"&descending="+descending+""+types; + return this.getClaimRequest(size,page,url); + + } + getClaimsByResult( size : number, page : number, resultId:string, keyword:string, sortby: string, descending: boolean, types: string):any { + console.info('ClaimsService: getClaims for result : '+resultId); + let url = this.baseUrl +"results/"+resultId+"/claims"+"?offset="+(size*(page-1) + "&limit="+size)+"&keyword="+keyword+"&sortby="+sortby+"&descending="+descending+""+types; + return this.getClaimRequest(size,page,url); + + } + getClaimsByProject( size : number, page : number, projectId:string, keyword:string, sortby: string, descending: boolean, types: string):any { + console.info('ClaimsService: getClaims for project : '+projectId); + let url = this.baseUrl +"projects/"+projectId+"/claims"+"?offset="+(size*(page-1) + "&limit="+size)+"&keyword="+keyword+"&sortby="+sortby+"&descending="+descending+""+types; + return this.getClaimRequest(size,page,url); + } + + deleteClaimById(claimId:string):any{ + console.warn('Trying to delete claim with id : '+claimId); + let url = this.baseUrl +"claims/"+claimId; + console.warn('Delete url: '+url); + let headers = new Headers({ 'Content-Type': 'application/json' }); + let options = new RequestOptions({ headers: headers }); + return this.http.delete( url, options).map(request => request.json()) + .do(request => console.info("After delete" )) + .catch(this.handleError); + + } + deleteBulk(claimIds:string[]):any{ + + console.warn('Trying to delete claims with ids : '+claimIds); + var url = ""; + + for(var claimId of claimIds){ + url=url+(url.length >0 ?"&":"")+"claimId="+claimId; + } + url= this.baseUrl +"claims/bulk?"+url; + console.warn('Delete url: '+url); + let headers = new Headers({ 'Content-Type': 'application/json' }); + let options = new RequestOptions({ headers: headers }); + return this.http.delete( url, options).map(request => request.json()) + .do(request => console.info("After delete" )) + .catch(this.handleError); + + } + insertBulkClaims(claims):any{ + console.warn('Trying toinsert claims : '+claims); + let url = this.baseUrl +"claims/bulk"; + let body = JSON.stringify( claims ); + console.warn('Json body: : '+body); + let headers = new Headers({ 'Content-Type': 'application/json' }); + let options = new RequestOptions({ headers: headers }); + return this.http.post(url, body, options) + .map(res => res.json()) + .do(request => console.info("Insert Response:"+request.status) ) + .catch(this.handleError); + + } + insertClaim(claim):any{ + console.warn('Trying toinsert claim : '+claim); + let url = this.baseUrl +"claims"; + let body = JSON.stringify( claim ); + let headers = new Headers({ 'Content-Type': 'application/json' }); + let options = new RequestOptions({ headers: headers }); + return this.http.post(url, body, options) + .map(res => res.json()) + .do(request => console.info("Insert Response:"+request.status) ) + .catch(this.handleError); + + } + + private handleError (error: Response) { + // in a real world app, we may send the error to some remote logging infrastructure + // instead of just logging it to the console + console.error(error); + return Observable.throw(error || 'Server error'); + } + + getClaim(id:string):any { + let url = this.baseUrl+"claims/"+id; + return new Promise((resolve, reject) => { + this.http.get(url) + .map(res => res.json()) + .subscribe( + data => { + resolve(data.data); + }, + err => { + reject(err); + } + ) + ; + }); + } + +} diff --git a/sample-components/sampleComponent-rc4/src/client.ts b/sample-components/sampleComponent-rc4/src/client.ts new file mode 100644 index 00000000..73d9212f --- /dev/null +++ b/sample-components/sampleComponent-rc4/src/client.ts @@ -0,0 +1,20 @@ +// the polyfills must be the first thing imported +import 'angular2-universal/polyfills'; + +// Angular 2 +import {enableProdMode} from '@angular/core'; +// Angular 2 Universal +import {prebootComplete} from 'angular2-universal'; + +// enable prod for faster renders +enableProdMode(); + +import {ngApp} from './main.browser'; + +// on document ready bootstrap Angular 2 +document.addEventListener('DOMContentLoaded', () => { + + ngApp() + .then(prebootComplete); + +}); diff --git a/sample-components/sampleComponent-rc4/src/index.html b/sample-components/sampleComponent-rc4/src/index.html new file mode 100644 index 00000000..8bd68c09 --- /dev/null +++ b/sample-components/sampleComponent-rc4/src/index.html @@ -0,0 +1,29 @@ + + + + OpenAIRE + + + + + + + + + + + + + + + + + Loading Universal ... + + + + + diff --git a/sample-components/sampleComponent-rc4/src/logo.png b/sample-components/sampleComponent-rc4/src/logo.png new file mode 100644 index 00000000..afea237f Binary files /dev/null and b/sample-components/sampleComponent-rc4/src/logo.png differ diff --git a/sample-components/sampleComponent-rc4/src/main.browser.ts b/sample-components/sampleComponent-rc4/src/main.browser.ts new file mode 100644 index 00000000..71e2e701 --- /dev/null +++ b/sample-components/sampleComponent-rc4/src/main.browser.ts @@ -0,0 +1,21 @@ +// Angular 2 Universal +import { bootstrap } from '@angular/platform-browser-dynamic'; +import { provideRouter } from '@angular/router'; +import { HTTP_PROVIDERS } from '@angular/http'; +import { disableDeprecatedForms, provideForms} from '@angular/forms'; +// Application +import {App, routes} from './app/app.component'; +// import {routes} from './app/app.routes'; + +// you must return bootstrap for client.ts +export function ngApp() { + return bootstrap(App, [ + ...HTTP_PROVIDERS, + // FORM_DIRECTIVES, + // FORM_PROVIDERS, + disableDeprecatedForms(), + + provideForms(), + provideRouter(routes) + ]); +} diff --git a/sample-components/sampleComponent-rc4/src/main.node.ts b/sample-components/sampleComponent-rc4/src/main.node.ts new file mode 100644 index 00000000..cab5c3cd --- /dev/null +++ b/sample-components/sampleComponent-rc4/src/main.node.ts @@ -0,0 +1,46 @@ +// the polyfills must be the first thing imported in node.js +// import 'angular2-universal/polyfills'; // polyfills are moved to server.ts + + +// Angular 2 Universal +import { + REQUEST_URL, + ORIGIN_URL, + NODE_LOCATION_PROVIDERS, + NODE_HTTP_PROVIDERS, + ExpressEngineConfig +} from 'angular2-universal'; + +import { provideRouter } from '@angular/router'; +import { APP_BASE_HREF } from '@angular/common'; + +// Application +import {App,routes} from './app/app.component'; +import { disableDeprecatedForms, provideForms} from '@angular/forms'; + +export function ngApp(req, res) { + let baseUrl = '/'; + let url = req.originalUrl || '/'; + + let config: ExpressEngineConfig = { + directives: [ + App + ], + platformProviders: [ + {provide: ORIGIN_URL, useValue: 'http://localhost:3000'}, + {provide: APP_BASE_HREF, useValue: baseUrl}, + ], + providers: [ + {provide: REQUEST_URL, useValue: url}, + NODE_HTTP_PROVIDERS, + provideRouter(routes), + disableDeprecatedForms(), + provideForms(), + NODE_LOCATION_PROVIDERS + ], + async: true, + preboot: false // { appRoot: 'app' } // your top level app component selector + }; + + res.render('index', config); +} diff --git a/sample-components/sampleComponent-rc4/src/server.ts b/sample-components/sampleComponent-rc4/src/server.ts new file mode 100644 index 00000000..26101e13 --- /dev/null +++ b/sample-components/sampleComponent-rc4/src/server.ts @@ -0,0 +1,79 @@ +// the polyfills must be the first thing imported in node.js +import 'angular2-universal/polyfills'; + +import * as path from 'path'; +import * as express from 'express'; +import * as bodyParser from 'body-parser'; +import * as cookieParser from 'cookie-parser'; + +// Angular 2 +import { enableProdMode } from '@angular/core'; +// Angular 2 Universal +import { expressEngine } from 'angular2-universal'; + +// enable prod for faster renders +enableProdMode(); + +const app = express(); +const ROOT = path.join(path.resolve(__dirname, '..')); + +// Express View +app.engine('.html', expressEngine); +app.set('views', __dirname); +app.set('view engine', 'html'); + +app.use(cookieParser('Angular 2 Universal')); +app.use(bodyParser.json()); + +// Serve static files +app.use('/assets', express.static(path.join(__dirname, 'assets'), {maxAge: 30})); +app.use(express.static(path.join(ROOT, 'dist/client'), {index: false})); +/* **AK** Add this path so that index.html can see files from node_modules folder (e.g. bootstrap files)*/ +app.use(express.static(path.join(ROOT, 'node_modules'), {index: false})); + + + +// import { serverApi } from './backend/api'; +// // Our API for demos only +// app.get('/data.json', serverApi); + +import { ngApp } from './main.node'; +// Routes with html5pushstate +// ensure routes match client-side-app +app.get('/', ngApp); +app.get('/claims', ngApp); +app.get('/claim', ngApp); +app.get('/home', ngApp); +app.get('/search', ngApp); +app.get('/search-publications', ngApp); +app.get('/advanced-search-publications', ngApp); +app.get('/my-claims', ngApp); +app.get('/linking', ngApp); +app.get('/demo-up', ngApp); +app.get('/up', ngApp); +app.get('/bulk-linking', ngApp); +app.get('/publication', ngApp); +app.get('/project', ngApp); +app.get('/person', ngApp); +app.get('/dataset', ngApp); +app.get('/organization', ngApp); +app.get('/deposit', ngApp); + +// use indexFile over ngApp only when there is too much load on the server +function indexFile(req, res) { + // when there is too much load on the server just send + // the index.html without prerendering for client-only + res.sendFile('/index.html', {root: __dirname}); +} + +app.get('*', function(req, res) { + res.setHeader('Content-Type', 'application/json'); + var pojo = { status: 404, message: 'No Content' }; + var json = JSON.stringify(pojo, null, 2); + res.status(404).send(json); +}); + +// Server +app.listen(3000, () => { + console.log('Listening on: http://localhost:3000'); +}); diff --git a/sample-components/sampleComponent-rc4/src/typings.d.ts b/sample-components/sampleComponent-rc4/src/typings.d.ts new file mode 100644 index 00000000..bf633427 --- /dev/null +++ b/sample-components/sampleComponent-rc4/src/typings.d.ts @@ -0,0 +1,74 @@ +/* + * Custom Type Definitions + * When including 3rd party modules you also need to include the type definition for the module + * if they don't provide one within the module. You can try to install it with typings +typings install node --save + * If you can't find the type definition in the registry we can make an ambient definition in + * this file for now. For example +declare module "my-module" { + export function doesSomething(value: string): string; +} + * + * If you're prototying and you will fix the types later you can also declare it as type any + * +declare var assert: any; + * + * If you're importing a module that uses Node.js modules which are CommonJS you need to import as + * +import * as _ from 'lodash' + * You can include your type definitions in this file until you create one for the typings registry + * see https://github.com/typings/registry + * + */ + + +// Extra variables that live on Global that will be replaced by webpack DefinePlugin +declare var ENV: string; +declare var HMR: boolean; +interface GlobalEnvironment { + ENV; + HMR; +} + +interface WebpackModule { + hot: { + data?: any, + idle: any, + accept(dependencies?: string | string[], callback?: (updatedDependencies?: any) => void): void; + decline(dependencies?: string | string[]): void; + dispose(callback?: (data?: any) => void): void; + addDisposeHandler(callback?: (data?: any) => void): void; + removeDisposeHandler(callback?: (data?: any) => void): void; + check(autoApply?: any, callback?: (err?: Error, outdatedModules?: any[]) => void): void; + apply(options?: any, callback?: (err?: Error, outdatedModules?: any[]) => void): void; + status(callback?: (status?: string) => void): void | string; + removeStatusHandler(callback?: (status?: string) => void): void; + }; +} + +interface WebpackRequire { + context(file: string, flag?: boolean, exp?: RegExp): any; +} + + +interface ErrorStackTraceLimit { + stackTraceLimit: number; +} + + +// Extend typings +interface NodeRequire extends WebpackRequire {} +interface ErrorConstructor extends ErrorStackTraceLimit {} +interface NodeModule extends WebpackModule {} +interface Global extends GlobalEnvironment {} + + +interface Thenable { + then( + onFulfilled?: (value: T) => U | Thenable, + onRejected?: (error: any) => U | Thenable): Thenable; + then( + onFulfilled?: (value: T) => U | Thenable, + onRejected?: (error: any) => void): Thenable; + catch(onRejected?: (error: any) => U | Thenable): Thenable; +} diff --git a/sample-components/sampleComponent-rc4/tsconfig.json b/sample-components/sampleComponent-rc4/tsconfig.json new file mode 100644 index 00000000..a6757c02 --- /dev/null +++ b/sample-components/sampleComponent-rc4/tsconfig.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "target": "es5", + "module": "commonjs", + "removeComments": true, + "sourceMap": true + }, + "exclude": [ + "typings/main.d.ts", + "typings/main", + "node_modules" + ], + "compileOnSave": false, + "buildOnSave": false, + "atom": { "rewriteTsconfig": false } +} diff --git a/sample-components/sampleComponent-rc4/typings.json b/sample-components/sampleComponent-rc4/typings.json new file mode 100644 index 00000000..67b4d1a4 --- /dev/null +++ b/sample-components/sampleComponent-rc4/typings.json @@ -0,0 +1,13 @@ +{ + "globalDependencies": { + "body-parser": "registry:dt/body-parser#0.0.0+20160317120654", + "compression": "registry:dt/compression#0.0.0+20160501162003", + "cookie-parser": "registry:dt/cookie-parser#1.3.4+20160316155526", + "es6-shim": "registry:dt/es6-shim#0.31.2+20160317120654", + "express": "registry:dt/express#4.0.0+20160317120654", + "express-serve-static-core": "registry:dt/express-serve-static-core#0.0.0+20160322035842", + "mime": "registry:dt/mime#0.0.0+20160316155526", + "node": "registry:dt/node#4.0.0+20160412142033", + "serve-static": "registry:dt/serve-static#0.0.0+20160317120654" + } +} diff --git a/sample-components/sampleComponent-rc4/webpack.config.js b/sample-components/sampleComponent-rc4/webpack.config.js new file mode 100644 index 00000000..4ad523b0 --- /dev/null +++ b/sample-components/sampleComponent-rc4/webpack.config.js @@ -0,0 +1,97 @@ +var webpack = require('webpack'); +var path = require('path'); + +var commonConfig = { + resolve: { + extensions: ['', '.ts', '.js', '.json'] + }, + module: { + loaders: [ + // TypeScript + { test: /\.ts$/, loaders: ['ts-loader', 'angular2-template-loader'] }, + { test: /\.html$/, loader: 'raw-loader' }, + { test: /\.css$/, loader: 'raw-loader' }, + { test: /\.json$/, loader: 'raw-loader' } + ], + preLoaders: [ + // needed to lower the filesize of angular due to inline source-maps + { test: /\.js$/, loader: 'source-map-loader' } + ], + }, + plugins: [ + new webpack.optimize.OccurenceOrderPlugin(true) + ] + +}; + + +var clientConfig = { + target: 'web', + entry: './src/client', + output: { + path: root('dist/client') + }, + node: { + global: true, + __dirname: true, + __filename: true, + process: true, + Buffer: false + } +}; + + +var serverConfig = { + target: 'node', + entry: './src/server', // use the entry file of the node server if everything is ts rather than es5 + output: { + path: root('dist/server'), + libraryTarget: 'commonjs2' + }, + externals: checkNodeImport, + node: { + global: true, + __dirname: true, + __filename: true, + process: true, + Buffer: true + } +}; + + + +// Default config +var defaultConfig = { + context: __dirname, + resolve: { + root: root('/src') + }, + output: { + publicPath: path.resolve(__dirname), + filename: 'index.js' + } +} + + + +var webpackMerge = require('webpack-merge'); +module.exports = [ + // Client + webpackMerge({}, defaultConfig, commonConfig, clientConfig), + + // Server + webpackMerge({}, defaultConfig, commonConfig, serverConfig) +] + +// Helpers +function checkNodeImport(context, request, cb) { + if (!path.isAbsolute(request) && request.charAt(0) !== '.') { + cb(null, 'commonjs ' + request); return; + } + cb(); +} + +function root(args) { + args = Array.prototype.slice.call(arguments, 0); + return path.join.apply(path, [__dirname].concat(args)); +} diff --git a/sample-components/sampleComponent-rc6/.editorconfig b/sample-components/sampleComponent-rc6/.editorconfig new file mode 100644 index 00000000..f1cc3ad3 --- /dev/null +++ b/sample-components/sampleComponent-rc6/.editorconfig @@ -0,0 +1,15 @@ +# http://editorconfig.org + +root = true + +[*] +charset = utf-8 +indent_style = space +indent_size = 2 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true + +[*.md] +insert_final_newline = false +trim_trailing_whitespace = false diff --git a/sample-components/sampleComponent-rc6/.gitignore b/sample-components/sampleComponent-rc6/.gitignore new file mode 100644 index 00000000..9e17510b --- /dev/null +++ b/sample-components/sampleComponent-rc6/.gitignore @@ -0,0 +1,12 @@ +/__build__ +/__server_build__ +/node_modules +/typings +/tsd_typings/ +npm-debug.log + +/dist/ + +.idea + +.DS_Store diff --git a/sample-components/sampleComponent-rc6/.vscode/launch.json b/sample-components/sampleComponent-rc6/.vscode/launch.json new file mode 100644 index 00000000..f2449acd --- /dev/null +++ b/sample-components/sampleComponent-rc6/.vscode/launch.json @@ -0,0 +1,46 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Launch", + "type": "node", + "request": "launch", + "program": "${workspaceRoot}/dist/server/index.js", + "stopOnEntry": false, + "args": [], + "cwd": "${workspaceRoot}", + "preLaunchTask": null, + "runtimeExecutable": null, + "runtimeArgs": [ + "--nolazy" + ], + "env": { + "NODE_ENV": "development" + }, + "externalConsole": false, + "sourceMaps": false, + "outDir": null + }, + { + "name": "Attach", + "type": "node", + "request": "attach", + "port": 5858, + "address": "localhost", + "restart": false, + "sourceMaps": false, + "outDir": null, + "localRoot": "${workspaceRoot}", + "remoteRoot": null + }, + { + "name": "Attach to Process", + "type": "node", + "request": "attach", + "processId": "${command.PickProcess}", + "port": 5858, + "sourceMaps": false, + "outDir": null + } + ] +} \ No newline at end of file diff --git a/sample-components/sampleComponent-rc6/README.md b/sample-components/sampleComponent-rc6/README.md new file mode 100644 index 00000000..8e3dbcc7 --- /dev/null +++ b/sample-components/sampleComponent-rc6/README.md @@ -0,0 +1,23 @@ +# Angular 2 Universal Starter [![Universal Angular 2](https://img.shields.io/badge/universal-angular2-brightgreen.svg?style=flat)](https://github.com/angular/universal) + +A minimal Angular 2 starter for Universal JavaScript using TypeScript and Webpack + +> If you're looking for the repo from the AngularConnect talk look in the [angular-connect branch](https://github.com/angular/universal-starter/tree/angular-connect) +If you're looking for a SystemJS version of the repo look in the [systemjs branch](https://github.com/angular/universal-starter/tree/systemjs) + +[![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy) + +## Installation + +* `npm install` + +## Serve + +* `npm start` to build your client app and start a web server +* `npm run build` to prepare a distributable bundle + +## Development +* run `npm start` and `npm run watch` in two separate terminals to build your client app, start a web server, and allow file changes to update in realtime + +## Watch files +* `npm run watch` to build your client app and start a web server diff --git a/sample-components/sampleComponent-rc6/app.json b/sample-components/sampleComponent-rc6/app.json new file mode 100644 index 00000000..1762bb6b --- /dev/null +++ b/sample-components/sampleComponent-rc6/app.json @@ -0,0 +1,12 @@ +{ + "name": "Angular 2 Universal Starter", + "description": "Angular 2 Universal starter kit by @AngularClass", + "repository": "https://github.com/angular/universal-starter", + "logo": "https://cloud.githubusercontent.com/assets/1016365/10639063/138338bc-7806-11e5-8057-d34c75f3cafc.png", + "env": { + "NPM_CONFIG_PRODUCTION": { + "description": "Install `webpack` and other development modules when deploying to allow full builds.", + "value": "false" + } + } +} diff --git a/sample-components/sampleComponent-rc6/nodemon.json b/sample-components/sampleComponent-rc6/nodemon.json new file mode 100644 index 00000000..97a836fb --- /dev/null +++ b/sample-components/sampleComponent-rc6/nodemon.json @@ -0,0 +1,7 @@ +{ + "watch": [ + "dist", + "src/index.html" + ], + "ext" : "js ts json html" +} diff --git a/sample-components/sampleComponent-rc6/package.json b/sample-components/sampleComponent-rc6/package.json new file mode 100644 index 00000000..d8a56916 --- /dev/null +++ b/sample-components/sampleComponent-rc6/package.json @@ -0,0 +1,70 @@ +{ + "name": "universal-starter", + "version": "2.0.0", + "description": "Angular 2 Universal starter kit by @AngularClass", + "repository": { + "type": "git", + "url": "https://github.com/angular/universal-starter.git" + }, + "scripts": { + "watch": "webpack --watch", + "prebuild": "rimraf dist", + "build": "webpack", + "build:prod": "webpack --progress -p", + "prestart": "npm run build", + "server": "nodemon dist/server/index.js", + "start": "npm run server", + "predebug": "npm run build", + "debug:build": "node-nightly --inspect --debug-brk node_modules/webpack/bin/webpack.js", + "debug": "node --debug-brk dist/server/index.js" + }, + "license": "MIT", + "contributors": [ + "AngularClass ", + "PatrickJS ", + "Jeff Whelpley ", + "Jeff Cross ", + "Mark Pieszak " + ], + "dependencies": { + "@angular/common": "2.0.0-rc.6", + "@angular/compiler": "2.0.0-rc.6", + "@angular/core": "2.0.0-rc.6", + "@angular/forms": "2.0.0-rc.6", + "@angular/http": "2.0.0-rc.6", + "@angular/platform-browser": "2.0.0-rc.6", + "@angular/platform-browser-dynamic": "2.0.0-rc.6", + "@angular/platform-server": "2.0.0-rc.6", + "@angular/router": "3.0.0-rc.2", + "angular2-platform-node": "~1.0.4", + "angular2-universal": "~1.0.4", + "angular2-universal-polyfills": "~1.0.4", + "angular2-express-engine": "~1.0.4", + "body-parser": "^1.15.2", + "express": "^4.14.0", + "methods": "~1.1.2", + "rxjs": "5.0.0-beta.11", + "zone.js": "0.6.17" + }, + "devDependencies": { + "@types/body-parser": "0.0.29", + "@types/compression": "0.0.29", + "@types/cookie-parser": "^1.3.29", + "@types/express": "^4.0.29", + "@types/express-serve-static-core": "^4.0.29", + "@types/mime": "0.0.28", + "@types/node": "^4.0.30", + "@types/serve-static": "^1.7.27", + "angular2-template-loader": "^0.4.0", + "cookie-parser": "^1.4.3", + "nodemon": "^1.10.0", + "raw-loader": "^0.5.1", + "rimraf": "^2.5.4", + "ts-loader": "^0.8.2", + "typescript": "2.0.0", + "webpack": "^2.1.0-beta.22", + "webpack-dev-middleware": "^1.6.1", + "webpack-dev-server": "^2.1.0-beta.0", + "webpack-merge": "^0.13.0" + } +} diff --git a/sample-components/sampleComponent-rc6/src/app/app.routing.ts b/sample-components/sampleComponent-rc6/src/app/app.routing.ts new file mode 100644 index 00000000..9386b275 --- /dev/null +++ b/sample-components/sampleComponent-rc6/src/app/app.routing.ts @@ -0,0 +1,29 @@ +import { ModuleWithProviders } from '@angular/core'; +import { Routes, RouterModule } from '@angular/router'; +import {ClaimsAdminComponent} from './claimPages/claims/claimsAdmin.component'; +import {HomeComponent} from './home/home.component'; +const appRoutes: Routes = [ + { path: '', + pathMatch: 'full', + redirectTo: 'home' }, + { path: 'claims', component: ClaimsAdminComponent }, + { path: 'home', component: HomeComponent } + +]; + + +// , +// { +// path: 'heroes', +// component: HeroListComponent, +// data: { +// title: 'Heroes List' +// } +// }, +// { path: 'hero/:id', component: HeroDetailComponent }, +// { path: '**', component: PageNotFoundComponent } +// export const appRoutingProviders: any[] = [ +// +// ]; + +export const routing: ModuleWithProviders = RouterModule.forRoot(appRoutes); diff --git a/sample-components/sampleComponent-rc6/src/app/app.ts b/sample-components/sampleComponent-rc6/src/app/app.ts new file mode 100644 index 00000000..636737c7 --- /dev/null +++ b/sample-components/sampleComponent-rc6/src/app/app.ts @@ -0,0 +1,40 @@ +import { Component } from '@angular/core'; + +import 'rxjs/Rx'; +@Component({ + selector: 'app', + template: ` +
+ + +
+ +
+ +
` +}) +export class App { + +} diff --git a/sample-components/sampleComponent-rc6/src/app/claimPages/claims/claims.component.html b/sample-components/sampleComponent-rc6/src/app/claimPages/claims/claims.component.html new file mode 100644 index 00000000..4518b03f --- /dev/null +++ b/sample-components/sampleComponent-rc6/src/app/claimPages/claims/claims.component.html @@ -0,0 +1,107 @@ +
+
+
+
+ +
Claims related to
+ +
+

+ +

+

+ +

+

+ +

+

+ +

+

+ +

+
+
+
+ + +
+ + + diff --git a/sample-components/sampleComponent-rc6/src/app/claimPages/claims/claims.component.ts b/sample-components/sampleComponent-rc6/src/app/claimPages/claims/claims.component.ts new file mode 100644 index 00000000..b8151b44 --- /dev/null +++ b/sample-components/sampleComponent-rc6/src/app/claimPages/claims/claims.component.ts @@ -0,0 +1,490 @@ +import {Component, ViewChild, Input} from '@angular/core'; +import {Location} from '@angular/common'; +import {Observable} from 'rxjs/Observable'; +import {ActivatedRoute, Router} from '@angular/router'; +import {ClaimsService} from '../../services/claims.service'; +import {Loading} from '../../common/modal/loading.component'; +import {Alert} from '../../common/modal/alert'; + + +@Component({ + selector: 'claims', + templateUrl: 'claims.component.html', + providers:[ ClaimsService] + +}) +export class ClaimsComponent { + constructor (private _claimService: ClaimsService, private route: ActivatedRoute, private _router:Router, private location: Location) { + } + + ngOnInit() { + // this.sub = this.route.queryParams.subscribe(params => { + + var params = []; + if( this.myClaims == 'true' ){ + this.fetchBy = "User"; + }else{ + + this.fetchBy = params['fetchBy']; + this.fetchBy = (this.types.indexOf(this.fetchBy) != -1)? this.fetchBy:'All'; + this.fetchId = params['fetchId']; + this.fetchId=this.fetchId?this.fetchId:''; + + } + + let page = (params['page']=== undefined)?1:+params['page']; + let size = (params['size']=== undefined)?10:+params['size']; + + this.keyword = (params['keyword']?params['keyword']:""); + this.inputkeyword = this.keyword; + this.page = ( page <= 0 ) ? 1 : page; + this.size = ( size <= 0 ) ? 10 : size; + this.entityTypes = []//(params['types']?params['types']:[]); + this.setTypes(params['types']); // check the appropriate checkboxes + // this.setSortby(params['sort']); + this.getClaims(); + + // }); + // this.sub = this.route.params.subscribe(params => { + // console.info(this.isAdmin+" "+this.myClaims+" Fetch by: "+this.fetchBy+" Fetch id: "+this.fetchId); + // if( this.myClaims == 'true' ){ + // console.info("Is myclaims"); + // this.fetchBy = "User"; + // }else{ + // console.info("Is admin"); + // + // console.info(this.isAdmin); + // + // this.fetchBy = params['fetchBy']; + // this.fetchBy = (this.types.indexOf(this.fetchBy) != -1)? this.fetchBy:'All'; + // this.fetchId = params['fetchId']; + // console.info("Fetch by:"+this.fetchBy+"Fetch id:"+this.fetchId); + // this.fetchId=this.fetchId?this.fetchId:''; + // + // } + // + // console.info(this.isAdmin+" "+this.myClaims+" Fetch by: "+this.fetchBy+" Fetch id: "+this.fetchId); + // let page = (params['page']=== undefined)?1:+params['page']; + // let size = (params['size']=== undefined)?10:+params['size']; + // + // this.keyword = (params['keyword']?params['keyword']:""); + // this.inputkeyword = this.keyword; + // this.page = ( page <= 0 ) ? 1 : page; + // this.size = ( size <= 0 ) ? 10 : size; + // this.entityTypes = []//(params['types']?params['types']:[]); + // this.setTypes(params['types']); // check the appropriate checkboxes + // this.setSortby(params['sort']); + // this.getClaims(); + // console.info("params: "+params['page']+" page "+page +" this.page: "+this.page ); + // }); + } + ngOnDestroy() { + this.sub.unsubscribe(); + } + sub: any; + //string because comes as input from component directive + @Input() enableDelete: string = 'false'; + @Input() myClaims: string= 'false' ; + @Input() isAdmin:string = 'false'; + page : number; + size:number; + keyword:string; // the keyword string to give to the request as parameter + inputkeyword:string; // the string written in the input field (keyword=inputkeyword when its length is bigger than 3 and the user stops typing) + lengths = [10,20,30,50]; + types = ["All","Project","Context","Result","User"]; + @Input() fetchBy:string; + @Input() fetchId:string; + + navigateTo: string = "Claims"; + resultsNum: number ; + claims: string[]; + + @ViewChild (Loading) loading : Loading ; + + //checkboxes: + publicationCB = false; + datasetCB = false; + contextCB = false; + projectCB = false; + entityTypes : string[] =[] ; + + descending = true; + sortby = "date"; + + selected=[]; + deleteMessage:string = ""; + showErrorMessage:boolean = false; + + //params for pagingFormatter to use when navigate to page + params; + @ViewChild(Alert) alert; + + claimsDeleted:number = 0; + + getClaims () { + this.selected=[]; + var types = ''; + this.showErrorMessage = false; + for (var type of this.entityTypes){ + types+=(types.length>0?'&':'')+"types="+type; + } + if(this.fetchBy =="Project" ){ + this._claimService.getClaimsByProject(this.size,this.page,this.fetchId,this.keyword,this.sortby,this.descending, types).subscribe( + data => { + this.claims = data.data; + this.resultsNum= data.total; + }, + err => { + console.error(err); + this.showErrorMessage = true; + } + ); + }else if(this.fetchBy =="User"){ + this._claimService.getClaimsByUser(this.size,this.page,this.fetchId,this.keyword,this.sortby,this.descending, types).subscribe( + data => { + this.claims = data.data; + this.resultsNum= data.total; + }, + err => { + console.error(err); + this.showErrorMessage = true; + } + ); + }else if(this.fetchBy =="Result"){ + this._claimService.getClaimsByResult(this.size,this.page,this.fetchId,this.keyword,this.sortby,this.descending, types).subscribe( + data => { + this.claims = data.data; + this.resultsNum= data.total; + }, + err => { + console.error(err); + this.showErrorMessage = true; + } + ); + }else if(this.fetchBy =="Context"){ + this._claimService.getClaimsBycontext(this.size,this.page,this.fetchId,this.keyword,this.sortby,this.descending, types).subscribe( + data => { + this.claims = data.data; + this.resultsNum= null; + this.resultsNum= data.total;//data.length; //TODO get the total results num + }, + err => { + console.error(err); + this.showErrorMessage = true; + } + ); + }else{ + this._claimService.getClaims(this.size,this.page,this.keyword,this.sortby,this.descending, types).subscribe( + data => { + this.claims = data.data; + this.resultsNum = null; + this.resultsNum= data.total;//data.length; //TODO get the total results num + }, + err => { + console.error(err); + this.showErrorMessage = true; + } + ); + } + } + + goToClaim(claimId: number){ + this._router.navigate( ['Claim', { id: claimId}] ); + } + goTo(page:number = 1){ + + this.page = page; + + this.location.go(location.pathname,this.getParametersString()); + this.getClaims(); + } + getParameters(){ + let params={ page: this.page, size: this.size, types: this.entityTypes, fetchBy: this.fetchBy, fetchId:this.fetchId, keyword : this.keyword, sort: this.getSortby() }; + return params; + } + getParametersString(){ + var params=''; + params+=(this.page==1?"":(params.length>0?'&':'')+"page="+this.page); + params+=(this.size==10?"":(params.length>0?'&':'')+"size="+this.size); + // params+=(this.entityTypes==''?"":(params.length>0?'&':'')+"types="+this.entityTypes); + var types=""; + for (var type of this.entityTypes){ + types+=(types.length>0?',':'')+type; + } + params+=(types.length>0)?"types="+types:""; + + if(this.isAdmin === 'true'){ + params+=(this.fetchBy=='All'?"":(params.length>0?'&':'')+"fetchBy="+this.fetchBy); + params+=(this.fetchId==''?"":(params.length>0?'&':'')+"fetchId="+this.fetchId); + } + params+=(this. getSortby()=='datedesc'?"":(params.length>0?'&':'')+"sort="+this. getSortby()); + params+=(this.keyword==''?"":(params.length>0?'&':'')+"keyword="+this.keyword); + return params; + } + changeLength(){ + this.goTo(); + } + clearFilters(){ + this.keyword = ''; + this.inputkeyword = ''; + this.publicationCB = false; + this.projectCB = false; + this.datasetCB = false; + this.contextCB = false; + this.entityTypes = []; + this.goTo(); + } + changeOrderby(sortby:string){ + if(sortby==this.sortby){ + this.descending = !this.descending; + }else{ + this.sortby = sortby; + this.descending = false; + } + this.goTo(); + } + setSortby(sortby:string){ + if(!sortby|| sortby == "datedesc"){ + this.descending = true; + this.sortby = "date"; + }else if(sortby == "dateasc"){ + this.descending = false; + this.sortby = "date"; + }else if(sortby == "userasc"){ + this.descending = false; + this.sortby = "user"; + }else if(sortby == "userdesc"){ + this.descending = true; + this.sortby = "user"; + }if(sortby =="sourceasc"){ + this.descending = false; + this.sortby = "source"; + }else if(sortby == "sourcedesc"){ + this.descending = true; + this.sortby = "source"; + }else if(sortby == "targetasc"){ + this.descending = false; + this.sortby = "target"; + }else if(sortby == "targetdesc"){ + this.descending = true; + this.sortby = "target"; + } + } + getSortby():string{ + if(this.descending){ + return this.sortby+"desc"; + }else{ + return this.sortby+"asc"; + } + + } + changeType(){ + this.entityTypes = []; + if(this.publicationCB){ + this.entityTypes.push('publication'); + } + if(this.datasetCB){ + this.entityTypes.push('dataset'); + } + if(this.projectCB){ + this.entityTypes.push('project'); + } + if(this.contextCB){ + this.entityTypes.push('context'); + } + + // if(this.publicationCB == true && this.datasetCB == true && this.contextCB == true && this.projectCB == true ){ + // this.entityTypes=""; + // }else{ + // this.entityTypes = ""; + // if(this.publicationCB == true){ + // this.entityTypes = "publication"; + // } + // if(this.datasetCB == true){ + // this.entityTypes += (this.entityTypes.length > 0?",":"")+"dataset"; + // } + // if(this.contextCB == true){ + // this.entityTypes += (this.entityTypes.length > 0?",":"")+"context"; + // } + // if(this.projectCB == true){ + // this.entityTypes += (this.entityTypes.length > 0?",":"")+"project"; + // } + // } + // console.debug("Type changed: "+this.entityTypes+" "+this.publicationCB+ this.datasetCB + this.contextCB + this.projectCB); + this.goTo(); + } + setTypes(types:string){ + if(!types){ + return; + } + if(types.length > 0){ + this.entityTypes = []; + if(types.indexOf("publication")!=-1){ + this.publicationCB = true; + this.entityTypes.push("publication"); + } + if(types.indexOf("dataset")!=-1){ + this.datasetCB = true; + this.entityTypes.push("dataset"); + } + if(types.indexOf("project")!=-1){ + this.projectCB = true; + this.entityTypes.push("project"); + } + if(types.indexOf("context")!=-1){ + this.contextCB = true; + this.entityTypes.push("context"); + } + } + if(this.publicationCB && this.datasetCB && this.contextCB && this.projectCB){ + this.entityTypes=[]; + } + } + changekeyword(){ + + if(this.inputkeyword.length >= 3 || this.inputkeyword.length == 0 ){ + this.keyword = this.inputkeyword; + this.page = 1; + this.goTo(); + } + + } + select(item:any,event){ + this.deleteMessage=""; + var value = event.currentTarget.checked; + if(value){ + this.selected.push(item); + }else{ + for (var _i = 0; _i < this.selected.length; _i++) { + let claim = this.selected[_i]; + if(claim['id'] == item.id){ + this.selected.splice(_i, 1); + } + } + + + } + } + selectAll(){ + this.selected = []; + for (var _i = 0; _i < this.claims.length; _i++) { + let claim = this.claims[_i]; + this.selected.push(claim); + } + this.deleteMessage = ""; + } + deselectAll(){ + this.selected = []; + this.deleteMessage=""; + } + isSelected(id:string){ + for (var _i = 0; _i < this.selected.length; _i++) { + let claim = this.selected[_i]; + if(claim['id'] == id){ + return true; + } + } + return false; + } + + + confirmOpen(){ + if(this.selected.length <= 0){ + + }else{ + this.alert.cancelButton = true; + this.alert.okButton = true; + this.alert.alertTitle = "Delete "+this.selected.length+" claim(s)"; + this.alert.message = this.selected.length+" claims will be deleted. Do you want to proceed? "; + this.alert.okButtonText = "Yes"; + this.alert.cancelButtonText = "No"; + this.alert.open(); + } + } + confirmClose(data){ + this.delete(); + } + delete(){ + this.deleteMessage=""; + this.loading.open(); + this.claimsDeleted = 0; + var ids = []; + for (var i = 0; i < this.selected.length; i++){ + var id =this.selected[i].id; + ids.push(id); + // var selected =this.selected[i].id; + // console.warn("Deleting claim with id:"+id); + // this.deleteById(id); + //TODO for multiple concurrent + } + this.batchDeleteById(ids); + } + + deleteById(id:string){ + + console.warn("Deleting claim with id:"+id); + // this._claimService.deleteClaimById(id); + this._claimService.deleteClaimById(id).subscribe( + res => { + console.info('Delete response'+res.code ); + console.warn("Deleted claim with id:"+ id); + //remove this claim from the + let newClaims=this.claims; + for (var _i = 0; _i < this.claims.length; _i++) { + let claim = this.claims[_i]; + if(claim['id'] == id){ + newClaims.splice(_i, 1); + } + } + //TODO should call getClaims??? + this.claimsDeleted++; + this.claims = newClaims; + if(this.claimsDeleted == this.selected.length){ + this.resultsNum = this.resultsNum - this.selected.length; + this.loading.close(); + this.selected = []; + } + + + }); + } + batchDeleteById(ids:string[]){ + + console.warn("Deleting claim with ids:"+ids); + this._claimService.deleteBulk(ids).subscribe( + res => { + console.info('Delete response'+res.code ); + console.warn("Deleted ids:"+ res.deletedIds); + console.warn("Not found ids:"+ res.notFoundIds); + //remove this claim from the + let newClaims=this.claims; + for(var id of res.deletedIds){ + for (var _i = 0; _i < this.claims.length; _i++) { + let claim = this.claims[_i]; + if(claim['id'] == id){ + newClaims.splice(_i, 1); + } + } + for (var _i = 0; _i < this.selected.length; _i++) { + let claim = this.selected[_i]; + if(claim['id'] == id){ + this.selected.splice(_i, 1); + } + } + } + this.claims = newClaims; + this.resultsNum = this.resultsNum - res.deletedIds.length; + this.loading.close(); + if(res.deletedIds.length>0){ + this.deleteMessage=this.deleteMessage+'
'+res.deletedIds.length+' claim(s) successfully deleted.
'; + } + if(res.notFoundIds.length>0){ + this.deleteMessage=this.deleteMessage+'
'+res.notFoundIds.length+' claim(s) couldn\'t be deleted.
'; + } + }); + } + pageChange($event) { + var page:number = +$event.value + this.goTo(page); + } +} diff --git a/sample-components/sampleComponent-rc6/src/app/claimPages/claims/claims.module.ts b/sample-components/sampleComponent-rc6/src/app/claimPages/claims/claims.module.ts new file mode 100644 index 00000000..11d9002b --- /dev/null +++ b/sample-components/sampleComponent-rc6/src/app/claimPages/claims/claims.module.ts @@ -0,0 +1,26 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { FormsModule } from '@angular/forms'; + +import {ClaimsComponent} from './claims.component'; +import {ClaimsService} from '../../services/claims.service'; +import {Claim} from '../../entities/claim'; +import {pagingFormatterNoLoad} from '../../common/pagingFormatterNoLoad.component'; + +// import {ClaimEntityFormatterModule} from '../../common/claimEntityFormatter.module'; +import {ClaimEntityFormatter} from '../../common/claimEntityFormatter.component'; +import {PublicationTitleFormatter} from '../../common/publicationTitleFormatter.component'; +import {ProjectTitleFormatter} from '../../common/projectTitleFormatter.component'; + +import {LoadingModule} from '../../common/modal/loading.module'; +// import {Loading} from '../../common/modal/loading.component'; + +@NgModule({ + imports: [ CommonModule, FormsModule, LoadingModule ], + declarations: [ ClaimsComponent, pagingFormatterNoLoad, ClaimEntityFormatter,PublicationTitleFormatter,ProjectTitleFormatter], + providers: [ ClaimsService ] +}) + +// exports: [ ContactComponent ], +// providers: [ ContactService ] +export class ClaimsModule { } diff --git a/sample-components/sampleComponent-rc6/src/app/claimPages/claims/claimsAdmin.component.ts b/sample-components/sampleComponent-rc6/src/app/claimPages/claims/claimsAdmin.component.ts new file mode 100644 index 00000000..a602bdc9 --- /dev/null +++ b/sample-components/sampleComponent-rc6/src/app/claimPages/claims/claimsAdmin.component.ts @@ -0,0 +1,36 @@ +import {Component, ViewChild, Input} from '@angular/core'; +import {Location} from '@angular/common'; +import {Observable} from 'rxjs/Observable'; + +@Component({ + selector: 'claims-admin', + template: ` +
+ + +
+ + +
+ TODO login +
+ `, + +}) +export class ClaimsAdminComponent { + constructor ( ) { + + } +user:string="argirok@di.uoa.gr"; + ngOnInit() { + + + } + + +} diff --git a/sample-components/sampleComponent-rc6/src/app/common/claimEntityFormatter.component.ts b/sample-components/sampleComponent-rc6/src/app/common/claimEntityFormatter.component.ts new file mode 100644 index 00000000..f2611255 --- /dev/null +++ b/sample-components/sampleComponent-rc6/src/app/common/claimEntityFormatter.component.ts @@ -0,0 +1,36 @@ +import {Component, Input} from '@angular/core'; + +//Usage Example " " + +//externalUrl +@Component({ + selector: 'claim-entity', + template: ` + +
+ ({{type}}) + +
+
+ (Project) + +
+
+ (Context) +
{{entity.title}}
+
+ ` +}) + +export class ClaimEntityFormatter { + @Input() entity: string[]; + @Input() type: string; + + constructor () {} + + ngOnInit() { + + } + + +} diff --git a/sample-components/sampleComponent-rc6/src/app/common/claimEntityFormatter.module.ts b/sample-components/sampleComponent-rc6/src/app/common/claimEntityFormatter.module.ts new file mode 100644 index 00000000..d75245c5 --- /dev/null +++ b/sample-components/sampleComponent-rc6/src/app/common/claimEntityFormatter.module.ts @@ -0,0 +1,12 @@ + +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { FormsModule } from '@angular/forms'; +import {PublicationTitleFormatter} from './publicationTitleFormatter.component'; +import {ProjectTitleFormatter} from './projectTitleFormatter.component'; +@NgModule({ + imports: [ CommonModule, FormsModule ], + declarations: [ PublicationTitleFormatter,ProjectTitleFormatter ] +}) + +export class ClaimEntityFormatterModule { } diff --git a/sample-components/sampleComponent-rc6/src/app/common/modal/alert.module.ts b/sample-components/sampleComponent-rc6/src/app/common/modal/alert.module.ts new file mode 100644 index 00000000..ef4e2b52 --- /dev/null +++ b/sample-components/sampleComponent-rc6/src/app/common/modal/alert.module.ts @@ -0,0 +1,13 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { FormsModule } from '@angular/forms'; +import {Open} from './open.component'; + +@NgModule({ + imports: [ CommonModule, FormsModule ], + declarations: [ Open] +}) + +// exports: [ ContactComponent ], +// providers: [ ContactService ] +export class AlertModule { } diff --git a/sample-components/sampleComponent-rc6/src/app/common/modal/alert.ts b/sample-components/sampleComponent-rc6/src/app/common/modal/alert.ts new file mode 100644 index 00000000..bf5d1f60 --- /dev/null +++ b/sample-components/sampleComponent-rc6/src/app/common/modal/alert.ts @@ -0,0 +1,110 @@ +import {Component, ViewEncapsulation, ComponentRef, ElementRef, Input, EventEmitter, Output} from '@angular/core'; +// import { DynamicComponentLoader} from '@angular/core'; + +import {Open} from './open.component'; + +@Component({ + selector: 'alert', + template: ` + + `, + encapsulation: ViewEncapsulation.None, +}) +/** + * API to an open alert window. + */ +export class Alert{ + /** + * Caption for the title. + */ + public alertTitle:string; + /** + * Describes if the alert contains Ok Button. + * The default Ok button will close the alert and emit the callback. + * Defaults to true. + */ + public okButton:boolean = true; + /** + * Caption for the OK button. + * Default: Ok + */ + public okButtonText:string= 'Ok'; + /** + * Describes if the alert contains cancel Button. + * The default Cancelbutton will close the alert. + * Defaults to true. + */ + public cancelButton:boolean = true; + /** + * Caption for the Cancel button. + * Default: Cancel + */ + public cancelButtonText:string = 'Cancel'; + /** + * if the alertMessage is true it will show the contentString inside alert body. + */ + public alertMessage:boolean = true; + /** + * Some message/content can be set in message which will be shown in alert body. + */ + public message:string; + /** + * if the value is true alert footer will be visible or else it will be hidden. + */ + public alertFooter:boolean= true; + /** + * shows alert header if the value is true. + */ + public alertHeader:boolean = true; + /** + * if the value is true alert will be visible or else it will be hidden. + */ + public isOpen:boolean=false; + /** + * Emitted when a ok button was clicked + * or when Ok method is called. + */ + @Output() public alertOutput:EventEmitter = new EventEmitter(); + constructor( public _elementRef: ElementRef){} + /** + * Opens a alert window creating backdrop. + */ + open(){ + this.isOpen= true; + } + /** + * ok method closes the modal and emits modalOutput. + */ + ok(){ + this.isOpen = false; + this.alertOutput.emit(true); + } + /** + * cancel method closes the moda. + */ + cancel(){ + this.isOpen = false; + } +} diff --git a/sample-components/sampleComponent-rc6/src/app/common/modal/loading.component.ts b/sample-components/sampleComponent-rc6/src/app/common/modal/loading.component.ts new file mode 100644 index 00000000..c046feae --- /dev/null +++ b/sample-components/sampleComponent-rc6/src/app/common/modal/loading.component.ts @@ -0,0 +1,49 @@ +import {Component, ViewEncapsulation, ComponentRef, ElementRef, Input, EventEmitter, Output} from '@angular/core'; + +@Component({ + selector: 'loading', + template: ` + + `, + encapsulation: ViewEncapsulation.None, +}) +/** + * API to an open alert window. + */ +export class Loading{ + +@Input() public message:string ="Loading"; + + /** + * if the value is true alert will be visible or else it will be hidden. + */ + public isOpen:boolean=false; + /** + * Emitted when a ok button was clicked + * or when Ok method is called. + */ + @Output() public alertOutput:EventEmitter = new EventEmitter(); + constructor( public _elementRef: ElementRef){} + /** + * Opens a alert window creating backdrop. + */ + open(){ + this.isOpen= true; + } + + close(){ + this.isOpen = false; + } +} diff --git a/sample-components/sampleComponent-rc6/src/app/common/modal/loading.module.ts b/sample-components/sampleComponent-rc6/src/app/common/modal/loading.module.ts new file mode 100644 index 00000000..a1ad036a --- /dev/null +++ b/sample-components/sampleComponent-rc6/src/app/common/modal/loading.module.ts @@ -0,0 +1,13 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { FormsModule } from '@angular/forms'; +import {Open} from './open.component'; + +@NgModule({ + imports: [ CommonModule, FormsModule ], + declarations: [ Open] +}) + +// exports: [ ContactComponent ], +// providers: [ ContactService ] +export class LoadingModule { } diff --git a/sample-components/sampleComponent-rc6/src/app/common/modal/open.component.ts b/sample-components/sampleComponent-rc6/src/app/common/modal/open.component.ts new file mode 100644 index 00000000..95add08d --- /dev/null +++ b/sample-components/sampleComponent-rc6/src/app/common/modal/open.component.ts @@ -0,0 +1,55 @@ +import {Directive, Input, HostBinding} from '@angular/core'; + +// todo: add animate +// todo: add init and on change +@Directive({selector: '[open]'}) +export class Open { + @HostBinding('style.display') + private display:string; + @HostBinding('class.in') + @HostBinding('attr.aria-expanded') + private isExpanded:boolean = true; + + @Input() + private set open(value:boolean) { + this.isExpanded = value; + this.toggle(); + } + + private get open():boolean { + return this.isExpanded; + } + + constructor() { + } + init() { + this.isExpanded = false; + this.display = 'none'; + } + toggle() { + if (this.isExpanded) { + this.hide(); + } else { + this.show(); + } + } + + hide() { + this.isExpanded = false; + this.display = 'none'; + if (typeof document !== 'undefined') { + let backDrop = document.getElementsByClassName("modal-backdrop"); + if(backDrop.length>0){ + document.body.removeChild(backDrop[0]); + } + } + } + + show() { + let backDrop = document.createElement('div'); + backDrop.className="modal-backdrop fade in"; + document.body.appendChild(backDrop); + this.isExpanded = true; + this.display = 'block'; + } +} diff --git a/sample-components/sampleComponent-rc6/src/app/common/pagingFormatterNoLoad.component.ts b/sample-components/sampleComponent-rc6/src/app/common/pagingFormatterNoLoad.component.ts new file mode 100644 index 00000000..42534afd --- /dev/null +++ b/sample-components/sampleComponent-rc6/src/app/common/pagingFormatterNoLoad.component.ts @@ -0,0 +1,75 @@ +import {Component, Input, Output, EventEmitter} from '@angular/core'; + + +//Usage Example + +@Component({ + selector: 'paging-no-load', + template: ` + + ` +}) + +export class pagingFormatterNoLoad { + @Input() currentPage: number = 1; + @Input() navigateTo: string; + @Input() term: string=''; + @Input() size: number=10; + @Input() totalResults: number = 10; + @Input() params; + + @Output() pageChange = new EventEmitter(); + + constructor () { + } + + ngOnInit() { + console.info("In paging -- CurrentPage:"+this.currentPage+" "+"total Pages = "+this.getTotalPages() +" Results num:"+this.totalResults); + } + getTotalPages(){ + var i= this.totalResults/this.size; + var integerI=parseInt(''+i); + return parseInt(''+((i==integerI)?i:i+1)); + } + onPrev(){ + this.currentPage=this.currentPage-1; + this.pageChange.emit({ + value: this.currentPage + }); + + } + + onNext(){ + + this.currentPage=this.currentPage+1; + this.pageChange.emit({ + value: this.currentPage + }); + } + onPage(pageNum: number){ + + this.currentPage=pageNum; + this.pageChange.emit({ + value: this.currentPage + }); + } +} diff --git a/sample-components/sampleComponent-rc6/src/app/common/projectTitleFormatter.component.ts b/sample-components/sampleComponent-rc6/src/app/common/projectTitleFormatter.component.ts new file mode 100644 index 00000000..5917768e --- /dev/null +++ b/sample-components/sampleComponent-rc6/src/app/common/projectTitleFormatter.component.ts @@ -0,0 +1,23 @@ +import {Component, Input} from '@angular/core'; +import {OpenaireProperties} from '../openaireProperties'; + +//Usage Example " " + +@Component({ + selector: 'project-title', + template: ` + + ` +}) + +export class ProjectTitleFormatter { + @Input() project: string[]; + private url:string; + constructor () {} + + ngOnInit() { + this.url = OpenaireProperties.getsearchLinkToProject() + "?projectId=" + this.project["openaireId"]; + } +} diff --git a/sample-components/sampleComponent-rc6/src/app/common/publicationTitleFormatter.component.ts b/sample-components/sampleComponent-rc6/src/app/common/publicationTitleFormatter.component.ts new file mode 100644 index 00000000..2c87c50a --- /dev/null +++ b/sample-components/sampleComponent-rc6/src/app/common/publicationTitleFormatter.component.ts @@ -0,0 +1,26 @@ +import {Component, Input} from '@angular/core'; + +//Usage Example " " + +@Component({ + selector: 'publication-title', + template: ` +
+
{{title}}
+
{{title}}
+
+ ` +}) + +export class PublicationTitleFormatter { + @Input() title: string[]; + @Input() url: string[]; + + constructor () {} + + ngOnInit() { + + } + + +} diff --git a/sample-components/sampleComponent-rc6/src/app/entities/claim.ts b/sample-components/sampleComponent-rc6/src/app/entities/claim.ts new file mode 100644 index 00000000..b5378c5f --- /dev/null +++ b/sample-components/sampleComponent-rc6/src/app/entities/claim.ts @@ -0,0 +1,15 @@ +export class Claim { + id: string; + sourceType: string; + targetType: string; + sourceId: string; + targetId: string; + date: string; + DOI: string; + project: Project + userMail: string; + +} +export class Project{ + +} diff --git a/sample-components/sampleComponent-rc6/src/app/home/home.component.html b/sample-components/sampleComponent-rc6/src/app/home/home.component.html new file mode 100644 index 00000000..fa7f4167 --- /dev/null +++ b/sample-components/sampleComponent-rc6/src/app/home/home.component.html @@ -0,0 +1,15 @@ + +
+
+
+
+
+ + + + +
+
+
+
+
diff --git a/sample-components/sampleComponent-rc6/src/app/home/home.component.ts b/sample-components/sampleComponent-rc6/src/app/home/home.component.ts new file mode 100644 index 00000000..03253360 --- /dev/null +++ b/sample-components/sampleComponent-rc6/src/app/home/home.component.ts @@ -0,0 +1,15 @@ +import {Component} from '@angular/core'; +import {Router} from '@angular/router'; +import {Observable} from 'rxjs/Observable'; +import {Location} from '@angular/common'; + +@Component({ + selector: 'home', + templateUrl: 'home.component.html', + }) + +export class HomeComponent { + constructor ( private _router: Router, private location: Location) {} + + +} diff --git a/sample-components/sampleComponent-rc6/src/app/openaireProperties.ts b/sample-components/sampleComponent-rc6/src/app/openaireProperties.ts new file mode 100644 index 00000000..796973ae --- /dev/null +++ b/sample-components/sampleComponent-rc6/src/app/openaireProperties.ts @@ -0,0 +1,89 @@ +export class OpenaireProperties { + //landing Pages + private static baseSearchLink="/" + private static searchLinkToPublication = "publication?articleId="; + private static searchLinkToProject = "project?projectId="; + private static searchLinkToPerson = "person?personId="; + private static searchLinkToDataProvider = "https://beta.openaire.eu/search/dataprovider?datasourceId="; + private static searchLinkToDataset = "dataset?datasetId="; + private static searchLinkToOrganization = "organization?organizationId="; + + // Services - APIs + + // public claimsAPIURL = "http://rudie.di.uoa.gr:8080/dnet-openaire-connector-service-1.0.0-SNAPSHOT/rest/claimsService/" + private static claimsAPIURL = "http://scoobydoo.di.uoa.gr:8181/dnet-openaire-connector-service-1.0.0-SNAPSHOT/rest/claimsService/"; + + private static searchAPIURL = "http://astero.di.uoa.gr:8080/dnet-functionality-services-2.0.0-SNAPSHOT/rest/v2.0/api/"; + // private searchAPIURL = "http://rudie.di.uoa.gr:8080/dnet-functionality-services-2.0.0-SNAPSHOT/rest/v2.0/api/"; + // private searchAPIURL = "http://scoobydoo.di.uoa.gr:8181/dnet-functionality-services-2.0.0-SNAPSHOT/rest/v2.0/api/"; + + private static searchServiveURL = "http://astero.di.uoa.gr:8080/dnet-functionality-services-2.0.0-SNAPSHOT/"; + // private static searchServiveURL = "http://scoobydoo.di.uoa.gr:8181/dnet-functionality-services-2.0.0-SNAPSHOT/"; + // private static searchServiveURL = "http://services.openaire.eu:8380/search/"; + //private static searchServiveURL = "http://rudie.di.uoa.gr:8080/dnet-functionality-services-2.0.0-SNAPSHOT/"; + + private static searchCrossrefAPIURL = "http://api.crossref.org/works"; + private static searchDataciteAPIURL = "http://search.datacite.org/api"; + private static searchOrcidURL = "https://pub.orcid.org/"; + + // Identifiers + private static pmidURL = "http://www.ncbi.nlm.nih.gov/pubmed/"; + private static doiURL = "http://dx.doi.org/"; + private static cordisURL = "http://cordis.europa.eu/projects/"; + private static pmcURL = "http://europepmc.org/articles/"; + + + //landing Pages' getters + public static getsearchLinkToPublication():string{ + return this.baseSearchLink + this.searchLinkToPublication; + } + public static getsearchLinkToDataset():string{ + return this.baseSearchLink + this.searchLinkToDataset; + } + public static getsearchLinkToProject():string{ + return this.baseSearchLink + this.searchLinkToProject; + } + public static getsearchLinkToPerson():string{ + return this.baseSearchLink + this.searchLinkToPerson; + } + public static getsearchLinkToOrganization():string{ + return this.searchLinkToOrganization; + } + public static getsearchLinkToDataProvider():string{ + return this.searchLinkToDataProvider; + } + + // Services - APIs' getters + public static getSearchAPIURL():string{ + return this.searchAPIURL; + } + public static getSearchServiceURL():string{ + return this.searchServiveURL; + } + public static getClaimsAPIURL():string{ + return this.claimsAPIURL; + } + public static getSearchCrossrefAPIURL():string{ + return this.searchCrossrefAPIURL; + } + public static getSearchDataciteAPIURL():string{ + return this.searchDataciteAPIURL; + } + public static getSearchOrcidURL():string{ + return this.searchOrcidURL; + } + + // Identifiers' getters + public static getPmidURL():string{ + return this.pmidURL; + } + public static getDoiURL():string{ + return this.doiURL; + } + public static getCordisURL():string{ + return this.cordisURL; + } + public static getPmcURL():string{ + return this.pmcURL; + } +} diff --git a/sample-components/sampleComponent-rc6/src/app/services/claims.service.ts b/sample-components/sampleComponent-rc6/src/app/services/claims.service.ts new file mode 100644 index 00000000..43c6abce --- /dev/null +++ b/sample-components/sampleComponent-rc6/src/app/services/claims.service.ts @@ -0,0 +1,131 @@ +import {Injectable} from '@angular/core'; +import {Jsonp, URLSearchParams,ResponseOptions, RequestOptions, Headers} from '@angular/http'; +import {Http, Response} from '@angular/http'; +import {Observable} from 'rxjs/Observable'; +import {Claim} from '../entities/claim'; +import {OpenaireProperties} from '../openaireProperties'; + +@Injectable() +export class ClaimsService { + private baseUrl; + constructor(private jsonp: Jsonp, private http: Http) { + this.baseUrl = OpenaireProperties.getClaimsAPIURL(); + } + + private getClaimRequest(size : number, page : number, url :string):any { + console.info('ClaimsService: Claims request: '+url); + return this.http.get( url) + .map(request => request.json()) + .do(request => console.info("Get claims: offset = "+(size*(page-1)) + " limit ="+size )) + .catch(this.handleError); + } + getClaims( size : number, page : number, keyword:string, sortby: string, descending: boolean, types: string):any { + console.info('ClaimsService: getClaims ' ); + console.info('ClaimsService: Types : '+types ); + let url = this.baseUrl +"claims"+"?offset="+(size*(page-1) + "&limit="+size)+"&keyword="+keyword+"&sortby="+sortby+"&descending="+descending+""+types; + return this.getClaimRequest(size,page,url); + + } + getClaimsByUser( size : number, page : number, user:string, keyword:string, sortby: string, descending: boolean, types: string):any { + console.info('ClaimsService: getClaims for user : '+user); + let url = this.baseUrl +"users/"+user+"/claims"+"?offset="+(size*(page-1) + "&limit="+size)+"&keyword="+keyword+"&sortby="+sortby+"&descending="+descending+""+types; + return this.getClaimRequest(size,page,url); + + } + getClaimsBycontext( size : number, page : number, contextId:string, keyword:string, sortby: string, descending: boolean, types: string):any { + console.info('ClaimsService: getClaims for context : '+contextId); + let url = this.baseUrl +"contexts/"+contextId+"/claims"+"?offset="+(size*(page-1) + "&limit="+size)+"&keyword="+keyword+"&sortby="+sortby+"&descending="+descending+""+types; + return this.getClaimRequest(size,page,url); + + } + getClaimsByResult( size : number, page : number, resultId:string, keyword:string, sortby: string, descending: boolean, types: string):any { + console.info('ClaimsService: getClaims for result : '+resultId); + let url = this.baseUrl +"results/"+resultId+"/claims"+"?offset="+(size*(page-1) + "&limit="+size)+"&keyword="+keyword+"&sortby="+sortby+"&descending="+descending+""+types; + return this.getClaimRequest(size,page,url); + + } + getClaimsByProject( size : number, page : number, projectId:string, keyword:string, sortby: string, descending: boolean, types: string):any { + console.info('ClaimsService: getClaims for project : '+projectId); + let url = this.baseUrl +"projects/"+projectId+"/claims"+"?offset="+(size*(page-1) + "&limit="+size)+"&keyword="+keyword+"&sortby="+sortby+"&descending="+descending+""+types; + return this.getClaimRequest(size,page,url); + } + + deleteClaimById(claimId:string):any{ + console.warn('Trying to delete claim with id : '+claimId); + let url = this.baseUrl +"claims/"+claimId; + console.warn('Delete url: '+url); + let headers = new Headers({ 'Content-Type': 'application/json' }); + let options = new RequestOptions({ headers: headers }); + return this.http.delete( url, options).map(request => request.json()) + .do(request => console.info("After delete" )) + .catch(this.handleError); + + } + deleteBulk(claimIds:string[]):any{ + + console.warn('Trying to delete claims with ids : '+claimIds); + var url = ""; + + for(var claimId of claimIds){ + url=url+(url.length >0 ?"&":"")+"claimId="+claimId; + } + url= this.baseUrl +"claims/bulk?"+url; + console.warn('Delete url: '+url); + let headers = new Headers({ 'Content-Type': 'application/json' }); + let options = new RequestOptions({ headers: headers }); + return this.http.delete( url, options).map(request => request.json()) + .do(request => console.info("After delete" )) + .catch(this.handleError); + + } + insertBulkClaims(claims):any{ + console.warn('Trying toinsert claims : '+claims); + let url = this.baseUrl +"claims/bulk"; + let body = JSON.stringify( claims ); + console.warn('Json body: : '+body); + let headers = new Headers({ 'Content-Type': 'application/json' }); + let options = new RequestOptions({ headers: headers }); + return this.http.post(url, body, options) + .map(res => res.json()) + .do(request => console.info("Insert Response:"+request.status) ) + .catch(this.handleError); + + } + insertClaim(claim):any{ + console.warn('Trying toinsert claim : '+claim); + let url = this.baseUrl +"claims"; + let body = JSON.stringify( claim ); + let headers = new Headers({ 'Content-Type': 'application/json' }); + let options = new RequestOptions({ headers: headers }); + return this.http.post(url, body, options) + .map(res => res.json()) + .do(request => console.info("Insert Response:"+request.status) ) + .catch(this.handleError); + + } + + private handleError (error: Response) { + // in a real world app, we may send the error to some remote logging infrastructure + // instead of just logging it to the console + console.error(error); + return Observable.throw(error || 'Server error'); + } + + getClaim(id:string):any { + let url = this.baseUrl+"claims/"+id; + return new Promise((resolve, reject) => { + this.http.get(url) + .map(res => res.json()) + .subscribe( + data => { + resolve(data.data); + }, + err => { + reject(err); + } + ) + ; + }); + } + +} diff --git a/sample-components/sampleComponent-rc6/src/assets/logo.png b/sample-components/sampleComponent-rc6/src/assets/logo.png new file mode 100644 index 00000000..afea237f Binary files /dev/null and b/sample-components/sampleComponent-rc6/src/assets/logo.png differ diff --git a/sample-components/sampleComponent-rc6/src/backend/api.ts b/sample-components/sampleComponent-rc6/src/backend/api.ts new file mode 100644 index 00000000..d8f4f517 --- /dev/null +++ b/sample-components/sampleComponent-rc6/src/backend/api.ts @@ -0,0 +1,24 @@ +// Our API for demos only +import {fakeDataBase} from './db'; +import {fakeDemoRedisCache} from './cache'; + +// you would use cookies/token etc +var USER_ID = 'f9d98cf1-1b96-464e-8755-bcc2a5c09077'; // hardcoded as an example + +// Our API for demos only +export function serverApi(req, res) { + let key = USER_ID + '/data.json'; + let cache = fakeDemoRedisCache.get(key); + if (cache !== undefined) { + console.log('/data.json Cache Hit'); + return res.json(cache); + } + console.log('/data.json Cache Miss'); + + fakeDataBase.get() + .then(data => { + fakeDemoRedisCache.set(key, data); + return data; + }) + .then(data => res.json(data)); +} diff --git a/sample-components/sampleComponent-rc6/src/backend/cache.ts b/sample-components/sampleComponent-rc6/src/backend/cache.ts new file mode 100644 index 00000000..490a3561 --- /dev/null +++ b/sample-components/sampleComponent-rc6/src/backend/cache.ts @@ -0,0 +1,17 @@ + + +var _fakeLRUcount = 0; +export const fakeDemoRedisCache = { + _cache: {}, + get: (key) => { + let cache = fakeDemoRedisCache._cache[key]; + _fakeLRUcount++; + if (_fakeLRUcount >= 10) { + fakeDemoRedisCache.clear(); + _fakeLRUcount = 0; + } + return cache; + }, + set: (key, data) => fakeDemoRedisCache._cache[key] = data, + clear: () => fakeDemoRedisCache._cache = {} +}; diff --git a/sample-components/sampleComponent-rc6/src/backend/db.ts b/sample-components/sampleComponent-rc6/src/backend/db.ts new file mode 100644 index 00000000..3ba8ea3d --- /dev/null +++ b/sample-components/sampleComponent-rc6/src/backend/db.ts @@ -0,0 +1,7 @@ +// Our API for demos only +export const fakeDataBase = { + get() { + let res = { data: 'This fake data came from the db on the server.' }; + return Promise.resolve(res); + } +}; diff --git a/sample-components/sampleComponent-rc6/src/client.ts b/sample-components/sampleComponent-rc6/src/client.ts new file mode 100644 index 00000000..d92fc324 --- /dev/null +++ b/sample-components/sampleComponent-rc6/src/client.ts @@ -0,0 +1,18 @@ +// the polyfills must be the first thing imported +import 'angular2-universal-polyfills'; + +// Angular 2 +import { enableProdMode} from '@angular/core'; +import { platformUniversalDynamic } from 'angular2-universal'; + +// enable prod for faster renders +enableProdMode(); + +import { main } from './main.browser'; + +// on document ready bootstrap Angular 2 +document.addEventListener('DOMContentLoaded', () => { + + platformUniversalDynamic().bootstrapModule(main()); + +}); diff --git a/sample-components/sampleComponent-rc6/src/index.html b/sample-components/sampleComponent-rc6/src/index.html new file mode 100644 index 00000000..8bd68c09 --- /dev/null +++ b/sample-components/sampleComponent-rc6/src/index.html @@ -0,0 +1,29 @@ + + + + OpenAIRE + + + + + + + + + + + + + + + + + Loading Universal ... + + + + + diff --git a/sample-components/sampleComponent-rc6/src/main.browser.ts b/sample-components/sampleComponent-rc6/src/main.browser.ts new file mode 100644 index 00000000..c4f7b5c7 --- /dev/null +++ b/sample-components/sampleComponent-rc6/src/main.browser.ts @@ -0,0 +1,72 @@ +import { NgModule } from '@angular/core'; +import { FormsModule } from '@angular/forms'; + +import { UniversalModule } from 'angular2-universal'; + +import { App } from './app/app'; +/* Feature Modules */ +import { LoadingModule } from './app/common/modal/loading.module'; +import {ClaimEntityFormatterModule } from './app/common/claimEntityFormatter.module'; +// +import {ClaimsModule } from './app/claimPages/claims/claims.module'; +//for routing: +import {ClaimsAdminComponent} from './app/claimPages/claims/claimsAdmin.component'; +import { routing } from './app/app.routing'; +import {Routes, RouterModule} from "@angular/router"; + + + +import {Open} from './app/common/modal/open.component'; + +import {Alert} from './app/common/modal/alert'; +import {Loading} from './app/common/modal/loading.component'; +import {ClaimsComponent} from './app/claimPages/claims/claims.component'; +import {ClaimsService} from './app/services/claims.service'; +import {Claim} from './app/entities/claim'; +import {pagingFormatterNoLoad} from './app/common/pagingFormatterNoLoad.component'; + +import {ClaimEntityFormatter} from './app/common/claimEntityFormatter.component'; +import {PublicationTitleFormatter} from './app/common/publicationTitleFormatter.component'; +import {ProjectTitleFormatter} from './app/common/projectTitleFormatter.component'; +import {HomeComponent} from './app/home/home.component'; +export function main() { + @NgModule({ + bootstrap: [ App ], + declarations: [ App, ClaimsAdminComponent, ClaimsComponent, ClaimEntityFormatter,pagingFormatterNoLoad, Open, ProjectTitleFormatter, PublicationTitleFormatter,HomeComponent, Loading, Alert], + imports: [ + UniversalModule, + FormsModule, + routing + ], + + providers: [ ClaimsService ] + + }) + + + + + +// +// //OpenModule, ClaimEntityFormatterModule,ClaimEntityFormatter, +// //ClaimsService +// export function main() { +// @NgModule({ +// bootstrap: [ App ], +// declarations: [ App, ClaimsAdminComponent], +// imports: [ +// UniversalModule, +// FormsModule, +// ClaimsModule, +// LoadingModule, +// +// routing +// ], +// +// providers: [ ] +// +// }) + class MainModule { + } + return MainModule; +} diff --git a/sample-components/sampleComponent-rc6/src/main.node.ts b/sample-components/sampleComponent-rc6/src/main.node.ts new file mode 100644 index 00000000..e5838609 --- /dev/null +++ b/sample-components/sampleComponent-rc6/src/main.node.ts @@ -0,0 +1,27 @@ +import { NgModule, Component } from '@angular/core'; +import { FormsModule } from '@angular/forms'; +import { UniversalModule } from 'angular2-universal'; + +import { App } from './app/app'; + +export function main(config) { + + @NgModule({ + bootstrap: [ App ], + declarations: [ App ], + imports: [ + UniversalModule.withConfig({ + document: config.document, + originUrl: 'http://localhost:3000', + baseUrl: '/', + requestUrl: '/', + // preboot: false, + preboot: { appRoot: ['app'], uglify: true }, + }), + FormsModule + ] + }) + class MainModule {} + + return MainModule +}; diff --git a/sample-components/sampleComponent-rc6/src/server.ts b/sample-components/sampleComponent-rc6/src/server.ts new file mode 100644 index 00000000..ab56fc8d --- /dev/null +++ b/sample-components/sampleComponent-rc6/src/server.ts @@ -0,0 +1,58 @@ +// the polyfills must be the first thing imported in node.js +import 'angular2-universal-polyfills'; + +import * as path from 'path'; +import * as express from 'express'; +import * as bodyParser from 'body-parser'; +import * as cookieParser from 'cookie-parser'; + +// Angular 2 +import { enableProdMode } from '@angular/core'; +// Angular 2 Universal +import { createEngine } from 'angular2-express-engine'; + +// enable prod for faster renders +enableProdMode(); + +const app = express(); +const ROOT = path.join(path.resolve(__dirname, '..')); + +// Express View +import { main } from './main.node'; +app.engine('.html', createEngine({ main })); +app.set('views', __dirname); +app.set('view engine', 'html'); + +app.use(cookieParser('Angular 2 Universal')); +app.use(bodyParser.json()); + +// Serve static files +app.use('/assets', express.static(path.join(__dirname, 'assets'), {maxAge: 30})); +app.use(express.static(path.join(ROOT, 'dist/client'), {index: false})); +/* **AK** Add this path so that index.html can see files from node_modules folder (e.g. bootstrap files)*/ +app.use(express.static(path.join(ROOT, 'node_modules'), {index: false})); + + + +import { serverApi } from './backend/api'; +// Our API for demos only +app.get('/data.json', serverApi); + +// Routes with html5pushstate +// ensure routes match client-side-app +app.get('/', (req, res) => res.render('index', {req, res})); +app.get('/claims', (req, res) => res.render('index', {req, res})); +app.get('/home', (req, res) => res.render('index', {req, res})); + + +app.get('*', function(req, res) { + res.setHeader('Content-Type', 'application/json'); + var pojo = { status: 404, message: 'No Content' }; + var json = JSON.stringify(pojo, null, 2); + res.status(404).send(json); +}); + +// Server +let server = app.listen(process.env.PORT || 3000, () => { + console.log(`Listening on: http://localhost:${server.address().port}`); +}); diff --git a/sample-components/sampleComponent-rc6/src/typings.d.ts b/sample-components/sampleComponent-rc6/src/typings.d.ts new file mode 100644 index 00000000..1c62346c --- /dev/null +++ b/sample-components/sampleComponent-rc6/src/typings.d.ts @@ -0,0 +1,75 @@ +/* + * Custom Type Definitions + * When including 3rd party modules you also need to include the type definition for the module + * if they don't provide one within the module. You can try to install it with typings +typings install node --save + * If you can't find the type definition in the registry we can make an ambient definition in + * this file for now. For example +declare module "my-module" { + export function doesSomething(value: string): string; +} + * + * If you're prototying and you will fix the types later you can also declare it as type any + * +declare var assert: any; + * + * If you're importing a module that uses Node.js modules which are CommonJS you need to import as + * +import * as _ from 'lodash' + * You can include your type definitions in this file until you create one for the typings registry + * see https://github.com/typings/registry + * + */ + + +// Extra variables that live on Global that will be replaced by webpack DefinePlugin +declare var ENV: string; +declare var HMR: boolean; +interface GlobalEnvironment { + ENV; + HMR; +} + +interface WebpackModule { + hot: { + data?: any, + idle: any, + accept(dependencies?: string | string[], callback?: (updatedDependencies?: any) => void): void; + decline(dependencies?: string | string[]): void; + dispose(callback?: (data?: any) => void): void; + addDisposeHandler(callback?: (data?: any) => void): void; + removeDisposeHandler(callback?: (data?: any) => void): void; + check(autoApply?: any, callback?: (err?: Error, outdatedModules?: any[]) => void): void; + apply(options?: any, callback?: (err?: Error, outdatedModules?: any[]) => void): void; + status(callback?: (status?: string) => void): void | string; + removeStatusHandler(callback?: (status?: string) => void): void; + }; +} + +interface WebpackRequire { + context(file: string, flag?: boolean, exp?: RegExp): any; +} + + +interface ErrorStackTraceLimit { + //stackTraceLimit: number; + stackTraceLimit(limit: number): void +} + + +// Extend typings +interface NodeRequire extends WebpackRequire {} +interface ErrorConstructor extends ErrorStackTraceLimit {} +interface NodeModule extends WebpackModule {} +interface Global extends GlobalEnvironment {} + + +interface Thenable { + then( + onFulfilled?: (value: T) => U | Thenable, + onRejected?: (error: any) => U | Thenable): Thenable; + then( + onFulfilled?: (value: T) => U | Thenable, + onRejected?: (error: any) => void): Thenable; + catch(onRejected?: (error: any) => U | Thenable): Thenable; +} diff --git a/sample-components/sampleComponent-rc6/tsconfig.json b/sample-components/sampleComponent-rc6/tsconfig.json new file mode 100644 index 00000000..96d822e5 --- /dev/null +++ b/sample-components/sampleComponent-rc6/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "declaration": false, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "module": "commonjs", + "moduleResolution": "node", + "outDir": "dist", + "sourceMap": true, + "sourceRoot": "src", + "target": "es5", + "lib": ["es6", "dom"] + }, + "exclude": [ + "node_modules" + ], + "compileOnSave": false, + "buildOnSave": false, + "atom": { "rewriteTsconfig": false } +} diff --git a/sample-components/sampleComponent-rc6/webpack.config.js b/sample-components/sampleComponent-rc6/webpack.config.js new file mode 100644 index 00000000..bfbbd742 --- /dev/null +++ b/sample-components/sampleComponent-rc6/webpack.config.js @@ -0,0 +1,92 @@ +var webpack = require('webpack'); +var path = require('path'); + +var commonConfig = { + resolve: { + extensions: ['', '.ts', '.js', '.json'] + }, + module: { + loaders: [ + // TypeScript + { test: /\.ts$/, loaders: ['ts-loader', 'angular2-template-loader'] }, + { test: /\.html$/, loader: 'raw-loader' }, + { test: /\.css$/, loader: 'raw-loader' }, + { test: /\.json$/, loader: 'raw-loader' } + ], + }, + plugins: [ + ] + +}; + + +var clientConfig = { + target: 'web', + entry: './src/client', + output: { + path: root('dist/client') + }, + node: { + global: true, + __dirname: true, + __filename: true, + process: true, + Buffer: false + } +}; + + +var serverConfig = { + target: 'node', + entry: './src/server', // use the entry file of the node server if everything is ts rather than es5 + output: { + path: root('dist/server'), + libraryTarget: 'commonjs2' + }, + externals: checkNodeImport, + node: { + global: true, + __dirname: true, + __filename: true, + process: true, + Buffer: true + } +}; + + + +// Default config +var defaultConfig = { + context: __dirname, + resolve: { + root: root('/src') + }, + output: { + publicPath: path.resolve(__dirname), + filename: 'index.js' + } +} + + + +var webpackMerge = require('webpack-merge'); +module.exports = [ + // Client + webpackMerge({}, defaultConfig, commonConfig, clientConfig), + + // Server + webpackMerge({}, defaultConfig, commonConfig, serverConfig) +] + +// Helpers +function checkNodeImport(context, request, cb) { + if (!path.isAbsolute(request) && request.charAt(0) !== '.') { + cb(null, 'commonjs ' + request); return; + } + cb(); +} + +function root(args) { + args = Array.prototype.slice.call(arguments, 0); + return path.join.apply(path, [__dirname].concat(args)); +} diff --git a/sample-components/sampleComponent-rc7/.editorconfig b/sample-components/sampleComponent-rc7/.editorconfig new file mode 100644 index 00000000..f1cc3ad3 --- /dev/null +++ b/sample-components/sampleComponent-rc7/.editorconfig @@ -0,0 +1,15 @@ +# http://editorconfig.org + +root = true + +[*] +charset = utf-8 +indent_style = space +indent_size = 2 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true + +[*.md] +insert_final_newline = false +trim_trailing_whitespace = false diff --git a/sample-components/sampleComponent-rc7/.gitignore b/sample-components/sampleComponent-rc7/.gitignore new file mode 100644 index 00000000..9e17510b --- /dev/null +++ b/sample-components/sampleComponent-rc7/.gitignore @@ -0,0 +1,12 @@ +/__build__ +/__server_build__ +/node_modules +/typings +/tsd_typings/ +npm-debug.log + +/dist/ + +.idea + +.DS_Store diff --git a/sample-components/sampleComponent-rc7/README.md b/sample-components/sampleComponent-rc7/README.md new file mode 100644 index 00000000..8e3dbcc7 --- /dev/null +++ b/sample-components/sampleComponent-rc7/README.md @@ -0,0 +1,23 @@ +# Angular 2 Universal Starter [![Universal Angular 2](https://img.shields.io/badge/universal-angular2-brightgreen.svg?style=flat)](https://github.com/angular/universal) + +A minimal Angular 2 starter for Universal JavaScript using TypeScript and Webpack + +> If you're looking for the repo from the AngularConnect talk look in the [angular-connect branch](https://github.com/angular/universal-starter/tree/angular-connect) +If you're looking for a SystemJS version of the repo look in the [systemjs branch](https://github.com/angular/universal-starter/tree/systemjs) + +[![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy) + +## Installation + +* `npm install` + +## Serve + +* `npm start` to build your client app and start a web server +* `npm run build` to prepare a distributable bundle + +## Development +* run `npm start` and `npm run watch` in two separate terminals to build your client app, start a web server, and allow file changes to update in realtime + +## Watch files +* `npm run watch` to build your client app and start a web server diff --git a/sample-components/sampleComponent-rc7/app.json b/sample-components/sampleComponent-rc7/app.json new file mode 100644 index 00000000..1762bb6b --- /dev/null +++ b/sample-components/sampleComponent-rc7/app.json @@ -0,0 +1,12 @@ +{ + "name": "Angular 2 Universal Starter", + "description": "Angular 2 Universal starter kit by @AngularClass", + "repository": "https://github.com/angular/universal-starter", + "logo": "https://cloud.githubusercontent.com/assets/1016365/10639063/138338bc-7806-11e5-8057-d34c75f3cafc.png", + "env": { + "NPM_CONFIG_PRODUCTION": { + "description": "Install `webpack` and other development modules when deploying to allow full builds.", + "value": "false" + } + } +} diff --git a/sample-components/sampleComponent-rc7/nodemon.json b/sample-components/sampleComponent-rc7/nodemon.json new file mode 100644 index 00000000..97a836fb --- /dev/null +++ b/sample-components/sampleComponent-rc7/nodemon.json @@ -0,0 +1,7 @@ +{ + "watch": [ + "dist", + "src/index.html" + ], + "ext" : "js ts json html" +} diff --git a/sample-components/sampleComponent-rc7/package.json b/sample-components/sampleComponent-rc7/package.json new file mode 100644 index 00000000..90c115bb --- /dev/null +++ b/sample-components/sampleComponent-rc7/package.json @@ -0,0 +1,72 @@ +{ + "name": "universal-starter", + "version": "2.0.0", + "description": "Angular 2 Universal starter kit by @AngularClass", + "repository": { + "type": "git", + "url": "https://github.com/angular/universal-starter.git" + }, + "scripts": { + "watch": "webpack --watch", + "prebuild": "rimraf dist", + "build": "webpack", + "build:prod": "webpack --progress -p", + "prestart": "npm run build", + "server": "nodemon dist/server/index.js", + "start": "npm run server", + "predebug": "npm run build", + "debug:build": "node-nightly --inspect --debug-brk node_modules/webpack/bin/webpack.js", + "debug": "node --debug-brk dist/server/index.js" + }, + "license": "MIT", + "contributors": [ + "AngularClass ", + "PatrickJS ", + "Jeff Whelpley ", + "Jeff Cross ", + "Mark Pieszak " + ], + "dependencies": { + "@angular/common": "2.0.0-rc.7", + "@angular/compiler": "2.0.0-rc.7", + "@angular/core": "2.0.0-rc.7", + "@angular/forms": "2.0.0-rc.7", + "@angular/http": "2.0.0-rc.7", + "@angular/platform-browser": "2.0.0-rc.7", + "@angular/platform-browser-dynamic": "2.0.0-rc.7", + "@angular/platform-server": "2.0.0-rc.7", + "@angular/router": "3.0.0-rc.3", + "angular2-platform-node": "~1.0.5", + "angular2-universal": "~1.0.5", + "angular2-universal-polyfills": "~1.0.5", + "angular2-express-engine": "~1.0.5", + "body-parser": "^1.15.2", + "express": "^4.14.0", + "methods": "~1.1.2", + "rxjs": "5.0.0-beta.12", + "zone.js": "~0.6.21" + }, + "devDependencies": { + "@angularclass/resolve-angular-routes": "^1.0.9", + "@types/body-parser": "0.0.29", + "@types/compression": "0.0.29", + "@types/cookie-parser": "^1.3.29", + "@types/express": "^4.0.29", + "@types/express-serve-static-core": "^4.0.29", + "@types/mime": "0.0.28", + "@types/node": "^4.0.30", + "@types/serve-static": "^1.7.27", + "angular2-template-loader": "^0.4.0", + "cookie-parser": "^1.4.3", + "nodemon": "^1.10.0", + "raw-loader": "^0.5.1", + "rimraf": "^2.5.4", + "ts-loader": "^0.8.2", + "ts-node": "^1.3.0", + "typescript": "2.0.0", + "webpack": "^2.1.0-beta.22", + "webpack-dev-middleware": "^1.6.1", + "webpack-dev-server": "^2.1.0-beta.0", + "webpack-merge": "^0.13.0" + } +} diff --git a/sample-components/sampleComponent-rc7/src/app/app.routing.ts b/sample-components/sampleComponent-rc7/src/app/app.routing.ts new file mode 100644 index 00000000..9386b275 --- /dev/null +++ b/sample-components/sampleComponent-rc7/src/app/app.routing.ts @@ -0,0 +1,29 @@ +import { ModuleWithProviders } from '@angular/core'; +import { Routes, RouterModule } from '@angular/router'; +import {ClaimsAdminComponent} from './claimPages/claims/claimsAdmin.component'; +import {HomeComponent} from './home/home.component'; +const appRoutes: Routes = [ + { path: '', + pathMatch: 'full', + redirectTo: 'home' }, + { path: 'claims', component: ClaimsAdminComponent }, + { path: 'home', component: HomeComponent } + +]; + + +// , +// { +// path: 'heroes', +// component: HeroListComponent, +// data: { +// title: 'Heroes List' +// } +// }, +// { path: 'hero/:id', component: HeroDetailComponent }, +// { path: '**', component: PageNotFoundComponent } +// export const appRoutingProviders: any[] = [ +// +// ]; + +export const routing: ModuleWithProviders = RouterModule.forRoot(appRoutes); diff --git a/sample-components/sampleComponent-rc7/src/app/app.ts b/sample-components/sampleComponent-rc7/src/app/app.ts new file mode 100644 index 00000000..636737c7 --- /dev/null +++ b/sample-components/sampleComponent-rc7/src/app/app.ts @@ -0,0 +1,40 @@ +import { Component } from '@angular/core'; + +import 'rxjs/Rx'; +@Component({ + selector: 'app', + template: ` +
+ + +
+ +
+ +
` +}) +export class App { + +} diff --git a/sample-components/sampleComponent-rc7/src/app/claimPages/claims/claims.component.html b/sample-components/sampleComponent-rc7/src/app/claimPages/claims/claims.component.html new file mode 100644 index 00000000..4518b03f --- /dev/null +++ b/sample-components/sampleComponent-rc7/src/app/claimPages/claims/claims.component.html @@ -0,0 +1,107 @@ +
+
+
+
+ +
Claims related to
+ +
+

+ +

+

+ +

+

+ +

+

+ +

+

+ +

+
+
+
+ + +
+ + + diff --git a/sample-components/sampleComponent-rc7/src/app/claimPages/claims/claims.component.ts b/sample-components/sampleComponent-rc7/src/app/claimPages/claims/claims.component.ts new file mode 100644 index 00000000..b8151b44 --- /dev/null +++ b/sample-components/sampleComponent-rc7/src/app/claimPages/claims/claims.component.ts @@ -0,0 +1,490 @@ +import {Component, ViewChild, Input} from '@angular/core'; +import {Location} from '@angular/common'; +import {Observable} from 'rxjs/Observable'; +import {ActivatedRoute, Router} from '@angular/router'; +import {ClaimsService} from '../../services/claims.service'; +import {Loading} from '../../common/modal/loading.component'; +import {Alert} from '../../common/modal/alert'; + + +@Component({ + selector: 'claims', + templateUrl: 'claims.component.html', + providers:[ ClaimsService] + +}) +export class ClaimsComponent { + constructor (private _claimService: ClaimsService, private route: ActivatedRoute, private _router:Router, private location: Location) { + } + + ngOnInit() { + // this.sub = this.route.queryParams.subscribe(params => { + + var params = []; + if( this.myClaims == 'true' ){ + this.fetchBy = "User"; + }else{ + + this.fetchBy = params['fetchBy']; + this.fetchBy = (this.types.indexOf(this.fetchBy) != -1)? this.fetchBy:'All'; + this.fetchId = params['fetchId']; + this.fetchId=this.fetchId?this.fetchId:''; + + } + + let page = (params['page']=== undefined)?1:+params['page']; + let size = (params['size']=== undefined)?10:+params['size']; + + this.keyword = (params['keyword']?params['keyword']:""); + this.inputkeyword = this.keyword; + this.page = ( page <= 0 ) ? 1 : page; + this.size = ( size <= 0 ) ? 10 : size; + this.entityTypes = []//(params['types']?params['types']:[]); + this.setTypes(params['types']); // check the appropriate checkboxes + // this.setSortby(params['sort']); + this.getClaims(); + + // }); + // this.sub = this.route.params.subscribe(params => { + // console.info(this.isAdmin+" "+this.myClaims+" Fetch by: "+this.fetchBy+" Fetch id: "+this.fetchId); + // if( this.myClaims == 'true' ){ + // console.info("Is myclaims"); + // this.fetchBy = "User"; + // }else{ + // console.info("Is admin"); + // + // console.info(this.isAdmin); + // + // this.fetchBy = params['fetchBy']; + // this.fetchBy = (this.types.indexOf(this.fetchBy) != -1)? this.fetchBy:'All'; + // this.fetchId = params['fetchId']; + // console.info("Fetch by:"+this.fetchBy+"Fetch id:"+this.fetchId); + // this.fetchId=this.fetchId?this.fetchId:''; + // + // } + // + // console.info(this.isAdmin+" "+this.myClaims+" Fetch by: "+this.fetchBy+" Fetch id: "+this.fetchId); + // let page = (params['page']=== undefined)?1:+params['page']; + // let size = (params['size']=== undefined)?10:+params['size']; + // + // this.keyword = (params['keyword']?params['keyword']:""); + // this.inputkeyword = this.keyword; + // this.page = ( page <= 0 ) ? 1 : page; + // this.size = ( size <= 0 ) ? 10 : size; + // this.entityTypes = []//(params['types']?params['types']:[]); + // this.setTypes(params['types']); // check the appropriate checkboxes + // this.setSortby(params['sort']); + // this.getClaims(); + // console.info("params: "+params['page']+" page "+page +" this.page: "+this.page ); + // }); + } + ngOnDestroy() { + this.sub.unsubscribe(); + } + sub: any; + //string because comes as input from component directive + @Input() enableDelete: string = 'false'; + @Input() myClaims: string= 'false' ; + @Input() isAdmin:string = 'false'; + page : number; + size:number; + keyword:string; // the keyword string to give to the request as parameter + inputkeyword:string; // the string written in the input field (keyword=inputkeyword when its length is bigger than 3 and the user stops typing) + lengths = [10,20,30,50]; + types = ["All","Project","Context","Result","User"]; + @Input() fetchBy:string; + @Input() fetchId:string; + + navigateTo: string = "Claims"; + resultsNum: number ; + claims: string[]; + + @ViewChild (Loading) loading : Loading ; + + //checkboxes: + publicationCB = false; + datasetCB = false; + contextCB = false; + projectCB = false; + entityTypes : string[] =[] ; + + descending = true; + sortby = "date"; + + selected=[]; + deleteMessage:string = ""; + showErrorMessage:boolean = false; + + //params for pagingFormatter to use when navigate to page + params; + @ViewChild(Alert) alert; + + claimsDeleted:number = 0; + + getClaims () { + this.selected=[]; + var types = ''; + this.showErrorMessage = false; + for (var type of this.entityTypes){ + types+=(types.length>0?'&':'')+"types="+type; + } + if(this.fetchBy =="Project" ){ + this._claimService.getClaimsByProject(this.size,this.page,this.fetchId,this.keyword,this.sortby,this.descending, types).subscribe( + data => { + this.claims = data.data; + this.resultsNum= data.total; + }, + err => { + console.error(err); + this.showErrorMessage = true; + } + ); + }else if(this.fetchBy =="User"){ + this._claimService.getClaimsByUser(this.size,this.page,this.fetchId,this.keyword,this.sortby,this.descending, types).subscribe( + data => { + this.claims = data.data; + this.resultsNum= data.total; + }, + err => { + console.error(err); + this.showErrorMessage = true; + } + ); + }else if(this.fetchBy =="Result"){ + this._claimService.getClaimsByResult(this.size,this.page,this.fetchId,this.keyword,this.sortby,this.descending, types).subscribe( + data => { + this.claims = data.data; + this.resultsNum= data.total; + }, + err => { + console.error(err); + this.showErrorMessage = true; + } + ); + }else if(this.fetchBy =="Context"){ + this._claimService.getClaimsBycontext(this.size,this.page,this.fetchId,this.keyword,this.sortby,this.descending, types).subscribe( + data => { + this.claims = data.data; + this.resultsNum= null; + this.resultsNum= data.total;//data.length; //TODO get the total results num + }, + err => { + console.error(err); + this.showErrorMessage = true; + } + ); + }else{ + this._claimService.getClaims(this.size,this.page,this.keyword,this.sortby,this.descending, types).subscribe( + data => { + this.claims = data.data; + this.resultsNum = null; + this.resultsNum= data.total;//data.length; //TODO get the total results num + }, + err => { + console.error(err); + this.showErrorMessage = true; + } + ); + } + } + + goToClaim(claimId: number){ + this._router.navigate( ['Claim', { id: claimId}] ); + } + goTo(page:number = 1){ + + this.page = page; + + this.location.go(location.pathname,this.getParametersString()); + this.getClaims(); + } + getParameters(){ + let params={ page: this.page, size: this.size, types: this.entityTypes, fetchBy: this.fetchBy, fetchId:this.fetchId, keyword : this.keyword, sort: this.getSortby() }; + return params; + } + getParametersString(){ + var params=''; + params+=(this.page==1?"":(params.length>0?'&':'')+"page="+this.page); + params+=(this.size==10?"":(params.length>0?'&':'')+"size="+this.size); + // params+=(this.entityTypes==''?"":(params.length>0?'&':'')+"types="+this.entityTypes); + var types=""; + for (var type of this.entityTypes){ + types+=(types.length>0?',':'')+type; + } + params+=(types.length>0)?"types="+types:""; + + if(this.isAdmin === 'true'){ + params+=(this.fetchBy=='All'?"":(params.length>0?'&':'')+"fetchBy="+this.fetchBy); + params+=(this.fetchId==''?"":(params.length>0?'&':'')+"fetchId="+this.fetchId); + } + params+=(this. getSortby()=='datedesc'?"":(params.length>0?'&':'')+"sort="+this. getSortby()); + params+=(this.keyword==''?"":(params.length>0?'&':'')+"keyword="+this.keyword); + return params; + } + changeLength(){ + this.goTo(); + } + clearFilters(){ + this.keyword = ''; + this.inputkeyword = ''; + this.publicationCB = false; + this.projectCB = false; + this.datasetCB = false; + this.contextCB = false; + this.entityTypes = []; + this.goTo(); + } + changeOrderby(sortby:string){ + if(sortby==this.sortby){ + this.descending = !this.descending; + }else{ + this.sortby = sortby; + this.descending = false; + } + this.goTo(); + } + setSortby(sortby:string){ + if(!sortby|| sortby == "datedesc"){ + this.descending = true; + this.sortby = "date"; + }else if(sortby == "dateasc"){ + this.descending = false; + this.sortby = "date"; + }else if(sortby == "userasc"){ + this.descending = false; + this.sortby = "user"; + }else if(sortby == "userdesc"){ + this.descending = true; + this.sortby = "user"; + }if(sortby =="sourceasc"){ + this.descending = false; + this.sortby = "source"; + }else if(sortby == "sourcedesc"){ + this.descending = true; + this.sortby = "source"; + }else if(sortby == "targetasc"){ + this.descending = false; + this.sortby = "target"; + }else if(sortby == "targetdesc"){ + this.descending = true; + this.sortby = "target"; + } + } + getSortby():string{ + if(this.descending){ + return this.sortby+"desc"; + }else{ + return this.sortby+"asc"; + } + + } + changeType(){ + this.entityTypes = []; + if(this.publicationCB){ + this.entityTypes.push('publication'); + } + if(this.datasetCB){ + this.entityTypes.push('dataset'); + } + if(this.projectCB){ + this.entityTypes.push('project'); + } + if(this.contextCB){ + this.entityTypes.push('context'); + } + + // if(this.publicationCB == true && this.datasetCB == true && this.contextCB == true && this.projectCB == true ){ + // this.entityTypes=""; + // }else{ + // this.entityTypes = ""; + // if(this.publicationCB == true){ + // this.entityTypes = "publication"; + // } + // if(this.datasetCB == true){ + // this.entityTypes += (this.entityTypes.length > 0?",":"")+"dataset"; + // } + // if(this.contextCB == true){ + // this.entityTypes += (this.entityTypes.length > 0?",":"")+"context"; + // } + // if(this.projectCB == true){ + // this.entityTypes += (this.entityTypes.length > 0?",":"")+"project"; + // } + // } + // console.debug("Type changed: "+this.entityTypes+" "+this.publicationCB+ this.datasetCB + this.contextCB + this.projectCB); + this.goTo(); + } + setTypes(types:string){ + if(!types){ + return; + } + if(types.length > 0){ + this.entityTypes = []; + if(types.indexOf("publication")!=-1){ + this.publicationCB = true; + this.entityTypes.push("publication"); + } + if(types.indexOf("dataset")!=-1){ + this.datasetCB = true; + this.entityTypes.push("dataset"); + } + if(types.indexOf("project")!=-1){ + this.projectCB = true; + this.entityTypes.push("project"); + } + if(types.indexOf("context")!=-1){ + this.contextCB = true; + this.entityTypes.push("context"); + } + } + if(this.publicationCB && this.datasetCB && this.contextCB && this.projectCB){ + this.entityTypes=[]; + } + } + changekeyword(){ + + if(this.inputkeyword.length >= 3 || this.inputkeyword.length == 0 ){ + this.keyword = this.inputkeyword; + this.page = 1; + this.goTo(); + } + + } + select(item:any,event){ + this.deleteMessage=""; + var value = event.currentTarget.checked; + if(value){ + this.selected.push(item); + }else{ + for (var _i = 0; _i < this.selected.length; _i++) { + let claim = this.selected[_i]; + if(claim['id'] == item.id){ + this.selected.splice(_i, 1); + } + } + + + } + } + selectAll(){ + this.selected = []; + for (var _i = 0; _i < this.claims.length; _i++) { + let claim = this.claims[_i]; + this.selected.push(claim); + } + this.deleteMessage = ""; + } + deselectAll(){ + this.selected = []; + this.deleteMessage=""; + } + isSelected(id:string){ + for (var _i = 0; _i < this.selected.length; _i++) { + let claim = this.selected[_i]; + if(claim['id'] == id){ + return true; + } + } + return false; + } + + + confirmOpen(){ + if(this.selected.length <= 0){ + + }else{ + this.alert.cancelButton = true; + this.alert.okButton = true; + this.alert.alertTitle = "Delete "+this.selected.length+" claim(s)"; + this.alert.message = this.selected.length+" claims will be deleted. Do you want to proceed? "; + this.alert.okButtonText = "Yes"; + this.alert.cancelButtonText = "No"; + this.alert.open(); + } + } + confirmClose(data){ + this.delete(); + } + delete(){ + this.deleteMessage=""; + this.loading.open(); + this.claimsDeleted = 0; + var ids = []; + for (var i = 0; i < this.selected.length; i++){ + var id =this.selected[i].id; + ids.push(id); + // var selected =this.selected[i].id; + // console.warn("Deleting claim with id:"+id); + // this.deleteById(id); + //TODO for multiple concurrent + } + this.batchDeleteById(ids); + } + + deleteById(id:string){ + + console.warn("Deleting claim with id:"+id); + // this._claimService.deleteClaimById(id); + this._claimService.deleteClaimById(id).subscribe( + res => { + console.info('Delete response'+res.code ); + console.warn("Deleted claim with id:"+ id); + //remove this claim from the + let newClaims=this.claims; + for (var _i = 0; _i < this.claims.length; _i++) { + let claim = this.claims[_i]; + if(claim['id'] == id){ + newClaims.splice(_i, 1); + } + } + //TODO should call getClaims??? + this.claimsDeleted++; + this.claims = newClaims; + if(this.claimsDeleted == this.selected.length){ + this.resultsNum = this.resultsNum - this.selected.length; + this.loading.close(); + this.selected = []; + } + + + }); + } + batchDeleteById(ids:string[]){ + + console.warn("Deleting claim with ids:"+ids); + this._claimService.deleteBulk(ids).subscribe( + res => { + console.info('Delete response'+res.code ); + console.warn("Deleted ids:"+ res.deletedIds); + console.warn("Not found ids:"+ res.notFoundIds); + //remove this claim from the + let newClaims=this.claims; + for(var id of res.deletedIds){ + for (var _i = 0; _i < this.claims.length; _i++) { + let claim = this.claims[_i]; + if(claim['id'] == id){ + newClaims.splice(_i, 1); + } + } + for (var _i = 0; _i < this.selected.length; _i++) { + let claim = this.selected[_i]; + if(claim['id'] == id){ + this.selected.splice(_i, 1); + } + } + } + this.claims = newClaims; + this.resultsNum = this.resultsNum - res.deletedIds.length; + this.loading.close(); + if(res.deletedIds.length>0){ + this.deleteMessage=this.deleteMessage+'
'+res.deletedIds.length+' claim(s) successfully deleted.
'; + } + if(res.notFoundIds.length>0){ + this.deleteMessage=this.deleteMessage+'
'+res.notFoundIds.length+' claim(s) couldn\'t be deleted.
'; + } + }); + } + pageChange($event) { + var page:number = +$event.value + this.goTo(page); + } +} diff --git a/sample-components/sampleComponent-rc7/src/app/claimPages/claims/claimsAdmin.component.ts b/sample-components/sampleComponent-rc7/src/app/claimPages/claims/claimsAdmin.component.ts new file mode 100644 index 00000000..a602bdc9 --- /dev/null +++ b/sample-components/sampleComponent-rc7/src/app/claimPages/claims/claimsAdmin.component.ts @@ -0,0 +1,36 @@ +import {Component, ViewChild, Input} from '@angular/core'; +import {Location} from '@angular/common'; +import {Observable} from 'rxjs/Observable'; + +@Component({ + selector: 'claims-admin', + template: ` +
+ + +
+ + +
+ TODO login +
+ `, + +}) +export class ClaimsAdminComponent { + constructor ( ) { + + } +user:string="argirok@di.uoa.gr"; + ngOnInit() { + + + } + + +} diff --git a/sample-components/sampleComponent-rc7/src/app/common/claimEntityFormatter.component.ts b/sample-components/sampleComponent-rc7/src/app/common/claimEntityFormatter.component.ts new file mode 100644 index 00000000..093b1cd5 --- /dev/null +++ b/sample-components/sampleComponent-rc7/src/app/common/claimEntityFormatter.component.ts @@ -0,0 +1,38 @@ +import {Component, Input} from '@angular/core'; +// import {PublicationTitleFormatter} from './publicationTitleFormatter.component'; +// import {ProjectTitleFormatter} from './projectTitleFormatter.component'; + +//Usage Example " " + +//externalUrl +@Component({ + selector: 'claim-entity', + template: ` + +
+ ({{type}}) + +
+
+ (Project) + +
+
+ (Context) +
{{entity.title}}
+
+ ` +}) + +export class ClaimEntityFormatter { + @Input() entity: string[]; + @Input() type: string; + + constructor () {} + + ngOnInit() { + + } + + +} diff --git a/sample-components/sampleComponent-rc7/src/app/common/modal/alert.ts b/sample-components/sampleComponent-rc7/src/app/common/modal/alert.ts new file mode 100644 index 00000000..bf5d1f60 --- /dev/null +++ b/sample-components/sampleComponent-rc7/src/app/common/modal/alert.ts @@ -0,0 +1,110 @@ +import {Component, ViewEncapsulation, ComponentRef, ElementRef, Input, EventEmitter, Output} from '@angular/core'; +// import { DynamicComponentLoader} from '@angular/core'; + +import {Open} from './open.component'; + +@Component({ + selector: 'alert', + template: ` + + `, + encapsulation: ViewEncapsulation.None, +}) +/** + * API to an open alert window. + */ +export class Alert{ + /** + * Caption for the title. + */ + public alertTitle:string; + /** + * Describes if the alert contains Ok Button. + * The default Ok button will close the alert and emit the callback. + * Defaults to true. + */ + public okButton:boolean = true; + /** + * Caption for the OK button. + * Default: Ok + */ + public okButtonText:string= 'Ok'; + /** + * Describes if the alert contains cancel Button. + * The default Cancelbutton will close the alert. + * Defaults to true. + */ + public cancelButton:boolean = true; + /** + * Caption for the Cancel button. + * Default: Cancel + */ + public cancelButtonText:string = 'Cancel'; + /** + * if the alertMessage is true it will show the contentString inside alert body. + */ + public alertMessage:boolean = true; + /** + * Some message/content can be set in message which will be shown in alert body. + */ + public message:string; + /** + * if the value is true alert footer will be visible or else it will be hidden. + */ + public alertFooter:boolean= true; + /** + * shows alert header if the value is true. + */ + public alertHeader:boolean = true; + /** + * if the value is true alert will be visible or else it will be hidden. + */ + public isOpen:boolean=false; + /** + * Emitted when a ok button was clicked + * or when Ok method is called. + */ + @Output() public alertOutput:EventEmitter = new EventEmitter(); + constructor( public _elementRef: ElementRef){} + /** + * Opens a alert window creating backdrop. + */ + open(){ + this.isOpen= true; + } + /** + * ok method closes the modal and emits modalOutput. + */ + ok(){ + this.isOpen = false; + this.alertOutput.emit(true); + } + /** + * cancel method closes the moda. + */ + cancel(){ + this.isOpen = false; + } +} diff --git a/sample-components/sampleComponent-rc7/src/app/common/modal/loading.component.ts b/sample-components/sampleComponent-rc7/src/app/common/modal/loading.component.ts new file mode 100644 index 00000000..c046feae --- /dev/null +++ b/sample-components/sampleComponent-rc7/src/app/common/modal/loading.component.ts @@ -0,0 +1,49 @@ +import {Component, ViewEncapsulation, ComponentRef, ElementRef, Input, EventEmitter, Output} from '@angular/core'; + +@Component({ + selector: 'loading', + template: ` + + `, + encapsulation: ViewEncapsulation.None, +}) +/** + * API to an open alert window. + */ +export class Loading{ + +@Input() public message:string ="Loading"; + + /** + * if the value is true alert will be visible or else it will be hidden. + */ + public isOpen:boolean=false; + /** + * Emitted when a ok button was clicked + * or when Ok method is called. + */ + @Output() public alertOutput:EventEmitter = new EventEmitter(); + constructor( public _elementRef: ElementRef){} + /** + * Opens a alert window creating backdrop. + */ + open(){ + this.isOpen= true; + } + + close(){ + this.isOpen = false; + } +} diff --git a/sample-components/sampleComponent-rc7/src/app/common/modal/open.component.ts b/sample-components/sampleComponent-rc7/src/app/common/modal/open.component.ts new file mode 100644 index 00000000..95add08d --- /dev/null +++ b/sample-components/sampleComponent-rc7/src/app/common/modal/open.component.ts @@ -0,0 +1,55 @@ +import {Directive, Input, HostBinding} from '@angular/core'; + +// todo: add animate +// todo: add init and on change +@Directive({selector: '[open]'}) +export class Open { + @HostBinding('style.display') + private display:string; + @HostBinding('class.in') + @HostBinding('attr.aria-expanded') + private isExpanded:boolean = true; + + @Input() + private set open(value:boolean) { + this.isExpanded = value; + this.toggle(); + } + + private get open():boolean { + return this.isExpanded; + } + + constructor() { + } + init() { + this.isExpanded = false; + this.display = 'none'; + } + toggle() { + if (this.isExpanded) { + this.hide(); + } else { + this.show(); + } + } + + hide() { + this.isExpanded = false; + this.display = 'none'; + if (typeof document !== 'undefined') { + let backDrop = document.getElementsByClassName("modal-backdrop"); + if(backDrop.length>0){ + document.body.removeChild(backDrop[0]); + } + } + } + + show() { + let backDrop = document.createElement('div'); + backDrop.className="modal-backdrop fade in"; + document.body.appendChild(backDrop); + this.isExpanded = true; + this.display = 'block'; + } +} diff --git a/sample-components/sampleComponent-rc7/src/app/common/pagingFormatterNoLoad.component.ts b/sample-components/sampleComponent-rc7/src/app/common/pagingFormatterNoLoad.component.ts new file mode 100644 index 00000000..42534afd --- /dev/null +++ b/sample-components/sampleComponent-rc7/src/app/common/pagingFormatterNoLoad.component.ts @@ -0,0 +1,75 @@ +import {Component, Input, Output, EventEmitter} from '@angular/core'; + + +//Usage Example + +@Component({ + selector: 'paging-no-load', + template: ` + + ` +}) + +export class pagingFormatterNoLoad { + @Input() currentPage: number = 1; + @Input() navigateTo: string; + @Input() term: string=''; + @Input() size: number=10; + @Input() totalResults: number = 10; + @Input() params; + + @Output() pageChange = new EventEmitter(); + + constructor () { + } + + ngOnInit() { + console.info("In paging -- CurrentPage:"+this.currentPage+" "+"total Pages = "+this.getTotalPages() +" Results num:"+this.totalResults); + } + getTotalPages(){ + var i= this.totalResults/this.size; + var integerI=parseInt(''+i); + return parseInt(''+((i==integerI)?i:i+1)); + } + onPrev(){ + this.currentPage=this.currentPage-1; + this.pageChange.emit({ + value: this.currentPage + }); + + } + + onNext(){ + + this.currentPage=this.currentPage+1; + this.pageChange.emit({ + value: this.currentPage + }); + } + onPage(pageNum: number){ + + this.currentPage=pageNum; + this.pageChange.emit({ + value: this.currentPage + }); + } +} diff --git a/sample-components/sampleComponent-rc7/src/app/common/projectTitleFormatter.component.ts b/sample-components/sampleComponent-rc7/src/app/common/projectTitleFormatter.component.ts new file mode 100644 index 00000000..5917768e --- /dev/null +++ b/sample-components/sampleComponent-rc7/src/app/common/projectTitleFormatter.component.ts @@ -0,0 +1,23 @@ +import {Component, Input} from '@angular/core'; +import {OpenaireProperties} from '../openaireProperties'; + +//Usage Example " " + +@Component({ + selector: 'project-title', + template: ` + + ` +}) + +export class ProjectTitleFormatter { + @Input() project: string[]; + private url:string; + constructor () {} + + ngOnInit() { + this.url = OpenaireProperties.getsearchLinkToProject() + "?projectId=" + this.project["openaireId"]; + } +} diff --git a/sample-components/sampleComponent-rc7/src/app/common/publicationTitleFormatter.component.ts b/sample-components/sampleComponent-rc7/src/app/common/publicationTitleFormatter.component.ts new file mode 100644 index 00000000..2c87c50a --- /dev/null +++ b/sample-components/sampleComponent-rc7/src/app/common/publicationTitleFormatter.component.ts @@ -0,0 +1,26 @@ +import {Component, Input} from '@angular/core'; + +//Usage Example " " + +@Component({ + selector: 'publication-title', + template: ` +
+
{{title}}
+
{{title}}
+
+ ` +}) + +export class PublicationTitleFormatter { + @Input() title: string[]; + @Input() url: string[]; + + constructor () {} + + ngOnInit() { + + } + + +} diff --git a/sample-components/sampleComponent-rc7/src/app/entities/claim.ts b/sample-components/sampleComponent-rc7/src/app/entities/claim.ts new file mode 100644 index 00000000..b5378c5f --- /dev/null +++ b/sample-components/sampleComponent-rc7/src/app/entities/claim.ts @@ -0,0 +1,15 @@ +export class Claim { + id: string; + sourceType: string; + targetType: string; + sourceId: string; + targetId: string; + date: string; + DOI: string; + project: Project + userMail: string; + +} +export class Project{ + +} diff --git a/sample-components/sampleComponent-rc7/src/app/home/home.component.html b/sample-components/sampleComponent-rc7/src/app/home/home.component.html new file mode 100644 index 00000000..fa7f4167 --- /dev/null +++ b/sample-components/sampleComponent-rc7/src/app/home/home.component.html @@ -0,0 +1,15 @@ + +
+
+
+
+
+ + + + +
+
+
+
+
diff --git a/sample-components/sampleComponent-rc7/src/app/home/home.component.ts b/sample-components/sampleComponent-rc7/src/app/home/home.component.ts new file mode 100644 index 00000000..03253360 --- /dev/null +++ b/sample-components/sampleComponent-rc7/src/app/home/home.component.ts @@ -0,0 +1,15 @@ +import {Component} from '@angular/core'; +import {Router} from '@angular/router'; +import {Observable} from 'rxjs/Observable'; +import {Location} from '@angular/common'; + +@Component({ + selector: 'home', + templateUrl: 'home.component.html', + }) + +export class HomeComponent { + constructor ( private _router: Router, private location: Location) {} + + +} diff --git a/sample-components/sampleComponent-rc7/src/app/openaireProperties.ts b/sample-components/sampleComponent-rc7/src/app/openaireProperties.ts new file mode 100644 index 00000000..796973ae --- /dev/null +++ b/sample-components/sampleComponent-rc7/src/app/openaireProperties.ts @@ -0,0 +1,89 @@ +export class OpenaireProperties { + //landing Pages + private static baseSearchLink="/" + private static searchLinkToPublication = "publication?articleId="; + private static searchLinkToProject = "project?projectId="; + private static searchLinkToPerson = "person?personId="; + private static searchLinkToDataProvider = "https://beta.openaire.eu/search/dataprovider?datasourceId="; + private static searchLinkToDataset = "dataset?datasetId="; + private static searchLinkToOrganization = "organization?organizationId="; + + // Services - APIs + + // public claimsAPIURL = "http://rudie.di.uoa.gr:8080/dnet-openaire-connector-service-1.0.0-SNAPSHOT/rest/claimsService/" + private static claimsAPIURL = "http://scoobydoo.di.uoa.gr:8181/dnet-openaire-connector-service-1.0.0-SNAPSHOT/rest/claimsService/"; + + private static searchAPIURL = "http://astero.di.uoa.gr:8080/dnet-functionality-services-2.0.0-SNAPSHOT/rest/v2.0/api/"; + // private searchAPIURL = "http://rudie.di.uoa.gr:8080/dnet-functionality-services-2.0.0-SNAPSHOT/rest/v2.0/api/"; + // private searchAPIURL = "http://scoobydoo.di.uoa.gr:8181/dnet-functionality-services-2.0.0-SNAPSHOT/rest/v2.0/api/"; + + private static searchServiveURL = "http://astero.di.uoa.gr:8080/dnet-functionality-services-2.0.0-SNAPSHOT/"; + // private static searchServiveURL = "http://scoobydoo.di.uoa.gr:8181/dnet-functionality-services-2.0.0-SNAPSHOT/"; + // private static searchServiveURL = "http://services.openaire.eu:8380/search/"; + //private static searchServiveURL = "http://rudie.di.uoa.gr:8080/dnet-functionality-services-2.0.0-SNAPSHOT/"; + + private static searchCrossrefAPIURL = "http://api.crossref.org/works"; + private static searchDataciteAPIURL = "http://search.datacite.org/api"; + private static searchOrcidURL = "https://pub.orcid.org/"; + + // Identifiers + private static pmidURL = "http://www.ncbi.nlm.nih.gov/pubmed/"; + private static doiURL = "http://dx.doi.org/"; + private static cordisURL = "http://cordis.europa.eu/projects/"; + private static pmcURL = "http://europepmc.org/articles/"; + + + //landing Pages' getters + public static getsearchLinkToPublication():string{ + return this.baseSearchLink + this.searchLinkToPublication; + } + public static getsearchLinkToDataset():string{ + return this.baseSearchLink + this.searchLinkToDataset; + } + public static getsearchLinkToProject():string{ + return this.baseSearchLink + this.searchLinkToProject; + } + public static getsearchLinkToPerson():string{ + return this.baseSearchLink + this.searchLinkToPerson; + } + public static getsearchLinkToOrganization():string{ + return this.searchLinkToOrganization; + } + public static getsearchLinkToDataProvider():string{ + return this.searchLinkToDataProvider; + } + + // Services - APIs' getters + public static getSearchAPIURL():string{ + return this.searchAPIURL; + } + public static getSearchServiceURL():string{ + return this.searchServiveURL; + } + public static getClaimsAPIURL():string{ + return this.claimsAPIURL; + } + public static getSearchCrossrefAPIURL():string{ + return this.searchCrossrefAPIURL; + } + public static getSearchDataciteAPIURL():string{ + return this.searchDataciteAPIURL; + } + public static getSearchOrcidURL():string{ + return this.searchOrcidURL; + } + + // Identifiers' getters + public static getPmidURL():string{ + return this.pmidURL; + } + public static getDoiURL():string{ + return this.doiURL; + } + public static getCordisURL():string{ + return this.cordisURL; + } + public static getPmcURL():string{ + return this.pmcURL; + } +} diff --git a/sample-components/sampleComponent-rc7/src/app/services/claims.service.ts b/sample-components/sampleComponent-rc7/src/app/services/claims.service.ts new file mode 100644 index 00000000..43c6abce --- /dev/null +++ b/sample-components/sampleComponent-rc7/src/app/services/claims.service.ts @@ -0,0 +1,131 @@ +import {Injectable} from '@angular/core'; +import {Jsonp, URLSearchParams,ResponseOptions, RequestOptions, Headers} from '@angular/http'; +import {Http, Response} from '@angular/http'; +import {Observable} from 'rxjs/Observable'; +import {Claim} from '../entities/claim'; +import {OpenaireProperties} from '../openaireProperties'; + +@Injectable() +export class ClaimsService { + private baseUrl; + constructor(private jsonp: Jsonp, private http: Http) { + this.baseUrl = OpenaireProperties.getClaimsAPIURL(); + } + + private getClaimRequest(size : number, page : number, url :string):any { + console.info('ClaimsService: Claims request: '+url); + return this.http.get( url) + .map(request => request.json()) + .do(request => console.info("Get claims: offset = "+(size*(page-1)) + " limit ="+size )) + .catch(this.handleError); + } + getClaims( size : number, page : number, keyword:string, sortby: string, descending: boolean, types: string):any { + console.info('ClaimsService: getClaims ' ); + console.info('ClaimsService: Types : '+types ); + let url = this.baseUrl +"claims"+"?offset="+(size*(page-1) + "&limit="+size)+"&keyword="+keyword+"&sortby="+sortby+"&descending="+descending+""+types; + return this.getClaimRequest(size,page,url); + + } + getClaimsByUser( size : number, page : number, user:string, keyword:string, sortby: string, descending: boolean, types: string):any { + console.info('ClaimsService: getClaims for user : '+user); + let url = this.baseUrl +"users/"+user+"/claims"+"?offset="+(size*(page-1) + "&limit="+size)+"&keyword="+keyword+"&sortby="+sortby+"&descending="+descending+""+types; + return this.getClaimRequest(size,page,url); + + } + getClaimsBycontext( size : number, page : number, contextId:string, keyword:string, sortby: string, descending: boolean, types: string):any { + console.info('ClaimsService: getClaims for context : '+contextId); + let url = this.baseUrl +"contexts/"+contextId+"/claims"+"?offset="+(size*(page-1) + "&limit="+size)+"&keyword="+keyword+"&sortby="+sortby+"&descending="+descending+""+types; + return this.getClaimRequest(size,page,url); + + } + getClaimsByResult( size : number, page : number, resultId:string, keyword:string, sortby: string, descending: boolean, types: string):any { + console.info('ClaimsService: getClaims for result : '+resultId); + let url = this.baseUrl +"results/"+resultId+"/claims"+"?offset="+(size*(page-1) + "&limit="+size)+"&keyword="+keyword+"&sortby="+sortby+"&descending="+descending+""+types; + return this.getClaimRequest(size,page,url); + + } + getClaimsByProject( size : number, page : number, projectId:string, keyword:string, sortby: string, descending: boolean, types: string):any { + console.info('ClaimsService: getClaims for project : '+projectId); + let url = this.baseUrl +"projects/"+projectId+"/claims"+"?offset="+(size*(page-1) + "&limit="+size)+"&keyword="+keyword+"&sortby="+sortby+"&descending="+descending+""+types; + return this.getClaimRequest(size,page,url); + } + + deleteClaimById(claimId:string):any{ + console.warn('Trying to delete claim with id : '+claimId); + let url = this.baseUrl +"claims/"+claimId; + console.warn('Delete url: '+url); + let headers = new Headers({ 'Content-Type': 'application/json' }); + let options = new RequestOptions({ headers: headers }); + return this.http.delete( url, options).map(request => request.json()) + .do(request => console.info("After delete" )) + .catch(this.handleError); + + } + deleteBulk(claimIds:string[]):any{ + + console.warn('Trying to delete claims with ids : '+claimIds); + var url = ""; + + for(var claimId of claimIds){ + url=url+(url.length >0 ?"&":"")+"claimId="+claimId; + } + url= this.baseUrl +"claims/bulk?"+url; + console.warn('Delete url: '+url); + let headers = new Headers({ 'Content-Type': 'application/json' }); + let options = new RequestOptions({ headers: headers }); + return this.http.delete( url, options).map(request => request.json()) + .do(request => console.info("After delete" )) + .catch(this.handleError); + + } + insertBulkClaims(claims):any{ + console.warn('Trying toinsert claims : '+claims); + let url = this.baseUrl +"claims/bulk"; + let body = JSON.stringify( claims ); + console.warn('Json body: : '+body); + let headers = new Headers({ 'Content-Type': 'application/json' }); + let options = new RequestOptions({ headers: headers }); + return this.http.post(url, body, options) + .map(res => res.json()) + .do(request => console.info("Insert Response:"+request.status) ) + .catch(this.handleError); + + } + insertClaim(claim):any{ + console.warn('Trying toinsert claim : '+claim); + let url = this.baseUrl +"claims"; + let body = JSON.stringify( claim ); + let headers = new Headers({ 'Content-Type': 'application/json' }); + let options = new RequestOptions({ headers: headers }); + return this.http.post(url, body, options) + .map(res => res.json()) + .do(request => console.info("Insert Response:"+request.status) ) + .catch(this.handleError); + + } + + private handleError (error: Response) { + // in a real world app, we may send the error to some remote logging infrastructure + // instead of just logging it to the console + console.error(error); + return Observable.throw(error || 'Server error'); + } + + getClaim(id:string):any { + let url = this.baseUrl+"claims/"+id; + return new Promise((resolve, reject) => { + this.http.get(url) + .map(res => res.json()) + .subscribe( + data => { + resolve(data.data); + }, + err => { + reject(err); + } + ) + ; + }); + } + +} diff --git a/sample-components/sampleComponent-rc7/src/assets/logo.png b/sample-components/sampleComponent-rc7/src/assets/logo.png new file mode 100644 index 00000000..afea237f Binary files /dev/null and b/sample-components/sampleComponent-rc7/src/assets/logo.png differ diff --git a/sample-components/sampleComponent-rc7/src/backend/api.ts b/sample-components/sampleComponent-rc7/src/backend/api.ts new file mode 100644 index 00000000..d8f4f517 --- /dev/null +++ b/sample-components/sampleComponent-rc7/src/backend/api.ts @@ -0,0 +1,24 @@ +// Our API for demos only +import {fakeDataBase} from './db'; +import {fakeDemoRedisCache} from './cache'; + +// you would use cookies/token etc +var USER_ID = 'f9d98cf1-1b96-464e-8755-bcc2a5c09077'; // hardcoded as an example + +// Our API for demos only +export function serverApi(req, res) { + let key = USER_ID + '/data.json'; + let cache = fakeDemoRedisCache.get(key); + if (cache !== undefined) { + console.log('/data.json Cache Hit'); + return res.json(cache); + } + console.log('/data.json Cache Miss'); + + fakeDataBase.get() + .then(data => { + fakeDemoRedisCache.set(key, data); + return data; + }) + .then(data => res.json(data)); +} diff --git a/sample-components/sampleComponent-rc7/src/backend/cache.ts b/sample-components/sampleComponent-rc7/src/backend/cache.ts new file mode 100644 index 00000000..490a3561 --- /dev/null +++ b/sample-components/sampleComponent-rc7/src/backend/cache.ts @@ -0,0 +1,17 @@ + + +var _fakeLRUcount = 0; +export const fakeDemoRedisCache = { + _cache: {}, + get: (key) => { + let cache = fakeDemoRedisCache._cache[key]; + _fakeLRUcount++; + if (_fakeLRUcount >= 10) { + fakeDemoRedisCache.clear(); + _fakeLRUcount = 0; + } + return cache; + }, + set: (key, data) => fakeDemoRedisCache._cache[key] = data, + clear: () => fakeDemoRedisCache._cache = {} +}; diff --git a/sample-components/sampleComponent-rc7/src/backend/db.ts b/sample-components/sampleComponent-rc7/src/backend/db.ts new file mode 100644 index 00000000..3ba8ea3d --- /dev/null +++ b/sample-components/sampleComponent-rc7/src/backend/db.ts @@ -0,0 +1,7 @@ +// Our API for demos only +export const fakeDataBase = { + get() { + let res = { data: 'This fake data came from the db on the server.' }; + return Promise.resolve(res); + } +}; diff --git a/sample-components/sampleComponent-rc7/src/client.ts b/sample-components/sampleComponent-rc7/src/client.ts new file mode 100644 index 00000000..d92fc324 --- /dev/null +++ b/sample-components/sampleComponent-rc7/src/client.ts @@ -0,0 +1,18 @@ +// the polyfills must be the first thing imported +import 'angular2-universal-polyfills'; + +// Angular 2 +import { enableProdMode} from '@angular/core'; +import { platformUniversalDynamic } from 'angular2-universal'; + +// enable prod for faster renders +enableProdMode(); + +import { main } from './main.browser'; + +// on document ready bootstrap Angular 2 +document.addEventListener('DOMContentLoaded', () => { + + platformUniversalDynamic().bootstrapModule(main()); + +}); diff --git a/sample-components/sampleComponent-rc7/src/index.html b/sample-components/sampleComponent-rc7/src/index.html new file mode 100644 index 00000000..2e9be605 --- /dev/null +++ b/sample-components/sampleComponent-rc7/src/index.html @@ -0,0 +1,31 @@ + + + + OpenAIRE + + + + + + + + + + + + + + + + + + + Loading Universal ... + + + + + diff --git a/sample-components/sampleComponent-rc7/src/main.browser.ts b/sample-components/sampleComponent-rc7/src/main.browser.ts new file mode 100644 index 00000000..cda7573b --- /dev/null +++ b/sample-components/sampleComponent-rc7/src/main.browser.ts @@ -0,0 +1,43 @@ +import { NgModule } from '@angular/core'; +import { FormsModule } from '@angular/forms'; + +import { UniversalModule } from 'angular2-universal'; + +import { App } from './app/app'; +//for routing: +import {ClaimsAdminComponent} from './app/claimPages/claims/claimsAdmin.component'; +import { routing } from './app/app.routing'; +import {Routes, RouterModule} from "@angular/router"; + + + +import {Open} from './app/common/modal/open.component'; + +import {Alert} from './app/common/modal/alert'; +import {Loading} from './app/common/modal/loading.component'; +import {ClaimsComponent} from './app/claimPages/claims/claims.component'; +import {ClaimsService} from './app/services/claims.service'; +import {Claim} from './app/entities/claim'; +import {pagingFormatterNoLoad} from './app/common/pagingFormatterNoLoad.component'; + +import {ClaimEntityFormatter} from './app/common/claimEntityFormatter.component'; +import {PublicationTitleFormatter} from './app/common/publicationTitleFormatter.component'; +import {ProjectTitleFormatter} from './app/common/projectTitleFormatter.component'; +import {HomeComponent} from './app/home/home.component'; +export function main() { + @NgModule({ + bootstrap: [ App ], + declarations: [ App, ClaimsAdminComponent, ClaimsComponent, ClaimEntityFormatter,pagingFormatterNoLoad, Open, ProjectTitleFormatter, PublicationTitleFormatter,HomeComponent, Loading, Alert], + imports: [ + UniversalModule, + FormsModule, + routing + ], + + providers: [ ClaimsService ] + + }) + class MainModule { + } + return MainModule; +} diff --git a/sample-components/sampleComponent-rc7/src/main.node.ts b/sample-components/sampleComponent-rc7/src/main.node.ts new file mode 100644 index 00000000..e5838609 --- /dev/null +++ b/sample-components/sampleComponent-rc7/src/main.node.ts @@ -0,0 +1,27 @@ +import { NgModule, Component } from '@angular/core'; +import { FormsModule } from '@angular/forms'; +import { UniversalModule } from 'angular2-universal'; + +import { App } from './app/app'; + +export function main(config) { + + @NgModule({ + bootstrap: [ App ], + declarations: [ App ], + imports: [ + UniversalModule.withConfig({ + document: config.document, + originUrl: 'http://localhost:3000', + baseUrl: '/', + requestUrl: '/', + // preboot: false, + preboot: { appRoot: ['app'], uglify: true }, + }), + FormsModule + ] + }) + class MainModule {} + + return MainModule +}; diff --git a/sample-components/sampleComponent-rc7/src/server.ts b/sample-components/sampleComponent-rc7/src/server.ts new file mode 100644 index 00000000..11c47e41 --- /dev/null +++ b/sample-components/sampleComponent-rc7/src/server.ts @@ -0,0 +1,55 @@ +// the polyfills must be the first thing imported in node.js +import 'angular2-universal-polyfills'; + +import * as path from 'path'; +import * as express from 'express'; +import * as bodyParser from 'body-parser'; +import * as cookieParser from 'cookie-parser'; + +// Angular 2 +import { enableProdMode } from '@angular/core'; +// Angular 2 Universal +import { createEngine } from 'angular2-express-engine'; + +// enable prod for faster renders +enableProdMode(); + +const app = express(); +const ROOT = path.join(path.resolve(__dirname, '..')); + +// Express View +import { main } from './main.node'; +app.engine('.html', createEngine({ main })); +app.set('views', __dirname); +app.set('view engine', 'html'); + +app.use(cookieParser('Angular 2 Universal')); +app.use(bodyParser.json()); + +// Serve static files +app.use('/assets', express.static(path.join(__dirname, 'assets'), {maxAge: 30})); +app.use(express.static(path.join(ROOT, 'dist/client'), {index: false})); + + +import { serverApi } from './backend/api'; +// Our API for demos only +app.get('/data.json', serverApi); + +// Routes with html5pushstate +// ensure routes match client-side-app +app.get('/', (req, res) => res.render('index', {req, res})); +app.get('/claims', (req, res) => res.render('index', {req, res})); +app.get('/home', (req, res) => res.render('index', {req, res})); + + +app.get('*', function(req, res) { + res.setHeader('Content-Type', 'application/json'); + var pojo = { status: 404, message: 'No Content' }; + var json = JSON.stringify(pojo, null, 2); + res.status(404).send(json); +}); + +// Server +let server = app.listen(process.env.PORT || 3000, () => { + console.log(`Listening on: http://localhost:${server.address().port}`); +}); diff --git a/sample-components/sampleComponent-rc7/src/typings.d.ts b/sample-components/sampleComponent-rc7/src/typings.d.ts new file mode 100644 index 00000000..1c62346c --- /dev/null +++ b/sample-components/sampleComponent-rc7/src/typings.d.ts @@ -0,0 +1,75 @@ +/* + * Custom Type Definitions + * When including 3rd party modules you also need to include the type definition for the module + * if they don't provide one within the module. You can try to install it with typings +typings install node --save + * If you can't find the type definition in the registry we can make an ambient definition in + * this file for now. For example +declare module "my-module" { + export function doesSomething(value: string): string; +} + * + * If you're prototying and you will fix the types later you can also declare it as type any + * +declare var assert: any; + * + * If you're importing a module that uses Node.js modules which are CommonJS you need to import as + * +import * as _ from 'lodash' + * You can include your type definitions in this file until you create one for the typings registry + * see https://github.com/typings/registry + * + */ + + +// Extra variables that live on Global that will be replaced by webpack DefinePlugin +declare var ENV: string; +declare var HMR: boolean; +interface GlobalEnvironment { + ENV; + HMR; +} + +interface WebpackModule { + hot: { + data?: any, + idle: any, + accept(dependencies?: string | string[], callback?: (updatedDependencies?: any) => void): void; + decline(dependencies?: string | string[]): void; + dispose(callback?: (data?: any) => void): void; + addDisposeHandler(callback?: (data?: any) => void): void; + removeDisposeHandler(callback?: (data?: any) => void): void; + check(autoApply?: any, callback?: (err?: Error, outdatedModules?: any[]) => void): void; + apply(options?: any, callback?: (err?: Error, outdatedModules?: any[]) => void): void; + status(callback?: (status?: string) => void): void | string; + removeStatusHandler(callback?: (status?: string) => void): void; + }; +} + +interface WebpackRequire { + context(file: string, flag?: boolean, exp?: RegExp): any; +} + + +interface ErrorStackTraceLimit { + //stackTraceLimit: number; + stackTraceLimit(limit: number): void +} + + +// Extend typings +interface NodeRequire extends WebpackRequire {} +interface ErrorConstructor extends ErrorStackTraceLimit {} +interface NodeModule extends WebpackModule {} +interface Global extends GlobalEnvironment {} + + +interface Thenable { + then( + onFulfilled?: (value: T) => U | Thenable, + onRejected?: (error: any) => U | Thenable): Thenable; + then( + onFulfilled?: (value: T) => U | Thenable, + onRejected?: (error: any) => void): Thenable; + catch(onRejected?: (error: any) => U | Thenable): Thenable; +} diff --git a/sample-components/sampleComponent-rc7/tsconfig.json b/sample-components/sampleComponent-rc7/tsconfig.json new file mode 100644 index 00000000..96d822e5 --- /dev/null +++ b/sample-components/sampleComponent-rc7/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "declaration": false, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "module": "commonjs", + "moduleResolution": "node", + "outDir": "dist", + "sourceMap": true, + "sourceRoot": "src", + "target": "es5", + "lib": ["es6", "dom"] + }, + "exclude": [ + "node_modules" + ], + "compileOnSave": false, + "buildOnSave": false, + "atom": { "rewriteTsconfig": false } +} diff --git a/sample-components/sampleComponent-rc7/webpack.config.ts b/sample-components/sampleComponent-rc7/webpack.config.ts new file mode 100644 index 00000000..b3aae5bb --- /dev/null +++ b/sample-components/sampleComponent-rc7/webpack.config.ts @@ -0,0 +1,102 @@ +var webpack = require('webpack'); +var path = require('path'); +var resolveNgRoute = require('@angularclass/resolve-angular-routes'); + + +var commonConfig = { + resolve: { + extensions: ['', '.ts', '.js', '.json'] + }, + module: { + preLoaders: [ + ], + loaders: [ + // TypeScript + { test: /\.ts$/, loaders: ['ts-loader', 'angular2-template-loader'] }, + { test: /\.html$/, loader: 'raw-loader' }, + { test: /\.css$/, loader: 'raw-loader' }, + { test: /\.json$/, loader: 'raw-loader' } + ], + }, + plugins: [ + new webpack.ContextReplacementPlugin( + // The (\\|\/) piece accounts for path separators in *nix and Windows + /angular(\\|\/)core(\\|\/)src(\\|\/)linker/, + root('./src'), + resolveNgRoute(root('./src')) + ) + ] + +}; + + +var clientConfig = { + target: 'web', + entry: './src/client', + output: { + path: root('dist/client') + }, + node: { + global: true, + __dirname: true, + __filename: true, + process: true, + Buffer: false + } +}; + + +var serverConfig = { + target: 'node', + entry: './src/server', // use the entry file of the node server if everything is ts rather than es5 + output: { + path: root('dist/server'), + libraryTarget: 'commonjs2' + }, + externals: checkNodeImport, + node: { + global: true, + __dirname: true, + __filename: true, + process: true, + Buffer: true + } +}; + + + +// Default config +var defaultConfig = { + context: __dirname, + resolve: { + root: root('/src') + }, + output: { + publicPath: path.resolve(__dirname), + filename: 'index.js' + } +} + + + +var webpackMerge = require('webpack-merge'); +module.exports = [ + // Client + webpackMerge({}, defaultConfig, commonConfig, clientConfig), + + // Server + webpackMerge({}, defaultConfig, commonConfig, serverConfig) +] + +// Helpers +function checkNodeImport(context, request, cb) { + if (!path.isAbsolute(request) && request.charAt(0) !== '.') { + cb(null, 'commonjs ' + request); return; + } + cb(); +} + +function root(args) { + args = Array.prototype.slice.call(arguments, 0); + return path.join.apply(path, [__dirname].concat(args)); +}