Add the version revisions system.

This commit is contained in:
2018-09-02 22:46:36 +02:00
parent 1d6b0bb348
commit 48dfaefa0c
14 changed files with 315 additions and 9 deletions

View File

@@ -0,0 +1,43 @@
package org.codiki.core.entities.persistence;
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
/**
* Entity which represents a version for the version revisions panel.
*
* @author florian
*
*/
@Entity
@Table(name="version")
public class Version implements Serializable {
private static final long serialVersionUID = -8803744005903941330L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String number;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
}

View File

@@ -0,0 +1,52 @@
package org.codiki.core.entities.persistence;
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
@Entity
@Table(name="version_revision")
public class VersionRevision implements Serializable {
private static final long serialVersionUID = 1837590467941917225L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String text;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "version_id")
private Version version;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public Version getVersion() {
return version;
}
public void setVersion(Version version) {
this.version = version;
}
}

View File

@@ -0,0 +1,16 @@
package org.codiki.core.repositories;
import java.util.Optional;
import org.codiki.core.entities.persistence.Version;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface VersionRepository extends CrudRepository<Version, Long> {
@Query("SELECT v FROM Version v ORDER BY v.number DESC")
Iterable<Version> findAllOrderByNumber();
Optional<Version> findByNumber(String pNumber);
}

View File

@@ -0,0 +1,16 @@
package org.codiki.core.repositories;
import java.util.List;
import org.codiki.core.entities.persistence.VersionRevision;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
@Repository
public interface VersionRevisionRepository extends CrudRepository<VersionRevision, Long> {
@Query("SELECT vr FROM VersionRevision vr JOIN FETCH vr.version WHERE vr.version.number = :versionNumber")
List<VersionRevision> findByVersionNumber(@Param("versionNumber") final String pVersionNumber);
}

View File

@@ -0,0 +1,33 @@
package org.codiki.versionrevisions;
import org.codiki.core.entities.persistence.Version;
import org.codiki.core.entities.persistence.VersionRevision;
import org.codiki.core.repositories.VersionRepository;
import org.codiki.core.repositories.VersionRevisionRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api/versionrevisions")
public class VersionRevisionController {
@Autowired
private VersionRevisionRepository repository;
@Autowired
private VersionRepository versionRepository;
@GetMapping("/versions")
public Iterable<Version> getVersions() {
return versionRepository.findAllOrderByNumber();
}
@GetMapping("/{versionNumber}")
public Iterable<VersionRevision> getVersionRevisionByVersionNumber(
@PathVariable("versionNumber") final String pVersionNumber) {
return repository.findByVersionNumber(pVersionNumber);
}
}

25
src/main/sql/update_1.0.1.sql Executable file
View File

@@ -0,0 +1,25 @@
CREATE TABLE IF NOT EXISTS version (
id SERIAL,
number VARCHAR,
CONSTRAINT pk_version PRIMARY KEY (id),
CONSTRAINT unique_number UNIQUE (number)
);
CREATE TABLE IF NOT EXISTS version_revision (
id SERIAL,
text VARCHAR,
version_id INTEGER,
CONSTRAINT pk_version_revision PRIMARY KEY (id),
CONSTRAINT fk_version_revision_version_id FOREIGN KEY (version_id) REFERENCES version (id)
);
CREATE INDEX IF NOT EXISTS version_id_idx ON version_revision (version_id);
INSERT INTO version (number) VALUES ('1.0.0'), ('1.0.1');
INSERT INTO version_revision (version_id, text) VALUES
(2, 'Sécurisation des routes de modification du profil.'),
(2, 'Correction de l''injection de code pour les images dans l''écran d''édition de wikis.'),
(2, 'Correction du système de sessions pour pouvoir ouvrir plusieurs onglets sans être déconnecté.'),
(2, 'Correction de l''accès à la documentation d''utilisation.'),
(2, 'Correction du placement d''icônes dans l''écran des paramètres de compte.'),
(2, 'Ajout de l''écran de révisions de versions');

View File

@@ -30,6 +30,7 @@ import { CreateUpdatePostComponent } from './posts/create-update/create-update-p
import { ForbiddenComponent } from './forbidden/forbidden.component';
import { SearchComponent } from './search/search.component';
import { SigninComponent } from './signin/signin.component';
import { VersionRevisionComponent } from './version-revisions/version-revisions.component';
// html components
import { ProgressBarComponent } from './core/directives/progress-bar/progress-bar.component';
@@ -48,6 +49,7 @@ import { ProfilEditionService } from './account-settings/profil-edition/profil-e
import { HeaderService } from './header/header.service';
import { CreateUpdatePostService } from './posts/create-update/create-update-post.service';
import { SearchService } from './search/search.service';
import { VersionRevisionService } from './version-revisions/version-revisions.service';
// Guards
import { AuthGuard } from './core/guards/auth.guard';
@@ -78,7 +80,8 @@ import { SigninService } from './signin/signin.service';
SigninComponent,
ProgressBarComponent,
SpinnerComponent,
SearchBarComponent
SearchBarComponent,
VersionRevisionComponent
],
imports: [
BrowserModule,
@@ -104,6 +107,7 @@ import { SigninService } from './signin/signin.service';
HeaderService,
CreateUpdatePostService,
SearchService,
VersionRevisionService,
AuthGuard,
{
provide: HTTP_INTERCEPTORS,

View File

@@ -14,6 +14,7 @@ import { CreateUpdatePostComponent } from './posts/create-update/create-update-p
import { ForbiddenComponent } from './forbidden/forbidden.component';
import { ProfilEditionComponent } from './account-settings/profil-edition/profil-edition.component';
import { SearchComponent } from './search/search.component';
import { VersionRevisionComponent } from './version-revisions/version-revisions.component';
import { AuthGuard } from './core/guards/auth.guard';
@@ -31,6 +32,7 @@ export const appRoutes: Routes = [
{ path: 'accountSettings', component: AccountSettingsComponent, canActivate: [AuthGuard] },
{ path: 'changePassword', component: ChangePasswordComponent, canActivate: [AuthGuard] },
{ path: 'profilEdit', component: ProfilEditionComponent, canActivate: [AuthGuard] },
{ path: 'versionrevisions', component: VersionRevisionComponent },
{ path: 'forbidden', component: ForbiddenComponent },
{ path: '', redirectTo: '/home', pathMatch: 'full' },
{ path: '**', component: NotFoundComponent }

View File

@@ -2,7 +2,7 @@ export class Role {
constructor(
public id: number,
public name: string
) {}
) { }
}
export class User {
@@ -15,7 +15,7 @@ export class User {
public inscriptionDate: Date,
public role: Role,
public token: string
) {}
) { }
}
export class Post {
@@ -28,7 +28,7 @@ export class Post {
public creationDate: Date,
public author: User,
public category: Category
) {}
) { }
}
export class Category {
@@ -36,14 +36,14 @@ export class Category {
public id: number,
public name: string,
public listSubCategories: Array<Category>
) {}
) { }
}
export class Image {
constructor(
public id: number,
public link: string
) {}
) { }
}
/**
@@ -54,5 +54,21 @@ export class PasswordWrapper {
public oldPassword: string,
public newPassword: string,
public confirmPassword: string
) {}
) { }
}
export class Version {
constructor(
public id: number,
public number: string,
public active: boolean
) { }
}
export class VersionRevision {
constructor(
public id: number,
public text: string,
public version: Version
) { }
}

View File

@@ -1,10 +1,12 @@
<footer class="page-footer indigo center-on-small-only">
<!-- fixed-bottom -->
<!-- fixed-bottom -->
<div class="footer-copyright">
<div class="container">
<span class="float-left">
<span class="anticopy">&copy;</span> 2017 Tous droits r&eacute;serv&eacute;s -
<i>{{appVersion}}</i>
<i id="appVersion" routerLink="/versionrevisions" mdbTooltip="Notes de versions" placement="top" mdbRippleRadius>
{{appVersion}}
</i>
</span>
<span class="float-right">
<a href="./assets/doc/codiki_user_manual.pdf" mdbTooltip="Manuel d'utilisation" placement="top" mdbRippleRadius>

View File

@@ -13,3 +13,7 @@ span.anticopy {
display: inline-block;
transform: rotate(180deg);
}
#appVersion {
color: rgba(255, 255, 255, 0.6);
}

View File

@@ -0,0 +1,22 @@
<div class="row">
<div class="col-md-3 col-lg-2">
<h1>Versions</h1>
<ul class="list-group">
<a *ngFor="let version of versionsList">
<li [className]="version.active ? 'list-group-item active' : 'list-group-item'"
(click)="showVersionRevision(version)">
{{version.number}}
</li>
</a>
</ul>
</div>
<div id="versionRevisionsArea" class="col-md-9 col-lg-10">
<ul *ngIf="versionRevisionsList.length">
<li *ngFor="let versionRevision of versionRevisionsList">
{{versionRevision.text}}
</li>
</ul>
<h4 *ngIf="!versionRevisionsList.length">Aucune note de révisions pour cette version.</h4>
</div>
</div>

View File

@@ -0,0 +1,48 @@
import { Component, OnInit } from '@angular/core';
import { VersionRevisionService } from './version-revisions.service';
import { VersionRevision, Version } from '../core/entities';
@Component({
selector: 'app-version-revisions',
templateUrl: 'version-revisions.component.html',
styles: [`
#versionRevisionsArea {
padding-top: 70px;
}
@media screen and (max-width: 767px) {
#versionRevisionsArea {
padding-top: 20px;
}
}
`]
})
export class VersionRevisionComponent implements OnInit {
versionsList: Array<Version>;
versionRevisionsList: Array<VersionRevision>;
constructor(
private versionRevisionService: VersionRevisionService
) {
this.versionsList = [];
this.versionRevisionsList = [];
}
ngOnInit(): void {
this.versionRevisionService.getVersions().subscribe(versionsList => {
this.versionsList = versionsList;
this.showVersionRevision(this.versionsList[0]);
});
}
showVersionRevision(version: Version): void {
this.versionsList.forEach(versionTmp => versionTmp.active = false);
version.active = true;
this.versionRevisionService.findByVersionNumber(version.number).subscribe(versionRevisionsList => {
this.versionRevisionsList = versionRevisionsList;
});
}
}

View File

@@ -0,0 +1,23 @@
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Version, VersionRevision } from '../core/entities';
import { Observable } from 'rxjs/Observable';
import { environment } from '../../environments/environment';
const VERSION_REVISIONS_URL = environment.apiUrl + '/api/versionrevisions';
@Injectable()
export class VersionRevisionService {
constructor(
private http: HttpClient
) {}
getVersions(): Observable<Array<Version>> {
return this.http.get<Array<Version>>(`${VERSION_REVISIONS_URL}/versions`);
}
findByVersionNumber(versionNumber: string): Observable<Array<VersionRevision>> {
return this.http.get<Array<VersionRevision>>(`${VERSION_REVISIONS_URL}/${versionNumber}`);
}
}