Project

General

Profile

1
import {Component, EventEmitter, Input, OnInit, Output, ViewChild} from '@angular/core';
2
import {ActivatedRoute, Router} from "@angular/router";
3
import {Subscriber} from 'rxjs';
4

    
5
import {ErrorCodes} from '../../openaireLibrary/utils/properties/errorCodes';
6
import {SearchUtilsClass} from '../../openaireLibrary/searchPages/searchUtils/searchUtils.class';
7
import {EnvProperties} from '../../openaireLibrary/utils/properties/env-properties';
8
import {ManageCommunityProjectsService} from '../../services/manageProjects.service';
9
import {SearchCommunityProjectsService} from '../../openaireLibrary/connect/projects/searchProjects.service';
10
import {RouterHelper} from '../../openaireLibrary/utils/routerHelper.class';
11

    
12
import {Session} from '../../openaireLibrary/login/utils/helper.class';
13
import {LoginErrorCodes} from '../../openaireLibrary/login/utils/guardHelper.class';
14
import {FormArray, FormBuilder, FormGroup} from "@angular/forms";
15
import {properties} from "../../../environments/environment";
16
import {CommunityService} from "../../openaireLibrary/connect/community/community.service";
17
import {Option} from "../../openaireLibrary/sharedComponents/input/input.component";
18
import {SearchInputComponent} from "../../openaireLibrary/sharedComponents/search-input/search-input.component";
19

    
20
declare var UIkit;
21

    
22
@Component({
23
  selector: 'remove-projects',
24
  templateUrl: './remove-projects.component.html'
25
})
26

    
27
export class RemoveProjectsComponent implements OnInit {
28
  public portal: string;
29
  public name: string;
30

    
31
  private subscriptions: any[] = [];
32

    
33
  public routerHelper: RouterHelper = new RouterHelper();
34
  private projectUrl = "https://" + ((properties.environment == "beta" || properties.environment == "development") ? "beta." : "") + "explore.openaire.eu" + properties.searchLinkToProject.split("?")[0];
35

    
36
  @Input() public showLoading: boolean = true;
37

    
38
  @Output() communityProjectsChanged = new EventEmitter();
39
  @Input() public communityProjects = [];
40
  public previewCommunityProjects = [];
41
  public communitySearchUtils: SearchUtilsClass = new SearchUtilsClass();
42
  public errorCodes: ErrorCodes;
43
  properties: EnvProperties = properties;
44

    
45
  private selectedCommunityProject: any;
46
  @ViewChild('AlertModalDeleteCommunity') alertModalDeleteCommunity;
47

    
48
  /* Paging */
49
  page: number = 1;
50
  resultsPerPage: number = properties.resultsPerPage;
51

    
52
  /* Search */
53
  @ViewChild('searchInputComponent') searchInputComponent: SearchInputComponent;
54
  filterForm: FormGroup;
55
  public fundersCtrl: FormArray;
56
  private searchText: RegExp = new RegExp('');
57
  public keyword: string = '';
58
  allOptions: Option[] = [];
59
  sortOptions: Option[] = [
60
    //{label:"Title (desc) ", value:{ sort: "title",descending: true }},
61
    {label: "Title ", value: {sort: "title", descending: false}},
62
    //{label:"Grant ID (desc) ", value:{ sort: "grant",descending: true }},
63
    {label: "Grant ID ", value: {sort: "grant", descending: false}},
64
    //{label:"Funder (desc) ", value:{ sort: "funder",descending: true }},
65
    {label: "Funder ", value: {sort: "funder", descending: false}}
66
  ];
67

    
68
  @Output() toggleView: EventEmitter<any> = new EventEmitter();
69
  @Input() public toggle: boolean = true;
70

    
71
  constructor(private route: ActivatedRoute, private _router: Router,
72
              private _fb: FormBuilder,
73
              private communityService: CommunityService,
74
              private _manageCommunityProjectsService: ManageCommunityProjectsService,
75
              private _searchCommunityProjectsService: SearchCommunityProjectsService) {
76
    this.errorCodes = new ErrorCodes();
77
    this.communitySearchUtils.status = this.errorCodes.LOADING;
78
  }
79

    
80
  ngOnInit() {
81
    this.communitySearchUtils.keyword = "";
82

    
83
    this.fundersCtrl = this._fb.array([]);
84
    this.filterForm = this._fb.group({
85
      keyword: [''],
86
      funder: this.fundersCtrl,
87
      sort: this._fb.control(this.sortOptions[0].value)
88
    });
89

    
90
    this.subscriptions.push(this.filterForm.get('keyword').valueChanges.subscribe(value => {
91
      this.searchText = new RegExp(value, 'i');
92
      this.page = 1;
93
      this.applyFilters();
94
    }));
95

    
96
    this.subscriptions.push(this.filterForm.get('funder').valueChanges.subscribe(value => {
97
      this.page = 1;
98
      this.applyFilters();
99
    }));
100

    
101
    this.subscriptions.push(this.filterForm.get('sort').valueChanges.subscribe(value => {
102
      this.page = 1;
103
      this.sort();
104
    }));
105

    
106
    this.subscriptions.push(this.communityService.getCommunityAsObservable().subscribe(community => {
107
      if (community) {
108
        this.portal = community.communityId;
109
        this.name = community.shortTitle;
110
        this.projectUrl = "https://"
111
          + ((this.properties.environment == "beta" || this.properties.environment == "development") ? "beta." : "")
112
          + this.portal + ".openaire.eu" + this.properties.searchLinkToProject.split("?")[0];
113

    
114
        this.keyword = '';
115
        this._getCommunityProjects();
116
      }
117
    }));
118
  }
119

    
120
  public ngOnDestroy() {
121
    this.subscriptions.forEach(sub => {
122
      if (sub instanceof Subscriber) {
123
        sub.unsubscribe();
124
      }
125
    });
126
  }
127

    
128
  public inCommunity(result: any): any {
129
    let found = false;
130
    for (let project of this.communityProjects) {
131
      if (project.opeaireId == result.id) {
132
        return true;
133
      } else if (result['title'].name.search("(" + project.grantId + ")") != -1 && result.funderShortname == project.funder) {
134
        return true;
135
      }
136
    }
137
    return found;
138

    
139
  }
140

    
141
  totalPages(): number {
142
    let totalPages: any = this.communitySearchUtils.totalResults / (this.resultsPerPage);
143
    if (!(Number.isInteger(totalPages))) {
144
      totalPages = (parseInt(totalPages, 10) + 1);
145
    }
146
    return totalPages;
147
  }
148

    
149
  public confirmedDeleteProject(data: any) {
150
    if (!Session.isLoggedIn()) {
151
      this._router.navigate(['/user-info'], {
152
        queryParams: {
153
          "errorCode": LoginErrorCodes.NOT_VALID,
154
          "redirectUrl": this._router.url
155
        }
156
      });
157
    } else {
158
      this.subscriptions.push(this._manageCommunityProjectsService.removeProject(this.properties, this.portal, this.selectedCommunityProject.id).subscribe(
159
        data => {
160
          let index = this.communityProjects.indexOf(this.selectedCommunityProject);
161
          this.communityProjects.splice(index, 1);
162

    
163
          this.applyFilters();
164

    
165
          UIkit.notification('Project successfully removed!', {
166
            status: 'success',
167
            timeout: 6000,
168
            pos: 'bottom-right'
169
          });
170

    
171
          this.communityProjectsChanged.emit({
172
            value: this.communityProjects,
173
          });
174

    
175
          this.communitySearchUtils.totalResults--;
176
          this.communitySearchUtils.page = 1;
177
        },
178
        err => {
179
          this.handleError('An error has been occurred. Try again later!');
180
          console.error(err);
181
        }
182
      ));
183
    }
184
  }
185

    
186
  public removeProject(communityProject: any) {
187
    if (!Session.isLoggedIn()) {
188
      this._router.navigate(['/user-info'], {
189
        queryParams: {
190
          "errorCode": LoginErrorCodes.NOT_VALID,
191
          "redirectUrl": this._router.url
192
        }
193
      });
194
    } else {
195
      this.selectedCommunityProject = communityProject;
196
      this.alertModalDeleteCommunity.cancelButton = true;
197
      this.alertModalDeleteCommunity.okButton = true;
198
      this.alertModalDeleteCommunity.alertTitle = "Remove project?";
199
      let title = "";
200
      if (communityProject.name) {
201
        title = communityProject.name;
202
      }
203
      if (communityProject.name && communityProject.acronym) {
204
        title += " (";
205
      }
206
      if (communityProject.acronym) {
207
        title += communityProject.acronym;
208
      }
209
      if (communityProject.name && communityProject.acronym) {
210
        title += ")";
211
      }
212
      this.alertModalDeleteCommunity.message = "Project";
213
      if (title) {
214
        this.alertModalDeleteCommunity.message += " '" + title + "' ";
215
      }
216
      this.alertModalDeleteCommunity.message += "will be removed from your community. Are you sure?";
217
      this.alertModalDeleteCommunity.okButtonText = "Yes";
218
      this.alertModalDeleteCommunity.open();
219
    }
220
  }
221

    
222
  public _getCommunityProjects() {
223
    if (!Session.isLoggedIn()) {
224
      this._router.navigate(['/user-info'], {
225
        queryParams: {
226
          "errorCode": LoginErrorCodes.NOT_VALID,
227
          "redirectUrl": this._router.url
228
        }
229
      });
230
    } else {
231
      this.communitySearchUtils.status = this.errorCodes.LOADING;
232
      this.communityProjects = [];
233
      this.communitySearchUtils.totalResults = 0;
234
      this.communitySearchUtils.page = 1;
235
      this.communitySearchUtils.keyword = "";
236

    
237
      this.subscriptions.push(this._searchCommunityProjectsService.searchProjects(this.properties, this.portal).subscribe(
238
        data => {
239
          this.communityProjects = data;
240
          this.previewCommunityProjects = this.communityProjects;
241
          this.sort();
242

    
243
          this.communitySearchUtils.totalResults = data.length;
244
          this.communitySearchUtils.status = this.errorCodes.DONE;
245

    
246
          this.communityProjectsChanged.emit({
247
            value: this.communityProjects,
248
          });
249

    
250
          this.createFunderFilter();
251

    
252
          this.showLoading = false;
253
        },
254
        err => {
255
          console.error(err);
256
          //TODO check erros (service not available, bad request)
257

    
258
          if (err.status == '404') {
259
            this.communitySearchUtils.status = this.errorCodes.NOT_FOUND;
260
          } else if (err.status == '500') {
261
            this.communitySearchUtils.status = this.errorCodes.ERROR;
262
          } else {
263
            this.communitySearchUtils.status = this.errorCodes.NOT_AVAILABLE;
264
          }
265

    
266
          this.showLoading = false;
267
        }
268
      ));
269
    }
270
  }
271

    
272
  public createFunderFilter(): void {
273
    let funders: Set<string> = new Set<string>();
274
    this.allOptions = [];
275
    let i;
276
    for (i = 0; i < this.communityProjects.length; i++) {
277
      let funder = this.communityProjects[i].funder;
278
      if (funder && !funders.has(funder)) {
279
        funders.add(funder);
280
        this.allOptions.push({label: funder, value: {id: funder, label: funder}});
281
      }
282
    }
283
  }
284

    
285
  public updatePage($event) {
286
    this.page = $event.value;
287
  }
288

    
289
  addNew() {
290
    this.toggleView.emit(null);
291
  }
292

    
293
  public applyFilters() {
294
    this.previewCommunityProjects = this.communityProjects.filter(project => {
295
      let return_value: boolean = (this.filterCommunityProjectByKeyword(project) && this.filterCommunityProjectByFunder(project));
296
      return return_value;
297
    });
298

    
299
    // check paging here!!!
300
    if (this.previewCommunityProjects.slice((this.page - 1) * this.resultsPerPage, this.page * this.resultsPerPage).length == 0) {
301
      this.page = 1;
302
    }
303

    
304
    this.sort();
305
  }
306

    
307
  public filterCommunityProjectByKeyword(project): boolean {
308
    const textFlag = this.searchText.toString() === ''
309
      || ((project.name + " " + project.acronym + " " + project.grantId + " " + project.funder)).match(this.searchText) != null;
310

    
311
    return textFlag;
312
  }
313

    
314
  public filterCommunityProjectByFunder(project): boolean {
315
    if (this.fundersCtrl.getRawValue().length == 0) {
316
      return true;
317
    }
318
    for (let funder of this.fundersCtrl.getRawValue()) {
319
      if (project.funder.toLowerCase().indexOf(funder.label.toLowerCase()) != -1) {
320
        return true;
321
      }
322
    }
323
    return false;
324
  }
325

    
326
  private sort() {
327
    let sortOption: { sort: string, descending: boolean } = this.filterForm.get('sort').value;
328

    
329
    this.previewCommunityProjects.sort((left, right): number => {
330
      if (sortOption.sort == "title") {
331
        if ((left.name + left.acronym) > (right.name + right.acronym)) {
332
          return sortOption.descending ? -1 : 1;
333
        } else if ((left.name + left.acronym) < (right.name + right.acronym)) {
334
          return sortOption.descending ? 1 : -1;
335
        }
336
      } else if (sortOption.sort == "grant") {
337
        if (left.grantId > right.grantId) {
338
          return sortOption.descending ? -1 : 1;
339
        } else if (left.grantId < right.grantId) {
340
          return sortOption.descending ? 1 : -1;
341
        }
342
      } else if (sortOption.sort == "funder") {
343
        if (left.funder > right.funder) {
344
          return sortOption.descending ? -1 : 1;
345
        } else if (left.funder < right.funder) {
346
          return sortOption.descending ? 1 : -1;
347
        }
348
      }
349

    
350
      return 0;
351
    });
352
  }
353

    
354
  public onSearchClose() {
355
    this.communitySearchUtils.keyword = this.filterForm.get('keyword').value;
356
  }
357

    
358
  public resetInput() {
359
    this.communitySearchUtils.keyword = null;
360
    this.searchInputComponent.reset()
361
  }
362

    
363
  handleError(message: string) {
364
    UIkit.notification(message, {
365
      status: 'danger',
366
      timeout: 6000,
367
      pos: 'bottom-right'
368
    });
369
  }
370
}
(6-6/6)