Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Recommendations on homepage #498

Merged
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

- Added search bar inside navbar with autocomplete suggested results. - [#403](https://github.com/DigitalExcellence/dex-frontend/issues/403)
- Refactored the home page. [#380](https://github.com/DigitalExcellence/dex-frontend/issues/380)
- Added project recommendations on the home page. [#497](https://github.com/DigitalExcellence/dex-frontend/issues/497)

### Changed

Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/app/components/app-layout/app-layout.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export class AppLayoutComponent implements OnInit {
});

this.router.events.subscribe((event) => {
if (event instanceof NavigationStart) {
if (event instanceof NavigationEnd) {
if ((event.url === '/home' || event.url === '/')) {
this.showSearchbar = true;
} else {
Expand Down
7 changes: 5 additions & 2 deletions src/app/modules/home/home.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ import { StripHtmlPipe } from 'src/app/utils/striptags.pipe';
import { PopoverModule } from 'ngx-bootstrap/popover';
import { ModalModule } from 'ngx-bootstrap/modal';
import { TooltipModule } from 'ngx-bootstrap/tooltip';
import { ProjectModule } from 'src/app/modules/project/project.module';
import { RecommendationCardsComponent } from './recommendations/recommendations.component';
import { ProjectModule } from '../project/project.module';

@NgModule({
declarations: [
Expand All @@ -22,7 +23,9 @@ import { ProjectModule } from 'src/app/modules/project/project.module';
PartnersComponent,
ContainerLeftComponent,
ContainerRightComponent,
StripHtmlPipe
StripHtmlPipe,
RecommendationCardsComponent

],
imports: [
CommonModule,
Expand Down
3 changes: 2 additions & 1 deletion src/app/modules/home/main/main.component.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<app-highlight-slider></app-highlight-slider>
<app-info-cards></app-info-cards>
<app-who-is-dex></app-who-is-dex>
<app-recommended-project-cards *ngIf="isLoggedIn()"></app-recommended-project-cards>
<app-who-is-dex *ngIf="!isLoggedIn()"></app-who-is-dex>
<app-container-left></app-container-left>
<app-partners></app-partners>
<app-container-right></app-container-right>
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<!--
Digital Excellence Copyright (C) 2020 Brend Smits
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation version 3 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
You can find a copy of the GNU Lesser General Public License
along with this program, in the LICENSE.md file in the root project directory.
If not, see https://www.gnu.org/licenses/lgpl-3.0.txt
-->

<div class="recommendedProjects" *ngIf="isAuthenticated && recommendations.length > 0">

<div class="inner">
<div class="text">
<h2>Your recommended projects</h2>
<ng-container *ngIf="recommendations">
<p class="large">Your top {{recommendations.length}} recommendations</p>
</ng-container>
</div>

<div class="cards">

<app-project
(click)="onClickRecommendedProject(project.id, project.name)"
*ngFor="let project of recommendations"
[project]="project"
[showListView]="false"
>
</app-project>


</div>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
*
* Digital Excellence Copyright (C) 2020 Brend Smits
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You can find a copy of the GNU Lesser General Public License
* along with this program, in the LICENSE.md file in the root project directory.
* If not, see https://www.gnu.org/licenses/lgpl-3.0.txt
*
*/

@import "assets/styles/variables";

//project recommendations
.recommendedProjects {
// margin-top: 220px;
padding: 40px 60px 20px 60px;
background-color: $light-mode-grey-quaternary;
margin: 0 -39px;
justify-content: center;
align-items: center;

.inner {
max-width: 1750px;
margin: auto;
width: 100%;
.text {
.large{
margin: 0 0 5px 0;
}
}
}


.cards {
display: grid;
gap: 30px;
max-width: 100%;
grid-auto-columns: 310px;
grid-auto-flow: column;
overflow-x: auto;
overflow-y: hidden;
padding: 20px 0;

//scrollbar stylingbody
&::-webkit-scrollbar {
height: 4px;
}

&::-webkit-scrollbar-track {
}

&::-webkit-scrollbar-thumb {
border-radius: 999px;
background-color: white;
}


}
}
86 changes: 86 additions & 0 deletions src/app/modules/home/recommendations/recommendations.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
* Digital Excellence Copyright (C) 2020 Brend Smits
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You can find a copy of the GNU Lesser General Public License
* along with this program, in the LICENSE.md file in the root project directory.
* If not, see https://www.gnu.org/licenses/lgpl-3.0.txt
*/

import { Component, OnInit } from '@angular/core';
import { SafeUrl } from '@angular/platform-browser';
import { finalize } from 'rxjs/operators';
import { Project } from 'src/app/models/domain/project';
import { AuthService } from 'src/app/services/auth.service';
import { FileRetrieverService } from 'src/app/services/file-retriever.service';
import { RecommendationService } from 'src/app/services/recommendation.service';
import { ProjectDetailModalUtility } from 'src/app/utils/project-detail-modal.util';

@Component({
selector: 'app-recommended-project-cards',
templateUrl: './recommendations.component.html',
styleUrls: ['./recommendations.component.scss'],
})
export class RecommendationCardsComponent implements OnInit {

public isAuthenticated: boolean;

/**
* Array to receive and store the projects from the api.
*/
public recommendations: Project[] = [];

/**
* Boolean to determine whether the component is loading the information from the api.
*/
public recommendationsLoading = true;

constructor(private recommendationService: RecommendationService,
private fileRetrieverService: FileRetrieverService,
private modalUtility: ProjectDetailModalUtility,
private authService: AuthService) {}

ngOnInit(): void {
this.authService.authNavStatus$.subscribe((status) => {
this.isAuthenticated = status;
if (status) {
this.recommendationService.getRecommendations(8)
.pipe(finalize(() => (this.recommendationsLoading = false)))
.subscribe((result) => {
this.recommendations = result;
this.recommendations.forEach(element => {
element.likeCount = element.likes.length;
});
});
}
});
}

/**
* Triggers on project click in the list.
* @param id project id.
* @param name project name
*/
public onClickRecommendedProject(id: number, name: string): void {
name = name.split(' ').join('-');
this.modalUtility.openProjectModal(id, name, '/home');
}

/**
* Method to get the url of the icon of the project. This is retrieved
* from the file retriever service
*/
public getIconUrl(project: Project): SafeUrl {
return this.fileRetrieverService.getIconUrl(project.projectIcon);
}


}
39 changes: 39 additions & 0 deletions src/app/services/recommendation.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Digital Excellence Copyright (C) 2020 Brend Smits
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You can find a copy of the GNU Lesser General Public License
* along with this program, in the LICENSE.md file in the root project directory.
* If not, see https://www.gnu.org/licenses/lgpl-3.0.txt
*/
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { API_CONFIG } from 'src/app/config/api-config';
import { Observable } from 'rxjs';
import { Project } from '../models/domain/project';

/**
* Service to retrieve autocompleted project suggestions based on typed.
*/
@Injectable({
providedIn: 'root',
})
export class RecommendationService {

protected readonly url = API_CONFIG.url + API_CONFIG.userRoute;

constructor(private http: HttpClient) {}

public getRecommendations(amountOfRecommendations): Observable<Array<Project>> {
return this.http.get<Array<Project>>(this.url + "/projectrecommendations/" + amountOfRecommendations);
}

}