Compare commits
8 Commits
gradle-set
...
c4e60bee2a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c4e60bee2a | ||
|
|
6a37419cf6 | ||
|
|
3b4003ff01 | ||
|
|
d12425d90a | ||
|
|
370ac7d814 | ||
|
|
f13fc79d92 | ||
|
|
0bec920670 | ||
|
|
021e0ce784 |
@@ -1,10 +1,10 @@
|
||||
<h1>{{title}}</h1>
|
||||
<h2>{{description}}</h2>
|
||||
<footer>
|
||||
<button type="button" class="secondary" (click)="closeDialog()" i18n>
|
||||
<button type="button" class="cod-btn secondary" (click)="closeDialog()" matRipple i18n>
|
||||
No
|
||||
</button>
|
||||
<button type="button" (click)="closeAndValidate()" i18n>
|
||||
<button type="button" class="cod-btn" (click)="closeAndValidate()" matRipple i18n>
|
||||
Yes
|
||||
</button>
|
||||
</footer>
|
||||
@@ -8,32 +8,5 @@
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
|
||||
button {
|
||||
padding: .8em 1.2em;
|
||||
border-radius: 10em;
|
||||
border: none;
|
||||
background-color: #3f51b5;
|
||||
color: white;
|
||||
transition: background-color .2s ease-in-out;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
&:hover {
|
||||
background-color: #5b6ed8;
|
||||
}
|
||||
|
||||
&.secondary {
|
||||
color: #3f51b5;
|
||||
background-color: white;
|
||||
|
||||
&:hover {
|
||||
background-color: #f2f4ff;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Component, inject, Input } from "@angular/core";
|
||||
import { MatRippleModule } from "@angular/material/core";
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from "@angular/material/dialog";
|
||||
|
||||
export interface ConfirmationDialogData {
|
||||
@@ -11,7 +12,7 @@ export interface ConfirmationDialogData {
|
||||
standalone: true,
|
||||
templateUrl: './confirmation-dialog.component.html',
|
||||
styleUrl: './confirmation-dialog.component.scss',
|
||||
imports: []
|
||||
imports: [MatRippleModule]
|
||||
})
|
||||
export class ConfirmationDialog {
|
||||
private readonly dialogRef = inject(MatDialogRef<ConfirmationDialog>);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<span class="copy-left">©</span>
|
||||
2016 - 2024 All rights reserved
|
||||
-
|
||||
2.0-alpha
|
||||
2.1
|
||||
<a [routerLink]="['./']" matTooltip="Health checking will be available in future..." i18n-matTooltip>
|
||||
<mat-icon>favorite</mat-icon>
|
||||
</a>
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
<div class="left">
|
||||
<button type="button" (click)="sideMenu.open()" matTooltip="Click to show side menu" i18n-matTooltip>
|
||||
<button type="button"
|
||||
(click)="sideMenu.open()"
|
||||
class="cod-btn icon"
|
||||
matTooltip="Click to show side menu"
|
||||
matRipple
|
||||
i18n-matTooltip>
|
||||
<mat-icon>menu</mat-icon>
|
||||
</button>
|
||||
<a [routerLink]="['/home']">
|
||||
@@ -14,7 +19,10 @@
|
||||
|
||||
<div class="right">
|
||||
@if (isAuthenticated) {
|
||||
<button mat-button class="button" [matMenuTriggerFor]="authenticatedUserMenu">
|
||||
<button type="button"
|
||||
class="cod-btn icon"
|
||||
[matMenuTriggerFor]="authenticatedUserMenu"
|
||||
matRipple>
|
||||
<mat-icon>more_vert</mat-icon>
|
||||
</button>
|
||||
<mat-menu #authenticatedUserMenu="matMenu">
|
||||
@@ -30,7 +38,7 @@
|
||||
</div>
|
||||
</mat-menu>
|
||||
} @else {
|
||||
<a [routerLink]="['/login']" class="button" matRipple i18n>Login</a>
|
||||
<a [routerLink]="['/login']" class="cod-btn" matRipple i18n>Login</a>
|
||||
}
|
||||
</div>
|
||||
<app-side-menu #sideMenu></app-side-menu>
|
||||
@@ -26,25 +26,6 @@ $headerHeight: 3.5em;
|
||||
padding: 0 1em;
|
||||
z-index: 2;
|
||||
|
||||
button {
|
||||
background-color: #3f51b5;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 10em;
|
||||
transition: background-color .2s ease-in-out;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
$buttonSize: 2.5em;
|
||||
width: $buttonSize;
|
||||
height: $buttonSize;
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
background-color: #5c6bc0;
|
||||
}
|
||||
}
|
||||
|
||||
a {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
@@ -120,45 +101,10 @@ $headerHeight: 3.5em;
|
||||
top: 0;
|
||||
right: 0;
|
||||
z-index: 2;
|
||||
|
||||
a {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
min-width: 5em;
|
||||
color: white;
|
||||
margin: 0.5em 0.5em;
|
||||
border-radius: 10em;
|
||||
text-decoration: none;
|
||||
padding: 0 .8em;
|
||||
background-color: #3f51b5;
|
||||
transition: background-color .2s ease-in-out;
|
||||
|
||||
&:hover {
|
||||
background-color: #5c6bc0;
|
||||
}
|
||||
}
|
||||
|
||||
button {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
min-width: 2.5em;
|
||||
color: white;
|
||||
margin: 0.5em 0.5em;
|
||||
border-radius: 10em;
|
||||
text-decoration: none;
|
||||
padding: 0;
|
||||
background-color: #3f51b5;
|
||||
transition: background-color .2s ease-in-out;
|
||||
|
||||
&:hover {
|
||||
background-color: #5c6bc0;
|
||||
}
|
||||
|
||||
mat-icon {
|
||||
margin: 0;
|
||||
}
|
||||
margin-right: .5em;
|
||||
|
||||
a, button {
|
||||
margin: .5em;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
<button type="button" class="close" (click)="closeDialog()">
|
||||
<button type="button"
|
||||
(click)="closeDialog()"
|
||||
class="cod-btn icon secondary close"
|
||||
matTooltip="Close"
|
||||
matRipple
|
||||
i18n-matTooltip>
|
||||
<mat-icon>close</mat-icon>
|
||||
</button>
|
||||
<header>
|
||||
<h1 i18n>Add a code block</h1>
|
||||
</header>
|
||||
<form [formGroup]="formGroup" (submit)="closeAndValidate()" ngNativeValidate>
|
||||
<form [formGroup]="formGroup" (submit)="closeAndValidate()" class="cod-form" ngNativeValidate>
|
||||
<div class="form-content">
|
||||
<mat-form-field>
|
||||
<mat-label i18n>Programming language</mat-label>
|
||||
@@ -21,11 +26,11 @@
|
||||
<textarea matInput formControlName="codeBlock"></textarea>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div class="actions">
|
||||
<button type="submit" i18n>
|
||||
<div class="actions reversed">
|
||||
<button type="submit" class="cod-btn" matRipple i18n>
|
||||
Validate
|
||||
</button>
|
||||
<button type="button" (click)="closeDialog()" class="secondary" i18n>
|
||||
<button type="button" (click)="closeDialog()" class="cod-btn secondary" matRipple i18n>
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -6,20 +6,6 @@
|
||||
position: relative;
|
||||
max-height: 90vh;
|
||||
|
||||
.close {
|
||||
position: absolute;
|
||||
top: 1em;
|
||||
right: 1em;
|
||||
width: 2.5em;
|
||||
height: 2.5em;
|
||||
border-radius: 10em;
|
||||
border: none;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
header {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
@@ -39,40 +25,6 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.actions {
|
||||
display: flex;
|
||||
flex-direction: row-reverse;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
button {
|
||||
padding: .8em 1.2em;
|
||||
border-radius: 10em;
|
||||
border: none;
|
||||
background-color: #3f51b5;
|
||||
color: white;
|
||||
transition: background-color .2s ease-in-out;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
&:hover {
|
||||
background-color: #5b6ed8;
|
||||
}
|
||||
|
||||
&.secondary {
|
||||
color: #3f51b5;
|
||||
background-color: white;
|
||||
|
||||
&:hover {
|
||||
background-color: #f2f4ff;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,12 @@
|
||||
import { Component, inject } from "@angular/core";
|
||||
import { FormBuilder, FormControl, ReactiveFormsModule, Validators } from "@angular/forms";
|
||||
import { MatRippleModule } from "@angular/material/core";
|
||||
import { MatDialogRef } from "@angular/material/dialog";
|
||||
import { MatFormFieldModule } from "@angular/material/form-field";
|
||||
import { MatIcon } from "@angular/material/icon";
|
||||
import { MatInputModule } from "@angular/material/input";
|
||||
import { MatSelectModule } from '@angular/material/select';
|
||||
import { MatTooltip } from "@angular/material/tooltip";
|
||||
|
||||
export interface ProgramingLanguage {
|
||||
code: string;
|
||||
@@ -91,7 +93,9 @@ export const PROGRAMMING_LANGUAGES: ProgramingLanguage[] = [
|
||||
MatFormFieldModule,
|
||||
MatIcon,
|
||||
MatInputModule,
|
||||
MatRippleModule,
|
||||
MatSelectModule,
|
||||
MatTooltip,
|
||||
ReactiveFormsModule,
|
||||
]
|
||||
})
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
<button type="button" class="close" (click)="closeDialog()">
|
||||
<button type="button"
|
||||
(click)="closeDialog()"
|
||||
class="cod-btn icon secondary close"
|
||||
matTooltip="Close"
|
||||
matRipple
|
||||
i18n-matTooltip>
|
||||
<mat-icon>close</mat-icon>
|
||||
</button>
|
||||
<header>
|
||||
@@ -19,10 +24,18 @@
|
||||
}
|
||||
</div>
|
||||
<footer>
|
||||
<button type="button" class="secondary" matRipple (click)="closeDialog()" i18n>
|
||||
<button type="button"
|
||||
(click)="closeDialog()"
|
||||
class="cod-btn secondary"
|
||||
matRipple
|
||||
i18n>
|
||||
Cancel
|
||||
</button>
|
||||
<button type="button" (click)="fileUpload.click()" matRipple i18n>
|
||||
<button type="button"
|
||||
(click)="fileUpload.click()"
|
||||
class="cod-btn"
|
||||
matRipple
|
||||
i18n>
|
||||
<mat-icon>upload_file</mat-icon>
|
||||
Add new picture
|
||||
</button>
|
||||
|
||||
@@ -6,20 +6,6 @@
|
||||
position: relative;
|
||||
max-height: 90vh;
|
||||
|
||||
.close {
|
||||
position: absolute;
|
||||
top: 1em;
|
||||
right: 1em;
|
||||
width: 2.5em;
|
||||
height: 2.5em;
|
||||
border-radius: 10em;
|
||||
border: none;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
header {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
|
||||
@@ -11,9 +11,14 @@ import { MatTooltip } from "@angular/material/tooltip";
|
||||
@Component({
|
||||
selector: 'app-picture-selection',
|
||||
standalone: true,
|
||||
imports: [MatProgressSpinnerModule, MatIcon, MatRippleModule, MatTooltip],
|
||||
templateUrl: './picture-selection-dialog.component.html',
|
||||
styleUrl: './picture-selection-dialog.component.scss',
|
||||
imports: [
|
||||
MatIcon,
|
||||
MatRippleModule,
|
||||
MatProgressSpinnerModule,
|
||||
MatTooltip
|
||||
],
|
||||
})
|
||||
export class PictureSelectionDialog implements OnInit {
|
||||
private readonly pictureRestService = inject(PictureRestService);
|
||||
|
||||
@@ -37,25 +37,53 @@
|
||||
</div>
|
||||
|
||||
<div class="actions">
|
||||
<button type="button" matTooltip="Click to insert a title 1 section" (click)="insertTitle(1)" i18n-matTooltip>
|
||||
<button type="button"
|
||||
(click)="insertTitle(1)"
|
||||
matTooltip="Click to insert a title 1 section"
|
||||
matRipple
|
||||
i18n-matTooltip>
|
||||
H1
|
||||
</button>
|
||||
<button type="button" matTooltip="Click to insert a title 2 section" (click)="insertTitle(2)" i18n-matTooltip>
|
||||
<button type="button"
|
||||
(click)="insertTitle(2)"
|
||||
matTooltip="Click to insert a title 2 section"
|
||||
matRipple
|
||||
i18n-matTooltip>
|
||||
H2
|
||||
</button>
|
||||
<button type="button" matTooltip="Click to insert a title 3 section" (click)="insertTitle(3)" i18n-matTooltip>
|
||||
<button type="button"
|
||||
(click)="insertTitle(3)"
|
||||
matTooltip="Click to insert a title 3 section"
|
||||
matRipple
|
||||
i18n-matTooltip>
|
||||
H3
|
||||
</button>
|
||||
<button type="button" matTooltip="Click to insert a picture" (click)="selectAPicture()" i18n-matTooltip>
|
||||
<mat-icon>image</mat-icon>
|
||||
</button>
|
||||
<button type="button" matTooltip="Click to insert a link" (click)="insertLink()" i18n-matTooltip>
|
||||
<button type="button"
|
||||
(click)="insertLink()"
|
||||
matTooltip="Click to insert a link"
|
||||
matRipple
|
||||
i18n-matTooltip>
|
||||
<mat-icon>link</mat-icon>
|
||||
</button>
|
||||
<button type="button" matTooltip="Click to insert a code block" (click)="displayCodeBlockDialog()" i18n-matTooltip>
|
||||
<button type="button"
|
||||
(click)="selectAPicture()"
|
||||
matTooltip="Click to insert a picture"
|
||||
matRipple
|
||||
i18n-matTooltip>
|
||||
<mat-icon>image</mat-icon>
|
||||
</button>
|
||||
<button type="button"
|
||||
(click)="displayCodeBlockDialog()"
|
||||
matTooltip="Click to insert a code block"
|
||||
matRipple
|
||||
i18n-matTooltip>
|
||||
<mat-icon>code</mat-icon>
|
||||
</button>
|
||||
<button type="button" disabled matTooltip="Click to display editor help" i18n-matTooltip>
|
||||
<button type="button"
|
||||
matTooltip="Click to display editor help"
|
||||
disabled
|
||||
matRipple
|
||||
i18n-matTooltip>
|
||||
<mat-icon>help</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
@@ -92,8 +120,12 @@
|
||||
</mat-tab>
|
||||
</mat-tab-group>
|
||||
<footer>
|
||||
<app-submit-button label="Save" [requestPending]="!!(isSaving$ | async)" i18n-label></app-submit-button>
|
||||
<button type="button" class="secondary" (click)="goPreviousLocation()" i18n>
|
||||
<app-submit-button [requestPending]="!!(isSaving$ | async)" i18n>Save</app-submit-button>
|
||||
<button type="button"
|
||||
class="cod-btn secondary"
|
||||
(click)="goPreviousLocation()"
|
||||
matRipple
|
||||
i18n>
|
||||
Cancel
|
||||
</button>
|
||||
</footer>
|
||||
|
||||
@@ -102,6 +102,11 @@
|
||||
|
||||
button {
|
||||
padding: 0;
|
||||
border-radius: 10em;
|
||||
border: none;
|
||||
background-color: #3f51b5;
|
||||
color: white;
|
||||
transition: background-color .2s ease-in-out;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
@@ -109,35 +114,16 @@
|
||||
height: 3em;
|
||||
box-shadow: 0 2px 5px 0 rgba(0,0,0,.16),0 2px 10px 0 rgba(0,0,0,.12);
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
button, a.button {
|
||||
padding: .8em 1.2em;
|
||||
border-radius: 10em;
|
||||
border: none;
|
||||
background-color: #3f51b5;
|
||||
color: white;
|
||||
transition: background-color .2s ease-in-out;
|
||||
|
||||
&:hover {
|
||||
background-color: #5b6ed8;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
background-color: #5f6aa6;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
&.secondary {
|
||||
color: #3f51b5;
|
||||
background-color: white;
|
||||
|
||||
&:hover {
|
||||
background-color: #f2f4ff;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
background-color: #5b6ed8;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
background-color: #5f6aa6;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import { CategoryService } from "../../core/service/category.service";
|
||||
import { SubmitButtonComponent } from "../submit-button/submit-button.component";
|
||||
import { PictureSelectionDialog } from "./picture-selection-dialog/picture-selection-dialog.component";
|
||||
import { PublicationEditionService } from "./publication-edition.service";
|
||||
import { MatRippleModule } from "@angular/material/core";
|
||||
|
||||
@Component({
|
||||
selector: 'app-publication-edition',
|
||||
@@ -26,6 +27,7 @@ import { PublicationEditionService } from "./publication-edition.service";
|
||||
MatDialogModule,
|
||||
MatIconModule,
|
||||
MatInputModule,
|
||||
MatRippleModule,
|
||||
MatProgressSpinnerModule,
|
||||
MatSelectModule,
|
||||
MatTabsModule,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<form [formGroup]="formGroup">
|
||||
<input name="search-query" placeholder="Search something..." formControlName="criteria" i18n-placeholder/>
|
||||
<button type="submit" (click)="searchPublications()">
|
||||
<button type="submit" (click)="searchPublications()" matRipple>
|
||||
<mat-icon>search</mat-icon>
|
||||
</button>
|
||||
</form>
|
||||
@@ -24,9 +24,10 @@
|
||||
border-radius: $borderRadiusValue;
|
||||
background-color: white;
|
||||
border: none;
|
||||
top: .4em;
|
||||
top: 0;
|
||||
right: 0;
|
||||
color: #aaaaaa;
|
||||
padding: .3em;
|
||||
|
||||
&:hover {
|
||||
background-color: #eee;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { HttpParams } from "@angular/common/http";
|
||||
import { Component, inject } from "@angular/core";
|
||||
import { FormBuilder, FormControl, ReactiveFormsModule, Validators } from "@angular/forms";
|
||||
import { MatRippleModule } from "@angular/material/core";
|
||||
import { MatIconModule } from "@angular/material/icon";
|
||||
import { Router } from "@angular/router";
|
||||
|
||||
@@ -11,8 +11,9 @@ import { Router } from "@angular/router";
|
||||
styleUrl: './publications-search-bar.component.scss',
|
||||
standalone: true,
|
||||
imports: [
|
||||
ReactiveFormsModule,
|
||||
MatIconModule
|
||||
MatIconModule,
|
||||
MatRippleModule,
|
||||
ReactiveFormsModule
|
||||
],
|
||||
providers: []
|
||||
})
|
||||
|
||||
@@ -6,7 +6,10 @@
|
||||
</div>
|
||||
<div class="sub-category-container {{category.isOpenned ? 'displayed' : ''}}">
|
||||
@for(subCategory of category.subCategories; track subCategory) {
|
||||
<a [routerLink]="['/publications']" [queryParams]="{'category-id': subCategory.id}" (click)="categoryClicked.emit()" class="sub-category">
|
||||
<a [routerLink]="['/publications']"
|
||||
[queryParams]="{'category-id': subCategory.id}"
|
||||
(click)="categoryClicked.emit()"
|
||||
class="sub-category">
|
||||
{{subCategory.name}}
|
||||
</a>
|
||||
}
|
||||
|
||||
@@ -8,8 +8,12 @@ import { RouterModule } from "@angular/router";
|
||||
@Component({
|
||||
selector: 'app-categories-menu',
|
||||
standalone: true,
|
||||
imports: [CommonModule, RouterModule, MatIconModule],
|
||||
templateUrl: './categories-menu.component.html',
|
||||
imports: [
|
||||
CommonModule,
|
||||
RouterModule,
|
||||
MatIconModule
|
||||
],
|
||||
styleUrl: './categories-menu.component.scss'
|
||||
})
|
||||
export class CategoriesMenuComponent implements OnInit {
|
||||
|
||||
@@ -4,7 +4,12 @@
|
||||
<img src="assets/images/codiki.png" alt="logo"/>
|
||||
Codiki
|
||||
</a>
|
||||
<button type="button" (click)="close()" matTooltip="Close the menu" i18n-matTooltip>
|
||||
<button type="button"
|
||||
(click)="close()"
|
||||
class="cod-btn icon"
|
||||
matTooltip="Close the menu"
|
||||
matRipple
|
||||
i18n-matTooltip>
|
||||
<mat-icon>close</mat-icon>
|
||||
</button>
|
||||
</h1>
|
||||
|
||||
@@ -41,24 +41,6 @@
|
||||
height: $imageSize;
|
||||
}
|
||||
}
|
||||
|
||||
button {
|
||||
border-radius: 10em;
|
||||
border: none;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 2.5em;
|
||||
height: 2.5em;
|
||||
color: white;
|
||||
background-color: #3f51b5;
|
||||
transition: background-color .2s ease-in-out;
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
background-color: #5c6bc0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
h2 {
|
||||
|
||||
@@ -3,13 +3,20 @@ import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { CategoriesMenuComponent } from './categories-menu/categories-menu.component';
|
||||
import { MatRippleModule } from '@angular/material/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-side-menu',
|
||||
standalone: true,
|
||||
imports: [CategoriesMenuComponent, MatIconModule, MatTooltipModule, RouterModule],
|
||||
templateUrl: './side-menu.component.html',
|
||||
styleUrl: './side-menu.component.scss'
|
||||
styleUrl: './side-menu.component.scss',
|
||||
imports: [
|
||||
CategoriesMenuComponent,
|
||||
MatIconModule,
|
||||
MatRippleModule,
|
||||
MatTooltipModule,
|
||||
RouterModule
|
||||
]
|
||||
})
|
||||
export class SideMenuComponent {
|
||||
isOpenned: boolean = false;
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
<button type="submit" [class]="color" [disabled]="disabled || requestPending" (click)="click.emit()">
|
||||
<button type="submit"
|
||||
class="cod-btn {{color}}"
|
||||
[disabled]="disabled || requestPending"
|
||||
(click)="click.emit()"
|
||||
matRipple>
|
||||
@if (requestPending) {
|
||||
<mat-spinner class="spinner {{color}}" [diameter]="25"></mat-spinner>
|
||||
}
|
||||
<span>
|
||||
{{ label }}
|
||||
<ng-content/>
|
||||
</span>
|
||||
</button>
|
||||
@@ -1,14 +1,18 @@
|
||||
import { CommonModule } from "@angular/common";
|
||||
import { Component, EventEmitter, Input, Output } from "@angular/core";
|
||||
import { MatRippleModule } from "@angular/material/core";
|
||||
import { MatProgressSpinnerModule } from "@angular/material/progress-spinner";
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'app-submit-button',
|
||||
standalone: true,
|
||||
imports: [MatProgressSpinnerModule, CommonModule],
|
||||
templateUrl: 'submit-button.component.html',
|
||||
styleUrl: 'submit-button.component.scss'
|
||||
styleUrl: 'submit-button.component.scss',
|
||||
imports: [
|
||||
CommonModule,
|
||||
MatRippleModule,
|
||||
MatProgressSpinnerModule
|
||||
]
|
||||
})
|
||||
export class SubmitButtonComponent {
|
||||
@Input() requestPending: boolean = false;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<form [formGroup]="loginForm" (submit)="performLogin()" ngNativeValidate>
|
||||
<form [formGroup]="loginForm" (submit)="performLogin()" class="cod-form card" ngNativeValidate>
|
||||
<h1 i18n>Login</h1>
|
||||
<div>
|
||||
<div class="form-field">
|
||||
<mat-icon>mail</mat-icon>
|
||||
<label for="email" i18n>
|
||||
Email address
|
||||
@@ -8,7 +8,7 @@
|
||||
</label>
|
||||
<input type="email" id="email" formControlName="email" autocomplete="email" required />
|
||||
</div>
|
||||
<div>
|
||||
<div class="form-field">
|
||||
<mat-icon>lock</mat-icon>
|
||||
<label for="password" i18n>
|
||||
Password
|
||||
@@ -16,8 +16,8 @@
|
||||
</label>
|
||||
<input type="password" id="password" formControlName="password" required />
|
||||
</div>
|
||||
<div class="actions">
|
||||
<button type="submit" i18n>Send</button>
|
||||
<a [routerLink]="['/signin']" i18n>Create an account</a>
|
||||
<div class="actions reversed">
|
||||
<app-submit-button [requestPending]="false" [disabled]="false" i18n>Send</app-submit-button>
|
||||
<a [routerLink]="['/signin']" class="cod-btn secondary" matRipple i18n>Create an account</a>
|
||||
</div>
|
||||
</form>
|
||||
@@ -4,79 +4,4 @@
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 1em;
|
||||
|
||||
form {
|
||||
width: 80%;
|
||||
max-width: 20em;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
gap: 1em;
|
||||
box-shadow: 0 2px 5px 0 rgba(0,0,0,.16),0 2px 10px 0 rgba(0,0,0,.12);
|
||||
border-radius: .5em;
|
||||
padding: 1em 1.5em;
|
||||
background-color: #ffffff;
|
||||
|
||||
h1 {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
div {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
gap: .1em;
|
||||
|
||||
mat-icon {
|
||||
position: absolute;
|
||||
top: 1.3em;
|
||||
left: .5em;
|
||||
color: #777;
|
||||
}
|
||||
|
||||
&.actions {
|
||||
flex-direction: row-reverse;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
a {
|
||||
color: #3f51b5;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
button, a.button {
|
||||
padding: .8em 1.2em;
|
||||
border-radius: 10em;
|
||||
border: none;
|
||||
background-color: #3f51b5;
|
||||
color: white;
|
||||
transition: background-color .2s ease-in-out;
|
||||
|
||||
&:hover {
|
||||
background-color: #5b6ed8;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
label {
|
||||
flex: 1;
|
||||
font-style: italic;
|
||||
padding-left: 1em;
|
||||
color: #777;
|
||||
|
||||
.required {
|
||||
color: red;
|
||||
}
|
||||
}
|
||||
|
||||
input {
|
||||
flex: 1;
|
||||
background-color: #eeeeee;
|
||||
border: none;
|
||||
border-radius: 10em;
|
||||
padding: 1em 1em 1em 3em;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,13 +5,21 @@ import { Subscription, debounceTime, map } from 'rxjs';
|
||||
import { LoginService } from './login.service';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { SubmitButtonComponent } from "../../components/submit-button/submit-button.component";
|
||||
import { MatRippleModule } from '@angular/material/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-login',
|
||||
standalone: true,
|
||||
templateUrl: './login.component.html',
|
||||
styleUrl: './login.component.scss',
|
||||
imports: [ReactiveFormsModule, MatIconModule, RouterModule],
|
||||
imports: [
|
||||
MatIconModule,
|
||||
MatRippleModule,
|
||||
ReactiveFormsModule,
|
||||
RouterModule,
|
||||
SubmitButtonComponent
|
||||
],
|
||||
providers: [LoginService, MatSnackBarModule]
|
||||
})
|
||||
export class LoginComponent implements OnInit, OnDestroy {
|
||||
|
||||
@@ -60,18 +60,24 @@ export class LoginService {
|
||||
performLogin(): void {
|
||||
const state = this.state;
|
||||
|
||||
// Check state is valid
|
||||
if (this.isStateValid(state)) {
|
||||
this.userRestService
|
||||
.login(state.request)
|
||||
.then((response) => {
|
||||
this.authenticationService.authenticate(response.accessToken, response.refreshToken);
|
||||
this.snackBar.open($localize`Authentication succeeded!`, $localize`Close`, { duration: 5000 });
|
||||
this.router.navigate(['/home']);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
this.snackBar.open($localize`Authentication failed.`, $localize`Close`, { duration: 5000 });
|
||||
});
|
||||
} else {
|
||||
this.snackBar.open($localize`Please, fill the inputs before send.`, $localize`Close`, { duration: 5000 });
|
||||
}
|
||||
}
|
||||
|
||||
this.userRestService
|
||||
.login(state.request)
|
||||
.then((response) => {
|
||||
this.authenticationService.authenticate(response.accessToken, response.refreshToken);
|
||||
this.snackBar.open($localize`Authentication succeeded!`, $localize`Close`, { duration: 5000 });
|
||||
this.router.navigate(['/home']);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
this.snackBar.open($localize`Authentication failed.`, $localize`Close`, { duration: 5000 });
|
||||
});
|
||||
isStateValid(state: LoginState): boolean {
|
||||
return !!state.request.email?.trim().length && !!state.request.password?.length;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
class="new-publication"
|
||||
matTooltip="Add a new publication"
|
||||
matTooltipPosition="left"
|
||||
matRipple
|
||||
i18n-matTooltip>
|
||||
+
|
||||
</a>
|
||||
|
||||
@@ -7,6 +7,7 @@ import { Publication } from "../../core/rest-services/publications/model/publica
|
||||
import { CommonModule } from "@angular/common";
|
||||
import { RouterModule } from "@angular/router";
|
||||
import { MatTooltipModule } from "@angular/material/tooltip";
|
||||
import { MatRippleModule } from "@angular/material/core";
|
||||
|
||||
|
||||
@Component({
|
||||
@@ -17,8 +18,9 @@ import { MatTooltipModule } from "@angular/material/tooltip";
|
||||
imports: [
|
||||
CommonModule,
|
||||
MatProgressSpinnerModule,
|
||||
PublicationListComponent,
|
||||
MatRippleModule,
|
||||
MatTooltipModule,
|
||||
PublicationListComponent,
|
||||
RouterModule
|
||||
],
|
||||
providers: [MyPublicationsService]
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
<a [routerLink]="['edit']"
|
||||
class="button action"
|
||||
matTooltip="Click to edit the publication"
|
||||
matRipple
|
||||
i18n-matTooltip>
|
||||
<mat-icon>edit</mat-icon>
|
||||
</a>
|
||||
@@ -33,6 +34,7 @@
|
||||
(click)="deletePublication()"
|
||||
matTooltip="Click to delete the publication"
|
||||
matTooltipPosition="left"
|
||||
matRipple
|
||||
i18n-matTooltip>
|
||||
<mat-icon>delete</mat-icon>
|
||||
Delete
|
||||
|
||||
@@ -1,25 +1,33 @@
|
||||
import { Component, OnDestroy, OnInit, inject } from '@angular/core';
|
||||
import { PublicationRestService } from '../../core/rest-services/publications/publication.rest-service';
|
||||
import { ActivatedRoute, Router, RouterModule } from '@angular/router';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { Publication } from '../../core/rest-services/publications/model/publication';
|
||||
import { MatSnackBar } from '@angular/material/snack-bar';
|
||||
import { CommonModule, Location } from '@angular/common';
|
||||
import { MatProgressSpinner } from '@angular/material/progress-spinner';
|
||||
import { MatTooltip, MatTooltipModule } from '@angular/material/tooltip';
|
||||
import { MatIcon } from '@angular/material/icon';
|
||||
import { AuthenticationService } from '../../core/service/authentication.service';
|
||||
import { Component, OnDestroy, OnInit, inject } from '@angular/core';
|
||||
import { MatRippleModule } from '@angular/material/core';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { MatIcon } from '@angular/material/icon';
|
||||
import { MatProgressSpinner } from '@angular/material/progress-spinner';
|
||||
import { MatSnackBar } from '@angular/material/snack-bar';
|
||||
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||
import { ActivatedRoute, RouterModule } from '@angular/router';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { ConfirmationDialog } from '../../components/confirmation-dialog/confirmation-dialog.component';
|
||||
import { Publication } from '../../core/rest-services/publications/model/publication';
|
||||
import { PublicationRestService } from '../../core/rest-services/publications/publication.rest-service';
|
||||
import { AuthenticationService } from '../../core/service/authentication.service';
|
||||
|
||||
declare let Prism: any;
|
||||
|
||||
@Component({
|
||||
selector: 'app-publication',
|
||||
standalone: true,
|
||||
imports: [CommonModule, MatProgressSpinner, MatTooltip, RouterModule, MatIcon, MatTooltipModule],
|
||||
templateUrl: './publication.component.html',
|
||||
styleUrl: './publication.component.scss'
|
||||
styleUrl: './publication.component.scss',
|
||||
imports: [
|
||||
CommonModule,
|
||||
MatIcon,
|
||||
MatRippleModule,
|
||||
MatProgressSpinner,
|
||||
MatTooltipModule,
|
||||
RouterModule
|
||||
]
|
||||
})
|
||||
export class PublicationComponent implements OnInit, OnDestroy {
|
||||
private readonly activatedRoute = inject(ActivatedRoute);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<form [formGroup]="signinForm" (submit)="performSignin()" ngNativeValidate>
|
||||
<form [formGroup]="signinForm" (submit)="performSignin()" class="cod-form card" ngNativeValidate>
|
||||
<h1 i18n>Signin</h1>
|
||||
<div>
|
||||
<div class="form-field">
|
||||
<mat-icon>person</mat-icon>
|
||||
<label for="pseudo" i18n>
|
||||
Pseudo
|
||||
@@ -8,7 +8,7 @@
|
||||
</label>
|
||||
<input type="text" id="pseudo" formControlName="pseudo" autocomplete="pseudo" required />
|
||||
</div>
|
||||
<div>
|
||||
<div class="form-field">
|
||||
<mat-icon>mail</mat-icon>
|
||||
<label for="email" i18n>
|
||||
Email address
|
||||
@@ -16,7 +16,7 @@
|
||||
</label>
|
||||
<input type="email" id="email" formControlName="email" autocomplete="email" required />
|
||||
</div>
|
||||
<div>
|
||||
<div class="form-field">
|
||||
<mat-icon>lock</mat-icon>
|
||||
<label for="password" i18n>
|
||||
Password
|
||||
@@ -24,7 +24,7 @@
|
||||
</label>
|
||||
<input type="password" id="password" formControlName="password" required />
|
||||
</div>
|
||||
<div>
|
||||
<div class="form-field">
|
||||
<mat-icon>lock</mat-icon>
|
||||
<label for="confirm-password" i18n>
|
||||
Confirm password
|
||||
@@ -32,8 +32,8 @@
|
||||
</label>
|
||||
<input type="password" id="confirm-password" formControlName="confirmPassword" required />
|
||||
</div>
|
||||
<div class="actions">
|
||||
<button type="submit" i18n>Send</button>
|
||||
<a [routerLink]="['/login']" i18n>I already have an account</a>
|
||||
<div class="actions reversed">
|
||||
<app-submit-button [requestPending]="false" [disabled]="false" i18n>Send</app-submit-button>
|
||||
<a [routerLink]="['/login']" class="cod-btn secondary" matRipple i18n>I already have an account</a>
|
||||
</div>
|
||||
</form>
|
||||
@@ -4,79 +4,4 @@
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 1em;
|
||||
|
||||
form {
|
||||
width: 80%;
|
||||
max-width: 20em;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
gap: 1em;
|
||||
box-shadow: 0 2px 5px 0 rgba(0,0,0,.16),0 2px 10px 0 rgba(0,0,0,.12);
|
||||
border-radius: .5em;
|
||||
padding: 1em 1.5em;
|
||||
background-color: #ffffff;
|
||||
|
||||
h1 {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
div {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
gap: .1em;
|
||||
|
||||
mat-icon {
|
||||
position: absolute;
|
||||
top: 1.3em;
|
||||
left: .5em;
|
||||
color: #777;
|
||||
}
|
||||
|
||||
&.actions {
|
||||
flex-direction: row-reverse;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
button {
|
||||
padding: .8em 1.2em;
|
||||
border-radius: 10em;
|
||||
border: none;
|
||||
background-color: #3f51b5;
|
||||
color: white;
|
||||
transition: background-color .2s ease-in-out;
|
||||
|
||||
&:hover {
|
||||
background-color: #5b6ed8;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
a {
|
||||
color: #3f51b5;
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
|
||||
label {
|
||||
flex: 1;
|
||||
font-style: italic;
|
||||
padding-left: 1em;
|
||||
color: #777;
|
||||
|
||||
.required {
|
||||
color: red;
|
||||
}
|
||||
}
|
||||
|
||||
input {
|
||||
flex: 1;
|
||||
background-color: #eeeeee;
|
||||
border: none;
|
||||
border-radius: 10em;
|
||||
padding: 1em 1em 1em 3em;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,13 +6,21 @@ import { Subscription, debounceTime, distinctUntilChanged, map } from 'rxjs';
|
||||
import { SigninService } from './signin.service';
|
||||
import { LoginService } from '../login/login.service';
|
||||
import { FormError } from '../../core/model/FormError';
|
||||
import { SubmitButtonComponent } from "../../components/submit-button/submit-button.component";
|
||||
import { MatRippleModule } from '@angular/material/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-signin',
|
||||
standalone: true,
|
||||
imports: [ReactiveFormsModule, MatIconModule, RouterModule],
|
||||
templateUrl: './signin.component.html',
|
||||
styleUrl: './signin.component.scss',
|
||||
imports: [
|
||||
MatIconModule,
|
||||
MatRippleModule,
|
||||
ReactiveFormsModule,
|
||||
RouterModule,
|
||||
SubmitButtonComponent
|
||||
],
|
||||
providers: [SigninService, LoginService]
|
||||
})
|
||||
export class SigninComponent implements OnInit, OnDestroy {
|
||||
|
||||
43
frontend/src/design_system/button.scss
Normal file
43
frontend/src/design_system/button.scss
Normal file
@@ -0,0 +1,43 @@
|
||||
button.cod-btn, a.cod-btn {
|
||||
padding: .8em 1.2em;
|
||||
border-radius: 10em;
|
||||
border: none;
|
||||
background-color: #3f51b5;
|
||||
color: white;
|
||||
transition: background-color .2s ease-in-out;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
&:hover {
|
||||
background-color: #5b6ed8;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&.secondary {
|
||||
color: #3f51b5;
|
||||
background-color: white;
|
||||
|
||||
&:hover {
|
||||
background-color: #f2f4ff;
|
||||
}
|
||||
}
|
||||
|
||||
&.icon {
|
||||
$buttonSize: 2.5em;
|
||||
width: $buttonSize;
|
||||
height: $buttonSize;
|
||||
padding: 0;
|
||||
|
||||
&.close {
|
||||
position: absolute;
|
||||
top: 1em;
|
||||
right: 1em;
|
||||
color: black;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
a.cod-btn {
|
||||
text-decoration: none;
|
||||
}
|
||||
64
frontend/src/design_system/form.scss
Normal file
64
frontend/src/design_system/form.scss
Normal file
@@ -0,0 +1,64 @@
|
||||
form.cod-form {
|
||||
&.card {
|
||||
width: 80%;
|
||||
max-width: 20em;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
gap: 1em;
|
||||
box-shadow: 0 2px 5px 0 rgba(0,0,0,.16),0 2px 10px 0 rgba(0,0,0,.12);
|
||||
border-radius: .5em;
|
||||
padding: 1em 1.5em;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
div {
|
||||
&.actions {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
&.reversed {
|
||||
flex-direction: row-reverse;
|
||||
}
|
||||
}
|
||||
|
||||
&.form-field {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
gap: .1em;
|
||||
|
||||
mat-icon {
|
||||
position: absolute;
|
||||
top: 1.3em;
|
||||
left: .5em;
|
||||
color: #777;
|
||||
}
|
||||
|
||||
label {
|
||||
flex: 1;
|
||||
font-style: italic;
|
||||
padding-left: 1em;
|
||||
color: #777;
|
||||
|
||||
.required {
|
||||
color: red;
|
||||
}
|
||||
}
|
||||
|
||||
input {
|
||||
flex: 1;
|
||||
background-color: #eeeeee;
|
||||
border: none;
|
||||
border-radius: 10em;
|
||||
padding: 1em 1em 1em 3em;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
2
frontend/src/design_system/index.scss
Normal file
2
frontend/src/design_system/index.scss
Normal file
@@ -0,0 +1,2 @@
|
||||
@use './button.scss';
|
||||
@use './form.scss';
|
||||
@@ -60,6 +60,7 @@
|
||||
"2308975396733519902": "Créer un compte",
|
||||
"1037765878727976611": "Connexion réussie",
|
||||
"6034686865111167926": "Une erreur est survenue lors de la connexion.",
|
||||
"5304730975301536612": "Veuillez renseigner tous les champs avant de valider.",
|
||||
"1041423751558601074": "Vos publications",
|
||||
"5463894166935799864": "Rédiger une nouvelle publication",
|
||||
"1519054954638405159": "Chargement de la liste de vos publications...",
|
||||
@@ -90,4 +91,4 @@
|
||||
"3461230574295546047": "J'ai déjà un compte",
|
||||
"5052944271008222026": "Les mots de passe saisis sont différents."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,6 +60,7 @@
|
||||
"2308975396733519902": "Create an account",
|
||||
"1037765878727976611": "Authentication succeeded!",
|
||||
"6034686865111167926": "Authentication failed.",
|
||||
"5304730975301536612": "Please, fill the inputs before send.",
|
||||
"1041423751558601074": "Your publications",
|
||||
"5463894166935799864": "Add a new publication",
|
||||
"1519054954638405159": "Publication loading...",
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/* You can add global styles to this file, and also import other style files */
|
||||
@use './design_system/index.scss';
|
||||
|
||||
html, body { height: 100%; }
|
||||
body {
|
||||
|
||||
Reference in New Issue
Block a user