Add the version revisions system.
This commit is contained in:
43
src/main/java/org/codiki/core/entities/persistence/Version.java
Executable file
43
src/main/java/org/codiki/core/entities/persistence/Version.java
Executable 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
52
src/main/java/org/codiki/core/entities/persistence/VersionRevision.java
Executable file
52
src/main/java/org/codiki/core/entities/persistence/VersionRevision.java
Executable 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
16
src/main/java/org/codiki/core/repositories/VersionRepository.java
Executable file
16
src/main/java/org/codiki/core/repositories/VersionRepository.java
Executable 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);
|
||||||
|
}
|
||||||
16
src/main/java/org/codiki/core/repositories/VersionRevisionRepository.java
Executable file
16
src/main/java/org/codiki/core/repositories/VersionRevisionRepository.java
Executable 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);
|
||||||
|
}
|
||||||
33
src/main/java/org/codiki/versionrevisions/VersionRevisionController.java
Executable file
33
src/main/java/org/codiki/versionrevisions/VersionRevisionController.java
Executable 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
25
src/main/sql/update_1.0.1.sql
Executable 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');
|
||||||
@@ -30,6 +30,7 @@ import { CreateUpdatePostComponent } from './posts/create-update/create-update-p
|
|||||||
import { ForbiddenComponent } from './forbidden/forbidden.component';
|
import { ForbiddenComponent } from './forbidden/forbidden.component';
|
||||||
import { SearchComponent } from './search/search.component';
|
import { SearchComponent } from './search/search.component';
|
||||||
import { SigninComponent } from './signin/signin.component';
|
import { SigninComponent } from './signin/signin.component';
|
||||||
|
import { VersionRevisionComponent } from './version-revisions/version-revisions.component';
|
||||||
|
|
||||||
// html components
|
// html components
|
||||||
import { ProgressBarComponent } from './core/directives/progress-bar/progress-bar.component';
|
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 { HeaderService } from './header/header.service';
|
||||||
import { CreateUpdatePostService } from './posts/create-update/create-update-post.service';
|
import { CreateUpdatePostService } from './posts/create-update/create-update-post.service';
|
||||||
import { SearchService } from './search/search.service';
|
import { SearchService } from './search/search.service';
|
||||||
|
import { VersionRevisionService } from './version-revisions/version-revisions.service';
|
||||||
|
|
||||||
// Guards
|
// Guards
|
||||||
import { AuthGuard } from './core/guards/auth.guard';
|
import { AuthGuard } from './core/guards/auth.guard';
|
||||||
@@ -78,7 +80,8 @@ import { SigninService } from './signin/signin.service';
|
|||||||
SigninComponent,
|
SigninComponent,
|
||||||
ProgressBarComponent,
|
ProgressBarComponent,
|
||||||
SpinnerComponent,
|
SpinnerComponent,
|
||||||
SearchBarComponent
|
SearchBarComponent,
|
||||||
|
VersionRevisionComponent
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
BrowserModule,
|
BrowserModule,
|
||||||
@@ -104,6 +107,7 @@ import { SigninService } from './signin/signin.service';
|
|||||||
HeaderService,
|
HeaderService,
|
||||||
CreateUpdatePostService,
|
CreateUpdatePostService,
|
||||||
SearchService,
|
SearchService,
|
||||||
|
VersionRevisionService,
|
||||||
AuthGuard,
|
AuthGuard,
|
||||||
{
|
{
|
||||||
provide: HTTP_INTERCEPTORS,
|
provide: HTTP_INTERCEPTORS,
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import { CreateUpdatePostComponent } from './posts/create-update/create-update-p
|
|||||||
import { ForbiddenComponent } from './forbidden/forbidden.component';
|
import { ForbiddenComponent } from './forbidden/forbidden.component';
|
||||||
import { ProfilEditionComponent } from './account-settings/profil-edition/profil-edition.component';
|
import { ProfilEditionComponent } from './account-settings/profil-edition/profil-edition.component';
|
||||||
import { SearchComponent } from './search/search.component';
|
import { SearchComponent } from './search/search.component';
|
||||||
|
import { VersionRevisionComponent } from './version-revisions/version-revisions.component';
|
||||||
|
|
||||||
import { AuthGuard } from './core/guards/auth.guard';
|
import { AuthGuard } from './core/guards/auth.guard';
|
||||||
|
|
||||||
@@ -31,6 +32,7 @@ export const appRoutes: Routes = [
|
|||||||
{ path: 'accountSettings', component: AccountSettingsComponent, canActivate: [AuthGuard] },
|
{ path: 'accountSettings', component: AccountSettingsComponent, canActivate: [AuthGuard] },
|
||||||
{ path: 'changePassword', component: ChangePasswordComponent, canActivate: [AuthGuard] },
|
{ path: 'changePassword', component: ChangePasswordComponent, canActivate: [AuthGuard] },
|
||||||
{ path: 'profilEdit', component: ProfilEditionComponent, canActivate: [AuthGuard] },
|
{ path: 'profilEdit', component: ProfilEditionComponent, canActivate: [AuthGuard] },
|
||||||
|
{ path: 'versionrevisions', component: VersionRevisionComponent },
|
||||||
{ path: 'forbidden', component: ForbiddenComponent },
|
{ path: 'forbidden', component: ForbiddenComponent },
|
||||||
{ path: '', redirectTo: '/home', pathMatch: 'full' },
|
{ path: '', redirectTo: '/home', pathMatch: 'full' },
|
||||||
{ path: '**', component: NotFoundComponent }
|
{ path: '**', component: NotFoundComponent }
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ export class Role {
|
|||||||
constructor(
|
constructor(
|
||||||
public id: number,
|
public id: number,
|
||||||
public name: string
|
public name: string
|
||||||
) {}
|
) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
export class User {
|
export class User {
|
||||||
@@ -15,7 +15,7 @@ export class User {
|
|||||||
public inscriptionDate: Date,
|
public inscriptionDate: Date,
|
||||||
public role: Role,
|
public role: Role,
|
||||||
public token: string
|
public token: string
|
||||||
) {}
|
) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Post {
|
export class Post {
|
||||||
@@ -28,7 +28,7 @@ export class Post {
|
|||||||
public creationDate: Date,
|
public creationDate: Date,
|
||||||
public author: User,
|
public author: User,
|
||||||
public category: Category
|
public category: Category
|
||||||
) {}
|
) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Category {
|
export class Category {
|
||||||
@@ -36,14 +36,14 @@ export class Category {
|
|||||||
public id: number,
|
public id: number,
|
||||||
public name: string,
|
public name: string,
|
||||||
public listSubCategories: Array<Category>
|
public listSubCategories: Array<Category>
|
||||||
) {}
|
) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Image {
|
export class Image {
|
||||||
constructor(
|
constructor(
|
||||||
public id: number,
|
public id: number,
|
||||||
public link: string
|
public link: string
|
||||||
) {}
|
) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -54,5 +54,21 @@ export class PasswordWrapper {
|
|||||||
public oldPassword: string,
|
public oldPassword: string,
|
||||||
public newPassword: string,
|
public newPassword: string,
|
||||||
public confirmPassword: 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
|
||||||
|
) { }
|
||||||
|
}
|
||||||
@@ -1,10 +1,12 @@
|
|||||||
<footer class="page-footer indigo center-on-small-only">
|
<footer class="page-footer indigo center-on-small-only">
|
||||||
<!-- fixed-bottom -->
|
<!-- fixed-bottom -->
|
||||||
<div class="footer-copyright">
|
<div class="footer-copyright">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<span class="float-left">
|
<span class="float-left">
|
||||||
<span class="anticopy">©</span> 2017 Tous droits réservés -
|
<span class="anticopy">©</span> 2017 Tous droits réservés -
|
||||||
<i>{{appVersion}}</i>
|
<i id="appVersion" routerLink="/versionrevisions" mdbTooltip="Notes de versions" placement="top" mdbRippleRadius>
|
||||||
|
{{appVersion}}
|
||||||
|
</i>
|
||||||
</span>
|
</span>
|
||||||
<span class="float-right">
|
<span class="float-right">
|
||||||
<a href="./assets/doc/codiki_user_manual.pdf" mdbTooltip="Manuel d'utilisation" placement="top" mdbRippleRadius>
|
<a href="./assets/doc/codiki_user_manual.pdf" mdbTooltip="Manuel d'utilisation" placement="top" mdbRippleRadius>
|
||||||
|
|||||||
@@ -13,3 +13,7 @@ span.anticopy {
|
|||||||
display: inline-block;
|
display: inline-block;
|
||||||
transform: rotate(180deg);
|
transform: rotate(180deg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#appVersion {
|
||||||
|
color: rgba(255, 255, 255, 0.6);
|
||||||
|
}
|
||||||
22
src/main/ts/src/app/version-revisions/version-revisions.component.html
Executable file
22
src/main/ts/src/app/version-revisions/version-revisions.component.html
Executable 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>
|
||||||
48
src/main/ts/src/app/version-revisions/version-revisions.component.ts
Executable file
48
src/main/ts/src/app/version-revisions/version-revisions.component.ts
Executable 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;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
23
src/main/ts/src/app/version-revisions/version-revisions.service.ts
Executable file
23
src/main/ts/src/app/version-revisions/version-revisions.service.ts
Executable 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}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user