Add a component to display a publication list and fix publication search rest service to handle ids.
This commit is contained in:
@@ -0,0 +1,9 @@
|
|||||||
|
package org.codiki.domain.publication.exception;
|
||||||
|
|
||||||
|
import org.codiki.domain.exception.FunctionnalException;
|
||||||
|
|
||||||
|
public class BadPublicationSearchCriterionException extends FunctionnalException {
|
||||||
|
public BadPublicationSearchCriterionException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,10 +13,7 @@ import org.codiki.domain.exception.RefreshTokenExpiredException;
|
|||||||
import org.codiki.domain.exception.UserDoesNotExistException;
|
import org.codiki.domain.exception.UserDoesNotExistException;
|
||||||
import org.codiki.domain.picture.exception.PictureNotFoundException;
|
import org.codiki.domain.picture.exception.PictureNotFoundException;
|
||||||
import org.codiki.domain.picture.exception.PictureUploadException;
|
import org.codiki.domain.picture.exception.PictureUploadException;
|
||||||
import org.codiki.domain.publication.exception.NoPublicationSearchResultException;
|
import org.codiki.domain.publication.exception.*;
|
||||||
import org.codiki.domain.publication.exception.PublicationEditionException;
|
|
||||||
import org.codiki.domain.publication.exception.PublicationNotFoundException;
|
|
||||||
import org.codiki.domain.publication.exception.PublicationUpdateForbiddenException;
|
|
||||||
import org.codiki.domain.user.exception.UserAlreadyExistsException;
|
import org.codiki.domain.user.exception.UserAlreadyExistsException;
|
||||||
import org.codiki.domain.user.exception.UserCreationException;
|
import org.codiki.domain.user.exception.UserCreationException;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
@@ -28,6 +25,7 @@ import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExcep
|
|||||||
@RestControllerAdvice
|
@RestControllerAdvice
|
||||||
public class GlobalControllerExceptionHandler extends ResponseEntityExceptionHandler {
|
public class GlobalControllerExceptionHandler extends ResponseEntityExceptionHandler {
|
||||||
@ExceptionHandler({
|
@ExceptionHandler({
|
||||||
|
BadPublicationSearchCriterionException.class,
|
||||||
CategoryDeletionException.class,
|
CategoryDeletionException.class,
|
||||||
CategoryEditionException.class,
|
CategoryEditionException.class,
|
||||||
CategoryNotFoundException.class,
|
CategoryNotFoundException.class,
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import org.codiki.domain.publication.model.Publication;
|
|||||||
import org.codiki.domain.publication.model.search.PublicationSearchCriterion;
|
import org.codiki.domain.publication.model.search.PublicationSearchCriterion;
|
||||||
import org.codiki.domain.publication.port.PublicationPort;
|
import org.codiki.domain.publication.port.PublicationPort;
|
||||||
import org.codiki.infrastructure.publication.model.PublicationEntity;
|
import org.codiki.infrastructure.publication.model.PublicationEntity;
|
||||||
|
import org.codiki.infrastructure.publication.model.PublicationSearchJpaCriterion;
|
||||||
import org.codiki.infrastructure.publication.model.PublicationSearchResult;
|
import org.codiki.infrastructure.publication.model.PublicationSearchResult;
|
||||||
import org.codiki.infrastructure.publication.repository.PublicationRepository;
|
import org.codiki.infrastructure.publication.repository.PublicationRepository;
|
||||||
import org.springframework.data.domain.Limit;
|
import org.springframework.data.domain.Limit;
|
||||||
@@ -48,7 +49,7 @@ public class PublicationJpaAdapter implements PublicationPort {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Publication> search(List<PublicationSearchCriterion> criteria) {
|
public List<Publication> search(List<PublicationSearchCriterion> criteria) {
|
||||||
List<PublicationSearchCriterion> adaptedCriteria = publicationSearchCriteriaJpaAdapter.adaptCriteriaForJpa(criteria);
|
List<PublicationSearchJpaCriterion> adaptedCriteria = publicationSearchCriteriaJpaAdapter.adaptCriteriaForJpa(criteria);
|
||||||
return repository.search(adaptedCriteria)
|
return repository.search(adaptedCriteria)
|
||||||
.stream()
|
.stream()
|
||||||
.map(PublicationEntity::toDomain)
|
.map(PublicationEntity::toDomain)
|
||||||
|
|||||||
@@ -3,12 +3,15 @@ package org.codiki.infrastructure.publication;
|
|||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.codiki.domain.publication.exception.BadPublicationSearchCriterionException;
|
||||||
import org.codiki.domain.publication.model.search.PublicationSearchCriterion;
|
import org.codiki.domain.publication.model.search.PublicationSearchCriterion;
|
||||||
|
import org.codiki.infrastructure.publication.model.PublicationSearchJpaCriterion;
|
||||||
|
import org.codiki.infrastructure.publication.model.PublicationSearchJpaField;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
public class PublicationSearchCriteriaJpaAdapter {
|
public class PublicationSearchCriteriaJpaAdapter {
|
||||||
public List<PublicationSearchCriterion> adaptCriteriaForJpa(List<PublicationSearchCriterion> initialCriteria) {
|
public List<PublicationSearchJpaCriterion> adaptCriteriaForJpa(List<PublicationSearchCriterion> initialCriteria) {
|
||||||
List<PublicationSearchCriterion> result = new LinkedList<>();
|
List<PublicationSearchCriterion> result = new LinkedList<>();
|
||||||
|
|
||||||
for (PublicationSearchCriterion criterion : initialCriteria) {
|
for (PublicationSearchCriterion criterion : initialCriteria) {
|
||||||
@@ -29,6 +32,19 @@ public class PublicationSearchCriteriaJpaAdapter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result.stream()
|
||||||
|
.map(this::mapToJpaCriterion)
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private PublicationSearchJpaCriterion mapToJpaCriterion(PublicationSearchCriterion criterion) {
|
||||||
|
return new PublicationSearchJpaCriterion(
|
||||||
|
PublicationSearchJpaField.fromDomain(criterion.searchField())
|
||||||
|
.orElseThrow(() -> new BadPublicationSearchCriterionException(
|
||||||
|
String.format("Unknown field research criterion: %s", criterion.searchField()))
|
||||||
|
),
|
||||||
|
criterion.searchType(),
|
||||||
|
criterion.value()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package org.codiki.infrastructure.publication.model;
|
||||||
|
|
||||||
|
import org.codiki.domain.publication.model.search.ComparisonType;
|
||||||
|
|
||||||
|
public record PublicationSearchJpaCriterion(
|
||||||
|
PublicationSearchJpaField searchField,
|
||||||
|
ComparisonType searchType,
|
||||||
|
Object value
|
||||||
|
) { }
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
package org.codiki.infrastructure.publication.model;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import org.codiki.domain.publication.model.search.PublicationSearchField;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public enum PublicationSearchJpaField {
|
||||||
|
ID,
|
||||||
|
KEY,
|
||||||
|
TITLE,
|
||||||
|
TEXT,
|
||||||
|
DESCRIPTION,
|
||||||
|
CREATION_DATE("creationDate"),
|
||||||
|
CATEGORY_ID("categoryId"),
|
||||||
|
AUTHOR_ID("author.id"),
|
||||||
|
AUTHOR_PSEUDO("author.pseudo");
|
||||||
|
|
||||||
|
private final String fieldName;
|
||||||
|
|
||||||
|
PublicationSearchJpaField() {
|
||||||
|
this.fieldName = name().toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
PublicationSearchJpaField(String fieldName) {
|
||||||
|
this.fieldName = fieldName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Optional<PublicationSearchJpaField> fromDomain(PublicationSearchField publicationSearchField) {
|
||||||
|
return Arrays.stream(values())
|
||||||
|
.filter(field -> field.name().equals(publicationSearchField.name()))
|
||||||
|
.findFirst();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
package org.codiki.infrastructure.publication.repository;
|
package org.codiki.infrastructure.publication.repository;
|
||||||
|
|
||||||
|
import org.codiki.infrastructure.publication.model.PublicationEntity;
|
||||||
|
import org.codiki.infrastructure.publication.model.PublicationSearchJpaCriterion;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.codiki.domain.publication.model.search.PublicationSearchCriterion;
|
|
||||||
import org.codiki.infrastructure.publication.model.PublicationEntity;
|
|
||||||
|
|
||||||
public interface CustomPublicationRepository {
|
public interface CustomPublicationRepository {
|
||||||
List<PublicationEntity> search(List<PublicationSearchCriterion> criteria);
|
List<PublicationEntity> search(List<PublicationSearchJpaCriterion> criteria);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,15 @@
|
|||||||
package org.codiki.infrastructure.publication.repository;
|
package org.codiki.infrastructure.publication.repository;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.codiki.domain.publication.model.search.PublicationSearchCriterion;
|
|
||||||
import org.codiki.infrastructure.publication.model.PublicationEntity;
|
|
||||||
import org.springframework.stereotype.Repository;
|
|
||||||
|
|
||||||
import jakarta.persistence.EntityManager;
|
import jakarta.persistence.EntityManager;
|
||||||
import jakarta.persistence.criteria.CriteriaBuilder;
|
import jakarta.persistence.criteria.CriteriaBuilder;
|
||||||
import jakarta.persistence.criteria.CriteriaQuery;
|
import jakarta.persistence.criteria.CriteriaQuery;
|
||||||
import jakarta.persistence.criteria.Predicate;
|
import jakarta.persistence.criteria.Predicate;
|
||||||
import jakarta.persistence.criteria.Root;
|
import jakarta.persistence.criteria.Root;
|
||||||
|
import org.codiki.infrastructure.publication.model.PublicationEntity;
|
||||||
|
import org.codiki.infrastructure.publication.model.PublicationSearchJpaCriterion;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
@Repository
|
@Repository
|
||||||
public class CustomPublicationRepositoryImpl implements CustomPublicationRepository {
|
public class CustomPublicationRepositoryImpl implements CustomPublicationRepository {
|
||||||
@@ -23,7 +22,7 @@ public class CustomPublicationRepositoryImpl implements CustomPublicationReposit
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<PublicationEntity> search(final List<PublicationSearchCriterion> criteria) {
|
public List<PublicationEntity> search(final List<PublicationSearchJpaCriterion> criteria) {
|
||||||
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
|
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
|
||||||
|
|
||||||
CriteriaQuery<PublicationEntity> query = criteriaBuilder.createQuery(PublicationEntity.class);
|
CriteriaQuery<PublicationEntity> query = criteriaBuilder.createQuery(PublicationEntity.class);
|
||||||
|
|||||||
@@ -1,14 +1,16 @@
|
|||||||
package org.codiki.infrastructure.publication.repository;
|
package org.codiki.infrastructure.publication.repository;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
import static org.codiki.domain.publication.model.search.PublicationSearchField.AUTHOR_PSEUDO;
|
|
||||||
import org.codiki.domain.publication.model.search.PublicationSearchCriterion;
|
|
||||||
import org.codiki.domain.publication.model.search.PublicationSearchField;
|
|
||||||
import org.codiki.infrastructure.publication.model.PublicationEntity;
|
import org.codiki.infrastructure.publication.model.PublicationEntity;
|
||||||
|
import org.codiki.infrastructure.publication.model.PublicationSearchJpaCriterion;
|
||||||
|
import org.codiki.infrastructure.publication.model.PublicationSearchJpaField;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import static jakarta.persistence.criteria.JoinType.LEFT;
|
import static jakarta.persistence.criteria.JoinType.LEFT;
|
||||||
|
import static org.codiki.infrastructure.publication.model.PublicationSearchJpaField.AUTHOR_PSEUDO;
|
||||||
|
|
||||||
import jakarta.persistence.criteria.CriteriaBuilder;
|
import jakarta.persistence.criteria.CriteriaBuilder;
|
||||||
import jakarta.persistence.criteria.From;
|
import jakarta.persistence.criteria.From;
|
||||||
import jakarta.persistence.criteria.Predicate;
|
import jakarta.persistence.criteria.Predicate;
|
||||||
@@ -17,7 +19,7 @@ import jakarta.persistence.criteria.Root;
|
|||||||
@Component
|
@Component
|
||||||
public class PublicationPredicateMapper {
|
public class PublicationPredicateMapper {
|
||||||
public Predicate map(
|
public Predicate map(
|
||||||
List<PublicationSearchCriterion> criteria,
|
List<PublicationSearchJpaCriterion> criteria,
|
||||||
CriteriaBuilder criteriaBuilder,
|
CriteriaBuilder criteriaBuilder,
|
||||||
Root<PublicationEntity> fromPublication
|
Root<PublicationEntity> fromPublication
|
||||||
) {
|
) {
|
||||||
@@ -28,13 +30,15 @@ public class PublicationPredicateMapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Predicate map(
|
private Predicate map(
|
||||||
PublicationSearchCriterion criterion,
|
PublicationSearchJpaCriterion criterion,
|
||||||
CriteriaBuilder criteriaBuilder,
|
CriteriaBuilder criteriaBuilder,
|
||||||
Root<PublicationEntity> fromPublication
|
Root<PublicationEntity> fromPublication
|
||||||
) {
|
) {
|
||||||
return switch (criterion.searchType()) {
|
return switch (criterion.searchType()) {
|
||||||
case EQUALS -> mapEqualsPredicate(criteriaBuilder, fromPublication, criterion.searchField(), criterion.value());
|
case EQUALS ->
|
||||||
case CONTAINS -> mapContainsPredicate(criteriaBuilder, fromPublication, criterion.searchField(), criterion.value());
|
mapEqualsPredicate(criteriaBuilder, fromPublication, criterion.searchField(), criterion.value());
|
||||||
|
case CONTAINS ->
|
||||||
|
mapContainsPredicate(criteriaBuilder, fromPublication, criterion.searchField(), criterion.value());
|
||||||
default -> null;
|
default -> null;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -42,28 +46,35 @@ public class PublicationPredicateMapper {
|
|||||||
private Predicate mapEqualsPredicate(
|
private Predicate mapEqualsPredicate(
|
||||||
CriteriaBuilder criteriaBuilder,
|
CriteriaBuilder criteriaBuilder,
|
||||||
Root<PublicationEntity> fromPublication,
|
Root<PublicationEntity> fromPublication,
|
||||||
PublicationSearchField searchField,
|
PublicationSearchJpaField searchField,
|
||||||
Object value
|
Object value
|
||||||
) {
|
) {
|
||||||
|
Predicate result;
|
||||||
|
|
||||||
From<?, ?> from = fromPublication;
|
From<?, ?> from = fromPublication;
|
||||||
String attributeName = searchField.name().toLowerCase();
|
String attributeName = searchField.getFieldName();
|
||||||
if (searchField == AUTHOR_PSEUDO) {
|
if (searchField == AUTHOR_PSEUDO) {
|
||||||
from = fromPublication.join("author", LEFT);
|
from = fromPublication.join("author", LEFT);
|
||||||
attributeName = "pseudo";
|
attributeName = "pseudo";
|
||||||
}
|
}
|
||||||
|
|
||||||
return criteriaBuilder.equal(
|
if (value instanceof UUID) {
|
||||||
|
result = criteriaBuilder.equal(from.get(attributeName), value);
|
||||||
|
} else {
|
||||||
|
result = criteriaBuilder.equal(
|
||||||
criteriaBuilder.lower(
|
criteriaBuilder.lower(
|
||||||
from.get(attributeName)
|
from.get(attributeName)
|
||||||
),
|
),
|
||||||
value
|
value
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
private Predicate mapContainsPredicate(
|
private Predicate mapContainsPredicate(
|
||||||
CriteriaBuilder criteriaBuilder,
|
CriteriaBuilder criteriaBuilder,
|
||||||
Root<PublicationEntity> fromPublication,
|
Root<PublicationEntity> fromPublication,
|
||||||
PublicationSearchField searchField,
|
PublicationSearchJpaField searchField,
|
||||||
Object value
|
Object value
|
||||||
) {
|
) {
|
||||||
From<?, ?> from = fromPublication;
|
From<?, ?> from = fromPublication;
|
||||||
|
|||||||
@@ -1,14 +1,17 @@
|
|||||||
package org.codiki.infrastructure.publication;
|
package org.codiki.infrastructure.publication;
|
||||||
|
|
||||||
|
import org.codiki.domain.publication.model.search.PublicationSearchCriterion;
|
||||||
|
import org.codiki.domain.publication.model.search.PublicationSearchField;
|
||||||
|
import org.codiki.infrastructure.publication.model.PublicationSearchJpaCriterion;
|
||||||
|
import org.codiki.infrastructure.publication.model.PublicationSearchJpaField;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Nested;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.codiki.domain.publication.model.search.ComparisonType.CONTAINS;
|
import static org.codiki.domain.publication.model.search.ComparisonType.CONTAINS;
|
||||||
import static org.codiki.domain.publication.model.search.PublicationSearchField.KEY;
|
|
||||||
import org.codiki.domain.publication.model.search.PublicationSearchCriterion;
|
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
|
||||||
import org.junit.jupiter.api.Nested;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
class PublicationSearchCriteriaJpaAdapterTest {
|
class PublicationSearchCriteriaJpaAdapterTest {
|
||||||
private PublicationSearchCriteriaJpaAdapter adapter;
|
private PublicationSearchCriteriaJpaAdapter adapter;
|
||||||
@@ -24,15 +27,15 @@ class PublicationSearchCriteriaJpaAdapterTest {
|
|||||||
void should_adapt_criteria_for_jpa() {
|
void should_adapt_criteria_for_jpa() {
|
||||||
// given
|
// given
|
||||||
List<PublicationSearchCriterion> initialCriteria = List.of(
|
List<PublicationSearchCriterion> initialCriteria = List.of(
|
||||||
new PublicationSearchCriterion(KEY, CONTAINS, "critère")
|
new PublicationSearchCriterion(PublicationSearchField.KEY, CONTAINS, "critère")
|
||||||
);
|
);
|
||||||
|
|
||||||
// when
|
// when
|
||||||
List<PublicationSearchCriterion> result = adapter.adaptCriteriaForJpa(initialCriteria);
|
List<PublicationSearchJpaCriterion> result = adapter.adaptCriteriaForJpa(initialCriteria);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
List<PublicationSearchCriterion> expectedResult = List.of(
|
List<PublicationSearchJpaCriterion> expectedResult = List.of(
|
||||||
new PublicationSearchCriterion(KEY, CONTAINS, "crit_re")
|
new PublicationSearchJpaCriterion(PublicationSearchJpaField.KEY, CONTAINS, "crit_re")
|
||||||
);
|
);
|
||||||
assertThat(result).isEqualTo(expectedResult);
|
assertThat(result).isEqualTo(expectedResult);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { HttpClient } from '@angular/common/http';
|
import { HttpClient, HttpParams } from '@angular/common/http';
|
||||||
import { Injectable, inject } from '@angular/core';
|
import { Injectable, inject } from '@angular/core';
|
||||||
import { lastValueFrom } from 'rxjs';
|
import { lastValueFrom } from 'rxjs';
|
||||||
import { Publication } from './model/publication';
|
import { Publication } from './model/publication';
|
||||||
@@ -20,4 +20,10 @@ export class PublicationRestService {
|
|||||||
update(publication: Publication): Promise<void> {
|
update(publication: Publication): Promise<void> {
|
||||||
return lastValueFrom(this.httpClient.put<void>(`/api/publications/${publication.id}`, publication));
|
return lastValueFrom(this.httpClient.put<void>(`/api/publications/${publication.id}`, publication));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
search(searchCriteria: string): Promise<Publication[]> {
|
||||||
|
let params = new HttpParams();
|
||||||
|
params = params.set('query', searchCriteria);
|
||||||
|
return lastValueFrom(this.httpClient.get<Publication[]>('/api/publications', { params }));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,2 @@
|
|||||||
<h1>Last publications</h1>
|
<h1>Last publications</h1>
|
||||||
<div class="publication-container">
|
<app-publication-list [publications$]="publications$"></app-publication-list>
|
||||||
<a *ngFor="let publication of publications$ | async" [routerLink]="['/publications/' + publication.id]" class="publication">
|
|
||||||
<img src="/pictures/{{ publication.illustrationId }}"/>
|
|
||||||
<div class="body">
|
|
||||||
<h1>{{publication.title}}</h1>
|
|
||||||
<h2>{{publication.description}}</h2>
|
|
||||||
</div>
|
|
||||||
<div class="footer">
|
|
||||||
<img src="/pictures/{{ publication.author.image }}" [matTooltip]="publication.author.name"/>
|
|
||||||
Publication posted by {{publication.author.name}}
|
|
||||||
<span class="publication-date">
|
|
||||||
({{ publication.creationDate | date: 'short' : 'fr-Fr' }})
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
@@ -5,11 +5,12 @@ import { Publication } from '../../core/rest-services/publications/model/publica
|
|||||||
import { RouterModule } from '@angular/router';
|
import { RouterModule } from '@angular/router';
|
||||||
import { MatTooltipModule } from '@angular/material/tooltip';
|
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { PublicationListComponent } from '../../components/publication-list/publication-list.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-home',
|
selector: 'app-home',
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [CommonModule, RouterModule, MatTooltipModule],
|
imports: [PublicationListComponent],
|
||||||
templateUrl: './home.component.html',
|
templateUrl: './home.component.html',
|
||||||
styleUrl: './home.component.scss',
|
styleUrl: './home.component.scss',
|
||||||
providers: [HomeService]
|
providers: [HomeService]
|
||||||
|
|||||||
Reference in New Issue
Block a user