Compare commits
1 Commits
Author | SHA1 | Date |
---|---|---|
|
e52caf08c8 | 8 months ago |
@ -1,30 +0,0 @@
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: Deploiement
|
||||
|
||||
|
||||
trigger:
|
||||
event:
|
||||
- push
|
||||
|
||||
steps:
|
||||
- name: docker-push
|
||||
image: plugins/docker
|
||||
settings:
|
||||
dockerfile: docker/Dockerfile
|
||||
context: .
|
||||
registry: hub.codefirst.iut.uca.fr
|
||||
mirror: https://proxy.iut.uca.fr:8443
|
||||
repo: hub.codefirst.iut.uca.fr/ludovic.castiglia/angular_minigame
|
||||
username:
|
||||
from_secret: SECRET_REGISTRY_USERNAME
|
||||
password:
|
||||
from_secret: SECRET_REGISTRY_PASSWORD
|
||||
|
||||
- name: deploy-container
|
||||
image: hub.codefirst.iut.uca.fr/thomas.bellembois/codefirst-dockerproxy-clientdrone:latest
|
||||
environment:
|
||||
IMAGENAME: hub.codefirst.iut.uca.fr/ludovic.castiglia/angular_minigame:latest
|
||||
CONTAINERNAME: sudoku
|
||||
COMMAND: create
|
||||
OVERWRITE: true
|
@ -1,4 +0,0 @@
|
||||
<Files *>
|
||||
Order Allow,Deny
|
||||
Deny from All
|
||||
</Files>
|
@ -1,13 +0,0 @@
|
||||
FROM node:alpine
|
||||
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
COPY . /usr/src/app
|
||||
|
||||
RUN npm install -g @angular/cli
|
||||
|
||||
RUN npm install
|
||||
|
||||
EXPOSE 80
|
||||
|
||||
CMD ["ng", "serve", "--host", "0.0.0.0", "--port", "80"]
|
@ -1,3 +1,3 @@
|
||||
<app-book-menu></app-book-menu>
|
||||
<!-- <app-book-menu></app-book-menu> -->
|
||||
|
||||
<router-outlet (activate)="onActivate($event)"></router-outlet>
|
@ -1,17 +1,21 @@
|
||||
import { Routes } from '@angular/router';
|
||||
import { BookListComponent } from './components/book-list/book-list.component';
|
||||
import { BookFormComponent } from './components/book-form/book-form.component';
|
||||
import { BookDetailComponent } from './components/book-detail/book-detail.component';
|
||||
import { LoginComponent } from './components/login/login.component';
|
||||
import { UserListComponent } from './components/user-list/user-list.component';
|
||||
import { UserDetailComponent } from './components/user-detail/user-detail.component';
|
||||
import { SudokuComponent } from './components/sudoku/sudoku.component';
|
||||
import { DifficultySelectorComponent } from './components/difficulty-selector/difficulty-selector.component'
|
||||
import { UserAccueilComponent } from './components/user-accueil/user-accueil.component';
|
||||
|
||||
export const routes: Routes = [
|
||||
{ path: '', component: LoginComponent },
|
||||
{ path: 'accueil', component: UserAccueilComponent },
|
||||
{ path: 'books', component: BookListComponent },
|
||||
{ path: 'book/add', component: BookFormComponent },
|
||||
{ path: 'book/:id', component: BookDetailComponent },
|
||||
{ path: 'users', component: UserListComponent },
|
||||
{ path: 'accueil', component: UserAccueilComponent },
|
||||
{ path: 'user/:id', component: UserDetailComponent },
|
||||
{ path: 'sudoku', component: DifficultySelectorComponent },
|
||||
{ path: 'sudoku/:difficulty', component: SudokuComponent },
|
||||
{ path: '**', redirectTo: '', pathMatch: 'full' }
|
||||
];
|
||||
|
@ -0,0 +1,12 @@
|
||||
<div *ngIf="selectedBook">
|
||||
<h2>{{selectedBook.title | uppercase}}</h2>
|
||||
<div><span>id: </span>{{selectedBook.id}}</div>
|
||||
<div>
|
||||
<label for="book-author">Auteur : </label>
|
||||
{{ selectedBook.author }}
|
||||
</div>
|
||||
<div>
|
||||
<label for="book-publicationDate">Date de publication : </label>
|
||||
{{ selectedBook.publicationDate | date: 'EEEE d MMMM y' }}
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,25 @@
|
||||
import { Component} from '@angular/core';
|
||||
import { UpperCasePipe, DatePipe, NgIf} from '@angular/common';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
|
||||
import { Book } from '../../models/book.model';
|
||||
import { BookService } from '../../services/book-service';
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
selector: 'app-book-detail',
|
||||
imports: [DatePipe, UpperCasePipe, NgIf],
|
||||
templateUrl: './book-detail.component.html',
|
||||
styles: ``
|
||||
})
|
||||
export class BookDetailComponent {
|
||||
selectedBook!: Book | undefined;
|
||||
|
||||
constructor(protected bookService: BookService, private activatedRoute: ActivatedRoute) {}
|
||||
|
||||
ngOnInit(){
|
||||
const id = this.activatedRoute.snapshot.params['id'];
|
||||
this.selectedBook = this.bookService.getBookById(id);
|
||||
console.log(this.selectedBook);
|
||||
}
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
<section>
|
||||
<h2>Add book form</h2>
|
||||
|
||||
<form [formGroup]="bookForm">
|
||||
<div>
|
||||
<mat-form-field class="full-width">
|
||||
<mat-label>Title</mat-label>
|
||||
<input matInput type="text" formControlName="title" />
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<mat-form-field class="full-width">
|
||||
<mat-label>Author</mat-label>
|
||||
<input matInput type="text" formControlName="author" />
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<mat-form-field class="full-width">
|
||||
<mat-label>Publication date</mat-label>
|
||||
<input matInput [matDatepicker]="picker" type="text" formControlName="publicationDate" />
|
||||
<mat-datepicker-toggle matIconSuffix [for]="picker"></mat-datepicker-toggle>
|
||||
<mat-datepicker #picker></mat-datepicker>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<button mat-flat-button color="primary" type="button" (click)="addBook()">Add</button>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
@ -0,0 +1,49 @@
|
||||
import { Component, EventEmitter, Output } from '@angular/core';
|
||||
|
||||
import { FormControl, FormGroup, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms';
|
||||
import { Book } from '../../models/book.model';
|
||||
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatNativeDateModule } from '@angular/material/core';
|
||||
import { MatDatepickerModule } from '@angular/material/datepicker';
|
||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||
import { MatInputModule } from '@angular/material/input';
|
||||
import { MatMenuModule } from '@angular/material/menu';
|
||||
|
||||
@Component({
|
||||
selector: 'app-book-form',
|
||||
standalone: true,
|
||||
imports: [
|
||||
MatFormFieldModule,
|
||||
MatInputModule,
|
||||
MatButtonModule,
|
||||
MatMenuModule,
|
||||
MatDatepickerModule,
|
||||
MatNativeDateModule,
|
||||
FormsModule,
|
||||
ReactiveFormsModule
|
||||
],
|
||||
templateUrl: './book-form.component.html'
|
||||
})
|
||||
export class BookFormComponent {
|
||||
@Output() addBookEvent = new EventEmitter<Book>();
|
||||
|
||||
book: Book = { id: 0, title: '', author: '', publicationDate: new Date() }
|
||||
bookForm: FormGroup = new FormGroup({
|
||||
title: new FormControl(this.book.title, Validators.required),
|
||||
author: new FormControl(this.book.author, Validators.required),
|
||||
publicationDate: new FormControl(this.book.publicationDate, Validators.required)
|
||||
});
|
||||
|
||||
addBook() {
|
||||
if (this.bookForm.invalid) {
|
||||
console.log("ERREUR");
|
||||
return;
|
||||
}
|
||||
|
||||
this.book = this.bookForm.value;
|
||||
|
||||
this.addBookEvent.emit(this.book);
|
||||
this.bookForm.reset();
|
||||
}
|
||||
}
|
@ -0,0 +1 @@
|
||||
<h1>Bienvenue sur la page d'accueil du Book Shop</h1>
|
@ -0,0 +1,12 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-book-home',
|
||||
standalone: true,
|
||||
imports: [],
|
||||
templateUrl: './book-home.component.html',
|
||||
styles: ``
|
||||
})
|
||||
export class BookHomeComponent {
|
||||
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
<h2>Book list</h2>
|
||||
|
||||
<ul>
|
||||
<li *ngFor="let book of books">
|
||||
<a routerLink="/book/{{ book.id }}">{{ book.title }}</a>
|
||||
</li>
|
||||
</ul>
|
@ -0,0 +1,23 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { NgFor, DatePipe } from '@angular/common';
|
||||
|
||||
import { Book } from '../../models/book.model';
|
||||
import { BookService } from '../../services/book-service'
|
||||
|
||||
@Component({
|
||||
selector: 'app-book-list',
|
||||
standalone: true,
|
||||
imports: [NgFor, DatePipe, RouterModule],
|
||||
templateUrl: './book-list.component.html'
|
||||
})
|
||||
export class BookListComponent {
|
||||
books: Book[] = [];
|
||||
|
||||
constructor(protected bookService: BookService){
|
||||
}
|
||||
|
||||
ngOnInit(){
|
||||
this.books = this.bookService.getAll();
|
||||
}
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
section {
|
||||
min-height: 50%;
|
||||
min-width: 50%;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%,-50%);
|
||||
border: 1px solid #000;
|
||||
border-radius: 50px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
section .btn {
|
||||
position: absolute;
|
||||
top: 0%;
|
||||
height: 100%;
|
||||
width: calc(100% - 1em);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-evenly;
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
<section>
|
||||
<h1>
|
||||
Choisir une difficulté:
|
||||
</h1>
|
||||
|
||||
<div class="btn">
|
||||
<button routerLink="/sudoku/easy" mat-flat-button color="primary">easy</button>
|
||||
<button routerLink="/sudoku/medium" mat-flat-button color="primary">medium</button>
|
||||
<button routerLink="/sudoku/hard" mat-flat-button color="primary">hard</button>
|
||||
</div>
|
||||
</section>
|
@ -1,23 +0,0 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { DifficultySelectorComponent } from './difficulty-selector.component';
|
||||
|
||||
describe('DifficultySelectorComponent', () => {
|
||||
let component: DifficultySelectorComponent;
|
||||
let fixture: ComponentFixture<DifficultySelectorComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [DifficultySelectorComponent]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(DifficultySelectorComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
@ -1,14 +0,0 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
|
||||
@Component({
|
||||
selector: 'app-difficulty-selector',
|
||||
standalone: true,
|
||||
imports: [RouterModule,MatButtonModule],
|
||||
templateUrl: './difficulty-selector.component.html',
|
||||
styleUrl: './difficulty-selector.component.css'
|
||||
})
|
||||
export class DifficultySelectorComponent {
|
||||
|
||||
}
|
@ -1,42 +1,21 @@
|
||||
<!-- <app-book-menu></app-book-menu> -->
|
||||
<app-book-menu></app-book-menu>
|
||||
|
||||
<section class="main">
|
||||
<p>sudoku works!</p>
|
||||
|
||||
<div class="haut">
|
||||
<div class="grid">
|
||||
<div *ngFor="let row of grille; let x = index" class="subgrid sub{{x}}">
|
||||
<div *ngFor="let cell of row; let y = index" class="case x{{x}} y{{y}}">
|
||||
<input *ngIf="cell != 0" type="number" value="{{cell}}" class="cell" max="9" min="0" id="xy{{x}}{{y}}" (change)="key()" (click)="colorSameRowCol(y,x,$event)">
|
||||
<input *ngIf="cell == 0" type="number" value="" class="cell" max="9" min="0" id="xy{{x}}{{y}}" (click)="colorSameRowCol(y,x,$event)" (change)="key()">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="button">
|
||||
<button (click)="publish()">
|
||||
soumettre
|
||||
</button>
|
||||
|
||||
<button (click)="corriger()">
|
||||
verrifier
|
||||
</button>
|
||||
|
||||
<p>nombre d'indice: {{nbIndice}}</p>
|
||||
<div class="grille">
|
||||
<div *ngFor="let row of grille" class="column">
|
||||
<div *ngFor="let cell of row" class="row">
|
||||
<input *ngIf="cell != 0" type="number" value="{{cell}}" class="cell" max="9" min="0">
|
||||
<input *ngIf="cell == 0" type="number" value="" class="cell" max="9" min="0">
|
||||
</div>
|
||||
</div>
|
||||
<div class="bas">
|
||||
<button *ngFor="let obj of [].constructor(9); let i = index" (click)="addNumber(i+1)">{{i+1}}<div id="btn{{i+1}}">{{nbEachNumber[i]}}</div></button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</section>
|
||||
<button (click)="publish()">
|
||||
valider la grille
|
||||
</button>
|
||||
|
||||
<section *ngIf="haveWin" class="winpopup">
|
||||
<h2>Vous avez gagné !</h2>
|
||||
<div class="menu">
|
||||
<button routerLink="/">
|
||||
retour à la page d'accueil
|
||||
</button>
|
||||
<button routerLink="/sudoku/">
|
||||
nouvelle partie
|
||||
</button>
|
||||
</div>
|
||||
</section>
|
||||
<button (click)="corriger()">
|
||||
corriger la grille
|
||||
</button>
|
@ -1,16 +1,22 @@
|
||||
<app-book-menu></app-book-menu>
|
||||
|
||||
<h2>{{formattedDate}}</h2>
|
||||
|
||||
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th *ngFor="let d of day">
|
||||
{{ d }}
|
||||
</th>
|
||||
<th>LUN</th>
|
||||
<th>MAR</th>
|
||||
<th>MER</th>
|
||||
<th>JEU</th>
|
||||
<th>VEN</th>
|
||||
<th>SAM</th>
|
||||
<th>DIM</th>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th *ngFor="let streak of streaks">
|
||||
{{ streak }}
|
||||
<th *ngFor="let azerty of streaks">
|
||||
{{ azerty }}
|
||||
</th>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
@ -1,40 +0,0 @@
|
||||
section {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%,-50%);
|
||||
min-height: 50vh;
|
||||
min-width: 50vw;
|
||||
}
|
||||
|
||||
thead, tr {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
thead {
|
||||
border-bottom: 1px solid #000;
|
||||
}
|
||||
|
||||
th, td {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
tbody {
|
||||
width: 100%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.pagination {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.pagination > * {
|
||||
margin: 20px;
|
||||
}
|
@ -1,29 +1,27 @@
|
||||
<!-- <app-book-menu></app-book-menu> -->
|
||||
<app-book-menu></app-book-menu>
|
||||
|
||||
<section>
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">Pseudo</th>
|
||||
<th scope="col" (click)="changeWatchedvar('nbPts')">Nombre de points</th>
|
||||
<th scope="col" (click)="changeWatchedvar('streak')">Streak</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngFor="let user of users">
|
||||
<td>{{user.login}}</td>
|
||||
<td>{{user.points}}</td>
|
||||
<td>{{user.streak}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<h2>User list</h2>
|
||||
|
||||
<div class="pagination">
|
||||
<button (click)="loadPage(-1)">
|
||||
<
|
||||
</button>
|
||||
<p>{{nbPage}}/{{userService.getNbPage()}}</p>
|
||||
<button (click)="loadPage(1)">
|
||||
>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</section>
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">Pseudo</th>
|
||||
<th scope="col" (click)="changeWatchedvar('nbPts')">Nombre de points</th>
|
||||
<th scope="col" (click)="changeWatchedvar('streak')">Streak</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngFor="let user of users">
|
||||
<td >{{user.login}}</td>
|
||||
<td>{{user.points}}</td>
|
||||
<td>{{user.streak}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<br>
|
||||
<button (click)="loadPage(-1)">
|
||||
<
|
||||
</button>
|
||||
<button (click)="loadPage(1)">
|
||||
>
|
||||
</button>
|
@ -1,33 +0,0 @@
|
||||
nav[mat-tab-nav-bar] {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
background-color: #333;
|
||||
padding: 10px 0
|
||||
}
|
||||
|
||||
mat-tab-link, button[mat-button] {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
color: white;
|
||||
background-color: #444;
|
||||
border: none;
|
||||
padding: 15px;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s;
|
||||
}
|
||||
|
||||
mat-tab-link:hover, button[mat-button]:hover {
|
||||
background-color: #555;
|
||||
}
|
||||
|
||||
a[mat-menu-item] {
|
||||
text-align: center;
|
||||
padding: 10px;
|
||||
display: block;
|
||||
color: #111;
|
||||
}
|
||||
|
||||
a[mat-menu-item]:hover {
|
||||
background-color: #555;
|
||||
}
|
||||
|
@ -0,0 +1,11 @@
|
||||
import { Book } from "../models/book.model";
|
||||
|
||||
export const BOOKS: Book[] = [
|
||||
{ id: 1, title: 'The Lord of the Rings - The Fellowship of the Ring', author: 'J.R.R. Tolkien', publicationDate: new Date('07/29/1954') },
|
||||
{ id: 2, title: 'The Lord of the Rings - The Two Towers', author: 'J.R.R. Tolkien', publicationDate: new Date('11/11/1954') },
|
||||
{ id: 3, title: 'The Lord of the Rings - The Return of the King', author: 'J.R.R. Tolkien', publicationDate: new Date('10/20/1955') },
|
||||
{ id: 4, title: 'Dune', author: 'Frank Herbert', publicationDate: new Date('1965') },
|
||||
{ id: 5, title: 'Dune Messiah', author: 'Frank Herbert', publicationDate: new Date('1969') },
|
||||
{ id: 6, title: 'It', author: 'Stephen King', publicationDate: new Date('09/15/1986') },
|
||||
{ id: 7, title: 'Do Androids Dream of Electric Sheep?', author: 'Philip K. Dick', publicationDate: new Date('1968') }
|
||||
];
|
@ -0,0 +1,50 @@
|
||||
import { HttpClient, HttpErrorResponse } from '@angular/common/http';
|
||||
import { Injectable } from "@angular/core";
|
||||
import { BOOKS } from "../datas/books.stub";
|
||||
import { Book } from "../models/book.model";
|
||||
|
||||
@Injectable()
|
||||
export class BookService {
|
||||
private books: Book[];
|
||||
private readonly bookApiUrl = 'https://66e8848bb17821a9d9dcf68c.mockapi.io/books';
|
||||
|
||||
public constructor(private http: HttpClient){
|
||||
this.books = BOOKS;
|
||||
|
||||
this.http.get<Book[]>(this.bookApiUrl).subscribe(books => {
|
||||
books.forEach(b => {
|
||||
this.addBookToLocal(b);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public getAll(): Book[]{
|
||||
return this.books;
|
||||
}
|
||||
|
||||
public getBookById(id: number): Book | undefined{
|
||||
return this.books.find(b => b.id === id);
|
||||
}
|
||||
|
||||
public addBook(book: Book): void{
|
||||
this.addBookToLocal(book);
|
||||
this.addBookToApi(book);
|
||||
}
|
||||
|
||||
private addBookToLocal(book: Book): void{
|
||||
//console.log('addBookToLocal', book);
|
||||
if(book.id === 0){
|
||||
book.id = Math.max(...this.books.map(b => b.id)) + 1;
|
||||
}
|
||||
|
||||
const existedBook = this.books.find(b => b.title === book.title || b.id === Number(book.id));
|
||||
if(existedBook)
|
||||
return;
|
||||
|
||||
this.books.push(book);
|
||||
}
|
||||
|
||||
private addBookToApi(book: Book): void{
|
||||
this.http.post<Book>(this.bookApiUrl, book).subscribe();
|
||||
}
|
||||
}
|
Loading…
Reference in new issue