Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision

Target

Select target project
  • web-et-numerique/factory/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_client
1 result
Select Git revision
Show changes
Commits on Source (2)
Showing
with 803 additions and 47 deletions
......@@ -88,7 +88,7 @@ const routes: Routes = [
canDeactivate: [DeactivateGuard],
},
{
path: 'posts',
path: 'news',
loadChildren: () => import('./post/post.module').then((m) => m.PostModule),
},
{
......
......@@ -9,14 +9,10 @@
<app-svg-icon (click)="openMenu()" [type]="'ico'" [icon]="'menu'" [iconClass]="'icon-32'"></app-svg-icon>
</div>
<div fxLayout="row" class="right-header" fxLayoutAlign="center center" fxLayoutGap="3vw">
<a routerLink="/home" [routerLinkActive]="'active'" i18n>Les acteurs</a>
<a routerLink="/news" [routerLinkActive]="'active'" i18n>Actualités</a>
<a routerLink="/home" [routerLinkActive]="'active'" i18n>Cartographie de acteurs</a>
<a routerLink="/about" [routerLinkActive]="'active'" i18n>Qui sommes-nous ?</a>
<!-- <a routerLink="/news" [routerLinkActive]="'active'" i18n>Actualités</a> -->
<!-- <a routerLink="/resources" [routerLinkActive]="'active'" i18n>Ressources</a> -->
<a *ngIf="isAdmin" routerLink="/admin" [routerLinkActive]="'active'">Administration</a>
<!-- <a *ngIf="isLoggedIn" routerLink="/profile" [routerLinkActive]="'active'" fxLayout="row" fxLayoutGap="1.5vh">
<app-svg-icon [type]="'ico'" [iconClass]="'icon-32'" [icon]="'user'" [iconColor]="'currentColor'"></app-svg-icon>
</a> -->
<button *ngIf="isLoggedIn" class="red" routerLink="/profile" [routerLinkActive]="'active'">
{{ displayName }}
</button>
......@@ -32,7 +28,8 @@
<div (click)="closeMenu()" class="ico-close-details"></div>
</div>
<div fxLayout="column" class="right-header" fxLayoutAlign="none baseline" fxLayoutGap="5vw">
<a routerLink="/home" [routerLinkActive]="'active'" (click)="closeMenu()" i18n>Les acteurs</a>
<a routerLink="/news" [routerLinkActive]="'active'" (click)="closeMenu()" i18n>Actualités</a>
<a routerLink="/home" [routerLinkActive]="'active'" (click)="closeMenu()" i18n>Cartographie de acteurs</a>
<a routerLink="/about" [routerLinkActive]="'active'" i18n>Qui sommes-nous ?</a>
<a *ngIf="isAdmin" routerLink="/admin" [routerLinkActive]="'active'" (click)="closeMenu()">Administration</a>
</div>
......@@ -47,7 +44,6 @@
</div>
<app-signup-modal *ngIf="displaySignUp" [openned]="isPopUpOpen" (closed)="closeSignUpModal($event)"></app-signup-modal>
<!-- <app-signin-modal *ngIf="!displaySignUp" [openned]="isPopUpOpen" (closed)="closeSignInModal()"></app-signin-modal> -->
<ng-template #customTitle>
<img class="desktop-show logo-grand-lyon" src="/assets/logos/resin.svg" alt />
......
......@@ -16,6 +16,6 @@ export class PostCardComponent implements OnInit {
ngOnInit(): void {}
public showDetails(post: Post): void {
this.router.navigateByUrl('posts/details/' + post.id, { state: { data: post } });
this.router.navigateByUrl('news/details/' + post.id, { state: { data: post } });
}
}
......@@ -31,6 +31,6 @@ export class PostDetailsComponent implements OnInit {
}
public backToPosts(): void {
this.router.navigateByUrl('/posts');
this.router.navigateByUrl('/news');
}
}
<div class="header-container">post-header works!</div>
<div class="header-container">
<div class="section-container" fxLayout="column" fxLayoutAlign="space-between">
<h1>Actualités</h1>
<div fxLayout="row" fxLayoutGap="5px" fxLayoutAlign="space-between flex-end" class="overflow">
<div fxLayout="row" class="row-mobile">
<div fxLayout="row" fxLayoutAlign="center center" *ngFor="let tag of tags.others">
<span
class="tag-button"
tabindex="0"
(click)="activateTag(tag)"
(keydown.enter)="activateTag(tag)"
[ngClass]="{ active: tag.slug === mainActiveTag.slug }"
>{{ tag.name }}</span
>
</div>
</div>
<div
class="btnSection"
fxLayout="row"
fxLayoutAlign="space-between center"
fxLayoutGap="16px"
(clickOutside)="closeModal()"
>
<button
type="button"
fxLayout="row"
[ngClass]="{
selected: modalTypeOpened === TypeModal.public,
containCheckedFilters: checkedPublicTags.length > 0
}"
fxLayoutAlign="space-between center"
(click)="openModal(TypeModal.public)"
>
<span class="text">Tout public</span>
<app-svg-icon
class="icon"
[type]="'ico'"
[iconClass]="modalTypeOpened === TypeModal.public ? 'white' : 'grey-1'"
[icon]="'news-public'"
></app-svg-icon>
<div class="arrow"></div>
</button>
<button
class="btn-filter-no-margin"
type="button"
fxLayout="row"
[ngClass]="{
selected: modalTypeOpened === TypeModal.location,
containCheckedFilters: checkedLocationTags.length > 0
}"
fxLayoutAlign="space-between center"
(click)="openModal(TypeModal.location)"
>
<span class="text">Toutes les communes</span>
<app-svg-icon
class="icon"
[type]="'ico'"
[iconClass]="modalTypeOpened === TypeModal.location ? 'white' : 'grey-1'"
[icon]="'news-location'"
></app-svg-icon>
<div class="arrow"></div>
</button>
<div *ngIf="modalTypeOpened">
<app-post-modal-filters
[modalType]="modalTypeOpened"
[tags]="getModalData()"
[inputCheckedTags]="getCheckedModalData()"
(searchEvent)="filter($event)"
(closeEvent)="closeModal()"
></app-post-modal-filters>
</div>
</div>
</div>
</div>
</div>
@import '../../../../assets/scss/color';
@import '../../../../assets/scss/buttons';
@import '../../../../assets/scss/typography';
@import '../../../../assets/scss/breakpoint';
@import '../../../../assets/scss/layout';
h1 {
margin-bottom: 0px;
}
.header-container {
height: #{$header-post-height};
background: $white;
}
.section-container {
height: 100%;
}
.btnSection {
padding: 16px 0 0px 0;
button {
background: $white;
height: 40px;
width: 100%;
border: 1px solid $grey-4;
padding: 3px 16px 3px 16px;
outline: none;
border-radius: 4px;
cursor: pointer;
white-space: nowrap;
@include btn-normal;
.arrow {
background-color: transparent;
border-bottom: 1px solid $grey-2;
border-right: 1px solid $grey-2;
transform: translateY(-25%) rotate(45deg);
margin: 0 5px 0 10px;
height: 7px;
width: 7px;
}
&:focus {
border-color: $blue-hover;
}
}
.selected {
background-color: $secondary-color;
border-color: $secondary-color !important;
color: $white;
.arrow {
background-color: transparent;
border-bottom: 1px solid $white;
border-right: 1px solid $white;
transform: translateY(25%) rotate(-135deg);
margin: 0 5px 0 10px;
height: 7px;
width: 7px;
}
}
.containCheckedFilters {
border-color: $secondary-color;
}
.icon {
display: none !important;
}
@media #{$desktop} {
button {
width: 90px;
}
.text {
display: none !important;
}
.icon {
display: inherit !important;
}
}
@media #{$tablet} {
button {
display: none !important;
}
}
}
// .btnSection {
// padding: 16px 0 0px 0;
// button {
// background: $white;
// height: 40px;
// width: 210px;
// border: 1px solid $grey-4;
// padding: 3px 16px 3px 16px;
// outline: none;
// border-radius: 4px;
// cursor: pointer;
// white-space: nowrap;
// @include btn-normal;
// .arrow {
// background-color: transparent;
// border-bottom: 1px solid $grey-2;
// border-right: 1px solid $grey-2;
// transform: translateY(-25%) rotate(45deg);
// margin: 0 5px 0 10px;
// height: 7px;
// width: 7px;
// }
// &:focus {
// border-color: $blue-hover;
// }
// }
// .selected {
// border-color: $primary-color !important;
// color: inherit;
// .arrow {
// background-color: transparent;
// border-bottom: 1px solid $primary-color;
// border-right: 1px solid $primary-color;
// transform: translateY(25%) rotate(-135deg);
// margin: 0 5px 0 10px;
// height: 7px;
// width: 7px;
// }
// }
// .containCheckedFilters {
// border-color: $secondary-color;
// }
// }
.tag-button {
padding: 8px 10px;
@include cn-regular-16;
cursor: pointer;
white-space: nowrap;
&.active {
background-color: $secondary-color;
color: $white;
}
&:focus {
outline-color: $secondary-color;
}
}
// Remove margin right on filter pop-up trigger
.btn-filter-no-margin {
margin-right: 0 !important;
}
.row-mobile {
@media #{$tablet} {
width: 100%;
justify-content: space-between;
}
}
.overflow {
@media #{$tablet} {
overflow-y: scroll;
}
}
import { Component, OnInit } from '@angular/core';
import { Component, EventEmitter, OnInit, Output } from '@angular/core';
import { Tag } from '../../models/tag.model';
import { TagWithMeta } from '../../models/tagWithMeta.model';
import * as _ from 'lodash';
import { TypeModalNews } from '../../enum/typeModalNews.enum';
import { ActivatedRoute, Router } from '@angular/router';
import { TagEnum } from '../../enum/tag.enum';
import { parseSlugToTag } from '../utils/NewsUtils';
@Component({
selector: 'app-post-header',
templateUrl: './post-header.component.html',
styleUrls: ['./post-header.component.scss']
styleUrls: ['./post-header.component.scss'],
})
export class PostHeaderComponent implements OnInit {
public modalTypeOpened: TypeModalNews;
public tags: TagWithMeta;
public mainActiveTag: Tag = new Tag({ slug: TagEnum.aLaUne });
public tagEnum = TagEnum;
constructor() { }
public checkedPublicTags: Tag[] = [];
public checkedLocationTags: Tag[] = [];
constructor(private route: ActivatedRoute, private router: Router) {}
ngOnInit(): void {
this.route.data.subscribe((data) => {
if (data.tags) {
this.tags = data.tags;
}
});
this.route.queryParams.subscribe((queryParams) => {
if (queryParams.mainTag) {
this.mainActiveTag = new Tag({ slug: queryParams.mainTag });
}
if (queryParams.publicTags) {
this.checkedPublicTags = parseSlugToTag(queryParams.publicTags);
}
if (queryParams.locationTags) {
this.checkedLocationTags = parseSlugToTag(queryParams.locationTags);
}
});
}
// Open the modal and display the list according to the right filter button
public openModal(modalType: TypeModalNews): void {
// if modal already opened, reset type
if (this.modalTypeOpened === modalType) {
this.closeModal();
} else if (this.modalTypeOpened !== modalType) {
this.modalTypeOpened = modalType;
}
}
public closeModal(): void {
this.modalTypeOpened = undefined;
}
// Accessor to template angular.
public get TypeModal(): typeof TypeModalNews {
return TypeModalNews;
}
public getModalData(): Tag[] {
if (this.modalTypeOpened === this.TypeModal.public) {
return this.tags.public;
}
return this.tags.commune;
}
public getCheckedModalData(): Tag[] {
if (this.modalTypeOpened === this.TypeModal.public) {
return this.checkedPublicTags;
}
return this.checkedLocationTags;
}
public activateTag(tag: Tag): void {
this.mainActiveTag = tag;
this.setQueryParam();
}
public filter(data: Tag[]): void {
if (this.modalTypeOpened === this.TypeModal.public) {
this.checkedPublicTags = data;
} else {
this.checkedLocationTags = data;
}
this.setQueryParam();
this.closeModal();
}
private setQueryParam(): void {
this.router.navigate([], {
relativeTo: this.route,
queryParams: {
mainTag: this.mainActiveTag.slug,
publicTags: this.checkedPublicTags.map((tag) => tag.slug),
locationTags: this.checkedLocationTags.map((tag) => tag.slug),
},
queryParamsHandling: 'merge',
});
}
}
<div class="section-container" fxLayout="row" fxLayoutGap="32px">
<div fxLayout="column" class="list-container" fxLayoutGap="16px">
<div fxLayout="column">
<div fxLayout="column" *ngIf="displayTags()">
<div fxLayout="row wrap" fxLayoutAlign="none center" fxLayoutGap="8px">
<div
fxLayout="row"
fxLayoutAlign="start center"
fxLayoutGap="9px"
*ngFor="let filter of filters | slice: 1"
class="tag"
(click)="removeTag(filter)"
>
<p>{{ filter.slug | titlecase }}</p>
<app-svg-icon [type]="'ico'" [iconColor]="'currentColor'" [icon]="'cancel'"></app-svg-icon>
</div>
</div>
</div>
<div fxLayout="column" *ngIf="isALaUneTag() && !displayTags()">
<div fxLayout="row" class="row-border" fxLayoutAlign="space-between center">
<h2>à la une</h2>
<app-button
......@@ -16,18 +31,33 @@
<div class="background-project-container">
<div class="project-content mobile" fxLayout="column">
<h2>appels à projets</h2>
<app-post-card
[post]="news"
[class]="'project'"
[ngClass]="{ 'last-child': last }"
*ngFor="let news of projectsNew; let last = last"
></app-post-card>
<div *ngIf="projectsNew.length !== 0">
<app-post-card
[post]="news"
[class]="'project'"
[ngClass]="{ 'last-child': last }"
*ngFor="let news of projectsNew; let last = last"
></app-post-card>
</div>
<div *ngIf="projectsNew.length === 0">
<p>Aucun appels à projet pour le moment.</p>
</div>
</div>
</div>
</div>
<div fxLayout="column">
<div fxLayout="row" class="row-border otherNews">
<h2>autres actualités</h2>
<div fxLayout="row" class="row-border" fxLayoutAlign="space-between center">
<h2 [ngClass]="{ 'padding-16-Top': isALaUneTag() && !displayTags() }">{{ getDisplayedTag() }}</h2>
<app-button
*ngIf="displayTags() || !isALaUneTag()"
[type]="'button'"
[style]="'buttonWithHash'"
[text]="'Publier votre actu'"
(action)="publishNews()"
></app-button>
</div>
<div *ngIf="leftColumnPosts.length <= 0" fxLayout="column">
<p>Aucun résultat ne correspond a votre recherche.</p>
</div>
<div fxLayout="row" fxLayoutGap="33px">
<div fxLayout="column" class="columnPosts">
......@@ -47,12 +77,17 @@
<div class="project-content" fxLayout="column">
<app-svg-icon [iconClass]="'icon-80'" [iconColor]="'inherit'" [type]="'post'" [icon]="'appels'"></app-svg-icon>
<h2>appels à projets</h2>
<app-post-card
[post]="news"
[class]="'project'"
[ngClass]="{ 'last-child': last }"
*ngFor="let news of projectsNew; let last = last"
></app-post-card>
<div *ngIf="projectsNew.length !== 0">
<app-post-card
[post]="news"
[class]="'project'"
[ngClass]="{ 'last-child': last }"
*ngFor="let news of projectsNew; let last = last"
></app-post-card>
</div>
<div *ngIf="projectsNew.length === 0">
<p>Aucun appels à projet pour le moment.</p>
</div>
</div>
</div>
</div>
......
......@@ -6,12 +6,11 @@
.section-container {
background: $grey-6;
margin-top: 40px;
min-height: 68vh;
width: 100%;
.row-border {
border-bottom: 1px dashed $grey-4;
padding-bottom: 16px;
&.otherNews {
padding-top: 24px;
}
}
h2 {
font-style: italic !important;
......@@ -100,3 +99,19 @@ h2 {
}
}
}
.tag {
background: $grey-3;
color: $white;
border-radius: 20px;
cursor: pointer;
margin-bottom: 10px;
padding: 0 20px;
p {
margin-top: 0;
margin-bottom: 0;
}
}
.padding-16-Top {
padding-top: 16px;
}
......@@ -3,8 +3,12 @@ import { WindowScrollService } from '../../../shared/service/windowScroll.servic
import { TagEnum } from '../../enum/tag.enum';
import { Pagination } from '../../models/pagination.model';
import { Post } from '../../models/post.model';
import { Tag } from '../../models/tag.model';
import { PostWithMeta } from '../../models/postWithMeta.model';
import { PostService } from '../../services/post.service';
import { ActivatedRoute, Router } from '@angular/router';
import * as _ from 'lodash';
import { parseSlugToTag } from '../utils/NewsUtils';
@Component({
selector: 'app-post-list',
......@@ -12,7 +16,24 @@ import { PostService } from '../../services/post.service';
styleUrls: ['./post-list.component.scss'],
})
export class PostListComponent implements OnInit {
constructor(private postService: PostService, private windowScrollService: WindowScrollService) {
public selectedMainTagSlug = '';
public selectedLocationTagSlug = [];
public selectedPublicTagsSlug = [];
public filters: Tag[];
public postsMobileView: Post[] = [];
public leftColumnPosts: Post[] = [];
public rightColumnPosts: Post[] = [];
public projectsNew: Post[] = [];
public bigNews: Post;
public pagination: Pagination;
public isLoading = false;
constructor(
private postService: PostService,
private windowScrollService: WindowScrollService,
private route: ActivatedRoute,
private router: Router
) {
this.windowScrollService.scrollY$.subscribe((evt: any) => {
if (evt && evt.target.offsetHeight + evt.target.scrollTop >= evt.target.scrollHeight - 200) {
if (!this.isLoading) {
......@@ -21,28 +42,86 @@ export class PostListComponent implements OnInit {
}
});
}
public postsMobileView: Post[] = [];
public leftColumnPosts: Post[] = [];
public rightColumnPosts: Post[] = [];
public projectsNew: Post[] = [];
public bigNews: Post;
public pagination: Pagination;
public isLoading = false;
ngOnInit(): void {
this.isLoading = true;
this.postService.getPosts(1).subscribe((news) => {
this.setNews(news);
// Init APP news list
this.postService.getPosts(1, [TagEnum.appels]).subscribe((news) => {
let projectNews = news.posts.map((news) => (news = this.addAuthorToPost(news)));
this.projectsNew = projectNews;
});
this.postService.getPosts(1, [TagEnum.aLaUne]).subscribe((news) => {
this.bigNews = this.addAuthorToPost(news.posts[0]);
});
this.postService.getPosts(1, [TagEnum.appels]).subscribe((news) => {
let projectNews = news.posts.map((news) => (news = this.addAuthorToPost(news)));
this.projectsNew = projectNews;
this.route.queryParams.subscribe((queryParams) => {
// If main tag is in route, set it
if (queryParams.mainTag) {
this.selectedMainTagSlug = queryParams.mainTag;
this.selectedPublicTagsSlug = parseSlugToTag(queryParams.publicTags);
this.selectedLocationTagSlug = parseSlugToTag(queryParams.locationTags);
// Set filters for search and display
this.filters = [
new Tag({ slug: queryParams.mainTag }),
...this.selectedLocationTagSlug,
...this.selectedPublicTagsSlug,
];
// Apply search
this.getPosts(this.filters);
} else {
// Init default news list
this.postService.getPosts(1).subscribe((news) => {
this.setNews(news);
});
}
});
}
public getPosts(filters?: Tag[]): void {
// Parse filter
let parsedFilters = null;
if (filters) {
parsedFilters = filters.map((filter) => {
return filter.slug;
});
// remove 'a la une' filter
parsedFilters = parsedFilters.filter((item) => {
return item !== TagEnum.aLaUne;
});
if (parsedFilters.length <= 0) {
parsedFilters = null;
}
}
// Reset posts
this.resetPosts();
this.postService.getPosts(1, parsedFilters).subscribe((news) => {
this.setNews(news);
});
}
public getDisplayedTag(): string {
if (!this.isALaUneTag()) {
return this.selectedMainTagSlug;
}
return 'autres actualités';
}
public isALaUneTag(): boolean {
if (!this.filters || this.filters[0].slug === TagEnum.aLaUne) {
return true;
}
return false;
}
public resetPosts(): void {
this.leftColumnPosts = [];
this.rightColumnPosts = [];
this.postsMobileView = [];
}
public publishNews(): void {}
//Transform excerpt post to have a custom author.
......@@ -78,4 +157,22 @@ export class PostListComponent implements OnInit {
});
this.isLoading = false;
}
public removeTag(tagToRemove: Tag): void {
_.remove(this.selectedPublicTagsSlug, { slug: tagToRemove.slug });
_.remove(this.selectedLocationTagSlug, { slug: tagToRemove.slug });
this.router.navigate([], {
relativeTo: this.route,
queryParams: {
mainTag: this.selectedMainTagSlug,
publicTags: this.selectedPublicTagsSlug.map((tag) => tag.slug),
locationTags: this.selectedLocationTagSlug.map((tag) => tag.slug),
},
queryParamsHandling: 'merge',
});
}
public displayTags(): boolean {
return this.selectedLocationTagSlug.length > 0 || this.selectedPublicTagsSlug.length > 0;
}
}
<div *ngIf="modalType" fxLayout="column" fxLayoutAlign="space-between" [ngClass]="['modal', 'modal' + getModalType()]">
<div class="body-wrap" fxLayout="column" fxLayoutAlign="space-between">
<div class="titleFilter" fxLayout="row" fxLayoutAlign="space-between">
<span>Filtres</span>
<div (click)="closeModal()" class="ico-close-details"></div>
</div>
<div class="contentModal" fxLayout="row wrap" fxLayoutAlign="flex-start" *ngIf="tags.length > 0">
<div class="blockFiltre">
<ul class="blockLigne">
<div fxLayout="row" class="ligneFiltre" *ngFor="let tag of tags">
<li class="checkbox">
<div class="checkboxItem">
<label>
<input
type="checkbox"
[checked]="getIndex(checkedTags, tag.slug) > -1"
[value]="tag.id"
(change)="onCheckboxChange($event, tag)"
/>
<span class="customCheck"></span>
<div class="label">{{ tag.name }}</div>
</label>
</div>
</li>
</div>
</ul>
</div>
</div>
<div class="footer" fxLayout="row" fxLayoutAlign="end center" fxLayoutGap="3vw">
<a (click)="clearFilters()" tabindex="0">Effacer</a>
<app-button [style]="'button'" [text]="'Appliquer'" (click)="emit(checkedTags)"></app-button>
</div>
</div>
</div>
@import '../../../../assets/scss/icons';
@import '../../../../assets/scss/color';
@import '../../../../assets/scss/typography';
@import '../../../../assets/scss/breakpoint';
@import '../../../../assets/scss/shapes';
@import '../../../../assets/scss/hyperlink';
@import '../../../../assets/scss/z-index';
.modallocation {
margin-left: -341px;
}
.modalpublic {
@media #{$desktop} {
margin-left: -446px;
}
margin-left: -566px;
}
.modal {
max-width: 341px;
width: 94%;
z-index: $modal-z-index !important;
position: absolute;
border-radius: 6px;
margin-top: 24px;
@media #{$large-phone} {
height: 100%;
max-height: auto;
max-width: auto;
width: 100%;
position: fixed;
top: 0;
left: 0;
border: none;
padding: 0;
}
@include background-hash($grey-2);
border: 1px solid $grey-4;
::-webkit-scrollbar {
width: 16px;
}
::-webkit-scrollbar-track {
background: $grey-6;
}
::-webkit-scrollbar-thumb {
background: $grey;
border-radius: 6px;
}
.body-wrap {
@media #{$large-phone} {
height: 100vh;
height: -webkit-fill-available;
}
.titleFilter {
display: none !important;
margin: 27px 25px 0px 25px;
@include cn-bold-26;
@media #{$large-phone} {
display: flex !important;
}
}
}
.contentModal {
overflow-y: auto;
max-width: 1100px;
border-bottom: 1px solid $grey;
margin-bottom: 16px;
max-height: 40vh;
@media #{$large-phone} {
max-height: none;
height: 100%;
}
.blockFiltre {
width: 100%;
margin: 0 32px;
padding: 40px 0;
border-bottom: 1px dashed $grey-4;
&:last-child {
padding-bottom: 32px;
border-bottom: none;
}
@media #{$large-phone} {
margin: 0 18px;
padding: 25px 0;
}
}
.blockLigne {
padding-left: 0;
-moz-column-count: 1;
-moz-column-gap: 46px;
-webkit-column-count: 1;
-webkit-column-gap: 46px;
column-count: 1;
column-gap: 46px;
margin: 0px;
@media #{$large-phone} {
-moz-column-count: 1;
-webkit-column-count: 1;
column-count: 1;
}
}
.ligneFiltre {
padding: 5px 0;
}
h4 {
@include cn-bold-16;
line-height: 17px;
text-transform: uppercase;
color: $grey-3;
display: flex;
align-items: center;
margin-top: 0;
margin-bottom: 9px;
}
.nbResult {
@include cn-regular-14;
line-height: 16px;
color: $grey-3;
padding-top: 3px;
}
label {
@include cn-regular-14;
}
}
.footer {
margin: 0px 20px 16px 0;
height: 32px;
}
}
a {
@include hyperlink;
}
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { PostModalFiltersComponent } from './post-modal-filters.component';
describe('PostModalFiltersComponent', () => {
let component: PostModalFiltersComponent;
let fixture: ComponentFixture<PostModalFiltersComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ PostModalFiltersComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(PostModalFiltersComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { Component, EventEmitter, Input, OnInit, Output, SimpleChanges } from '@angular/core';
import { Tag } from '../../models/tag.model';
import { TypeModalNews } from '../../enum/typeModalNews.enum';
import { OnChanges } from '@angular/core';
@Component({
selector: 'app-post-modal-filters',
templateUrl: './post-modal-filters.component.html',
styleUrls: ['./post-modal-filters.component.scss'],
})
export class PostModalFiltersComponent implements OnInit, OnChanges {
@Input() public modalType: TypeModalNews;
@Input() public tags: Tag[];
@Output() searchEvent = new EventEmitter();
@Output() closeEvent = new EventEmitter();
// Checkbox variable
@Input() public inputCheckedTags: Tag[] = [];
public checkedTags: Tag[] = [];
constructor() {}
ngOnChanges(changes: SimpleChanges): void {
if (changes.inputCheckedTags) {
this.checkedTags = this.inputCheckedTags;
}
}
ngOnInit(): void {
this.checkedTags = this.inputCheckedTags;
}
// Management of the checkbox event (Check / Uncheck)
public onCheckboxChange(event, tag: Tag): void {
if (event.target.checked) {
this.checkedTags.push(tag);
} else {
// Check if the module is present in the list and remove it
if (this.getIndex(this.checkedTags, tag.slug) > -1) {
this.checkedTags.splice(this.getIndex(this.checkedTags, tag.slug), 1);
}
}
}
// Clear only filters in the current modal
public clearFilters(): void {
this.checkedTags = [];
this.searchEvent.emit(this.checkedTags);
}
public getModalType(): string {
switch (this.modalType) {
case TypeModalNews.location:
return 'location';
case TypeModalNews.public:
return 'public';
default:
return '';
}
}
public emit(data: Tag[]): void {
this.searchEvent.emit(data);
}
public getIndex(array: Tag[], slug: string): number {
return array.findIndex((tag: Tag) => tag.slug === slug);
}
public closeModal(): void {
this.closeEvent.emit();
}
}
import { Tag } from '../../models/tag.model';
export function parseSlugToTag(data: Tag[] | string): Tag[] {
let otherTags = [];
if (Array.isArray(data)) {
otherTags = data.map((slug) => new Tag({ slug: slug }));
} else if (data) {
otherTags = [new Tag({ slug: data })];
}
return otherTags;
}
export enum TagEnum {
aLaUne = 'a-la-une',
appels = 'appels',
projets = 'projets',
formations = 'formations',
infos = 'infos',
dossiers = 'dossiers',
etudes = 'etudes',
ressources = 'ressources',
}
export enum TypeModalNews {
public = 1,
location,
}
export class Tag {
id: string;
name: string;
slug: string;
description: string; // Description is used to ut categories on tags
constructor(obj?: any) {
Object.assign(this, obj);
}
}
import { Tag } from './tag.model';
export class TagWithMeta {
commune: Tag[];
public: Tag[];
others: Tag[];
}
<app-post-header></app-post-header>
<app-post-header (filterTags)="setFilters($event)"></app-post-header>
<div class="section-container">
<!-- <app-post-list [filters]="filters"></app-post-list> -->
<router-outlet></router-outlet>
</div>