diff --git a/Makefile b/Makefile deleted file mode 100644 index 2cc99ccb24900d50303a4c892b1cac627bb1a9fd..0000000000000000000000000000000000000000 --- a/Makefile +++ /dev/null @@ -1,22 +0,0 @@ -JVM= java -EXEC= mvn exec:$(JVM) -PACKAGE= mvn package -DIR_COMP= compilation/ -DIR_GATE= gateway/ -DIR_CLIE= client/ -ANGC= ng serve --open - -COMP_PORT= 6999 -GATE_PORT= 7000 - -all: package - -run: - cd $(DIR_GATE) ; $(PACKAGE) ; $(EXEC) & - cd $(DIR_COMP) ; $(PACKAGE) ; $(EXEC) & - cd $(DIR_CLIE) ; $(ANGC) - -clean: SHELL:=/bin/bash - @echo "kill $(lsof -t -i :6999)" -# kill $(lsof -t -i :$(GATE_PORT)) - \ No newline at end of file diff --git a/README.md b/README.md index 925944827869c46a017a4e549a09cda553198409..7b8e74335e6ed32985847cc522332fe0298afe2b 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,22 @@ # Dojo Hepia -## 2.5.0 update : +## DojoHepia-v0.5 update +- A sensei is now able to + - Kata + - Disable + - Edit + - Delete + - Program + - Delete + - Edit + +- Users can see theirs done and ongoing katas +- Markdown support added for kata instructions +- New display in kata-displayer +- Database improvement +- Bug fixed + - Click tag -- Now users can create their own account -- Already trusted sensei can generate token, this token can be used by someone who wants to create a Sensei account -- Auth token and Sponsorship token have now expiration date (six day and ten minutes each respectively). ## RUN ME - DojoHepia @@ -15,71 +27,23 @@ <p>DOCKER-COMPOSE</p> <p>ANGULAR CLI</p> -### Temporary user ids : - -| Username | Password | Privileges | -|----------|----------|------------| -| shodai | admin | shodai | - - -<p>When connected to shodai account, you can generate tokens to create further sensei in "Sponsorship" (location : left nav bar)</p> - -<p>All created account without token will automatically be ranked as "monji"</p> -<b>Users privileges hierarchy</b> - -<p>shodai>sensei>monji</p> - #### 1. Mongo Database -##### 1.2 Create container +##### 1.1 Create the database container >./mongodb/ -``` -docker-compose up -d -``` -##### 1.3 Create user - ->./mongodb/ ``` -docker-compose exec mongo mongo admin -u root -password : example +docker-compose up -d ``` -insert the following command : +`If en error occurs, please log into docker hub (should not happen)` ``` -use DojoHepia - -db.createUser( - { - user: "shodai", - pwd: "shodai", - roles: [ - { role: "readWrite", db: "DojoHepia" } - ] - } -) +docker login ``` -##### (optional) Importing data -<p>If you want to popularize the database with programs,katas and subscription, you can insert the following files in the mongo db database</p> - ->./mongodb/data/programs ->./mongodb/data/programssubscription - -<p>to import the datas, copy them and to the following steps :</p> - ->./mongodb/ -``` -docker-compose exec mongo mongo admin -u root -password : example -``` -``` -use DojoHepia -db.Programs.insertMany(<programs-copied-data>); -db.ProgramsSubscription.insertMany(<programs-subscription-copied-data>); -``` +> **PLEASE NOTE**: The database will initialize itself with data #### 2. Gateway >./gateway/ @@ -95,7 +59,7 @@ npm install ng serve --open ``` -#### 4. Compilateur +#### 4. Compiler ##### 4.1 Pull java container @@ -115,7 +79,30 @@ mvn package mvn exec:java ``` +### Already registered users : + +| Username | Password | Privileges | +|----------|----------|------------| +| shodai | admin | shodai | +| noob | noob | monji | + +<b>Users privileges hierarchy</b> +<p>shodai>sensei>monji</p> + +#### Create a Sensei account + +If you want to generate an account with Sensei privileges, please do the following steps + +1. Login with the 'shodai' account +2. Go to Subscription (on the side navigation menu) +3. Hit 'Generate a token', and copy it +4. Logout from your current account +5. Click on 'Create a account' +6. Check the 'I have a token' box +7. Past the copied token into the newly generated input box +8. A new account with Sensei has been created, you can now use it +> **PLEASE NOTE**: All created account without token will automatically be ranked as "monji" ## Vocabulaire | Art - Martial | Dojo Hepia | diff --git a/client/angular.json b/client/angular.json index 1a4878afa5ffb48d166e546ecd18d7655205e56b..c67be7fa1066cc42fa1d9337108727ea698a6de6 100644 --- a/client/angular.json +++ b/client/angular.json @@ -25,9 +25,16 @@ "styles": [ "./node_modules/@angular/material/prebuilt-themes/pink-bluegrey.css", "./node_modules/bootstrap/dist/css/bootstrap.css", + "node_modules/prismjs/themes/prisme-darkula.css", + "node_modules/prismjs/plugins/line-highlight/prism-line-highlight.css", "src/styles.scss" ], - "scripts": [], + "scripts": ["node_modules/marked/lib/marked.js", + "node_modules/prismjs/prism.js", + "node_modules/prismjs/components/prism-java.min.js", + "node_modules/prismjs/components/prism-python.min.js", + "node_modules/prismjs/plugins/line-highlight/prism-line-highlight.js" + ], "es5BrowserSupport": true }, "configurations": { diff --git a/client/package-lock.json b/client/package-lock.json index 5a1dc920edd1efe9e049fa1df6b352709438ebeb..fbaf692385e41537ab44db6598a78021387418a4 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -690,6 +690,11 @@ "@types/jasmine": "*" } }, + "@types/marked": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/@types/marked/-/marked-0.6.5.tgz", + "integrity": "sha512-6kBKf64aVfx93UJrcyEZ+OBM5nGv4RLsI6sR1Ar34bpgvGVRoyTgpxn4ZmtxOM5aDTAaaznYuYUH8bUX3Nk3YA==" + }, "@types/node": { "version": "8.9.5", "resolved": "https://registry.npmjs.org/@types/node/-/node-8.9.5.tgz", @@ -2094,6 +2099,17 @@ "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", "dev": true }, + "clipboard": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.4.tgz", + "integrity": "sha512-Vw26VSLRpJfBofiVaFb/I8PVfdI1OxKcYShe6fm0sP/DtmiWQNCjhM/okTvdCo0G+lMMm1rMYbk4IK4x1X+kgQ==", + "optional": true, + "requires": { + "good-listener": "^1.2.2", + "select": "^1.1.2", + "tiny-emitter": "^2.0.0" + } + }, "cliui": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", @@ -2727,6 +2743,12 @@ "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", "dev": true }, + "delegate": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz", + "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==", + "optional": true + }, "delegates": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", @@ -4356,6 +4378,15 @@ "minimatch": "~3.0.2" } }, + "good-listener": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz", + "integrity": "sha1-1TswzfkxPf+33JoNR3CWqm0UXFA=", + "optional": true, + "requires": { + "delegate": "^3.1.2" + } + }, "graceful-fs": { "version": "4.1.15", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", @@ -6112,6 +6143,11 @@ "object-visit": "^1.0.0" } }, + "marked": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/marked/-/marked-0.6.2.tgz", + "integrity": "sha512-LqxwVH3P/rqKX4EKGz7+c2G9r98WeM/SW34ybhgNGhUQNKtf1GmmSkJ6cDGJ/t6tiyae49qRkpyTw2B9HOrgUA==" + }, "md5.js": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", @@ -6486,6 +6522,17 @@ "resolved": "https://registry.npmjs.org/ngx-bootstrap/-/ngx-bootstrap-4.1.1.tgz", "integrity": "sha512-2vbjMXxzFX6hz929474It6yI3LyFLm9V4vkLGlCGuhyPWi4G5kuLl3j5Wrj1CsBG9+Cz9xQM9JT6gZnkXBgaTw==" }, + "ngx-markdown": { + "version": "7.1.5", + "resolved": "https://registry.npmjs.org/ngx-markdown/-/ngx-markdown-7.1.5.tgz", + "integrity": "sha512-boL1eQkdHHwVQuLsRF4eaIxuBx2PoJidO/YStLU2a0u6Q7VCjaZI09oSPgsAmsDjJ/Hu7ZWGPv475H7BGJ8iCw==", + "requires": { + "@types/marked": "^0.6.0", + "marked": "^0.6.0", + "prismjs": "^1.16.0", + "tslib": "^1.9.0" + } + }, "ngx-ui-loader": { "version": "7.2.2", "resolved": "https://registry.npmjs.org/ngx-ui-loader/-/ngx-ui-loader-7.2.2.tgz", @@ -7429,6 +7476,14 @@ "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", "dev": true }, + "prismjs": { + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.16.0.tgz", + "integrity": "sha512-OA4MKxjFZHSvZcisLGe14THYsug/nF6O1f0pAJc0KN0wTyAcLqmsbE+lTGKSpyh+9pEW57+k6pg2AfYR+coyHA==", + "requires": { + "clipboard": "^2.0.0" + } + }, "process": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", @@ -8218,6 +8273,12 @@ } } }, + "select": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz", + "integrity": "sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0=", + "optional": true + }, "select-hose": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", @@ -9458,6 +9519,12 @@ "setimmediate": "^1.0.4" } }, + "tiny-emitter": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz", + "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==", + "optional": true + }, "tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", diff --git a/client/package.json b/client/package.json index 2fad21703397ae3603faff239a6b1e241ce042c3..ad7b018f5b5b3f4212ba1a8bd0db0318f793775a 100644 --- a/client/package.json +++ b/client/package.json @@ -32,6 +32,7 @@ "ng2-ace-editor": "^0.3.9", "ngx-alerts": "^3.4.3", "ngx-bootstrap": "^4.1.1", + "ngx-markdown": "^7.1.5", "ngx-ui-loader": "^7.2.2", "rxjs": "~6.3.3", "uuid": "^3.3.2", diff --git a/client/src/app/app-routing.module.ts b/client/src/app/app-routing.module.ts index 4398032abb74b329e27b58a42784910390ef6f1a..3335f607f43a4d2749dae092eec94e846e298cfb 100644 --- a/client/src/app/app-routing.module.ts +++ b/client/src/app/app-routing.module.ts @@ -13,6 +13,8 @@ import {SubscriptionComponent} from './component/subscription/subscription.compo import {MineComponent} from './component/mine/mine.component'; import {SigninComponent} from './component/signin/signin.component'; import {TokenComponent} from './component/token/token.component'; +import {ProgramEditComponent} from './component/program-edit/program-edit.component'; +import {KataEditComponent} from './component/kata-edit/kata-edit.component'; const routes: Routes = [ {path: '', component: ProgramDisplayerComponent, canActivate: [AuthGuard], data: {roles: [Role.shodai, Role.monji, Role.sensei]}}, @@ -25,9 +27,11 @@ const routes: Routes = [ {path: 'program/mine', component: MineComponent, canActivate: [AuthGuard], data: {roles: [Role.shodai, Role.sensei]}}, {path: 'program/search', component: SearchbyComponent, canActivate: [AuthGuard], data: {roles: [Role.shodai, Role.monji, Role.sensei]}}, {path: 'kata-displayer/:id', component: KataDisplayerComponent, canActivate: [AuthGuard], data: {roles: [Role.shodai, Role.monji, Role.sensei]}}, + {path: 'kata/edit/:id/:language', component: KataEditComponent, canActivate: [AuthGuard], data: {roles: [Role.shodai, Role.sensei]}}, {path: 'kata/:prid/:id', component: KataComponent, canActivate: [AuthGuard], data: {roles: [Role.shodai, Role.monji, Role.sensei]}}, {path: 'program/create', component: ProgramCreateComponent, canActivate: [AuthGuard], data: {roles: [Role.shodai, Role.sensei]}}, - {path: 'kata_create/:id/:language', component: KataCreateComponent, canActivate: [AuthGuard], data: {roles: [Role.shodai, Role.sensei]}}, + {path: 'program/edit/:id', component: ProgramEditComponent, canActivate: [AuthGuard], data: {roles: [Role.shodai, Role.sensei]}}, + {path: 'kata/create/:id/:language', component: KataCreateComponent, canActivate: [AuthGuard], data: {roles: [Role.shodai, Role.sensei]}}, {path: '**', redirectTo: ''} ]; diff --git a/client/src/app/app.module.ts b/client/src/app/app.module.ts index 2e362717de67331c44d604dd6ccc50e127c1b812..0de8d39676c4d15efcd1c6081ef1acc66b265b75 100644 --- a/client/src/app/app.module.ts +++ b/client/src/app/app.module.ts @@ -21,13 +21,19 @@ import { MatSnackBarModule, MatCheckboxModule, MatBadgeModule, - MatProgressSpinnerModule + MatProgressSpinnerModule, MatBottomSheetModule } from '@angular/material'; + +import {MatDialogModule} from '@angular/material/dialog'; import {AppRoutingModule} from './app-routing.module'; import {RouterModule} from '@angular/router'; -import {KataDisplayerComponent} from './component/kata-displayer/kata-displayer.component'; +import { + DeleteProgramDialogComponent, + KataDisplayerComponent, + MoreActionKataDialogComponent +} from './component/kata-displayer/kata-displayer.component'; import {ProgramDisplayerComponent} from './component/program-displayer/program-displayer.component'; -import {KataComponent} from './component/kata/kata.component'; +import {KataComponent, KataSurrenderDialogComponent} from './component/kata/kata.component'; import {AceEditorModule} from 'ng2-ace-editor'; import {KataCreateComponent} from './component/kata-create/kata-create.component'; import {ProgramCreateComponent} from './component/program-create/program-create.component'; @@ -39,14 +45,17 @@ import {AlertModule} from 'ngx-alerts'; import {LoginComponent} from './component/login/login.component'; import {JwtInterceptor} from './_helper/jwt.interceptor'; import {ErrorInterceptor} from './_helper/error.interceptor'; -import { ProfilCardComponent } from './component/user/profil-card/profil-card.component'; -import { CardDisplayerComponent } from './component/program-displayer/card-displayer/card-displayer.component'; -import { SearchbyComponent } from './component/searchby/searchby.component'; -import { SubscriptionComponent } from './component/subscription/subscription.component'; -import { MineComponent } from './component/mine/mine.component'; -import { CardNoneallDisplayerComponent } from './component/program-displayer/card-noneall-displayer/card-noneall-displayer.component'; -import { SigninComponent } from './component/signin/signin.component'; -import { TokenComponent } from './component/token/token.component'; +import {ProfilCardComponent} from './component/user/profil-card/profil-card.component'; +import {CardDisplayerComponent} from './component/program-displayer/card-displayer/card-displayer.component'; +import {SearchbyComponent} from './component/searchby/searchby.component'; +import {SubscriptionComponent} from './component/subscription/subscription.component'; +import {MineComponent} from './component/mine/mine.component'; +import {CardNoneallDisplayerComponent} from './component/program-displayer/card-noneall-displayer/card-noneall-displayer.component'; +import {SigninComponent} from './component/signin/signin.component'; +import {TokenComponent} from './component/token/token.component'; +import { ProgramEditComponent } from './component/program-edit/program-edit.component'; +import { MarkdownModule } from 'ngx-markdown'; +import { KataEditComponent } from './component/kata-edit/kata-edit.component'; @NgModule({ @@ -69,7 +78,13 @@ import { TokenComponent } from './component/token/token.component'; MineComponent, CardNoneallDisplayerComponent, SigninComponent, - TokenComponent + TokenComponent, + MoreActionKataDialogComponent, + DeleteProgramDialogComponent, + KataSurrenderDialogComponent, + ProgramEditComponent, + KataEditComponent, + ], imports: [ @@ -94,12 +109,15 @@ import { TokenComponent } from './component/token/token.component'; HttpClientModule, NgxUiLoaderModule, AlertModule.forRoot({maxMessages: 5, timeout: 5000, position: 'right'}), + MarkdownModule.forRoot(), ReactiveFormsModule, MatCardModule, MatBadgeModule, - MatProgressSpinnerModule - + MatProgressSpinnerModule, + MatDialogModule, + MatBottomSheetModule ], + entryComponents: [DeleteProgramDialogComponent, KataSurrenderDialogComponent, MoreActionKataDialogComponent], providers: [{provide: HTTP_INTERCEPTORS, useClass: JwtInterceptor, multi: true}, { provide: HTTP_INTERCEPTORS, useClass: ErrorInterceptor, diff --git a/client/src/app/component/kata-create/kata-create.component.html b/client/src/app/component/kata-create/kata-create.component.html index 925f3d0a040acacb8bf46821f8fb0d6340b1d416..1cf40916e9fc71bcdf77edcc054fff2c183d71a0 100644 --- a/client/src/app/component/kata-create/kata-create.component.html +++ b/client/src/app/component/kata-create/kata-create.component.html @@ -28,14 +28,15 @@ <div *ngIf="submitted && f.assert.errors" class="invalid-feedback"> <div *ngIf="f.assert.errors.required">Please choose an option</div> </div> + </div> <div class="form-group"> <label for="number">Unlock solution at (> -1)</label> <input type="number" formControlName="number" value="1" class="form-control" [ngClass]="{ 'is-invalid': submitted && f.assert.errors}"/> <div *ngIf="submitted && f.number.errors" class="invalid-feedback"> - <div *ngIf="f.number.errors.required">Please choose the number of tries before unlocking the "surrender - option" + <div *ngIf="f.number.errors.min">Please choose the number of tries before unlocking the "surrender" + option (min : 0) </div> </div> </div> @@ -44,16 +45,31 @@ <mat-expansion-panel> <mat-expansion-panel-header> <mat-panel-title> - Kata's instruction + Kata's instruction (Markdown supported) </mat-panel-title> </mat-expansion-panel-header> - <div class="form-group"> - <textarea class="form-control" style="width:100%" formControlName="instruction" + + + <mat-grid-list cols="2" rowHeight="700px"> + <mat-grid-tile> + <div class="form-group"> + <textarea style="margin-top: 10px;height: 680px" class="form-control" formControlName="instruction" [ngClass]="{ 'is-invalid': submitted && f.instruction.errors }"></textarea> - <div *ngIf="submitted && f.instruction.errors" class="invalid-feedback"> - <div *ngIf="f.instruction.errors.required">Kata needs instructions</div> - </div> - </div> + <div *ngIf="submitted && f.instruction.errors" class="invalid-feedback"> + <div *ngIf="f.instruction.errors.required">Kata needs instructions</div> + </div> + + </div> + </mat-grid-tile> + <mat-grid-tile> + <div class="markdown-output" [data]="f.instruction.value" markdown ngPreserveWhitespaces> + + </div> + </mat-grid-tile> + </mat-grid-list> + + + </mat-expansion-panel> <mat-expansion-panel> diff --git a/client/src/app/component/kata-create/kata-create.component.ts b/client/src/app/component/kata-create/kata-create.component.ts index 2cd98ee987db4864d130fd51f46d4f73456337d1..e77a435bcb8ed76c51d0b16e21162fffe8ed1882 100644 --- a/client/src/app/component/kata-create/kata-create.component.ts +++ b/client/src/app/component/kata-create/kata-create.component.ts @@ -91,9 +91,10 @@ export class KataCreateComponent implements OnInit { rules: this.f.instruction.value, keepAssert: this.f.assert.value, nbAttempt: this.f.number.value, - programID: this.programId, - difficulty: 'Ceinture blanche' - })).subscribe(data => this.router.navigate(['/kata-displayer/' + this.programId + ''])); + difficulty: 'Ceinture blanche', + activated: true + + }), this.programId).subscribe(data => this.router.navigate(['/kata-displayer/' + this.programId + ''])); } try(): void { @@ -126,7 +127,7 @@ export class KataCreateComponent implements OnInit { this.CreateForm = this.formBuilder.group({ title: ['', Validators.required], assert: ['', Validators.required], - number: ['', Validators.required], + number: ['', Validators.min(0)], instruction: ['', Validators.required], }); diff --git a/client/src/app/component/kata-displayer/kata-dialog-moreactions.html b/client/src/app/component/kata-displayer/kata-dialog-moreactions.html new file mode 100644 index 0000000000000000000000000000000000000000..f20db0a8a5ca7a0855cddbd0afa6beaf78c848fe --- /dev/null +++ b/client/src/app/component/kata-displayer/kata-dialog-moreactions.html @@ -0,0 +1,24 @@ +<mat-nav-list> + <h2>Actions on {{data.title}}</h2> + <div mat-dialog-actions> + <a mat-list-item (click)="delete()"> + + <span mat-line>Delete</span> + <span mat-line>delete the kata, cannot be undone</span> + </a> + </div> + <a mat-list-item *ngIf="data.isActivated" (click)="deactivate()"> + <span mat-line>Disable</span> + <span mat-line>the kata will be disabled, users won't be able to accomplish it anymore</span> + </a> + <a mat-list-item *ngIf="!data.isActivated" (click)="deactivate()"> + <span mat-line>Enable</span> + <span mat-line>the kata will be enabled, users will be able to accomplish it</span> + </a> + + <a mat-list-item (click)="edit()"> + <span mat-line>Edit</span> + <span mat-line>edit kata</span> + </a> + <button mat-button style="float:right" (click)="onNoClick()" cdkFocusInital>Cancel</button> +</mat-nav-list> diff --git a/client/src/app/component/kata-displayer/kata-displayer.component.html b/client/src/app/component/kata-displayer/kata-displayer.component.html index 0a29300392237157709a092c2a998ea2e8fbca24..6bf9b15d1fde9c96fe69a97d6c2a923b3ef796c5 100644 --- a/client/src/app/component/kata-displayer/kata-displayer.component.html +++ b/client/src/app/component/kata-displayer/kata-displayer.component.html @@ -1,39 +1,43 @@ <div class="container" *ngIf="!error"> <div *ngIf="inforreceived"> - <h1 class="title" style="margin:2rem 0 0 2rem;">{{programTitle}} + <h1 class="title" style="margin:2rem 0 0 2rem;">{{program.title}} <br/> - <span class="subtitle">{{programSensei}} <span class="language"> {{programLanguage}}</span> + <span class="subtitle">{{program.sensei}} <span class="language"> {{program.language}}</span> </span> - <button mat-button style="margin:0 3rem 0 0;float:right;" *ngIf="isOwner" - routerLink="/kata_create/{{idProgram}}/{{programLanguage}}">Create a new kata - </button> - <button mat-button style="margin:0 3rem 0 0;float:right" *ngIf="isOwner" (click)="deleteProgram(idProgram)">Delete - this - program - </button> + <div *ngIf="isOwner"> + <button mat-button style="margin:0 3rem 0 0;float:right;" + routerLink="/kata/create/{{programid}}/{{program.language}}">Add Kata + </button> + <button mat-button style="margin:0 3rem 0 0;float:right" routerLink="/program/edit/{{programid}}">Edit</button> + <button mat-button style="margin:0 3rem 0 0;float:right" (click)="openDialog()">Delete</button> + </div> + <button mat-button style="margin:0 3rem 0 0;float:right" *ngIf="!isOwner" (click)="subscribe()">{{subvalue}}</button> </h1> + </div> <br/> + <span style="margin:0 0 0 2rem;" class="subtitle">{{program.description}}</span> + <hr/> + <span style="margin:2rem 0 0 2rem;" *ngFor="let tag of program.tags"> + <span class="tag">{{tag}}</span> + </span> - <div *ngIf="katas" disabled [ngClass]="isSubscribed ? '' : 'notsub'"> - + <div *ngIf="katas" disabled [ngClass]="isSubscribed ? '' : 'deactivated'"> <div class="d-flex flex-wrap justify-content-start"> <span *ngFor="let kata of katas"> - <div class="card" routerLink="/kata/{{idProgram}}/{{kata.id}}"> + <div *ngIf="kata.activated || isOwner" class="card" > <div class="card-body"> - <h5 class="card-title"><a class="title" - routerLink="/kata/{{idProgram}}/{{kata.id}}">{{kata.title}}</a> - <span style="float:right;" - [ngClass]="{'TODO':kata.status==='TODO','ON-GOING':kata.status==='ON-GOING','RESOLVED':kata.status==='RESOLVED','FAILED': kata.status==='FAILED'}">{{kata.status}}</span></h5> + <h5 class="card-title" [ngClass]="kata.activated ? '' : 'deactivatedcard'"><a class="title" + routerLink="/kata/{{programid}}/{{kata.id}}">{{kata.title}}</a> + <span style="float:right;" *ngIf="kata.activated" [ngClass]="{'TODO':kata.status==='TODO','ONGOING':kata.status==='ONGOING','RESOLVED':kata.status==='RESOLVED','FAILED': kata.status==='FAILED'}">{{kata.status}}</span> + <span style="float:right;" *ngIf="!kata.activated" class="DISABLED">DISABLED</span></h5> <br/> <h6 class="card-subtitle mb-2 text-muted">{{kata.difficulty}}</h6> - <!-- <button mat-button *ngIf="isOwner" (click)="deleteKata(kata.id)" class="card-link">Delete kata</button>--> - <!--<button mat-button *ngIf="isOwner" routerLink="#">Statistics</button>--> - <!--<p class="card-text">{{kata.description}}</p>--> + <a *ngIf="isOwner" (click)="openDialogMoreActions(kata.title,kata.id,kata.activated)" class="card-link">More..</a> </div> </div> </span> diff --git a/client/src/app/component/kata-displayer/kata-displayer.component.scss b/client/src/app/component/kata-displayer/kata-displayer.component.scss index 0292df1218afb6cc8be9eb78c87e1b0bec8fb408..ff164d91c856d1af4b20d1fd3975e090fe3e6d95 100644 --- a/client/src/app/component/kata-displayer/kata-displayer.component.scss +++ b/client/src/app/component/kata-displayer/kata-displayer.component.scss @@ -4,6 +4,7 @@ } .title { + font-size: 20px; color:var(--color-cloud); } @@ -12,13 +13,21 @@ font-size:15px; color:var(--color-dark-grey) !important; } -.notsub{ +.deactivated{ pointer-events: none; /* for "disabled" effect */ opacity: 0.5; background: var(--color-dark-blue); } +.deactivatedcard{ + pointer-events: none; + /* for "disabled" effect */ + opacity: 0.5; + background: var(--color-dark-blue); +} + + * { font-family: "Helvetica Neue"; @@ -28,14 +37,19 @@ margin: 2rem; background-color: var(--color-dark-blue); } -a { - text-decoration: none; + +a{ + color: var(--color-cloud); +} + +a:hover{ + color: var(--color-cloud); } + .card:hover{ background-color: var(--color-electro); border:1px solid var(--color-electro); - cursor: pointer; } .TODO { @@ -46,10 +60,28 @@ a { color: rgba(46, 204, 113, 1.0); } -.ON-GOING { +.ONGOING { color: rgba(230, 126, 34, 1.0); } .FAILED{ color:rgba(231, 76, 60,1.0); } + +.DISABLED{ + color: rgba(9, 132, 227, 1.0); +} + + +.tag { + background-color: rgba(99, 110, 114, 0.4); + color: rgba(9, 132, 227, 1.0); + padding: 3px; + margin-right: 3px; +} + +.card-link{ + border-bottom: 1px solid var(--color-language-hover); + cursor: pointer; + float:right; +} diff --git a/client/src/app/component/kata-displayer/kata-displayer.component.ts b/client/src/app/component/kata-displayer/kata-displayer.component.ts index 490baa36a62130ae7154762ffca9f3b4136eb334..dd7cfb0508881600904be18070dc947ceb76cf14 100644 --- a/client/src/app/component/kata-displayer/kata-displayer.component.ts +++ b/client/src/app/component/kata-displayer/kata-displayer.component.ts @@ -1,4 +1,4 @@ -import {Component, OnInit} from '@angular/core'; +import {Component, EventEmitter, Inject, OnInit} from '@angular/core'; import {KataShowCase} from './kataShowCase'; import {ActivatedRoute, Router} from '@angular/router'; import {Location} from '@angular/common'; @@ -10,22 +10,32 @@ import {v4 as uuid} from 'uuid'; import {ProgramSubscriptionService} from '../../services/program/subs/program-subscription.service'; import {ProgramService} from '../../services/program/program.service'; import {KataService} from '../../services/kata/kata.service'; -import {MatSnackBar} from '@angular/material'; +import {MAT_DIALOG_DATA, MatBottomSheet, MatSnackBar} from '@angular/material'; +import {MatDialog, MatDialogRef} from '@angular/material/dialog'; +import {Program} from '../program-displayer/program'; +export interface MoreActionsKata { + title: string; + id: string; + isActivated: boolean; + language: string; +} + @Component({ selector: 'app-kata-displayer', templateUrl: './kata-displayer.component.html', styleUrls: ['./kata-displayer.component.scss'] }) + + export class KataDisplayerComponent implements OnInit { katas: KataShowCase[]; - idProgram: string; - programTitle: string; - programLanguage: string; - programSensei: string; - programSenseiID: string; + programid: string; + + program: Program; + error = false; isSubscribed = false; currentUser: User; @@ -49,28 +59,56 @@ export class KataDisplayerComponent implements OnInit { private auth: AuthenticationService, private programSubscription: ProgramSubscriptionService, private router: Router, - private snackBar: MatSnackBar + private snackBar: MatSnackBar, + public dialog: MatDialog ) { } - deleteKata(kataid: string){ + openDialog(): void { + const dialogRef = this.dialog.open(DeleteProgramDialogComponent, { + width: '400px', + data: this.program.title + }); + dialogRef.afterClosed().subscribe(result => { + if (result) { + this.programService.delete(this.programid).subscribe(() => this.router.navigate(['program/mine'])); + } + }); + } + + openDialogMoreActions(kataTitle: string, kataId: string, activated: boolean): void { + const dialogRef = this.dialog.open(MoreActionKataDialogComponent, { + width: '600px', + data: {title: kataTitle, id: kataId, isActivated: activated, language: this.program.language} + }); + dialogRef.componentInstance.reloadKata.subscribe(() => { + this.kataService.getKatasDetails(this.programid, this.auth.currentUserValue.id).subscribe((datas: KataShowCase[]) => { + this.katas = datas; + }); + }); + dialogRef.afterClosed().subscribe(result => { + if (result) { + + } + }); } getIsOwner() { - if (this.currentUser.id === this.programSenseiID) { - this.isOwner = true; - this.isSubscribed = true; - } + this.programService.isOwner(this.programid, this.currentUser.id).subscribe((data: boolean) => { + if (data) { + this.isOwner = true; + this.isSubscribed = true; + } + }); } subscribe() { if (this.nullsubs) { - this.programSubscription.createSubscription(JSON.stringify({ + this.programSubscription.create(this.currentUser.id, JSON.stringify({ id: uuid(), - iduser: this.currentUser.id, - idprogram: this.idProgram, + idprogram: this.programid, status: true, nbKataDone: 0, katas: [] @@ -78,19 +116,23 @@ export class KataDisplayerComponent implements OnInit { this.isSubscribed = true; this.nullsubs = false; this.subvalue = 'Unsubscribe'; - this.programSubscription.getSubs(this.idProgram, this.currentUser.id).subscribe((data: ProgramSubscription) => this.subscription = data); + this.snackBar.open('Subscribed from ' + this.program.title, '', { + duration: 2000 + }); + // tslint:disable-next-line:max-line-length + this.programSubscription.getSubs(this.programid, this.currentUser.id).subscribe((data: ProgramSubscription) => this.subscription = data); }); } else { this.isSubscribed = !this.isSubscribed; - this.programSubscription.toggle(JSON.stringify({programid: this.idProgram, userid: this.currentUser.id})).subscribe(() => { + this.programSubscription.toggle(JSON.stringify({programid: this.programid, userid: this.currentUser.id})).subscribe(() => { if (this.isSubscribed) { this.subvalue = 'Unsubscribe'; - this.snackBar.open('Subscribed to ' + this.programTitle,'', { + this.snackBar.open('Subscribed to ' + this.program.title, '', { duration: 2000 }); } else { this.subvalue = 'Subscribe'; - this.snackBar.open('Unsubscribed from ' + this.programTitle,'', { + this.snackBar.open('Unsubscribed from ' + this.program.title, '', { duration: 2000 }); } @@ -99,9 +141,8 @@ export class KataDisplayerComponent implements OnInit { } getSubs() { - this.programSubscription.getSubs(this.idProgram, this.currentUser.id).subscribe((data: ProgramSubscription) => { + this.programSubscription.getSubs(this.programid, this.currentUser.id).subscribe((data: ProgramSubscription) => { this.subscription = data; - console.log(data); this.isSubscribed = this.subscription.status; if (!this.isSubscribed) { this.subvalue = 'Subscribe'; @@ -117,29 +158,16 @@ export class KataDisplayerComponent implements OnInit { }); } - deleteProgram(id: string) { - if (confirm('Are you sure you want to delete this program ? all katas and users datas regarding this katas will be deleted as well.')) { - this.programService.deleteProgram(id).subscribe(() => { - this.router.navigate(['program/mine']); - }); - } - } - getKatas() { this.ngxLoader.start(); - this.programService.getDetails(this.idProgram).subscribe((data: string[]) => { - this.programTitle = data[0]; - this.programLanguage = data[1]; - this.programSensei = data[2]; - console.log(data[3]); - this.programSenseiID = data[3]; + this.programService.getById(this.programid).subscribe((data: Program) => { + this.program = data; this.getIsOwner(); this.getSubs(); - this.inforreceived = true; - this.kataService.getKatasDetails(this.idProgram, this.auth.currentUserValue.id).subscribe((datas: KataShowCase[]) => { + this.kataService.getKatasDetails(this.programid, this.auth.currentUserValue.id).subscribe((datas: KataShowCase[]) => { this.katas = datas; this.ngxLoader.stop(); }); @@ -151,10 +179,68 @@ export class KataDisplayerComponent implements OnInit { })); } + ngOnInit() { - this.idProgram = this.route.snapshot.paramMap.get('id'); + this.programid = this.route.snapshot.paramMap.get('id'); this.currentUser = this.auth.currentUserValue; this.getKatas(); } } + +@Component({ + selector: 'dialog-overview-example-dialog', + templateUrl: 'program-dialog-delete.html', +}) +export class DeleteProgramDialogComponent { + + constructor( + public dialogRef: MatDialogRef<DeleteProgramDialogComponent>, + @Inject(MAT_DIALOG_DATA) public data: string) { + } + + onNoClick(): void { + this.dialogRef.close(); + } + +} + +@Component({ + selector: 'dialog-overview-example-dialog', + templateUrl: 'kata-dialog-moreactions.html', +}) +export class MoreActionKataDialogComponent { + + constructor( + public dialogRef: MatDialogRef<MoreActionKataDialogComponent>, + @Inject(MAT_DIALOG_DATA) public data: MoreActionsKata, + private kataService: KataService, + private router: Router) { + } + + reloadKata = new EventEmitter<any>(); + + deactivate(): void { + this.kataService.deactivate(this.data.id).subscribe(() => { + this.reloadKata.emit(); + this.dialogRef.close(); + }); + } + + delete(): void { + this.kataService.delete(this.data.id).subscribe(() => { + this.reloadKata.emit(); + this.dialogRef.close(); + }); + } + + edit(): void { + this.router.navigate(['kata/edit/' + this.data.id + '/' + this.data.language]); + this.dialogRef.close(); + } + + onNoClick(): void { + this.dialogRef.close(); + } + +} diff --git a/client/src/app/component/kata-displayer/kataShowCase.ts b/client/src/app/component/kata-displayer/kataShowCase.ts index 01043af95ebb554d40b1be61bfd3d439d5db1c98..47a65effd2134bcc812e38a99c52a7c91e5e4fbe 100644 --- a/client/src/app/component/kata-displayer/kataShowCase.ts +++ b/client/src/app/component/kata-displayer/kataShowCase.ts @@ -3,6 +3,7 @@ export interface KataShowCase { difficulty: string; id: string; status: string; + activated: boolean; } diff --git a/client/src/app/component/kata-displayer/kataShowCaseMock.ts b/client/src/app/component/kata-displayer/kataShowCaseMock.ts deleted file mode 100644 index d9827e49f72cd5d6414b1558dd6f45310bc4e6af..0000000000000000000000000000000000000000 --- a/client/src/app/component/kata-displayer/kataShowCaseMock.ts +++ /dev/null @@ -1,15 +0,0 @@ -/*import {KataShowCase} from './kataShowCase'; - -export const KATAS: KataShowCase[] = [ - { - id: 0, - title: 'Multiplication par 2', - difficulty: 'Ceinture Blanche', - idProgram: 0, - description: 'Multiplier tous les chiffres d\'un tableau par 2', - status: 'TODO' - }, - {id: 1, title: 'Fopen', difficulty: 'Ceinture Jaune', idProgram: 1, description: 'TOFILL', status: 'FAILED'}, - {id: 2, title: 'Fwrite', difficulty: 'Ceinture Verte', idProgram: 1, description: 'TOFILL', status: 'RESOLVED'} -]; -*/ diff --git a/client/src/app/component/kata-displayer/program-dialog-delete.html b/client/src/app/component/kata-displayer/program-dialog-delete.html new file mode 100644 index 0000000000000000000000000000000000000000..3b24347db6ed493bdec74e6e1980259f52f3d39f --- /dev/null +++ b/client/src/app/component/kata-displayer/program-dialog-delete.html @@ -0,0 +1,8 @@ +<h1 mat-dialog-title>Are you sure you want to delete '{{data}}' ?</h1> +<div mat-dialog-content> + <p>All kata will be destroyed, cannot be undone.</p> +</div> +<div mat-dialog-actions> + <button mat-button (click)="onNoClick()" cdkFocusInital>No</button> + <button mat-button [mat-dialog-close]="true">Yes</button> +</div> diff --git a/client/src/app/component/kata-edit/kata-edit.component.html b/client/src/app/component/kata-edit/kata-edit.component.html new file mode 100644 index 0000000000000000000000000000000000000000..28fb605b2b9f0ffb73eee6851e3799d6cd7b81f7 --- /dev/null +++ b/client/src/app/component/kata-edit/kata-edit.component.html @@ -0,0 +1,114 @@ +<div class="d-flex justify-content-center" *ngIf="kata" style="margin-top:2%"> + <div class="d-flex flex-column"> + <form [formGroup]="EditForm"> + + <mat-accordion> + <mat-expansion-panel expanded="true"> + <mat-expansion-panel-header> + <mat-panel-title> + Kata's informations + </mat-panel-title> + </mat-expansion-panel-header> + + <div class="form-group"> + <label for="title">Title</label> + <input type="text" [(ngModel)]="kata.title" formControlName="title" class="form-control" + [ngClass]="{ 'is-invalid': submitted && f.title.errors }"/> + <div *ngIf="submitted && f.title.errors" class="invalid-feedback"> + <div *ngIf="f.title.errors.required">Kata needs a title</div> + </div> + </div> + <div class="form-group"> + <label for="assert">Display assert box</label> + <select class="form-control" formControlName="assert" + [ngClass]="{ 'is-invalid': submitted && f.assert.errors}"> + <option value="true">yes</option> + <option value="false">no</option> + </select> + <div *ngIf="submitted && f.assert.errors" class="invalid-feedback"> + <div *ngIf="f.assert.errors.required">Please choose an option</div> + </div> + + </div> + + <div class="form-group"> + <label for="number">Unlock solution at (> -1)</label> + <input [(ngModel)]="kata.nbAttempt" type="number" formControlName="number" class="form-control" + [ngClass]="{ 'is-invalid': submitted && f.number.errors}"/> + <div *ngIf="submitted && f.number.errors" class="invalid-feedback"> + <div *ngIf="f.number.errors.min">Please choose the number of tries before unlocking the "surrender" + option (min : 0) + </div> + </div> + </div> + + </mat-expansion-panel> + <mat-expansion-panel> + <mat-expansion-panel-header> + <mat-panel-title> + Kata's instruction (Markdown supported) + </mat-panel-title> + </mat-expansion-panel-header> + + + <mat-grid-list cols="2" rowHeight="700px"> + <mat-grid-tile> + <div class="form-group"> + <textarea [(ngModel)]="kata.rules" style="margin-top: 10px;height: 680px" class="form-control" formControlName="instruction" + [ngClass]="{ 'is-invalid': submitted && f.instruction.errors }"></textarea> + <div *ngIf="submitted && f.instruction.errors" class="invalid-feedback"> + <div *ngIf="f.instruction.errors.required">Kata needs instructions</div> + </div> + + </div> + </mat-grid-tile> + <mat-grid-tile> + <div class="markdown-output" [data]="f.instruction.value" markdown ngPreserveWhitespaces> + + </div> + </mat-grid-tile> + </mat-grid-list> + + + + </mat-expansion-panel> + + <mat-expansion-panel> + <mat-expansion-panel-header> + <mat-panel-title> + Kata + </mat-panel-title> + </mat-expansion-panel-header> + + <mat-grid-list cols="2" rowHeight="310px"> + <mat-grid-tile> + <app-terminal-code [code]="kata.solution" [type]="language" + (new)="OnNewEventSolution($event)"></app-terminal-code> + </mat-grid-tile> + <mat-grid-tile> + <app-terminal-code [code]="kata.cassert" [type]="language" + (new)="OnNewEventAssert($event)"></app-terminal-code> + </mat-grid-tile> + + <mat-grid-tile> + <app-terminal-code [code]="kata.canva" [type]="language" (new)="OnNewEventCanva($event)"></app-terminal-code> + </mat-grid-tile> + <mat-grid-tile> + <textarea [ngClass]="{'success':status === 0,'error':status === 1,'':status === 2}" + style="white-space: pre-wrap;" disabled>{{result}}</textarea> + </mat-grid-tile> + </mat-grid-list> + + <br/> + + <button mat-button [disabled]="compiling" (click)="try()">Try my solution</button> + <button mat-button [disabled]="compiling" (click)="save()" style="float:right">Save kata</button> + + </mat-expansion-panel> + </mat-accordion> + + </form> + </div> +</div> + +<span *ngIf="!kata"><ngx-ui-loader></ngx-ui-loader></span> diff --git a/client/src/app/component/kata-edit/kata-edit.component.spec.ts b/client/src/app/component/kata-edit/kata-edit.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..d2af0ed18fbfb87ef8c61a571a36c78babb078e2 --- /dev/null +++ b/client/src/app/component/kata-edit/kata-edit.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { KataEditComponent } from './kata-edit.component'; + +describe('KataEditComponent', () => { + let component: KataEditComponent; + let fixture: ComponentFixture<KataEditComponent>; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ KataEditComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(KataEditComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/client/src/app/component/kata-edit/kata-edit.component.ts b/client/src/app/component/kata-edit/kata-edit.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..59a69c5b4e653f8ab57aa10a6d46f014c5152495 --- /dev/null +++ b/client/src/app/component/kata-edit/kata-edit.component.ts @@ -0,0 +1,131 @@ +import {Component, OnInit} from '@angular/core'; +import {ActivatedRoute, Router} from '@angular/router'; +import {Location} from '@angular/common'; +import {KataService} from '../../services/kata/kata.service'; +import {CompilationService} from '../../services/compilation/compilation.service'; +import {FormBuilder, FormGroup, Validators} from '@angular/forms'; +import {Kata} from '../kata/kata'; +import {AuthenticationService} from '../../services/auth/authentication.service'; + +@Component({ + selector: 'app-kata-edit', + templateUrl: './kata-edit.component.html', + styleUrls: ['../kata-create/kata-create.component.scss'] +}) +export class KataEditComponent implements OnInit { + + constructor( + private route: ActivatedRoute, + private auth: AuthenticationService, + private location: Location, + private kataService: KataService, + public router: Router, + private compilationService: CompilationService, + private formBuilder: FormBuilder) { + } + + kata: Kata; + EditForm: FormGroup; + submitted = false; + + compiling = false; + kataid: string; + language: string; + + status = 2; + result: string; + + get f() { + return this.EditForm.controls; + } + + OnNewEventAssert(event: any): void { + this.kata.cassert = event.toString(); + } + + OnNewEventCanva(event: any): void { + this.kata.canva = event.toString(); + } + + OnNewEventSolution(event: any): void { + this.kata.solution = event.toString(); + } + + getKata(): void { + this.kataService.isOwner(this.kataid, this.auth.currentUserValue.id).subscribe((data: boolean) => { + if (data) { + this.kataService.getKata(this.kataid).subscribe((kata: Kata) => { + this.kata = kata; + }); + } else { + this.router.navigate(['/']); + } + }); + } + + try(): void { + this.compiling = true; + let response; + + this.compilationService.compilationServer(JSON.stringify({ + language: this.language, + stream: this.kata.solution, + assert: this.kata.cassert + })).subscribe((data: string) => { + response = data; + if (response.exit === 0) { + this.status = 0; + this.result = response.output + '\nTests passed'; + } else { + this.status = 1; + this.result = response.error; + } + this.compiling = false; + this.result += '\nExecuted in : ' + response.time + 'ms'; + }); + } + + save(): void { + this.submitted = true; + + if (this.EditForm.invalid) { + return; + } + + if (this.f.number.value < 0) { + return; + } + + this.kataService.update(JSON.stringify({ + id: this.kataid, + title: this.f.title.value, + language: this.language, + canva: this.kata.canva, + cassert: this.kata.cassert, + solution: this.kata.solution, + rules: this.f.instruction.value, + keepAssert: this.f.assert.value, + nbAttempt: this.f.number.value, + difficulty: 'Ceinture blanche', + activated: this.kata.activated + })).subscribe((data: string) => { + this.router.navigate(['kata-displayer/' + data]); + }); + + } + + ngOnInit() { + this.kataid = this.route.snapshot.paramMap.get('id'); + this.language = this.route.snapshot.paramMap.get('language'); + + this.getKata(); + this.EditForm = this.formBuilder.group({ + title: ['', Validators.required], + assert: ['', Validators.required], + number: ['', Validators.min(0)], + instruction: ['', Validators.required], + }); + } + + +} diff --git a/client/src/app/component/kata/kata-dialog-surrender.html b/client/src/app/component/kata/kata-dialog-surrender.html new file mode 100644 index 0000000000000000000000000000000000000000..98a6440b5c3ba060960b9e8a284d992f5ea070e0 --- /dev/null +++ b/client/src/app/component/kata/kata-dialog-surrender.html @@ -0,0 +1,8 @@ +<h1 mat-dialog-title>Are you sure you want to surrender ?</h1> +<div mat-dialog-content> + <p>The solution will be displayed but you won't be able to gain level on this kata again.</p> +</div> +<div mat-dialog-actions> + <button mat-button (click)="onNoClick()">No</button> + <button mat-button [mat-dialog-close]="true" cdkFocusInitial>Yes</button> +</div> diff --git a/client/src/app/component/kata/kata.component.html b/client/src/app/component/kata/kata.component.html index 4476726f3612b645b53ac1234e580350b0b8a1d6..c5ab88a906597a3726010b77dc33d8fc47d72f72 100644 --- a/client/src/app/component/kata/kata.component.html +++ b/client/src/app/component/kata/kata.component.html @@ -2,25 +2,27 @@ <span *ngIf="katareceived"> <div class="d-flex flex-column"> <div class="p-2 title"> - {{kata.title}} <a routerLink="/kata-displayer/{{programID}}">- {{programTitle}}</a> - <br><span class="subtitle">{{programSensei}} <span class="language"> {{kata.language}}</span></span> + {{kata.title}} <a routerLink="/kata-displayer/{{programid}}">- {{program.title}}</a> + <br><span class="subtitle">{{program.sensei}} <span class="language"> {{kata.language}}</span></span> <span style="float:right"><span - [ngClass]="{'TODO':kataStatus==='TODO','ON-GOING':kataStatus==='ON-GOING','RESOLVED':kataStatus==='RESOLVED','FAILED': kataStatus==='FAILED'}">{{kataStatus}}</span> | ATTEMPTS : {{nbAttempt}}</span> + [ngClass]="{'TODO':kataStatus==='TODO','ONGOING':kataStatus==='ONGOING','RESOLVED':kataStatus==='RESOLVED','FAILED': kataStatus==='FAILED'}">{{kataStatus}}</span> | ATTEMPTS : {{nbAttempt}}</span> </div> <div class="p-2 "><label class="header">rules :</label><label style="margin-left: 20px;" class="header">{{this.filename}}</label></div> <div class="p-2 "> - <textarea disabled style="text-align: justify">{{kata.rules}}</textarea> + <div style="height: 300px;" class="markdown-output" [data]="kata.rules" markdown ngPreserveWhitespaces> + + </div> <app-terminal-code style="margin-left: 20px;" [code]="kata.canva" [type]="kata.language" (new)="OnNewEvent($event)"></app-terminal-code> </div> -<div class="p-2 "><label [hidden]="assert" style="margin-right: 20px;" class="header">{{assertname}}</label><label - [ngClass]="{'header':true,'no-assert':assert===true}">output :</label></div> +<div class="p-2 "><label [hidden]="kata.keepAssert" style="margin-right: 20px;" class="header">{{assertname}}</label><label + [ngClass]="{'header':true,'no-assert':kata.keepAssert===true}">output :</label></div> <div class="p-2"> - <app-terminal-assert [hidden]="assert" [code]="kata.cassert" [type]="kata.language"></app-terminal-assert> - <textarea [ngClass]="{'success':status === 0,'error':status === 1,'':status === 2,'no-assert':assert===true}" + <app-terminal-assert [hidden]="kata.keepAssert" [code]="kata.cassert" [type]="kata.language"></app-terminal-assert> + <textarea [ngClass]="{'success':status === 0,'error':status === 1,'':status === 2,'no-assert':kata.keepAssert===true}" style="white-space: pre-wrap;" disabled>{{result}}</textarea> </div> @@ -33,7 +35,7 @@ style="float:right">Run</button> <img style="float:right" *ngIf="compiling" src="data:image/gif;base64,R0lGODlhEAAQAPIAAP///wAAAMLCwkJCQgAAAGJiYoKCgpKSkiH/C05FVFNDQVBFMi4wAwEAAAAh/hpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh+QQJCgAAACwAAAAAEAAQAAADMwi63P4wyklrE2MIOggZnAdOmGYJRbExwroUmcG2LmDEwnHQLVsYOd2mBzkYDAdKa+dIAAAh+QQJCgAAACwAAAAAEAAQAAADNAi63P5OjCEgG4QMu7DmikRxQlFUYDEZIGBMRVsaqHwctXXf7WEYB4Ag1xjihkMZsiUkKhIAIfkECQoAAAAsAAAAABAAEAAAAzYIujIjK8pByJDMlFYvBoVjHA70GU7xSUJhmKtwHPAKzLO9HMaoKwJZ7Rf8AYPDDzKpZBqfvwQAIfkECQoAAAAsAAAAABAAEAAAAzMIumIlK8oyhpHsnFZfhYumCYUhDAQxRIdhHBGqRoKw0R8DYlJd8z0fMDgsGo/IpHI5TAAAIfkECQoAAAAsAAAAABAAEAAAAzIIunInK0rnZBTwGPNMgQwmdsNgXGJUlIWEuR5oWUIpz8pAEAMe6TwfwyYsGo/IpFKSAAAh+QQJCgAAACwAAAAAEAAQAAADMwi6IMKQORfjdOe82p4wGccc4CEuQradylesojEMBgsUc2G7sDX3lQGBMLAJibufbSlKAAAh+QQJCgAAACwAAAAAEAAQAAADMgi63P7wCRHZnFVdmgHu2nFwlWCI3WGc3TSWhUFGxTAUkGCbtgENBMJAEJsxgMLWzpEAACH5BAkKAAAALAAAAAAQABAAAAMyCLrc/jDKSatlQtScKdceCAjDII7HcQ4EMTCpyrCuUBjCYRgHVtqlAiB1YhiCnlsRkAAAOwAAAAAAAAAAAA=="/> - <button mat-button [disabled]="compiling || isResolved" (click)="Surrender()" + <button mat-button [disabled]="compiling || isResolved" (click)="openDialog()" style="margin-right: 10px">Surrender</button> </div> </div> diff --git a/client/src/app/component/kata/kata.component.scss b/client/src/app/component/kata/kata.component.scss index db0786b4e2234402aaa720b431b189f8f9169d8d..252c7eb44952c71181b4ea26299556b806b7f9f7 100644 --- a/client/src/app/component/kata/kata.component.scss +++ b/client/src/app/component/kata/kata.component.scss @@ -77,7 +77,7 @@ textarea { color: rgba(46, 204, 113, 1.0); } -.ON-GOING { +.ONGOING { color: rgba(230, 126, 34, 1.0); } diff --git a/client/src/app/component/kata/kata.component.ts b/client/src/app/component/kata/kata.component.ts index 14b1186ff7525a76552f8156b92addc7581c41f5..35cf336006fcc496f414a52dbfe3b1eee5ce7300 100644 --- a/client/src/app/component/kata/kata.component.ts +++ b/client/src/app/component/kata/kata.component.ts @@ -1,4 +1,4 @@ -import {Component, OnInit} from '@angular/core'; +import {Component, Inject, OnInit} from '@angular/core'; import {ActivatedRoute, Router} from '@angular/router'; import {Location} from '@angular/common'; import {Kata} from './kata'; @@ -13,6 +13,9 @@ import {v4 as uuid} from 'uuid'; import {KataSubscriptionService} from '../../services/kata/kata-subscription.service'; import {ProgramService} from '../../services/program/program.service'; import {KataService} from '../../services/kata/kata.service'; +import {MAT_DIALOG_DATA, MatDialog, MatDialogRef} from '@angular/material'; +import {Program} from '../program-displayer/program'; + @Component({ selector: 'app-kata', @@ -22,25 +25,26 @@ import {KataService} from '../../services/kata/kata.service'; export class KataComponent implements OnInit { kata: Kata; - idKata: string; + kataid: string; status = 2; result = ''; - programID: string; - programTitle: string; - programSensei: string; + programid: string; + program: Program; + + error = false; nbAttempt = 0; + kataStatus = ''; kataInfo: KataSubscription; compiling = false; isResolved = false; filename = ''; assertname = ''; - nbAttemptBeforeSurreding: number; - newTry = false; + newTry = false; katareceived = false; - assert = true; + LANG: Canva; @@ -55,11 +59,11 @@ export class KataComponent implements OnInit { private alertService: AlertService, private kataSubscriptionService: KataSubscriptionService, private auth: AuthenticationService, - private router: Router + private router: Router, + public dialog: MatDialog ) { } - getLANG(id: string): void { this.LANG = this.langservice.getLANG(id)[0]; this.assertname = this.LANG.assertname; @@ -68,13 +72,12 @@ export class KataComponent implements OnInit { getKata(): void { this.ngxLoader.start(); - this.programService.getDetails(this.programID).subscribe((data: string[]) => { - this.programSensei = data[2]; - this.programTitle = data[0]; - this.kataService.getKata(this.programID, this.idKata).subscribe((datas: Kata) => { + this.programService.getById(this.programid).subscribe((data: Program) => { + this.program = data; + this.kataService.getKata(this.kataid).subscribe((datas: Kata) => { this.kata = datas; - this.assert = !datas.keepAssert; - this.nbAttemptBeforeSurreding = datas.nbAttempt; + this.kata.keepAssert = !datas.keepAssert; + this.getLANG(this.kata.language); this.ngxLoader.stop(); this.getSubscription(); @@ -99,23 +102,29 @@ export class KataComponent implements OnInit { this.alertService.info('This won\'t affect your overall score'); } - Surrender() { - if (this.nbAttempt >= this.nbAttemptBeforeSurreding) { - if (confirm('Are you sure you want to surrender ? the solution will be displayed but you won\'t be able to make xp on this kata again.')) { - this.kataSubscriptionService.update(JSON.stringify({ - kataid: this.idKata, - programid: this.programID, - userid: this.auth.currentUserValue.id, - sol: this.kata.solution, - status: 'FAILED' - })).subscribe(() => { - this.kata.canva = this.kata.solution; - this.kataStatus = 'FAILED'; - this.isResolved = true; - }); - } + openDialog(): void { + if (this.nbAttempt >= this.kata.nbAttempt) { + const dialogRef = this.dialog.open(KataSurrenderDialogComponent, { + width: '400px' + }); + + dialogRef.afterClosed().subscribe(result => { + if (result) { + this.kataSubscriptionService.update(JSON.stringify({ + kataid: this.kataid, + programid: this.programid, + userid: this.auth.currentUserValue.id, + sol: this.kata.solution, + status: 'FAILED' + })).subscribe(() => { + this.kata.canva = this.kata.solution; + this.kataStatus = 'FAILED'; + this.isResolved = true; + }); + } + }); } else { - this.alertService.warning('Oh.. Looks like you did not try enough !\nThe surrender options is unlock at ' + this.nbAttemptBeforeSurreding + ' tries for this kata.'); + this.alertService.warning('Oh.. Looks like you did not try enough !\nThe surrender options is unlocked at ' + this.kata.nbAttempt + ' tries for this kata.'); } } @@ -137,16 +146,16 @@ export class KataComponent implements OnInit { if (!this.isResolved && !this.newTry) { this.nbAttempt++; this.kataSubscriptionService.increment(JSON.stringify({ - kataid: this.idKata, - programid: this.programID, + kataid: this.kataid, + programid: this.programid, userid: this.auth.currentUserValue.id })).subscribe(() => { if (response.exit === 0) { this.kataStatus = 'RESOLVED'; this.kataSubscriptionService.update(JSON.stringify({ - kataid: this.idKata, - programid: this.programID, + kataid: this.kataid, + programid: this.programid, userid: this.auth.currentUserValue.id, sol: stream, status: this.kataStatus @@ -160,7 +169,7 @@ export class KataComponent implements OnInit { this.status = 1; this.result = response.error; this.alertService.danger('Run failed !'); - if (this.nbAttempt >= this.nbAttemptBeforeSurreding) { + if (this.nbAttempt === this.kata.nbAttempt) { this.alertService.info('Solution unlocked ! you can now surrender peasant.'); } } @@ -184,35 +193,60 @@ export class KataComponent implements OnInit { } getSubscription() { - this.kataSubscriptionService.get(this.idKata, this.programID, this.auth.currentUserValue.id).subscribe((data: KataSubscription) => { - this.kataInfo = data; - this.nbAttempt = this.kataInfo.nbAttempt; - this.kataStatus = this.kataInfo.status; - if (this.kataInfo.status === 'RESOLVED' || this.kataInfo.status === 'FAILED') { - this.isResolved = true; - this.kata.canva = this.kataInfo.mysol; - } - }, error1 => { - if (error1.status === 404) { - this.kataSubscriptionService.create(JSON.stringify({ - id: uuid(), - kataid: this.idKata, - programid: this.programID, - userid: this.auth.currentUserValue.id - })).subscribe(() => { - this.nbAttempt = 0; - this.kataStatus = 'ON-GOING'; - }); - } else { - this.router.navigate([/kata-displayer/ + this.programID]); - } + this.kataSubscriptionService.isSubscribed(this.auth.currentUserValue.id, this.programid).subscribe((isSubscribed: boolean) => { + this.kataService.isActivated(this.kataid).subscribe((data: boolean) => { + if (!isSubscribed || !data) { + this.router.navigate([/kata-displayer/ + this.programid]); + } else { + this.kataSubscriptionService.get(this.kataid, this.programid, this.auth.currentUserValue.id).subscribe((data: KataSubscription) => { + this.kataInfo = data; + this.nbAttempt = this.kataInfo.nbAttempt; + this.kataStatus = this.kataInfo.status; + if (this.kataInfo.status === 'RESOLVED' || this.kataInfo.status === 'FAILED') { + this.isResolved = true; + this.kata.canva = this.kataInfo.mysol; + } + }, error1 => { + if (error1.status === 404) { + this.kataSubscriptionService.create(JSON.stringify({ + id: uuid(), + kataid: this.kataid, + programid: this.programid, + userid: this.auth.currentUserValue.id + })).subscribe(() => { + this.nbAttempt = 0; + this.kataStatus = 'ONGOING'; + }); + } + }); + } + }); }); + } ngOnInit() { - this.programID = this.route.snapshot.paramMap.get('prid'); - this.idKata = this.route.snapshot.paramMap.get('id'); + this.programid = this.route.snapshot.paramMap.get('prid'); + this.kataid = this.route.snapshot.paramMap.get('id'); this.getKata(); } } + +@Component({ + selector: 'dialog-overview-example-dialog', + templateUrl: 'kata-dialog-surrender.html', +}) +export class KataSurrenderDialogComponent { + + constructor( + public dialogRef: MatDialogRef<KataSurrenderDialogComponent>, + @Inject(MAT_DIALOG_DATA) public data: string) { + } + + onNoClick(): void { + this.dialogRef.close(); + } + +} + diff --git a/client/src/app/component/kata/kata.ts b/client/src/app/component/kata/kata.ts index 603cb6b73cfd41b5dcf52350587485559be85614..4f66d8c0f2bc64d5a07bc5e65c49883892fa6950 100644 --- a/client/src/app/component/kata/kata.ts +++ b/client/src/app/component/kata/kata.ts @@ -8,6 +8,6 @@ export interface Kata { cassert: string; keepAssert: boolean; nbAttempt: number; - programID: string; difficulty: string; + activated: boolean; } diff --git a/client/src/app/component/kata/kataMock.ts b/client/src/app/component/kata/kataMock.ts deleted file mode 100644 index 9e5cbbf391cf64d9909b7da52fcebdea2e15d72c..0000000000000000000000000000000000000000 --- a/client/src/app/component/kata/kataMock.ts +++ /dev/null @@ -1,21 +0,0 @@ -/* -import {Kata} from './kata'; - -// TODO un kata n'a pas besoin de programtitile, ca devrait être passé par la classe d'en dessus (idem pour sensei) -export const KATAS: Kata[] = [{ - id: 0, - language: 'python', - programTitle: 'Arrays in Python', - sensei: 'Orestis Pileas Malaspinas', - title: 'Multiplication par 2', - canva: 'def multiTwo(n):', - rules: 'Le but ici est de jouer avec les tableaux en python. dans cet exercice, il faut multiplier tous les éléments d\'un tableau par 2.\neasyline([2,4]) donnera par exemple [4,8]', - assert: 'from assertpy import assert_that\n' + - 'import sample as m\n' + - '\n' + - 'assert_that(m.multiTwo([1,2])).is_equal_to([2,4])\n' + - 'assert_that(m.multiTwo([45,53,12])).is_equal_to([90,106,24])\n' + - 'assert_that(m.multiTwo([3])).is_equal_to([6])', - solution: 'def multiTwo(n):\n' + ' return [i*2 for i in n]' -}]; -*/ diff --git a/client/src/app/component/login/login.component.ts b/client/src/app/component/login/login.component.ts index f6a108a040ab56ffcccf5ee0cc74b187f10ebb2c..2eae3dbf732a06d5604127e63c0413d1b9b7e37d 100644 --- a/client/src/app/component/login/login.component.ts +++ b/client/src/app/component/login/login.component.ts @@ -42,7 +42,8 @@ export class LoginComponent implements OnInit { .pipe(first()) .subscribe( data => { - this.router.navigate([this.returnUrl]); + console.log(this.returnUrl); + //this.router.navigate([this.returnUrl]); location.reload(); }, error => { diff --git a/client/src/app/component/main-left-side-nav/main-left-side-nav.component.html b/client/src/app/component/main-left-side-nav/main-left-side-nav.component.html index 4784723815466635aa1ef08f25c7b8d359e792c7..6fd7fb149e8df982ebf7f8fcc8507870762f87b8 100644 --- a/client/src/app/component/main-left-side-nav/main-left-side-nav.component.html +++ b/client/src/app/component/main-left-side-nav/main-left-side-nav.component.html @@ -1,11 +1,11 @@ <mat-sidenav-container class="sidenav-container"> - <mat-sidenav #drawer class="sidenav" fixedInViewport="true" + <mat-sidenav *ngIf="currentUser" #drawer class="sidenav" fixedInViewport="true" [attr.role]="(isHandset$ | async) ? 'dialog' : 'navigation'" [mode]="(isHandset$ | async) ? 'over' : 'side'" [opened]="!(isHandset$ | async)"> <mat-toolbar><a class="title" routerLink="/">DOJO HEPIA</a></mat-toolbar> <mat-nav-list *ngIf="currentUser"> - <a mat-list-item routerLink="/program/all" routerLinkActive="active-list-item">All programs</a> + <a mat-list-item routerLink="/program/all" routerLinkActive="active-list-item">Programs</a> <div *ngIf="currentUser.role != Role.monji"> <a mat-list-item routerLink="/program/create" routerLinkActive="active-list-item">New program</a> <a mat-list-item routerLink="/program/mine" routerLinkActive="active-list-item">My programs</a> diff --git a/client/src/app/component/program-create/program-create.component.html b/client/src/app/component/program-create/program-create.component.html index cf6ca8b0b02d53c1dbcb3a2183d4e2af5e906f0b..573ab8e0a78e742fb8d2c360993aa3529c0ce8e6 100644 --- a/client/src/app/component/program-create/program-create.component.html +++ b/client/src/app/component/program-create/program-create.component.html @@ -6,7 +6,7 @@ <div class="form-group"> <label for="title">Title</label> <input type="text" formControlName="title" class="form-control" - [ngClass]="{ 'is-invalid': submitted && f.title.errors }"/> + [ngClass]="{ 'is-invalid': submitted && f.title.errors }" value="dweksj"/> <div *ngIf="submitted && f.title.errors" class="invalid-feedback"> <div *ngIf="f.title.errors.required">Program needs a title</div> </div> @@ -21,6 +21,7 @@ <div *ngIf="submitted && f.language.errors" class="invalid-feedback"> <div *ngIf="f.language.errors.required">Program needs a language</div> </div> + </div> <div class="form-group"> <label for="description">Description</label> diff --git a/client/src/app/component/program-create/program-create.component.scss b/client/src/app/component/program-create/program-create.component.scss index c5adfa629aa3fb24ce45f1e3b379810ab1e8670b..09dd4163493b82d4fd054ec92f2ec24c21c10362 100644 --- a/client/src/app/component/program-create/program-create.component.scss +++ b/client/src/app/component/program-create/program-create.component.scss @@ -78,3 +78,7 @@ legend { } +.form-control:disabled{ +background-color: rgba(236, 240, 241, .05); +} + diff --git a/client/src/app/component/program-create/program-create.component.ts b/client/src/app/component/program-create/program-create.component.ts index 64f91823b75302294449b94df0f709b5eb9b5590..b42dffd7ca2c537e644905dc070cd1b974f22ddb 100644 --- a/client/src/app/component/program-create/program-create.component.ts +++ b/client/src/app/component/program-create/program-create.component.ts @@ -39,7 +39,7 @@ export class ProgramCreateComponent implements OnInit { return; } - this.programService.createProgram(JSON.stringify({ + this.programService.create(JSON.stringify({ id: this.programToKata, sensei: this.currentUser.username, language: this.f.language.value, @@ -50,16 +50,15 @@ export class ProgramCreateComponent implements OnInit { idsensei: this.currentUser.id, katas: [] })).subscribe(() => { - this.programSubscription.createSubscription(JSON.stringify({ + this.programSubscription.create(this.currentUser.id, JSON.stringify({ id: uuid(), - iduser: this.currentUser.id, idprogram: this.programToKata, status: true, nbKataDone: 0, katas: [] })).subscribe(() => { if (newkata) { - this.router.navigate(['/kata_create/' + this.programToKata + '/' + this.f.language.value + '']); + this.router.navigate(['/kata/create/' + this.programToKata + '/' + this.f.language.value + '']); } else { this.router.navigate(['/program/mine']); } diff --git a/client/src/app/component/program-displayer/card-displayer/card-displayer.component.css b/client/src/app/component/program-displayer/card-displayer/card-displayer.component.css index a9de49a9cbf3adc7ccb9639fc9a7117409aa8575..dd0fb14062fb308d002f1930a4608ff168741485 100644 --- a/client/src/app/component/program-displayer/card-displayer/card-displayer.component.css +++ b/client/src/app/component/program-displayer/card-displayer/card-displayer.component.css @@ -9,6 +9,10 @@ cursor: pointer; } +a{ + color: var(--color-cloud); +} + a:hover{ color: var(--color-cloud); } diff --git a/client/src/app/component/program-displayer/card-displayer/card-displayer.component.html b/client/src/app/component/program-displayer/card-displayer/card-displayer.component.html index 2eeda515c009a757cc857bfb17700f5b79eed5c4..08eff6162d38243733a0e6fc958979c1a255c0b5 100644 --- a/client/src/app/component/program-displayer/card-displayer/card-displayer.component.html +++ b/client/src/app/component/program-displayer/card-displayer/card-displayer.component.html @@ -4,7 +4,7 @@ <div *ngFor="let program of programs"> <div class="card"> <div class="card-body"> - <a routerLink="/kata-displayer/{{program.programID}}"><h5 class="card-title">{{program.title}}</h5></a> + <a routerLink="/kata-displayer/{{program.id}}"><h5 class="card-title">{{program.title}}</h5></a> <h6 class="card-subtitle mb-2 text-muted"><a><span (click)="querySearch('sensei',program.sensei)" class="sensei">{{program.sensei}}</span> </a> <a><span (click)="querySearch('language',program.language)" class="language">{{program.language}}</span></a> diff --git a/client/src/app/component/program-displayer/card-noneall-displayer/card-noneall-displayer.component.html b/client/src/app/component/program-displayer/card-noneall-displayer/card-noneall-displayer.component.html index 720470ddbed789f1b37c37c71d3fd0d332411616..0582f340bda33f1d0f41cc48344beb0472976653 100644 --- a/client/src/app/component/program-displayer/card-noneall-displayer/card-noneall-displayer.component.html +++ b/client/src/app/component/program-displayer/card-noneall-displayer/card-noneall-displayer.component.html @@ -4,7 +4,7 @@ <div *ngFor="let program of programs"> <div class="card"> <div class="card-body"> - <a routerLink="/kata-displayer/{{program.programID}}"><h5 class="card-title">{{program.title}}<span + <a routerLink="/kata-displayer/{{program.id}}"><h5 class="card-title">{{program.title}}<span style="float:right" [hidden]="program.nbKataDone == -1">{{+program.nbKataDone / +program.nbKata * 100}} %</span></h5></a> <h6 class="card-subtitle mb-2 text-muted"><a><span (click)="querySearch('sensei',program.sensei)" class="sensei">{{program.sensei}}</span> </a> diff --git a/client/src/app/component/program-displayer/card-noneall-displayer/card-noneall-displayer.component.ts b/client/src/app/component/program-displayer/card-noneall-displayer/card-noneall-displayer.component.ts index b4125f5ff0ee0e0892098fb06ee9a9ae907c5788..051c9c0cd747a40a5c60c02982f18fea80ae3123 100644 --- a/client/src/app/component/program-displayer/card-noneall-displayer/card-noneall-displayer.component.ts +++ b/client/src/app/component/program-displayer/card-noneall-displayer/card-noneall-displayer.component.ts @@ -25,7 +25,7 @@ export class CardNoneallDisplayerComponent implements OnInit { this.filter = true; this.programs = this.programs.filter((x) => { if (type === 'tags') { - return x[type].filter((t) => t === res); + return x[type].filter((t) => t === res)[0] === res; } return x[type] === res; }); diff --git a/client/src/app/component/program-displayer/program-displayer.component.ts b/client/src/app/component/program-displayer/program-displayer.component.ts index 59f45a0476af216f97a99cadca8e5f8a13fa7c64..08a3a7b0ea69c278d964506b677f541958930fe5 100644 --- a/client/src/app/component/program-displayer/program-displayer.component.ts +++ b/client/src/app/component/program-displayer/program-displayer.component.ts @@ -20,7 +20,7 @@ export class ProgramDisplayerComponent implements OnInit { getProgram(): void { this.ngxLoader.start(); - this.programService.getPrograms().subscribe((data: Program[]) => { + this.programService.get().subscribe((data: Program[]) => { this.programs = data; this.ngxLoader.stop(); }, error1 => { diff --git a/client/src/app/component/program-displayer/program.ts b/client/src/app/component/program-displayer/program.ts index 435246862b0da5dfbca7c52960a2d0fdd2e09462..c98a62be46feb102b00471c62bdb60d473ae774d 100644 --- a/client/src/app/component/program-displayer/program.ts +++ b/client/src/app/component/program-displayer/program.ts @@ -1,5 +1,5 @@ export interface Program { - programID: string; + id: string; title: string; language: string; sensei: string; diff --git a/client/src/app/component/program-displayer/programMock.ts b/client/src/app/component/program-displayer/programMock.ts deleted file mode 100644 index a505b6f54df64d27b2baef1b52111c39abd6b813..0000000000000000000000000000000000000000 --- a/client/src/app/component/program-displayer/programMock.ts +++ /dev/null @@ -1,23 +0,0 @@ -/*import {Program} from './program'; - -export const PROGRAMS: Program[] = [ - { - id: 0, - title: 'Arrays in Python', - language: 'python', - sensei: 'Orestis Pileas Malaspinas', - nbKata: 1, - description: 'Apprenez à jouer avec les tableaux en python', - tag: ['arrays', 'numbers'] - }, { - id: 1, - title: 'Let IO !', - language: 'java', - sensei: 'Stéphane Malandin', - nbKata: 2, - description: 'I/O in java', - tag: ['I/O', 'writeable'] - } -]; - -*/ diff --git a/client/src/app/component/program-edit/program-edit.component.html b/client/src/app/component/program-edit/program-edit.component.html new file mode 100644 index 0000000000000000000000000000000000000000..dc7a5d89491d7521659a3ef6b7ec4e72b9c4bb48 --- /dev/null +++ b/client/src/app/component/program-edit/program-edit.component.html @@ -0,0 +1,44 @@ +<div class="d-flex justify-content-center" *ngIf="program" style="margin-top:2%"> + <div class="d-flex flex-column"> + <fieldset> + <legend>Editing : {{program.title}}</legend> + <form [formGroup]="UpdateForm"> + <div class="form-group"> + <label for="title">Title</label> + <input [(ngModel)]="program.title" type="text" formControlName="title" class="form-control" + [ngClass]="{ 'is-invalid': submitted && f.title.errors }"/> + <div *ngIf="submitted && f.title.errors" class="invalid-feedback"> + <div *ngIf="f.title.errors.required">Program needs a title</div> + </div> + </div> + <div class="form-group"> + <label for="language">Targeted language</label> + <input value="{{program.language}}" type="text" [disabled]="true" class="form-control"/> + </div> + <div class="form-group"> + <label for="description">Description</label> + <textarea [(ngModel)]="program.description" class="form-control" formControlName="description" + [ngClass]="{ 'is-invalid': submitted && f.description.errors }"></textarea> + <div *ngIf="submitted && f.description.errors" class="invalid-feedback"> + <div *ngIf="f.description.errors.required">Program needs a description</div> + </div> + </div> + <div class="form-group"> + <label for="tags">Tags</label> + <input [(ngModel)]="program.tags" class="form-control" type="text" [ngClass]="{ 'is-invalid': submitted && f.tags.errors }" formControlName="tags" placeholder="format: tag1,tag2,.."/> + <div *ngIf="submitted && f.tags.errors" class="invalid-feedback"> + <div *ngIf="f.tags.errors.required">Program needs one or more tags</div> + </div> + </div> + <div class="form-group"> + <button mat-button routerLink="/kata-displayer/{{programid}}">Cancel</button> + <button mat-button class="button" (click)="save()" style="float:right">Save</button> + </div> + + </form> + </fieldset> + </div> + +</div> + +<span *ngIf="!program"><ngx-ui-loader></ngx-ui-loader></span> diff --git a/client/src/app/component/program-edit/program-edit.component.spec.ts b/client/src/app/component/program-edit/program-edit.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..4163b469032f8db1d97a298fd28f1f0c89d9da18 --- /dev/null +++ b/client/src/app/component/program-edit/program-edit.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ProgramEditComponent } from './program-edit.component'; + +describe('ProgramEditComponent', () => { + let component: ProgramEditComponent; + let fixture: ComponentFixture<ProgramEditComponent>; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ ProgramEditComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ProgramEditComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/client/src/app/component/program-edit/program-edit.component.ts b/client/src/app/component/program-edit/program-edit.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..c4736f4605e785cc7fb8248195b1e6882c28e8ab --- /dev/null +++ b/client/src/app/component/program-edit/program-edit.component.ts @@ -0,0 +1,61 @@ +import {Component, OnInit} from '@angular/core'; +import {FormBuilder, FormGroup, Validators} from '@angular/forms'; +import {ProgramService} from '../../services/program/program.service'; +import {ActivatedRoute, Router} from '@angular/router'; +import {Program} from '../program-displayer/program'; +import {AuthenticationService} from '../../services/auth/authentication.service'; +import {NgxUiLoaderService} from 'ngx-ui-loader'; + +@Component({ + selector: 'app-program-edit', + templateUrl: './program-edit.component.html', + styleUrls: ['../program-create/program-create.component.scss'] +}) +export class ProgramEditComponent implements OnInit { + + constructor(private formBuilder: FormBuilder, + private programService: ProgramService, + private router: Router, + private auth: AuthenticationService, + private route: ActivatedRoute, + private ngxLoader: NgxUiLoaderService) { + } + + UpdateForm: FormGroup; + program: Program; + submitted = false; + programid: string; + + get f() { + return this.UpdateForm.controls; + } + + save() { + this.program.description = this.f.description.value; + this.program.title = this.f.title.value; + this.program.tags = this.f.tags.value.toString().split(','); + this.programService.update(this.programid, this.program).subscribe(() => this.router.navigate(['/kata-displayer/' + this.programid + ''])); + } + + ngOnInit() { + this.ngxLoader.start(); + this.programid = this.route.snapshot.paramMap.get('id'); + this.programService.isOwner(this.programid, this.auth.currentUserValue.id).subscribe((data: boolean) => { + if (!data) { + this.router.navigate(['/']); + } else { + this.programService.getById(this.programid).subscribe((program: Program) => { + this.program = program; + this.ngxLoader.stop(); + }); + } + }); + + this.UpdateForm = this.formBuilder.group({ + title: ['', Validators.required], + description: ['', Validators.required], + tags: ['', Validators.required], + }); + } + +} diff --git a/client/src/app/component/signin/signin.component.html b/client/src/app/component/signin/signin.component.html index 8b449413c70d56f762cd4ffd251b2436503554b9..a2e77a24fcb7341177d92db497a08a588cc3f27c 100644 --- a/client/src/app/component/signin/signin.component.html +++ b/client/src/app/component/signin/signin.component.html @@ -1,28 +1,12 @@ <div class="container" style="margin-top:10%"> <form [formGroup]="signinForm" (ngSubmit)="onSubmit()"> - - <!-- <div class="form-group"> - <label for="firstname">First name</label> - <input type="text" formControlName="firstname" class="form-control" [ngClass]="{ 'is-invalid': submitted && f.firstname.errors }"/> - <div *ngIf="submitted && f.firstname.errors" class="invalid-feedback"> - <div *ngIf="f.firstname.errors.required">First name is required</div> - </div> - </div> - - <div class="form-group"> - <label for="lastname">Last name</label> - <input type="text" formControlName="lastname" class="form-control" [ngClass]="{ 'is-invalid': submitted && f.lastname.errors }"/> - <div *ngIf="submitted && f.lastname.errors" class="invalid-feedback"> - <div *ngIf="f.lastname.errors.required">Last name is required</div> - </div> - </div>--> - - <div class="form-group"> <label for="username">Username</label> - <input type="text" formControlName="username" class="form-control" [ngClass]="{ 'is-invalid': submitted && f.username.errors }"/> + <input type="text" pattern="[A-Za-z0-9-]*" formControlName="username" class="form-control" [ngClass]="{ 'is-invalid': submitted && f.username.errors }"/> <div *ngIf="submitted && f.username.errors" class="invalid-feedback"> <div *ngIf="f.username.errors.required">Username is required</div> + <div *ngIf="f.username.errors.pattern">Username can only contain numbers (0-9), letters (a-z, A-Z) and '-'</div> + <div *ngIf="f.username.errors.minlength">Username must contain at least 6 character</div> </div> </div> <div class="form-group"> @@ -30,6 +14,7 @@ <input type="password" formControlName="password" class="form-control" [ngClass]="{ 'is-invalid': submitted && f.password.errors }"/> <div *ngIf="submitted && f.password.errors" class="invalid-feedback"> <div *ngIf="f.password.errors.required">Password is required</div> + <div *ngIf="f.password.errors.minlength">Password must contain at least 6 character</div> </div> </div> <div class="form-group"> diff --git a/client/src/app/component/signin/signin.component.ts b/client/src/app/component/signin/signin.component.ts index 0b0de48c2c12a56de6c0950142ab5feeabf41318..92a0e804c790340d253ff54cb6d7b85f418bed0d 100644 --- a/client/src/app/component/signin/signin.component.ts +++ b/client/src/app/component/signin/signin.component.ts @@ -71,7 +71,7 @@ export class SigninComponent implements OnInit { this.signinForm = this.formBuilder.group({ // firstname: ['', Validators.required], // lastname: ['', Validators.required], - username: ['', Validators.required], + username: ['', Validators.required, Validators.pattern('[A-Za-z0-9-]*')], token: ['', null], password: ['', Validators.required] }); diff --git a/client/src/app/component/subscription/subscription.component.html b/client/src/app/component/subscription/subscription.component.html index 293248617134381cd9c82afce5ad6726cf155e13..29369509b799b1b6db327d69adeb4d3021cfcc68 100644 --- a/client/src/app/component/subscription/subscription.component.html +++ b/client/src/app/component/subscription/subscription.component.html @@ -1,8 +1,14 @@ <div class="container" *ngIf="programs"> <h1 style="margin:2rem 0 0 2rem;text-align: center">My subscription</h1> <hr> - <app-card-noneall-displayer [programs]="programs"></app-card-noneall-displayer> - + <div *ngIf="programsOngoing.length != 0"> + <h4 style="margin:2rem 0 0 2rem">Ongoing programs</h4> + <app-card-noneall-displayer [programs]="programsOngoing"></app-card-noneall-displayer> + </div> + <div *ngIf="programsDone.length != 0"> + <h4 style="margin:2rem 0 0 2rem">Done programs</h4> + <app-card-noneall-displayer [programs]="programsDone"></app-card-noneall-displayer> + </div> </div> <div *ngIf="programReceivedFailed"> diff --git a/client/src/app/component/subscription/subscription.component.ts b/client/src/app/component/subscription/subscription.component.ts index 1fff01a6173ea7f598bfddfec463c532de80b19f..87fbf1b2126c0cfcc5687545c08b4e4a83a260c0 100644 --- a/client/src/app/component/subscription/subscription.component.ts +++ b/client/src/app/component/subscription/subscription.component.ts @@ -12,6 +12,8 @@ import {ProgramSubscriptionService} from '../../services/program/subs/program-su export class SubscriptionComponent implements OnInit { programs: Program[]; + programsDone: Program[]; + programsOngoing: Program[]; programReceivedFailed = false; constructor(private programSubscription: ProgramSubscriptionService, private ngxLoader: NgxUiLoaderService, private auth: AuthenticationService) { @@ -21,11 +23,14 @@ export class SubscriptionComponent implements OnInit { this.ngxLoader.start(); this.programSubscription.getSubscription(this.auth.currentUserValue.id).subscribe((data: Program[]) => { - this.programs = data.filter((x) => x.sensei !== this.auth.currentUserValue.username); + this.programs = data; if (this.programs.length === 0) { this.programReceivedFailed = true; } + this.programsDone = this.programs.filter((x) => x.nbKataDone === x.nbKata); + this.programsOngoing = this.programs.filter((x) => x.nbKataDone !== x.nbKata); + this.ngxLoader.stop(); }, error1 => { if (error1.status === 404) { diff --git a/client/src/app/interfaces/subscriptions/ProgramSubscription.ts b/client/src/app/interfaces/subscriptions/ProgramSubscription.ts index 9ae38ba695b0e8d0f64f87d234041350230c2932..3d2a79456dafa3cda34bedcca27dbe56509dd9e1 100644 --- a/client/src/app/interfaces/subscriptions/ProgramSubscription.ts +++ b/client/src/app/interfaces/subscriptions/ProgramSubscription.ts @@ -3,7 +3,6 @@ import {KataSubscription} from './KataSubscription'; export interface ProgramSubscription { _id: string; id: string; - iduser: string; idprogram: string; status: boolean; nbKataDone: number; diff --git a/client/src/app/services/auth/authentication.service.ts b/client/src/app/services/auth/authentication.service.ts index f327743ad4bcc244be147043c852786a24197957..e76af42e1d9207a5c4d1bc6a46ef2805b516d5cf 100644 --- a/client/src/app/services/auth/authentication.service.ts +++ b/client/src/app/services/auth/authentication.service.ts @@ -19,7 +19,7 @@ export class AuthenticationService { } login(username: string, password: string) { - return this.http.post<any>('http://localhost:7000/jwt/request/', {username, password}) + return this.http.post<any>('http://localhost:7000/user/tokenrequest/', {username, password}) .pipe(map(user => { // login successful if there's a jwt token in the response if (user && user.token) { diff --git a/client/src/app/services/compilation/compilation.service.ts b/client/src/app/services/compilation/compilation.service.ts index 35844fd747051ddb9d1a5451515b931a67972404..f85ceb4979d00b2f73a3b11dd3e994ae95c12fc0 100644 --- a/client/src/app/services/compilation/compilation.service.ts +++ b/client/src/app/services/compilation/compilation.service.ts @@ -7,7 +7,7 @@ import {HttpClient} from '@angular/common/http'; export class CompilationService { compilationServer(obj: string) { - return this.http.post('http://localhost:7000/run/', obj); + return this.http.post('http://localhost:7000/kata/run/', obj); } constructor(private http: HttpClient) { diff --git a/client/src/app/services/kata/kata-subscription.service.ts b/client/src/app/services/kata/kata-subscription.service.ts index 45c3d54c7eb199faa28ce34084e5aa83add555d7..aed7e9cdcc952f6e74cfc901c494390f19de4b68 100644 --- a/client/src/app/services/kata/kata-subscription.service.ts +++ b/client/src/app/services/kata/kata-subscription.service.ts @@ -23,6 +23,10 @@ export class KataSubscriptionService { return this.http.post('http://localhost:7000/kata/update/subscription', obj); } + isSubscribed(userid: string, programid: string) { + return this.http.get('http://localhost:7000/program/issubscribed/' + userid + '/' + programid); + } + constructor(private http: HttpClient) { } } diff --git a/client/src/app/services/kata/kata.service.ts b/client/src/app/services/kata/kata.service.ts index a8b6aa8602df4cc22d6e6777a18ac067452f646d..7d2e96e87d30d9b358b8d09db38c27db719715f4 100644 --- a/client/src/app/services/kata/kata.service.ts +++ b/client/src/app/services/kata/kata.service.ts @@ -6,16 +6,36 @@ import {HttpClient} from '@angular/common/http'; }) export class KataService { - publish(obj: string) { - return this.http.post('http://localhost:7000/kata/create', obj); + publish(kata: string, programid: string) { + return this.http.post('http://localhost:7000/kata/create', {kata, programid}); } getKatasDetails(program: string, userid: string) { - return this.http.get('http://localhost:7000/program/getkatas/details/' + program + '/' + userid); + return this.http.get('http://localhost:7000/kata/details/' + program + '/' + userid); } - getKata(programID: string, kataID: string) { - return this.http.get('http://localhost:7000/program/getkata/' + programID + '/' + kataID + ''); + getKata(kataid: string) { + return this.http.get('http://localhost:7000/kata/' + kataid + ''); + } + + delete(kataid: string) { + return this.http.post('http://localhost:7000/kata/delete/', kataid); + } + + deactivate(kataid: string) { + return this.http.post('http://localhost:7000/kata/toggleactivation', kataid); + } + + isOwner(kataid: string, userid: string) { + return this.http.get('http://localhost:7000/kata/isowner/' + kataid + '/' + userid); + } + + update(obj: string) { + return this.http.post('http://localhost:7000/kata/update', obj); + } + + isActivated(kataid: string) { + return this.http.get('http://localhost:7000/kata/isactivated/' + kataid); } constructor(private http: HttpClient) { diff --git a/client/src/app/services/program/program.service.ts b/client/src/app/services/program/program.service.ts index e27a9295213c8df238b99e7e6196ba14ea96dd9a..9cba4b37cd120c28eb026a9e4de79b9e3dd317b9 100644 --- a/client/src/app/services/program/program.service.ts +++ b/client/src/app/services/program/program.service.ts @@ -1,27 +1,36 @@ import {Injectable} from '@angular/core'; import {HttpClient} from '@angular/common/http'; +import {Program} from '../../component/program-displayer/program'; @Injectable({ providedIn: 'root' }) export class ProgramService { - createProgram(obj: string) { + create(obj: string) { return this.http.post('http://localhost:7000/program/create', obj); } - getPrograms() { - return this.http.get('http://localhost:7000/program/getdetails'); + get() { + return this.http.get('http://localhost:7000/program/details'); } - getDetails(id: string) { - return this.http.get('http://localhost:7000/program/getdetails/' + id + ''); + getById(id: string) { + return this.http.get('http://localhost:7000/program/details/' + id + ''); } - deleteProgram(id: string) { + delete(id: string) { return this.http.post('http://localhost:7000/program/delete', JSON.stringify({programid: id})); } + isOwner(programid: string, userid: string) { + return this.http.get('http://localhost:7000/program/isowner/' + userid + '/' + programid); + } + + update(programid: string, program: Program) { + return this.http.post('http://localhost:7000/program/update', {programid, program}); + } + constructor(private http: HttpClient) { } } diff --git a/client/src/app/services/program/search/fetch-program-by-type.service.ts b/client/src/app/services/program/search/fetch-program-by-type.service.ts index 11466faabaf381ee974eee54aec64f4385d4bee2..aeea9308328ba12359b3824f6285ded4131e07d3 100644 --- a/client/src/app/services/program/search/fetch-program-by-type.service.ts +++ b/client/src/app/services/program/search/fetch-program-by-type.service.ts @@ -7,7 +7,7 @@ import {HttpClient} from '@angular/common/http'; export class FetchProgramByTypeService { getPrograms(type: string, res: string) { - return this.http.get('http://localhost:7000/search/' + type + '/' + res); + return this.http.get('http://localhost:7000/program/search/' + type + '/' + res); } diff --git a/client/src/app/services/program/subs/program-subscription.service.ts b/client/src/app/services/program/subs/program-subscription.service.ts index b5c40ec5ba5c1633be20839c2857163fb43524cc..440d00764584d58486eff9e7a79d776357791892 100644 --- a/client/src/app/services/program/subs/program-subscription.service.ts +++ b/client/src/app/services/program/subs/program-subscription.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import {Injectable} from '@angular/core'; import {HttpClient} from '@angular/common/http'; @Injectable({ @@ -6,20 +6,20 @@ import {HttpClient} from '@angular/common/http'; }) export class ProgramSubscriptionService { - createSubscription(obj: string) { - return this.http.post('http://localhost:7000/program/createsubscription', obj); + create(userid: string, obj: string) { + return this.http.post('http://localhost:7000/program/createsubscription', {userid, obj}); } getMine(userid: string) { - return this.http.get('http://localhost:7000/subscription/mine/' + userid + ''); + return this.http.get('http://localhost:7000/program/' + userid + ''); } getSubscription(userid: string) { - return this.http.get('http://localhost:7000/subscription/get/' + userid); + return this.http.get('http://localhost:7000/program/subscription/' + userid); } getSubs(programid: string, userid: string) { - return this.http.get('http://localhost:7000/program/getsubscription/' + programid + '/' + userid + ''); + return this.http.get('http://localhost:7000/program/subscription/' + programid + '/' + userid + ''); } toggle(obj: string) { diff --git a/client/src/styles.scss b/client/src/styles.scss index f28ad0c7c16fce2f85e4a6607286a6fe539906a6..b4b8e55cc1789928c8784c0be4ae700928d4c037 100644 --- a/client/src/styles.scss +++ b/client/src/styles.scss @@ -61,6 +61,22 @@ button:focus{ hr{ border: 1px solid var(--color-dark-blue); + margin:1rem 2rem 1rem 2rem; +} + +.mat-dialog-container { + background-color: var(--color-soft-light-blue); + color:var(--color-cloud) } +.markdown-output { +background-color: var(--color-dark-blue); + border: 2px solid rgba(44, 62, 80, 1.0); + overflow: scroll; + height: 680px; + width:500px; + max-height: 680px; + border-radius: 6px; + padding: 10px; +} diff --git a/compilation/.idea/workspace.xml b/compilation/.idea/workspace.xml index 6c357ed1ba298443e6379c17a22b5519c0e828bd..bb369879d56c6983fc878dab4687a3fd35e9b8b1 100644 --- a/compilation/.idea/workspace.xml +++ b/compilation/.idea/workspace.xml @@ -1,16 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <project version="4"> <component name="ChangeListManager"> - <list default="true" id="8d8fb2c1-8426-4933-8193-ee68625cf8de" name="Default Changelist" comment=""> - <change beforePath="$PROJECT_DIR$/../README.md" beforeDir="false" afterPath="$PROJECT_DIR$/../README.md" afterDir="false" /> - <change beforePath="$PROJECT_DIR$/../client/src/app/component/kata-displayer/kata-displayer.component.html" beforeDir="false" afterPath="$PROJECT_DIR$/../client/src/app/component/kata-displayer/kata-displayer.component.html" afterDir="false" /> - <change beforePath="$PROJECT_DIR$/src/main/java/DockerCompilation.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/DockerCompilation.java" afterDir="false" /> - <change beforePath="$PROJECT_DIR$/../gateway/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/../gateway/.idea/workspace.xml" afterDir="false" /> - <change beforePath="$PROJECT_DIR$/../gateway/src/main/java/MongoDB.java" beforeDir="false" afterPath="$PROJECT_DIR$/../gateway/src/main/java/MongoDB.java" afterDir="false" /> - <change beforePath="$PROJECT_DIR$/../gateway/src/main/java/app.java" beforeDir="false" afterPath="$PROJECT_DIR$/../gateway/src/main/java/app.java" afterDir="false" /> - <change beforePath="$PROJECT_DIR$/../gateway/target/classes/MongoDB.class" beforeDir="false" afterPath="$PROJECT_DIR$/../gateway/target/classes/MongoDB.class" afterDir="false" /> - <change beforePath="$PROJECT_DIR$/../gateway/target/classes/app.class" beforeDir="false" afterPath="$PROJECT_DIR$/../gateway/target/classes/app.class" afterDir="false" /> - </list> + <list default="true" id="8d8fb2c1-8426-4933-8193-ee68625cf8de" name="Default Changelist" comment="" /> <ignored path="$PROJECT_DIR$/out/" /> <ignored path="$PROJECT_DIR$/target/" /> <option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" /> @@ -23,17 +14,7 @@ <option name="isMigrated" value="true" /> </component> <component name="FileEditorManager"> - <leaf SIDE_TABS_SIZE_LIMIT_KEY="300"> - <file pinned="false" current-in-tab="true"> - <entry file="file://$PROJECT_DIR$/src/main/java/DockerCompilation.java"> - <provider selected="true" editor-type-id="text-editor"> - <state relative-caret-position="247"> - <caret line="20" column="114" selection-start-line="20" selection-start-column="114" selection-end-line="20" selection-end-column="114" /> - </state> - </provider> - </entry> - </file> - </leaf> + <leaf /> </component> <component name="FileTemplateManagerImpl"> <option name="RECENT_TEMPLATES"> @@ -68,10 +49,9 @@ </MavenImportingSettings> </option> </component> - <component name="ProjectFrameBounds" extendedState="6" fullScreen="true"> - <option name="y" value="23" /> - <option name="width" value="1920" /> - <option name="height" value="1121" /> + <component name="ProjectFrameBounds" fullScreen="true"> + <option name="width" value="954" /> + <option name="height" value="1200" /> </component> <component name="ProjectLevelVcsManager" settingsEditedManually="true" /> <component name="ProjectView"> @@ -79,7 +59,7 @@ <foldersAlwaysOnTop value="true" /> </navigator> <panes> - <pane id="PackagesPane" /> + <pane id="Scope" /> <pane id="ProjectPane"> <subPane> <expand> @@ -92,11 +72,35 @@ <item name="compilation" type="462c0819:PsiDirectoryNode" /> <item name="share_docker_file" type="462c0819:PsiDirectoryNode" /> </path> + <path> + <item name="compilation" type="b2602c69:ProjectViewProjectNode" /> + <item name="compilation" type="462c0819:PsiDirectoryNode" /> + <item name="src" type="462c0819:PsiDirectoryNode" /> + </path> + <path> + <item name="compilation" type="b2602c69:ProjectViewProjectNode" /> + <item name="compilation" type="462c0819:PsiDirectoryNode" /> + <item name="src" type="462c0819:PsiDirectoryNode" /> + <item name="main" type="462c0819:PsiDirectoryNode" /> + </path> + <path> + <item name="compilation" type="b2602c69:ProjectViewProjectNode" /> + <item name="compilation" type="462c0819:PsiDirectoryNode" /> + <item name="src" type="462c0819:PsiDirectoryNode" /> + <item name="main" type="462c0819:PsiDirectoryNode" /> + <item name="java" type="462c0819:PsiDirectoryNode" /> + </path> + <path> + <item name="compilation" type="b2602c69:ProjectViewProjectNode" /> + <item name="compilation" type="462c0819:PsiDirectoryNode" /> + <item name="src" type="462c0819:PsiDirectoryNode" /> + <item name="test" type="462c0819:PsiDirectoryNode" /> + </path> </expand> <select /> </subPane> </pane> - <pane id="Scope" /> + <pane id="PackagesPane" /> </panes> </component> <component name="PropertiesComponent"> @@ -199,11 +203,28 @@ <workItem from="1557931166779" duration="192000" /> <workItem from="1557988860203" duration="849000" /> <workItem from="1558017128365" duration="97000" /> + <workItem from="1558030078148" duration="202000" /> + <workItem from="1558084475254" duration="208000" /> + <workItem from="1558333722642" duration="2241000" /> + <workItem from="1558371760302" duration="207000" /> + <workItem from="1558420145734" duration="2681000" /> + <workItem from="1558506362151" duration="2227000" /> + <workItem from="1558594362417" duration="2527000" /> + <workItem from="1558618819750" duration="404000" /> + <workItem from="1558678823354" duration="477000" /> + <workItem from="1558686906594" duration="593000" /> + <workItem from="1558688532907" duration="1316000" /> + <workItem from="1558704495966" duration="1103000" /> + <workItem from="1558939614514" duration="553000" /> + <workItem from="1558958789221" duration="925000" /> + <workItem from="1559024581666" duration="529000" /> + <workItem from="1559030399057" duration="613000" /> + <workItem from="1559111518428" duration="363000" /> </task> <servers /> </component> <component name="TimeTrackingManager"> - <option name="totallyTimeSpent" value="42051000" /> + <option name="totallyTimeSpent" value="59220000" /> </component> <component name="TodoView"> <todo-panel id="selected-file"> @@ -215,9 +236,10 @@ </todo-panel> </component> <component name="ToolWindowManager"> - <frame x="0" y="0" width="1440" height="900" extended-state="6" /> + <frame x="0" y="0" width="1920" height="1200" extended-state="0" /> + <editor active="true" /> <layout> - <window_info content_ui="combo" id="Project" order="0" visible="true" weight="0.3490701" /> + <window_info content_ui="combo" id="Project" order="0" weight="0.4084132" /> <window_info id="Structure" order="1" side_tool="true" weight="0.25" /> <window_info id="Image Layers" order="2" /> <window_info id="Designer" order="3" /> @@ -226,7 +248,7 @@ <window_info id="Favorites" order="6" side_tool="true" /> <window_info anchor="bottom" id="Message" order="0" /> <window_info anchor="bottom" id="Find" order="1" weight="0.32891566" /> - <window_info anchor="bottom" id="Run" order="2" weight="0.21927711" /> + <window_info anchor="bottom" id="Run" order="2" weight="0.41061947" /> <window_info anchor="bottom" id="Debug" order="3" weight="0.3987952" /> <window_info anchor="bottom" id="Cvs" order="4" weight="0.25" /> <window_info anchor="bottom" id="Inspection" order="5" weight="0.4" /> @@ -296,16 +318,6 @@ <component name="editorHistoryManager"> <entry file="file://$PROJECT_DIR$/share_docker_file/test.txt" /> <entry file="file://$PROJECT_DIR$/docker/java/files/java_test.sh" /> - <entry file="file://$PROJECT_DIR$/src/main/java/HostCompilation.java"> - <provider selected="true" editor-type-id="text-editor"> - <state relative-caret-position="382"> - <caret line="42" column="40" selection-start-line="42" selection-start-column="34" selection-end-line="42" selection-end-column="40" /> - <folding> - <element signature="imports" expanded="true" /> - </folding> - </state> - </provider> - </entry> <entry file="file://$PROJECT_DIR$/docker/java/dockerfile"> <provider selected="true" editor-type-id="text-editor"> <state relative-caret-position="105"> @@ -322,13 +334,6 @@ </entry> <entry file="file://$PROJECT_DIR$/share_docker_file/sample.py" /> <entry file="file://$PROJECT_DIR$/share_docker_file/assert.py" /> - <entry file="file://$PROJECT_DIR$/src/main/java/app.java"> - <provider selected="true" editor-type-id="text-editor"> - <state relative-caret-position="195"> - <caret line="14" lean-forward="true" selection-start-line="14" selection-end-line="14" /> - </state> - </provider> - </entry> <entry file="file://$PROJECT_DIR$/pom.xml"> <provider selected="true" editor-type-id="text-editor"> <state> @@ -348,13 +353,33 @@ </entry> <entry file="file://$PROJECT_DIR$/share_docker_file/kata.java" /> <entry file="file://$PROJECT_DIR$/share_docker_file/Main.java" /> + <entry file="file://$PROJECT_DIR$/share_docker_file/Main.class"> + <provider selected="true" editor-type-id="text-editor" /> + </entry> + <entry file="file://$PROJECT_DIR$/src/main/java/app.java"> + <provider selected="true" editor-type-id="text-editor"> + <state relative-caret-position="195"> + <caret line="14" selection-start-line="14" selection-end-line="14" /> + </state> + </provider> + </entry> <entry file="file://$PROJECT_DIR$/src/main/java/DockerCompilation.java"> <provider selected="true" editor-type-id="text-editor"> - <state relative-caret-position="247"> + <state relative-caret-position="255"> <caret line="20" column="114" selection-start-line="20" selection-start-column="114" selection-end-line="20" selection-end-column="114" /> </state> </provider> </entry> + <entry file="file://$PROJECT_DIR$/src/main/java/HostCompilation.java"> + <provider selected="true" editor-type-id="text-editor"> + <state relative-caret-position="240"> + <caret line="16" column="44" selection-start-line="16" selection-start-column="44" selection-end-line="16" selection-end-column="44" /> + <folding> + <element signature="imports" expanded="true" /> + </folding> + </state> + </provider> + </entry> </component> <component name="masterDetails"> <states> diff --git a/compilation/share_docker_file/Kata.class b/compilation/share_docker_file/Kata.class index 117730112f0014d3a78257896966d9e5bfdd28e0..47afd6e8b052133e04156ff2022f3f96c3f4c335 100644 Binary files a/compilation/share_docker_file/Kata.class and b/compilation/share_docker_file/Kata.class differ diff --git a/compilation/share_docker_file/Main.class b/compilation/share_docker_file/Main.class index 1851a4bf47c7c830118373aec92396149a74c6f1..344f6444558eccc6b29fe3bde8cd7092bc7f10c0 100644 Binary files a/compilation/share_docker_file/Main.class and b/compilation/share_docker_file/Main.class differ diff --git a/compilation/share_docker_file/__pycache__/sample.cpython-34.pyc b/compilation/share_docker_file/__pycache__/sample.cpython-34.pyc index 761d5e6c7dbaefd90fde4b7528c6b7aa017d8f2e..1a7ac70068df5596fcfa6f21dd6d17ddc61d35cc 100644 Binary files a/compilation/share_docker_file/__pycache__/sample.cpython-34.pyc and b/compilation/share_docker_file/__pycache__/sample.cpython-34.pyc differ diff --git a/compilation/target/05-1.0-SNAPSHOT.jar b/compilation/target/05-1.0-SNAPSHOT.jar index b508109229c066d7fc6c9596d60c715150eb7f78..af4b86bf0747b3f69c6c5ffcda38b4825ae014d3 100644 Binary files a/compilation/target/05-1.0-SNAPSHOT.jar and b/compilation/target/05-1.0-SNAPSHOT.jar differ diff --git a/gateway/.idea/workspace.xml b/gateway/.idea/workspace.xml index 8776e03cd3f006ef5c3b2a1ef42a13175b6b61da..189a1dfc2a709b61664da7faf532711ee6d2dc13 100644 --- a/gateway/.idea/workspace.xml +++ b/gateway/.idea/workspace.xml @@ -1,15 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <project version="4"> <component name="ChangeListManager"> - <list default="true" id="e6a1f2e5-4f60-4227-82bb-83eb10fa94a5" name="Default Changelist" comment=""> - <change beforePath="$PROJECT_DIR$/../README.md" beforeDir="false" afterPath="$PROJECT_DIR$/../README.md" afterDir="false" /> - <change beforePath="$PROJECT_DIR$/../client/src/app/component/kata-displayer/kata-displayer.component.html" beforeDir="false" afterPath="$PROJECT_DIR$/../client/src/app/component/kata-displayer/kata-displayer.component.html" afterDir="false" /> - <change beforePath="$PROJECT_DIR$/../compilation/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/../compilation/.idea/workspace.xml" afterDir="false" /> - <change beforePath="$PROJECT_DIR$/../compilation/src/main/java/DockerCompilation.java" beforeDir="false" afterPath="$PROJECT_DIR$/../compilation/src/main/java/DockerCompilation.java" afterDir="false" /> - <change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" /> - <change beforePath="$PROJECT_DIR$/src/main/java/MongoDB.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/MongoDB.java" afterDir="false" /> - <change beforePath="$PROJECT_DIR$/src/main/java/app.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/app.java" afterDir="false" /> - </list> + <list default="true" id="e6a1f2e5-4f60-4227-82bb-83eb10fa94a5" name="Default Changelist" comment="" /> <ignored path="$PROJECT_DIR$/out/" /> <ignored path="$PROJECT_DIR$/target/" /> <option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" /> @@ -37,60 +29,78 @@ </component> <component name="FileEditorManager"> <leaf SIDE_TABS_SIZE_LIMIT_KEY="300"> - <file pinned="false" current-in-tab="true"> - <entry file="file://$PROJECT_DIR$/src/main/java/app.java"> + <file pinned="false" current-in-tab="false"> + <entry file="file://$PROJECT_DIR$/src/main/java/ch/hepia/repository/cursors/Programs.java"> <provider selected="true" editor-type-id="text-editor"> - <state relative-caret-position="210"> - <caret line="30" column="79" lean-forward="true" selection-start-line="30" selection-start-column="79" selection-end-line="30" selection-end-column="79" /> - <folding> - <element signature="imports" expanded="true" /> - </folding> + <state relative-caret-position="60"> + <caret line="4" selection-start-line="4" selection-end-line="4" /> + </state> + </provider> + </entry> + </file> + <file pinned="false" current-in-tab="false"> + <entry file="file://$PROJECT_DIR$/src/main/java/ch/hepia/repository/cursors/UserInterface.java"> + <provider selected="true" editor-type-id="text-editor"> + <state relative-caret-position="60"> + <caret line="4" column="18" selection-start-line="4" selection-start-column="18" selection-end-line="4" selection-end-column="18" /> </state> </provider> </entry> </file> <file pinned="false" current-in-tab="false"> - <entry file="file://$PROJECT_DIR$/src/main/java/MongoDB.java"> + <entry file="file://$PROJECT_DIR$/src/main/java/ch/hepia/repository/cursors/ProgramInterface.java"> + <provider selected="true" editor-type-id="text-editor"> + <state relative-caret-position="45"> + <caret line="3" lean-forward="true" selection-start-line="3" selection-end-line="3" /> + </state> + </provider> + </entry> + </file> + <file pinned="false" current-in-tab="true"> + <entry file="file://$PROJECT_DIR$/src/main/java/ch/hepia/repository/ProgramsDataBase.java"> <provider selected="true" editor-type-id="text-editor"> - <state relative-caret-position="678"> - <caret line="283" selection-start-line="283" selection-end-line="283" /> + <state relative-caret-position="813"> + <caret line="62" lean-forward="true" selection-start-line="62" selection-end-line="62" /> <folding> <element signature="imports" expanded="true" /> - <element signature="e#12452#12453#0" expanded="true" /> - <element signature="e#12528#12529#0" expanded="true" /> </folding> </state> </provider> </entry> </file> <file pinned="false" current-in-tab="false"> - <entry file="file://$PROJECT_DIR$/src/main/java/LiveDB.java"> + <entry file="file://$PROJECT_DIR$/src/main/java/ch/hepia/repository/cursors/Users.java"> <provider selected="true" editor-type-id="text-editor"> - <state relative-caret-position="660"> - <caret line="46" selection-start-line="46" selection-end-line="46" /> + <state relative-caret-position="90"> + <caret line="6" column="19" selection-start-line="6" selection-start-column="19" selection-end-line="6" selection-end-column="19" /> + <folding> + <element signature="imports" expanded="true" /> + </folding> </state> </provider> </entry> </file> <file pinned="false" current-in-tab="false"> - <entry file="file://$PROJECT_DIR$/src/main/java/MockUser.java"> + <entry file="file://$PROJECT_DIR$/src/main/java/App.java"> <provider selected="true" editor-type-id="text-editor"> - <state relative-caret-position="150"> - <caret line="10" column="22" selection-start-line="10" selection-start-column="22" selection-end-line="10" selection-end-column="22" /> + <state relative-caret-position="5265"> + <caret line="351" column="21" selection-start-line="351" selection-start-column="21" selection-end-line="351" selection-end-column="21" /> + <folding> + <element signature="imports" expanded="true" /> + </folding> </state> </provider> </entry> </file> <file pinned="false" current-in-tab="false"> - <entry file="file://$PROJECT_DIR$/src/main/java/Program.java"> + <entry file="file://$PROJECT_DIR$/src/main/java/ch/hepia/repository/MongoDB.java"> <provider selected="true" editor-type-id="text-editor"> - <state relative-caret-position="45"> - <caret line="3" column="47" selection-start-line="3" selection-start-column="42" selection-end-line="3" selection-end-column="47" /> + <state relative-caret-position="607"> + <caret line="384" column="49" selection-start-line="384" selection-start-column="49" selection-end-line="384" selection-end-column="49" /> <folding> - <element signature="e#1540#1541#0" expanded="true" /> - <element signature="e#1571#1572#0" expanded="true" /> - <element signature="e#1619#1620#0" expanded="true" /> - <element signature="e#1659#1660#0" expanded="true" /> + <element signature="imports" expanded="true" /> + <element signature="e#17136#17137#0" expanded="true" /> + <element signature="e#17208#17209#0" expanded="true" /> </folding> </state> </provider> @@ -107,18 +117,43 @@ </component> <component name="FindInProjectRecents"> <findStrings> - <find>handler</find> - <find>get_id</find> - <find>slee</find> - <find>thread</find> - <find>out</find> - <find>println</find> - <find>programid</find> - <find>idprogram</find> + <find>402</find> + <find>subc</find> + <find>dele</find> + <find>push</find> + <find>isSubs</find> + <find>upd</find> + <find>details</find> <find>programID</find> - <find>sea</find> - <find>dou</find> + <find>getProgramID</find> + <find>katashowcase</find> + <find>togg</find> + <find>increment</find> + <find>decre</find> + <find>decrement</find> + <find>tog</find> + <find>toggle</find> + <find>isOw</find> + <find>kata</find> + <find>kata/up</find> + <find>program/upda</find> + <find>ON-G</find> + <find>update</find> + <find>ac</find> + <find>activated</find> + <find>issu</find> + <find>subscr</find> + <find>issub</find> + <find>status</find> + <find>ch.hepia.repository.modals.interfaces.Users</find> + <find>ch/hepia/repository/modals/</find> </findStrings> + <replaceStrings> + <replace>Users</replace> + </replaceStrings> + <dirStrings> + <dir>$PROJECT_DIR$/.idea</dir> + </dirStrings> </component> <component name="Git.Settings"> <option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$/.." /> @@ -128,20 +163,37 @@ <list> <option value="$PROJECT_DIR$/src/main/java/programManagement.java" /> <option value="$PROJECT_DIR$/src/main/java/liveDB.java" /> - <option value="$PROJECT_DIR$/src/main/java/KataShowCase.java" /> <option value="$PROJECT_DIR$/src/main/java/JWT.java" /> <option value="$PROJECT_DIR$/src/main/java/JWToken.java" /> <option value="$PROJECT_DIR$/pom.xml" /> <option value="$PROJECT_DIR$/src/main/java/Program.java" /> - <option value="$PROJECT_DIR$/src/main/java/Kata.java" /> <option value="$PROJECT_DIR$/src/main/java/KataSubscription.java" /> - <option value="$PROJECT_DIR$/src/main/java/ProgramSubscription.java" /> - <option value="$PROJECT_DIR$/src/main/java/ProgramShowCase.java" /> - <option value="$PROJECT_DIR$/src/main/java/ProgramsDataBase.java" /> - <option value="$PROJECT_DIR$/src/main/java/LiveDB.java" /> <option value="$PROJECT_DIR$/src/main/java/MockUser.java" /> - <option value="$PROJECT_DIR$/src/main/java/MongoDB.java" /> + <option value="$PROJECT_DIR$/src/main/java/LiveDB.java" /> + <option value="$PROJECT_DIR$/src/main/java/Katatest.java" /> + <option value="$PROJECT_DIR$/src/main/java/Kata.java" /> + <option value="$PROJECT_DIR$/src/main/java/KataShowCase.java" /> + <option value="$PROJECT_DIR$/src/main/java/ProgramShowCase.java" /> + <option value="$PROJECT_DIR$/src/main/java/ProgramSubscription.java" /> + <option value="$PROJECT_DIR$/src/main/java/User.java" /> <option value="$PROJECT_DIR$/src/main/java/app.java" /> + <option value="$PROJECT_DIR$/src/main/java/MongoDB.java" /> + <option value="$PROJECT_DIR$/src/main/java/ProgramsDataBase.java" /> + <option value="$PROJECT_DIR$/src/main/java/User/User.java" /> + <option value="$PROJECT_DIR$/src/main/java/Kata/Kata.java" /> + <option value="$PROJECT_DIR$/src/main/java/Kata/KataShowCase.java" /> + <option value="$PROJECT_DIR$/src/main/java/Program/ProgramShowCase.java" /> + <option value="$PROJECT_DIR$/src/main/java/MongoDataBase/MongoDB.java" /> + <option value="$PROJECT_DIR$/src/main/java/MongoDataBase/ProgramsDataBase.java" /> + <option value="$PROJECT_DIR$/src/main/java/ch/hepia/database/ProgramsDataBase.java" /> + <option value="$PROJECT_DIR$/src/main/java/Users.java" /> + <option value="$PROJECT_DIR$/src/main/java/ch/hepia/repository/MongoDB.java" /> + <option value="$PROJECT_DIR$/src/main/java/ch/hepia/repository/cursors/Users.java" /> + <option value="$PROJECT_DIR$/src/main/java/App.java" /> + <option value="$PROJECT_DIR$/src/main/java/ch/hepia/repository/modals/interfaces/Users.java" /> + <option value="$PROJECT_DIR$/src/main/java/ch/hepia/repository/cursors/UserInterface.java" /> + <option value="$PROJECT_DIR$/src/main/java/ch/hepia/repository/cursors/ProgramInterface.java" /> + <option value="$PROJECT_DIR$/src/main/java/ch/hepia/repository/ProgramsDataBase.java" /> </list> </option> </component> @@ -172,9 +224,8 @@ </option> </component> <component name="ProjectFrameBounds" fullScreen="true"> - <option name="y" value="23" /> - <option name="width" value="1920" /> - <option name="height" value="1121" /> + <option name="width" value="954" /> + <option name="height" value="1200" /> </component> <component name="ProjectLevelVcsManager" settingsEditedManually="true"> <ConfirmationsSetting value="1" id="Add" /> @@ -183,7 +234,56 @@ <navigator proportions="" version="1"> <foldersAlwaysOnTop value="true" /> </navigator> - <panes /> + <panes> + <pane id="Scope" /> + <pane id="PackagesPane" /> + <pane id="ProjectPane"> + <subPane> + <expand> + <path> + <item name="gateway" type="b2602c69:ProjectViewProjectNode" /> + <item name="gateway" type="462c0819:PsiDirectoryNode" /> + </path> + <path> + <item name="gateway" type="b2602c69:ProjectViewProjectNode" /> + <item name="gateway" type="462c0819:PsiDirectoryNode" /> + <item name="src" type="462c0819:PsiDirectoryNode" /> + </path> + <path> + <item name="gateway" type="b2602c69:ProjectViewProjectNode" /> + <item name="gateway" type="462c0819:PsiDirectoryNode" /> + <item name="src" type="462c0819:PsiDirectoryNode" /> + <item name="main" type="462c0819:PsiDirectoryNode" /> + </path> + <path> + <item name="gateway" type="b2602c69:ProjectViewProjectNode" /> + <item name="gateway" type="462c0819:PsiDirectoryNode" /> + <item name="src" type="462c0819:PsiDirectoryNode" /> + <item name="main" type="462c0819:PsiDirectoryNode" /> + <item name="java" type="462c0819:PsiDirectoryNode" /> + </path> + <path> + <item name="gateway" type="b2602c69:ProjectViewProjectNode" /> + <item name="gateway" type="462c0819:PsiDirectoryNode" /> + <item name="src" type="462c0819:PsiDirectoryNode" /> + <item name="main" type="462c0819:PsiDirectoryNode" /> + <item name="java" type="462c0819:PsiDirectoryNode" /> + <item name="repository" type="462c0819:PsiDirectoryNode" /> + </path> + <path> + <item name="gateway" type="b2602c69:ProjectViewProjectNode" /> + <item name="gateway" type="462c0819:PsiDirectoryNode" /> + <item name="src" type="462c0819:PsiDirectoryNode" /> + <item name="main" type="462c0819:PsiDirectoryNode" /> + <item name="java" type="462c0819:PsiDirectoryNode" /> + <item name="repository" type="462c0819:PsiDirectoryNode" /> + <item name="modals" type="462c0819:PsiDirectoryNode" /> + </path> + </expand> + <select /> + </subPane> + </pane> + </panes> </component> <component name="PropertiesComponent"> <property name="ASKED_SHARE_PROJECT_CONFIGURATION_FILES" value="true" /> @@ -197,6 +297,16 @@ <property name="nodejs_interpreter_path.stuck_in_default_project" value="undefined stuck path" /> <property name="nodejs_npm_path_reset_for_default_project" value="true" /> <property name="restartRequiresConfirmation" value="false" /> + <property name="settings.editor.selected.configurable" value="editing.templates" /> + </component> + <component name="RecentsManager"> + <key name="MoveClassesOrPackagesDialog.RECENTS_KEY"> + <recent name="ch.hepia.repository.cursors" /> + <recent name="ch.hepia.repository.modals.interfaces" /> + <recent name="ch.hepia.database.modal" /> + <recent name="MongoDataBase" /> + <recent name="User" /> + </key> </component> <component name="RunDashboard"> <option name="ruleStates"> @@ -211,8 +321,8 @@ </option> </component> <component name="RunManager"> - <configuration name="app" type="Application" factoryName="Application" temporary="true" nameIsGenerated="true"> - <option name="MAIN_CLASS_NAME" value="app" /> + <configuration name="App" type="Application" factoryName="Application" temporary="true" nameIsGenerated="true"> + <option name="MAIN_CLASS_NAME" value="App" /> <module name="09" /> <method v="2"> <option name="Make" enabled="true" /> @@ -220,7 +330,7 @@ </configuration> <recent_temporary> <list> - <item itemvalue="Application.app" /> + <item itemvalue="Application.App" /> </list> </recent_temporary> </component> @@ -270,11 +380,29 @@ <workItem from="1557931164526" duration="197000" /> <workItem from="1557988857639" duration="10612000" /> <workItem from="1558017000960" duration="198000" /> + <workItem from="1558030075300" duration="204000" /> + <workItem from="1558084470968" duration="444000" /> + <workItem from="1558333721373" duration="4445000" /> + <workItem from="1558367436433" duration="1864000" /> + <workItem from="1558371763230" duration="910000" /> + <workItem from="1558420148058" duration="25396000" /> + <workItem from="1558506364520" duration="21575000" /> + <workItem from="1558594362546" duration="8510000" /> + <workItem from="1558618825113" duration="758000" /> + <workItem from="1558678826979" duration="6207000" /> + <workItem from="1558686907517" duration="1426000" /> + <workItem from="1558688549265" duration="3224000" /> + <workItem from="1558704498663" duration="1560000" /> + <workItem from="1558939613389" duration="2910000" /> + <workItem from="1558958791114" duration="4133000" /> + <workItem from="1559024582648" duration="477000" /> + <workItem from="1559030400602" duration="2688000" /> + <workItem from="1559111520857" duration="1592000" /> </task> <servers /> </component> <component name="TimeTrackingManager"> - <option name="totallyTimeSpent" value="137016000" /> + <option name="totallyTimeSpent" value="225339000" /> </component> <component name="TodoView"> <todo-panel id="selected-file"> @@ -286,10 +414,10 @@ </todo-panel> </component> <component name="ToolWindowManager"> - <frame x="0" y="0" width="1440" height="900" extended-state="0" /> + <frame x="0" y="0" width="1920" height="1200" extended-state="0" /> <editor active="true" /> <layout> - <window_info content_ui="combo" id="Project" order="0" sideWeight="0.49924126" weight="0.18025751" /> + <window_info content_ui="combo" id="Project" order="0" sideWeight="0.49924126" visible="true" weight="0.1970181" /> <window_info id="Structure" order="1" sideWeight="0.5007587" side_tool="true" weight="0.20127796" /> <window_info id="Image Layers" order="2" /> <window_info id="Designer" order="3" /> @@ -298,17 +426,17 @@ <window_info id="Favorites" order="6" side_tool="true" /> <window_info anchor="bottom" id="Message" order="0" /> <window_info anchor="bottom" id="Find" order="1" weight="0.32920355" /> - <window_info anchor="bottom" id="Run" order="2" weight="0.35903615" /> - <window_info anchor="bottom" id="Debug" order="3" weight="0.3987952" /> + <window_info anchor="bottom" id="Run" order="2" weight="0.3460177" /> + <window_info anchor="bottom" id="Debug" order="3" weight="0.39823008" /> <window_info anchor="bottom" id="Cvs" order="4" weight="0.25" /> <window_info anchor="bottom" id="Inspection" order="5" weight="0.4" /> <window_info anchor="bottom" id="TODO" order="6" weight="0.32891566" /> <window_info anchor="bottom" id="Docker" order="7" show_stripe_button="false" /> <window_info anchor="bottom" id="Version Control" order="8" weight="0.32891566" /> <window_info anchor="bottom" id="Database Changes" order="9" /> - <window_info anchor="bottom" id="Terminal" order="10" weight="0.32891566" /> + <window_info anchor="bottom" id="Terminal" order="10" weight="0.3283186" /> <window_info anchor="bottom" id="Event Log" order="11" side_tool="true" /> - <window_info anchor="bottom" id="Messages" order="12" weight="0.3253012" /> + <window_info anchor="bottom" id="Messages" order="12" weight="0.32477877" /> <window_info anchor="right" id="Commander" internal_type="SLIDING" order="0" type="SLIDING" weight="0.4" /> <window_info anchor="right" id="Ant Build" order="1" weight="0.25" /> <window_info anchor="right" content_ui="combo" id="Hierarchy" order="2" weight="0.25" /> @@ -327,69 +455,90 @@ <breakpoint-manager> <breakpoints> <line-breakpoint enabled="true" type="java-line"> - <url>file://$PROJECT_DIR$/src/main/java/MongoDB.java</url> - <line>213</line> + <url>file://$PROJECT_DIR$/src/main/java/App.java</url> + <line>231</line> + <properties /> + <option name="timeStamp" value="12" /> + </line-breakpoint> + <line-breakpoint enabled="true" type="java-line"> + <url>file://$PROJECT_DIR$/src/main/java/ch/hepia/repository/MongoDB.java</url> + <line>200</line> <properties /> - <option name="timeStamp" value="8" /> + <option name="timeStamp" value="16" /> </line-breakpoint> <line-breakpoint enabled="true" type="java-line"> - <url>file://$PROJECT_DIR$/src/main/java/MongoDB.java</url> - <line>201</line> + <url>file://$PROJECT_DIR$/src/main/java/ch/hepia/repository/MongoDB.java</url> + <line>399</line> <properties /> - <option name="timeStamp" value="9" /> + <option name="timeStamp" value="20" /> + </line-breakpoint> + <line-breakpoint enabled="true" type="java-line"> + <url>file://$PROJECT_DIR$/src/main/java/ch/hepia/repository/MongoDB.java</url> + <line>139</line> + <properties /> + <option name="timeStamp" value="21" /> </line-breakpoint> </breakpoints> </breakpoint-manager> + <watches-manager> + <configuration name="Application"> + <watch expression="input.get("programid")" language="JAVA" /> + <watch expression="input.get("program").toString()" language="JAVA" /> + <watch expression="k.getId()" language="JAVA" /> + <watch expression="database.getCollection("Programs",Program.class).find(eq("katas._id", k.getId())).first().getId()" language="JAVA" /> + <watch expression="kata.iterator().next().getStatus();" /> + </configuration> + </watches-manager> </component> <component name="debuggerHistoryManager"> <expressions id="watch"> <expression> - <expression-string>p.getKatas().contains(kataid)</expression-string> + <expression-string>database.getCollection("Programs",Program.class).find(eq("katas._id", k.getId())).first().getId()</expression-string> <language-id>JAVA</language-id> <evaluation-mode>EXPRESSION</evaluation-mode> </expression> <expression> - <expression-string>p.getKatas().get("id","0");</expression-string> + <expression-string>database.getCollection("Programs",Program.class).find(eq("katas._id", k.getId())).first()</expression-string> <language-id>JAVA</language-id> <evaluation-mode>EXPRESSION</evaluation-mode> </expression> <expression> - <expression-string>database.getCollection("ProgramsSubscription", ProgramSubscription.class).find(combine(eq("iduser", userid), eq("idprogram", programid), eq("status", true),elemMatch("katas",Do) ))).first()</expression-string> + <expression-string>database.getCollection("Programs",Program.class).find(eq("programSubscriptions.katas._id", k.getId())).first()</expression-string> <language-id>JAVA</language-id> <evaluation-mode>EXPRESSION</evaluation-mode> </expression> <expression> - <expression-string>database.getCollection("ProgramsSubscription", ProgramSubscription.class).find(combine(eq("iduser", userid), eq("idprogram", programid), eq("status", true),elemMatch("katas",Document.parse(kataid) ))).first()</expression-string> + <expression-string>database.getCollection("Programs",Program.class).find(eq("programSubscriptions.katas._id", k.getId())).first().getId();</expression-string> <language-id>JAVA</language-id> <evaluation-mode>EXPRESSION</evaluation-mode> </expression> <expression> - <expression-string>database.getCollection("ProgramsSubscription", ProgramSubscription.class).find(combine(eq("iduser", userid), eq("idprogram", programid), eq("status", true),elemMatch("katas._id",kataid ))).first()</expression-string> + <expression-string>k.getId()</expression-string> <language-id>JAVA</language-id> <evaluation-mode>EXPRESSION</evaluation-mode> </expression> <expression> - <expression-string>database.getCollection("ProgramsSubscription", ProgramSubscription.class).find(combine(eq("iduser", userid), eq("idprogram", programid), eq("status", true),eq("katas.1._id",kataid ))).first()</expression-string> + <expression-string>input.get("program").toString()</expression-string> <language-id>JAVA</language-id> <evaluation-mode>EXPRESSION</evaluation-mode> </expression> <expression> - <expression-string>database.getCollection("ProgramsSubscription", ProgramSubscription.class).find(combine(eq("iduser", userid), eq("idprogram", programid), eq("status", true),eq("katas.0._id",kataid ))).first()</expression-string> + <expression-string>input.getString("program").toString()</expression-string> <language-id>JAVA</language-id> <evaluation-mode>EXPRESSION</evaluation-mode> </expression> <expression> - <expression-string>database.getCollection("ProgramsSubscription", ProgramSubscription.class).find(combine(eq("iduser", userid), eq("idprogram", programid), eq("status", true),eq("katas._id",kataid ))).first()</expression-string> + <expression-string>input.getString("program")</expression-string> <language-id>JAVA</language-id> <evaluation-mode>EXPRESSION</evaluation-mode> </expression> <expression> - <expression-string>database.getCollection("ProgramsSubscription", ProgramSubscription.class).find(combine(eq("iduser", userid), eq("idprogram", programid), eq("status", true),eq("katas.id",kataid ))).first()</expression-string> + <expression-string>input.getString("progrma")</expression-string> <language-id>JAVA</language-id> <evaluation-mode>EXPRESSION</evaluation-mode> </expression> <expression> - <expression-string>database.getCollection("ProgramsSubscription", ProgramSubscription.class).find(combine(eq("iduser", userid), eq("idprogram", programid))).first()</expression-string> + <expression-string>input.getClass()</expression-string> <language-id>JAVA</language-id> <evaluation-mode>EXPRESSION</evaluation-mode> </expression> @@ -412,13 +561,6 @@ </provider> </entry> <entry file="file://$PROJECT_DIR$/src/main/java/JWToken.java" /> - <entry file="file://$PROJECT_DIR$/pom.xml"> - <provider selected="true" editor-type-id="text-editor"> - <state relative-caret-position="455"> - <caret line="83" column="4" selection-start-line="83" selection-start-column="4" selection-end-line="83" selection-end-column="4" /> - </state> - </provider> - </entry> <entry file="jar://$MAVEN_REPOSITORY$/io/javalin/javalin/2.8.0/javalin-2.8.0.jar!/io/javalin/Context.class"> <provider selected="true" editor-type-id="text-editor"> <state relative-caret-position="218"> @@ -429,129 +571,166 @@ <entry file="jar://$MAVEN_REPOSITORY$/io/javalin/javalin/2.8.0/javalin-2.8.0.jar!/io/javalin/core/util/ContextUtil.class"> <provider selected="true" editor-type-id="text-editor" /> </entry> - <entry file="file://$PROJECT_DIR$/src/main/java/KataShowCase.java"> + <entry file="jar://$MAVEN_REPOSITORY$/org/mongodb/mongo-java-driver/3.10.2/mongo-java-driver-3.10.2.jar!/com/mongodb/client/AggregateIterable.class"> <provider selected="true" editor-type-id="text-editor"> - <state relative-caret-position="20"> - <caret line="7" column="25" selection-start-line="7" selection-start-column="19" selection-end-line="7" selection-end-column="25" /> - <folding> - <element signature="e#443#444#0" expanded="true" /> - <element signature="e#476#477#0" expanded="true" /> - <element signature="e#737#738#0" expanded="true" /> - <element signature="e#766#767#0" expanded="true" /> - <element signature="e#810#811#0" expanded="true" /> - <element signature="e#846#847#0" expanded="true" /> - </folding> + <state relative-caret-position="75"> + <caret line="6" column="43" selection-start-line="6" selection-start-column="36" selection-end-line="6" selection-end-column="43" /> </state> </provider> </entry> - <entry file="file://$PROJECT_DIR$/src/main/java/ProgramSubscription.java"> + <entry file="jar://$MAVEN_REPOSITORY$/org/mongodb/mongo-java-driver/3.10.2/mongo-java-driver-3.10.2.jar!/org/bson/Document.class"> <provider selected="true" editor-type-id="text-editor"> - <state relative-caret-position="165"> - <caret line="13" column="34" selection-start-line="13" selection-start-column="34" selection-end-line="13" selection-end-column="34" /> - <folding> - <element signature="e#401#402#0" expanded="true" /> - <element signature="e#431#432#0" expanded="true" /> - <element signature="e#1246#1247#0" expanded="true" /> - <element signature="e#1271#1272#0" expanded="true" /> - <element signature="e#1307#1308#0" expanded="true" /> - <element signature="e#1335#1336#0" expanded="true" /> - </folding> + <state relative-caret-position="-774"> + <caret line="6" column="13" selection-start-line="6" selection-start-column="13" selection-end-line="6" selection-end-column="13" /> </state> </provider> </entry> - <entry file="file://$PROJECT_DIR$/src/main/java/Kata.java"> + <entry file="file://$PROJECT_DIR$/src/main/java/Katatest.java" /> + <entry file="jar://$MAVEN_REPOSITORY$/org/mongodb/mongo-java-driver/3.10.2/mongo-java-driver-3.10.2.jar!/com/mongodb/Function.class"> <provider selected="true" editor-type-id="text-editor"> <state relative-caret-position="90"> - <caret line="6" lean-forward="true" selection-start-line="6" selection-end-line="6" /> + <caret line="7" column="6" selection-start-line="7" selection-start-column="6" selection-end-line="7" selection-end-column="6" /> </state> </provider> </entry> - <entry file="file://$PROJECT_DIR$/src/main/java/ProgramShowCase.java"> + <entry file="file://$PROJECT_DIR$/src/main/java/ch/hepia/repository/modals/program/ProgramSubscription.java"> <provider selected="true" editor-type-id="text-editor"> - <state> - <caret column="27" lean-forward="true" selection-start-column="27" selection-end-column="27" /> + <state relative-caret-position="60"> + <caret line="4" column="10" selection-start-line="4" selection-start-column="10" selection-end-line="4" selection-end-column="10" /> </state> </provider> </entry> - <entry file="file://$PROJECT_DIR$/src/main/java/ProgramsDataBase.java"> + <entry file="jar://$MAVEN_REPOSITORY$/org/mongodb/mongo-java-driver/3.10.2/mongo-java-driver-3.10.2.jar!/com/mongodb/client/model/Aggregates.class"> <provider selected="true" editor-type-id="text-editor"> - <state relative-caret-position="425"> - <caret line="43" column="20" selection-start-line="43" selection-start-column="20" selection-end-line="43" selection-end-column="20" /> + <state relative-caret-position="263"> + <caret line="25" column="44" lean-forward="true" selection-start-line="25" selection-start-column="44" selection-end-line="25" selection-end-column="44" /> </state> </provider> </entry> - <entry file="file://$PROJECT_DIR$/src/main/java/KataSubscription.java"> + <entry file="jar://$MAVEN_REPOSITORY$/org/eclipse/jetty/jetty-server/9.4.15.v20190215/jetty-server-9.4.15.v20190215.jar!/org/eclipse/jetty/server/HttpChannel.class"> + <provider selected="true" editor-type-id="text-editor" /> + </entry> + <entry file="file://$PROJECT_DIR$/pom.xml"> <provider selected="true" editor-type-id="text-editor"> - <state relative-caret-position="75"> - <caret line="5" column="26" selection-start-line="5" selection-start-column="24" selection-end-line="5" selection-end-column="26" /> + <state relative-caret-position="1245"> + <caret line="83" column="4" selection-start-line="83" selection-start-column="4" selection-end-line="83" selection-end-column="4" /> + </state> + </provider> + </entry> + <entry file="file://$PROJECT_DIR$/src/main/java/LiveDB.java" /> + <entry file="file://$PROJECT_DIR$/src/main/java/ch/hepia/repository/modals/kata/KataSubscription.java"> + <provider selected="true" editor-type-id="text-editor"> + <state relative-caret-position="120"> + <caret line="8" column="26" lean-forward="true" selection-start-line="8" selection-start-column="26" selection-end-line="8" selection-end-column="26" /> + </state> + </provider> + </entry> + <entry file="file://$PROJECT_DIR$/src/main/java/ch/hepia/repository/modals/program/ProgramShowCase.java"> + <provider selected="true" editor-type-id="text-editor"> + <state relative-caret-position="465"> + <caret line="31" column="20" selection-start-line="31" selection-start-column="20" selection-end-line="31" selection-end-column="20" /> + </state> + </provider> + </entry> + <entry file="file://$PROJECT_DIR$/src/main/java/ch/hepia/repository/modals/program/Program.java"> + <provider selected="true" editor-type-id="text-editor"> + <state relative-caret-position="60"> + <caret line="6" column="13" selection-start-line="6" selection-start-column="13" selection-end-line="6" selection-end-column="13" /> + </state> + </provider> + </entry> + <entry file="file://$PROJECT_DIR$/src/main/java/ch/hepia/repository/modals/kata/KataShowCase.java"> + <provider selected="true" editor-type-id="text-editor"> + <state relative-caret-position="60"> + <caret line="4" column="11" selection-start-line="4" selection-start-column="11" selection-end-line="4" selection-end-column="11" /> </state> </provider> </entry> - <entry file="file://$PROJECT_DIR$/src/main/java/LiveDB.java"> + <entry file="file://$PROJECT_DIR$/src/main/java/ch/hepia/repository/modals/kata/Kata.java"> <provider selected="true" editor-type-id="text-editor"> - <state relative-caret-position="660"> - <caret line="46" selection-start-line="46" selection-end-line="46" /> + <state relative-caret-position="105"> + <caret line="7" lean-forward="true" selection-start-line="7" selection-end-line="7" /> </state> </provider> </entry> - <entry file="file://$PROJECT_DIR$/src/main/java/MockUser.java"> + <entry file="file://$PROJECT_DIR$/src/main/java/ch/hepia/repository/modals/user/User.java"> <provider selected="true" editor-type-id="text-editor"> - <state relative-caret-position="150"> - <caret line="10" column="22" selection-start-line="10" selection-start-column="22" selection-end-line="10" selection-end-column="22" /> + <state relative-caret-position="225"> + <caret line="15" column="5" lean-forward="true" selection-start-line="15" selection-start-column="5" selection-end-line="15" selection-end-column="5" /> <folding> - <element signature="e#98#99#0" expanded="true" /> - <element signature="e#123#124#0" expanded="true" /> - <element signature="e#159#160#0" expanded="true" /> - <element signature="e#187#188#0" expanded="true" /> - <element signature="e#217#218#0" expanded="true" /> - <element signature="e#243#244#0" expanded="true" /> - <element signature="e#281#282#0" expanded="true" /> - <element signature="e#311#312#0" expanded="true" /> - <element signature="e#476#477#0" expanded="true" /> - <element signature="e#507#508#0" expanded="true" /> - <element signature="e#555#556#0" expanded="true" /> - <element signature="e#595#596#0" expanded="true" /> - <element signature="e#627#628#0" expanded="true" /> - <element signature="e#655#656#0" expanded="true" /> - <element signature="e#697#698#0" expanded="true" /> - <element signature="e#731#732#0" expanded="true" /> - <element signature="e#646#647#0" expanded="true" /> - <element signature="e#677#678#0" expanded="true" /> - <element signature="e#725#726#0" expanded="true" /> - <element signature="e#765#766#0" expanded="true" /> + <element signature="imports" expanded="true" /> </folding> </state> </provider> </entry> - <entry file="file://$PROJECT_DIR$/src/main/java/Program.java"> + <entry file="file://$PROJECT_DIR$/src/main/java/ch/hepia/repository/cursors/Katas.java" /> + <entry file="file://$PROJECT_DIR$/src/main/java/ch/hepia/repository/MongoDB.java"> <provider selected="true" editor-type-id="text-editor"> - <state relative-caret-position="45"> - <caret line="3" column="47" selection-start-line="3" selection-start-column="42" selection-end-line="3" selection-end-column="47" /> + <state relative-caret-position="607"> + <caret line="384" column="49" selection-start-line="384" selection-start-column="49" selection-end-line="384" selection-end-column="49" /> + <folding> + <element signature="imports" expanded="true" /> + <element signature="e#17136#17137#0" expanded="true" /> + <element signature="e#17208#17209#0" expanded="true" /> + </folding> + </state> + </provider> + </entry> + <entry file="file://$PROJECT_DIR$/src/main/java/ch/hepia/repository/cursors/Users.java"> + <provider selected="true" editor-type-id="text-editor"> + <state relative-caret-position="90"> + <caret line="6" column="19" selection-start-line="6" selection-start-column="19" selection-end-line="6" selection-end-column="19" /> + <folding> + <element signature="imports" expanded="true" /> + </folding> + </state> + </provider> + </entry> + <entry file="file://$PROJECT_DIR$/src/main/java/App.java"> + <provider selected="true" editor-type-id="text-editor"> + <state relative-caret-position="5265"> + <caret line="351" column="21" selection-start-line="351" selection-start-column="21" selection-end-line="351" selection-end-column="21" /> <folding> - <element signature="e#1540#1541#0" expanded="true" /> - <element signature="e#1571#1572#0" expanded="true" /> - <element signature="e#1619#1620#0" expanded="true" /> - <element signature="e#1659#1660#0" expanded="true" /> + <element signature="imports" expanded="true" /> </folding> </state> </provider> </entry> - <entry file="file://$PROJECT_DIR$/src/main/java/MongoDB.java"> + <entry file="file://$PROJECT_DIR$/src/main/java/ch/hepia/repository/modals/interfaces/Users.java"> <provider selected="true" editor-type-id="text-editor"> - <state relative-caret-position="678"> - <caret line="283" selection-start-line="283" selection-end-line="283" /> + <state relative-caret-position="75"> + <caret line="5" selection-start-line="5" selection-end-line="5" /> <folding> <element signature="imports" expanded="true" /> - <element signature="e#12452#12453#0" expanded="true" /> - <element signature="e#12528#12529#0" expanded="true" /> </folding> </state> </provider> </entry> - <entry file="file://$PROJECT_DIR$/src/main/java/app.java"> + <entry file="file://$PROJECT_DIR$/src/main/java/ch/hepia/repository/cursors/Programs.java"> + <provider selected="true" editor-type-id="text-editor"> + <state relative-caret-position="60"> + <caret line="4" selection-start-line="4" selection-end-line="4" /> + </state> + </provider> + </entry> + <entry file="file://$PROJECT_DIR$/src/main/java/ch/hepia/repository/cursors/UserInterface.java"> + <provider selected="true" editor-type-id="text-editor"> + <state relative-caret-position="60"> + <caret line="4" column="18" selection-start-line="4" selection-start-column="18" selection-end-line="4" selection-end-column="18" /> + </state> + </provider> + </entry> + <entry file="file://$PROJECT_DIR$/src/main/java/ch/hepia/repository/cursors/ProgramInterface.java"> + <provider selected="true" editor-type-id="text-editor"> + <state relative-caret-position="45"> + <caret line="3" lean-forward="true" selection-start-line="3" selection-end-line="3" /> + </state> + </provider> + </entry> + <entry file="file://$PROJECT_DIR$/src/main/java/ch/hepia/repository/ProgramsDataBase.java"> <provider selected="true" editor-type-id="text-editor"> - <state relative-caret-position="210"> - <caret line="30" column="79" lean-forward="true" selection-start-line="30" selection-start-column="79" selection-end-line="30" selection-end-column="79" /> + <state relative-caret-position="813"> + <caret line="62" lean-forward="true" selection-start-line="62" selection-end-line="62" /> <folding> <element signature="imports" expanded="true" /> </folding> diff --git a/gateway/pom.xml b/gateway/pom.xml index cd0341544210e2d316aa6dbcab837b352f8cf243..bd95e581eb6323ac51a3f0573e5769cc28db1b11 100644 --- a/gateway/pom.xml +++ b/gateway/pom.xml @@ -20,7 +20,7 @@ </execution> </executions> <configuration> - <mainClass>app</mainClass> + <mainClass>App</mainClass> <cleanupDaemonThreads>false</cleanupDaemonThreads> </configuration> </plugin> diff --git a/gateway/src/main/java/app.java b/gateway/src/main/java/App.java similarity index 59% rename from gateway/src/main/java/app.java rename to gateway/src/main/java/App.java index 4fe36aab1b0475b2ef9f1f1548a325993d0e6612..a6c6142cc0d3e9927ef78a1c3c478af8c8050d03 100644 --- a/gateway/src/main/java/app.java +++ b/gateway/src/main/java/App.java @@ -1,11 +1,15 @@ +import ch.hepia.repository.modals.kata.*; + +import ch.hepia.repository.MongoDB; +import ch.hepia.repository.ProgramsDataBase; +import ch.hepia.repository.modals.program.*; +import ch.hepia.repository.modals.user.User; import com.auth0.jwt.JWT; import com.auth0.jwt.JWTCreator; import com.auth0.jwt.JWTVerifier; import com.auth0.jwt.algorithms.Algorithm; import com.auth0.jwt.exceptions.JWTVerificationException; -import com.auth0.jwt.interfaces.DecodedJWT; import com.fasterxml.jackson.databind.ObjectMapper; -import io.javalin.Context; import io.javalin.Handler; import io.javalin.Javalin; import io.javalin.security.Role; @@ -19,10 +23,7 @@ import java.io.*; import java.net.ConnectException; import java.net.HttpURLConnection; import java.net.URL; -import java.util.ArrayList; -import java.util.Date; -import java.util.HashMap; -import java.util.Map; +import java.util.*; import static io.javalin.security.SecurityUtil.roles; @@ -31,25 +32,22 @@ import static io.javalin.security.SecurityUtil.roles; * Created by Alexandre Vanini for Hepia © HEPIA 2019 (Bachelor Thesis project) * Purpose : Http Server */ -public class app { +public class App { // Roles of the routes enum Roles implements Role { - SHODAI, // Super user role - SENSEI, // High user role - MONJI, // Middle user role - ANYONE // Low user role + SHODAI, // Super ch.hepia.database.modal.user role + SENSEI, // High ch.hepia.database.modal.user role + MONJI, // low ch.hepia.database.modal.user role + ANYONE // null ch.hepia.database.modal.user role } - // Data base object, can be changed if your object extends "ProgramsDataBase" + // Data base object, can be changed if your object extends "MongoDataBase.ProgramsDataBase" private static ProgramsDataBase db = new MongoDB(); // Jackson Object mapper, convert received stream into Java Designed Object private static ObjectMapper objectMapper = new ObjectMapper(); - // Temporary list of users - private static ArrayList<MockUser> users = new ArrayList<>(); - /** * Entry point of the gateway, no args needed * @@ -60,9 +58,9 @@ public class app { // JWT //secret Algorithm algorithm = Algorithm.HMAC256("cd47488e09fa86d6e2549b824cb1f47422921539"); - // Every time a user is requesting a token, it passes trough here - // It generates a token based on user's name and his level - JWTGenerator<MockUser> generator = (user, alg) -> { + // Every time a ch.hepia.database.modal.user is requesting a token, it passes trough here + // It generates a token based on ch.hepia.database.modal.user's name and his level + JWTGenerator<User> generator = (user, alg) -> { JWTCreator.Builder token = JWT.create() .withClaim("username", user.getUsername()) .withClaim("level", user.getLevel()) @@ -81,8 +79,8 @@ public class app { // Javalin server creation Javalin app = Javalin.create().enableCorsForAllOrigins(); - // Every time a user tries to reach a route of the server, it passes trough the before handler. - // This ensure the user has a compatible token to reach routes, if the token is faked or deprecated, it returns a 401 status (Unauthorized) + // Every time a ch.hepia.database.modal.user tries to reach a route of the server, it passes trough the before handler. + // This ensure the ch.hepia.database.modal.user has a compatible token to reach routes, if the token is faked or deprecated, it returns a 401 status (Unauthorized) app.before(decodeHandler); Map<String, Role> rolesMapping = new HashMap<String, Role>(); @@ -105,7 +103,7 @@ public class app { /** * Compilation route - body must contain data to compile */ - app.post("/run/", ctx -> { + app.post("/kata/run/", ctx -> { HttpURLConnection connection = null; @@ -144,36 +142,37 @@ public class app { /** PROGRAM **/ /** - * Create a program -> Expect complete object like Program in body + * Create a ch.hepia.database.modal.program -> Expect complete object like Program.Program in body */ app.post("/program/create", ctx -> { - Program prg = objectMapper.readValue(ctx.body(), Program.class); - db.createProgram(prg); + Program program = objectMapper.readValue(ctx.body(), Program.class); + db.create(program); ctx.status(200); }, roles(Roles.SHODAI, Roles.SENSEI)); - app.get("/program/getdetails", ctx -> { - ArrayList<ProgramShowCase> prgsc = db.getProgramsDetails(); - if (prgsc != null) - if (prgsc.size() == 0) - ctx.status(404); - else - ctx.json(prgsc); + app.get("/program/details", ctx -> { + Optional<List<ProgramShowCase>> prgsc = db.programsDetails(); + + if (prgsc.isPresent()) + ctx.json(prgsc.get()); else ctx.status(404); + }, roles(Roles.SHODAI, Roles.SENSEI, Roles.MONJI)); - app.get("program/getdetails/:id", ctx -> { - ArrayList<String> s = db.getProgramDetailsByID(ctx.pathParam("id")); - if (s.size() == 0) - ctx.status(404); + app.get("program/details/:id", ctx -> { + Optional<ProgramShowCase> s = db.programDetailsById(ctx.pathParam("id")); + if (s.isPresent()) + ctx.json(s.get()); else - ctx.json(s); + ctx.status(404); + }, roles(Roles.SHODAI, Roles.SENSEI, Roles.MONJI)); - app.post("/kata/create", ctx -> { - Kata kt = objectMapper.readValue(ctx.body(), Kata.class); - db.createKata(kt); + app.post("/program/update", ctx -> { + JSONObject input = new JSONObject(ctx.body()); + ProgramShowCase program = objectMapper.readValue(input.get("program").toString(), ProgramShowCase.class); + db.update(input.getString("programid"),program); ctx.status(200); }, roles(Roles.SHODAI, Roles.SENSEI)); @@ -187,29 +186,66 @@ public class app { /** KATAS **/ - app.get("/program/getkatas/details/:id/:userid", ctx -> { - ArrayList<KataShowCase> ktsc = db.getProgramKatasDetails(ctx.pathParam("id"), ctx.pathParam("userid")); - ctx.json(ktsc); + app.get("/kata/isactivated/:kataid", ctx -> { + boolean isActivated = db.isKataActivated(ctx.pathParam("kataid")); + ctx.status(200).json(isActivated); + }, roles(Roles.SHODAI, Roles.SENSEI,Roles.MONJI)); + + app.post("/kata/update", ctx -> { + Kata kata = objectMapper.readValue(ctx.body(), Kata.class); + String programid = db.update(kata); + ctx.status(200).json(programid); + }, roles(Roles.SHODAI, Roles.SENSEI)); + + app.post("kata/toggleactivation", ctx -> { + db.toggleKataActivation(ctx.body()); + ctx.status(200); + }, roles(Roles.SHODAI, Roles.SENSEI)); + + app.post("/kata/create", ctx -> { + JSONObject input = new JSONObject(ctx.body()); + Kata kata = objectMapper.readValue(input.getString("kata"), Kata.class); + db.create(kata,input.getString("programid")); + ctx.status(200); + }, roles(Roles.SHODAI, Roles.SENSEI)); + + app.get("/kata/details/:programid/:userid", ctx -> { + Optional<List<KataShowCase>> ktsc = db.kataDetails(ctx.pathParam("programid"), ctx.pathParam("userid")); + ctx.json(ktsc.get()); }, roles(Roles.SHODAI, Roles.SENSEI, Roles.MONJI)); - app.get("/program/getkata/:prid/:id", ctx -> { + app.get("/kata/:kataid", ctx -> { - Kata kata = db.getProgramKata(ctx.pathParam("prid"), ctx.pathParam("id")); - if (kata.getId() == null) - ctx.status(404); + Optional<Kata> kata = db.kata(ctx.pathParam("kataid")); + if (kata.isPresent()) + ctx.json(kata.get()); else - ctx.json(kata); + ctx.status(404); + }, roles(Roles.SHODAI, Roles.SENSEI, Roles.MONJI)); + app.get("/kata/isowner/:kataid/:userid", ctx -> { + boolean isOwner = db.isKataOwner(ctx.pathParam("userid"), ctx.pathParam("kataid")); + ctx.status(200).json(isOwner); + }, roles(Roles.SHODAI, Roles.SENSEI, Roles.MONJI)); + + + app.post("/kata/delete/", ctx -> { + db.deleteKata(ctx.body()); + ctx.status(200); + }, roles(Roles.SHODAI, Roles.SENSEI)); + /******************/ /** USER **/ - app.post("jwt/request/", ctx -> { + app.post("/user/tokenrequest/", ctx -> { JSONObject ids = new JSONObject(ctx.body()); - MockUser u = db.checkUser(ids.getString("username"), ids.getString("password")); - if (!(u == null)) { + Optional<User> user = db.checkUserCredentials(ids.getString("username"), ids.getString("password")); + + if (user.isPresent()) { + User u = user.get(); String token = provider.generateToken(u); HashMap<String, String> p = new HashMap<>(); @@ -228,16 +264,13 @@ public class app { /******************/ /** PROGRAM SEARCH **/ - app.get("search/:type/:resource", ctx -> { - ArrayList<ProgramShowCase> p = db.getProgramDetailsByResource(ctx.pathParam("type"), ctx.pathParam("resource")); - - if (p != null) - if (p.size() == 0) - ctx.status(404).json("No program matched the specified query"); - else - ctx.json(p); + app.get("program/search/:type/:resource", ctx -> { + Optional<List<ProgramShowCase>> p = db.programDetailsFiltered(ctx.pathParam("type"), ctx.pathParam("resource")); + if (p.isPresent()) + ctx.json(p.get()); else - ctx.status(404).json("No program matched the specified query"); + ctx.status(404).json("No ch.hepia.database.modal.program matched the specified query"); + }, roles(Roles.SHODAI, Roles.SENSEI, Roles.MONJI)); /******************/ @@ -245,40 +278,47 @@ public class app { /** PROGRAM SUBSCRIPTION **/ - app.get("program/getsubscription/:programid/:userid", ctx -> { - ProgramSubscription p = db.getSubscriptionByID(ctx.pathParam("userid"), ctx.pathParam("programid")); - if (!(p == null)) - ctx.json(p); + app.get("/program/issubscribed/:userid/:programid", ctx -> { + boolean isSubscribed = db.isSubscribed(ctx.pathParam("userid"), ctx.pathParam("programid")); + ctx.status(200).json(isSubscribed); + }, roles(Roles.SHODAI, Roles.SENSEI, Roles.MONJI)); + + app.get("/program/isowner/:userid/:programid", ctx -> { + boolean isOwner = db.isProgramOwner(ctx.pathParam("userid"), ctx.pathParam("programid")); + ctx.status(200).json(isOwner); + }, roles(Roles.SHODAI, Roles.SENSEI,Roles.MONJI)); + + app.get("program/subscription/:programid/:userid", ctx -> { + Optional<ProgramSubscription> p = db.subscriptionByID(ctx.pathParam("userid"), ctx.pathParam("programid")); + if (p.isPresent()) + ctx.json(p.get()); else { ctx.status(404); } }, roles(Roles.SHODAI, Roles.SENSEI, Roles.MONJI)); - app.get("/subscription/get/:userid", ctx -> { - ArrayList<ProgramShowCase> prgsc = db.getUserSubscription(ctx.pathParam("userid")); - if (prgsc != null) - if (prgsc.size() == 0) - ctx.status(404); - else - ctx.json(prgsc); + app.get("program/subscription/:userid", ctx -> { + Optional<List<ProgramShowCase>> prgsc = db.userSubscriptions(ctx.pathParam("userid")); + if (prgsc.isPresent()) + ctx.json(prgsc.get()); else ctx.status(404); + }, roles(Roles.SHODAI, Roles.SENSEI, Roles.MONJI)); - app.get("/subscription/mine/:userid", ctx -> { - ArrayList<ProgramShowCase> prgsc = db.getUserProgram(ctx.pathParam("userid")); - if (prgsc != null) - if (prgsc.size() == 0) - ctx.status(404); - else - ctx.json(prgsc); + app.get("/program/:userid", ctx -> { + Optional<List<ProgramShowCase>> prgsc = db.userPrograms(ctx.pathParam("userid")); + + if (prgsc.isPresent()) + ctx.json(prgsc.get()); else ctx.status(404); }, roles(Roles.SHODAI, Roles.SENSEI)); app.post("program/createsubscription", ctx -> { - ProgramSubscription prg = objectMapper.readValue(ctx.body(), ProgramSubscription.class); - db.createProgramSubscritpion(prg); + JSONObject obj = new JSONObject(ctx.body()); + ProgramSubscription programSubscription = objectMapper.readValue(obj.getString("obj"), ProgramSubscription.class); + db.create(obj.getString("userid"), programSubscription); ctx.status(200); }, roles(Roles.SHODAI, Roles.SENSEI, Roles.MONJI)); @@ -293,16 +333,12 @@ public class app { /** KATA SUBSCRIPTION **/ app.get("kata/get/subscriptioninfos/:userid/:programid/:kataid", ctx -> { - KataSubscription k = db.getKataSubscriptionByID(ctx.pathParam("kataid"), ctx.pathParam("programid"), ctx.pathParam("userid")); - - if (!(k == null)) - if (k.getId() == null) - ctx.status(402); - else - ctx.status(200).json(k); - else if (k == null) - ctx.status(404); + Optional<KataSubscription> k = db.kataSubscriptionById(ctx.pathParam("kataid"), ctx.pathParam("programid"), ctx.pathParam("userid")); + if (k.isPresent()) + ctx.status(200).json(k.get()); + else + ctx.status(404); }, roles(Roles.SHODAI, Roles.SENSEI, Roles.MONJI)); @@ -314,7 +350,7 @@ public class app { app.post("kata/inc/subscription", ctx -> { JSONObject obj = new JSONObject(ctx.body()); - db.incKataSubscriptionAttempt(obj.getString("kataid"), obj.getString("programid"), obj.getString("userid")); + db.incrementKataSubscriptionAttempt(obj.getString("kataid"), obj.getString("programid"), obj.getString("userid")); ctx.status(200); }, roles(Roles.SHODAI, Roles.SENSEI, Roles.MONJI)); @@ -336,12 +372,12 @@ public class app { ctx.json(token); }, roles(Roles.SHODAI, Roles.SENSEI)); - app.post("user/signin", ctx -> { + app.post("/signin", ctx -> { JSONObject input = new JSONObject(ctx.body()); String username = input.getString("username"); String password = input.getString("password"); String id = input.getString("id"); - if (db.doUserExists(username)) { + if (db.isExisting(username)) { ctx.status(400).json("Username '" + username + "' already exists"); } else { if (!input.get("token").equals("")) { @@ -352,13 +388,13 @@ public class app { .build(); //Reusable verifier instance checker.verify(input.getString("token")); - db.createUser(new MockUser(id, username, "sensei", password)); + db.create(new User(id, username, "sensei", password)); ctx.status(200); } catch (JWTVerificationException exception) { ctx.status(400).json("Bad token"); } } else { - db.createUser(new MockUser(id, username, "monji", password)); + db.create(new User(id, username, "monji", password)); ctx.status(200); } diff --git a/gateway/src/main/java/KataShowCase.java b/gateway/src/main/java/KataShowCase.java deleted file mode 100644 index 345ea1e1390e0127dbb657610c0cd0132785180d..0000000000000000000000000000000000000000 --- a/gateway/src/main/java/KataShowCase.java +++ /dev/null @@ -1,42 +0,0 @@ -public class KataShowCase { - private String title,difficulty,id,status; - - public KataShowCase(String title, String difficulty, String id, String status){ - this.difficulty = difficulty; - this.title = title; - this.id = id; - this.status = status; - } - - public String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } - - public String getDifficulty() { - return difficulty; - } - - public void setDifficulty(String difficulty) { - this.difficulty = difficulty; - } - - public String getId() { - return id; - } - - public void setId(String programID) { - this.id = programID; - } - - public String getStatus() { - return status; - } - - public void setStatus(String status) { - this.status = status; - } -} diff --git a/gateway/src/main/java/LiveDB.java b/gateway/src/main/java/LiveDB.java deleted file mode 100644 index b9a7c4ef0d761f9b3b53332f147f829cbf9733f1..0000000000000000000000000000000000000000 --- a/gateway/src/main/java/LiveDB.java +++ /dev/null @@ -1,152 +0,0 @@ -import java.util.ArrayList; - -public class LiveDB extends ProgramsDataBase { - - ArrayList<Kata> katas; - ArrayList<Program> programs; - - public LiveDB() { - this.programs = new ArrayList<>(); - this.katas = new ArrayList<>(); - } - - public void createProgram(Program prg) { - this.programs.add(prg); - } - - public void createKata(Kata kata) { - - for (Program p : this.programs) - if (p.getId().equals(kata.getProgramID())) { - p.setNbKata(p.getNbKata() + 1); - p.getKatas().add(kata); - break; - } - } - - public ArrayList<ProgramShowCase> getProgramsDetails() { - ArrayList<ProgramShowCase> p = new ArrayList<>(); - - for (Program prg : this.programs) - p.add(new ProgramShowCase(prg.getTitle(), prg.getSensei(), prg.getLanguage(), prg.getDescription(), prg.getNbKata(), prg.getTags(), prg.getId())); - - return p; - } - - public Kata getProgramKata(String programID, String kataID) { - ArrayList<Kata> ktemp = new ArrayList<>(); - Kata kata = new Kata(); - for (Program prg : this.programs) - if (prg.getId().equals(programID)) - ktemp = prg.getKatas(); - for(Kata k : ktemp) - if(k.getId().equals(kataID)) - kata = k; - return kata; - } - - public ArrayList<KataShowCase> getProgramKatasDetails(String programID, String userid) { - ArrayList<KataShowCase> ktsc = new ArrayList<>(); - ArrayList<Kata> kt = new ArrayList<>(); - for (Program prg : this.programs) - if (prg.getId().equals(programID)) { - kt = prg.getKatas(); - break; - } - - for (Kata k : kt) - ktsc.add(new KataShowCase(k.getTitle(), k.getDifficulty(), k.getId(), "TODO")); - return ktsc; - } - - public ArrayList<String> getProgramDetailsByID(String id){ - ArrayList<String> infos = new ArrayList<>(); - - for (Program p : this.programs) - if(p.getId().equals(id)){ - infos.add(p.getTitle()); - infos.add(p.getLanguage()); - infos.add(p.getSensei()); - break; - } - - return infos; - } - - @Override - public ArrayList<ProgramShowCase> getProgramDetailsByResource(String type, String resource) { - return null; - } - - @Override - public ProgramSubscription getSubscriptionByID(String userid, String idrogram) { - return null; - } - - @Override - public void createProgramSubscritpion(ProgramSubscription p) { - - } - - @Override - public void toggleSubscription(String userid, String idrogram) { - - } - - @Override - public ArrayList<ProgramShowCase> getUserSubscription(String userid) { - return null; - } - - @Override - public ArrayList<ProgramShowCase> getUserProgram(String userid) { - return null; - } - - @Override - public ArrayList<KataSubscription> getKataSubscription(String programid, String userid) { - return null; - } - - @Override - public KataSubscription getKataSubscriptionByID(String kataid, String programid, String userid) { - return null; - } - - @Override - public void createKataSubscription(String kataid, String programid, String userid) { - - } - - @Override - public void incKataSubscriptionAttempt(String kataid, String programid, String userid) { - - } - - @Override - public void updateKataSubscription(String kataid, String programid, String userid, String sol, String status) { - - } - - @Override - public void deleteProgram(String programid) { - - } - - @Override - public void createUser(MockUser u) { - - } - - @Override - public MockUser checkUser(String username, String password) { - return null; - } - - @Override - public boolean doUserExists(String username) { - return false; - } - - -} \ No newline at end of file diff --git a/gateway/src/main/java/MongoDB.java b/gateway/src/main/java/MongoDB.java deleted file mode 100644 index da0e2ab312d3f2b3536ffacb4e267ce5a87685e0..0000000000000000000000000000000000000000 --- a/gateway/src/main/java/MongoDB.java +++ /dev/null @@ -1,284 +0,0 @@ -import com.mongodb.*; -import com.mongodb.client.MongoCollection; -import com.mongodb.client.MongoDatabase; -import com.mongodb.client.model.Indexes; -import org.bson.codecs.configuration.CodecRegistry; -import org.bson.codecs.pojo.PojoCodecProvider; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.regex.Pattern; - -import static com.mongodb.client.model.Filters.*; -import static com.mongodb.client.model.Updates.*; -import static com.mongodb.client.model.Projections.*; -import static org.bson.codecs.configuration.CodecRegistries.fromProviders; -import static org.bson.codecs.configuration.CodecRegistries.fromRegistries; - -public class MongoDB extends ProgramsDataBase { - private MongoClient mongoClient; - private MongoDatabase database; - - CodecRegistry pojoCodecRegistry = fromRegistries(MongoClient.getDefaultCodecRegistry(), - fromProviders(PojoCodecProvider.builder().automatic(true).build())); - - public MongoDB() { - MongoCredential credential = MongoCredential.createCredential("shodai", "DojoHepia", "shodai".toCharArray()); - this.mongoClient = new MongoClient(new ServerAddress("localhost", 27017), Arrays.asList(credential), MongoClientOptions.builder().codecRegistry(pojoCodecRegistry).build()); - this.database = mongoClient.getDatabase("DojoHepia"); - database.getCollection("Programs").createIndex(Indexes.ascending("title")); - - if (!doUserExists("shodai")) { - createUser(new MockUser("0", "shodai", "shodai", "d033e22ae348aeb5660fc2140aec35850c4da997")); - } - - } - - public void createProgram(Program prg) { - MongoCollection<Program> programs = database.getCollection("Programs", Program.class); - programs.insertOne(prg); - } - - public void createKata(Kata kata) { - ArrayList<Kata> katas = database.getCollection("Programs", Program.class).find(eq("_id", kata.getProgramID())).first().getKatas(); - katas.add(kata); - - MongoCollection<Program> programs = database.getCollection("Programs", Program.class); - programs.updateOne(eq("_id", kata.getProgramID()), combine(inc("nbKata", 1), set("katas", katas))); - } - - public ArrayList<ProgramShowCase> getProgramsDetails() { - ArrayList<ProgramShowCase> p = new ArrayList<>(); - MongoCollection<Program> programs = database.getCollection("Programs", Program.class); - - for (Program prg : programs.find()) - p.add(new ProgramShowCase(prg.getTitle(), prg.getSensei(), prg.getLanguage(), prg.getDescription(), prg.getNbKata(), prg.getTags(), prg.getId())); - - return p; - } - - public Kata getProgramKata(String programID, String kataID) { - - Kata kata = new Kata(); - - MongoCollection<Program> programs = database.getCollection("Programs", Program.class); - ArrayList<Kata> katas = programs.find(eq("_id", programID)).first().getKatas(); - - for (Kata k : katas) - if (k.getId().equals(kataID)) { - kata = k; - break; - } - return kata; - - } - - public ArrayList<KataShowCase> getProgramKatasDetails(String programID, String userid) { - ArrayList<KataShowCase> ktsc = new ArrayList<>(); - MongoCollection<Program> programs = database.getCollection("Programs", Program.class); - - ArrayList<Kata> k = programs.find(eq("_id", programID)).first().getKatas(); - - k.forEach(x -> { - ktsc.add(new KataShowCase(x.getTitle(), x.getDifficulty(), x.getId(), getKataStatus(x.getId(), programID, userid))); - }); - - return ktsc; - } - - /** - * TODO Vraiment très couteux........ - * - * @param kataid - * @param programid - * @param userid - * @return - */ - - private String getKataStatus(String kataid, String programid, String userid) { - MongoCollection<ProgramSubscription> programs = database.getCollection("ProgramsSubscription", ProgramSubscription.class); - ProgramSubscription subscription = programs.find(combine(eq("iduser", userid), eq("idprogram", programid))).first(); - - if (subscription == null) - return "TODO"; - - ArrayList<KataSubscription> k = subscription.getKatas(); - - for (KataSubscription ks : k) { - if (ks.getId().equals(kataid)) - return ks.getStatus(); - } - return "TODO"; - } - - public ArrayList<String> getProgramDetailsByID(String id) { - ArrayList<String> infos = new ArrayList<>(); - - MongoCollection<Program> programs = database.getCollection("Programs", Program.class); - Program p = programs.find(eq("_id", id)).first(); - - if (p != null) { - infos.add(p.getTitle()); - infos.add(p.getLanguage()); - infos.add(p.getSensei()); - infos.add(p.getIdsensei()); - } - return infos; - } - - public ArrayList<ProgramShowCase> getProgramDetailsByResource(String type, String resource) { - ArrayList<ProgramShowCase> p = new ArrayList<>(); - - MongoCollection<Program> cprograms = database.getCollection("Programs", Program.class); - Pattern regex = Pattern.compile(resource, Pattern.CASE_INSENSITIVE); - Iterable<Program> programs = cprograms.find(eq(type, regex)); - - - programs.forEach(x -> { - p.add(new ProgramShowCase(x.getTitle(), x.getSensei(), x.getLanguage(), x.getDescription(), x.getNbKata(), x.getTags(), x.getId(), -1)); - }); - - return p; - } - - public ProgramSubscription getSubscriptionByID(String userid, String idrogram) { - MongoCollection<ProgramSubscription> programSubs = database.getCollection("ProgramsSubscription", ProgramSubscription.class); - ProgramSubscription prgsub = programSubs.find(combine(eq("idprogram", idrogram), eq("iduser", userid))).first(); - - return prgsub; - } - - public void createProgramSubscritpion(ProgramSubscription p) { - MongoCollection<ProgramSubscription> programSubs = database.getCollection("ProgramsSubscription", ProgramSubscription.class); - programSubs.insertOne(p); - } - - public void toggleSubscription(String userid, String idrogram) { - MongoCollection<ProgramSubscription> programSubs = database.getCollection("ProgramsSubscription", ProgramSubscription.class); - ProgramSubscription prog = programSubs.find(combine(eq("idprogram", idrogram), eq("iduser", userid))).first(); - - if (prog.getStatus()) - programSubs.updateOne(combine(eq("idprogram", idrogram), eq("iduser", userid)), set("status", false)); - else - programSubs.updateOne(combine(eq("idprogram", idrogram), eq("iduser", userid)), set("status", true)); - - } - - public ArrayList<ProgramShowCase> getUserSubscription(String userid) { - Iterable<ProgramSubscription> s = database.getCollection("ProgramsSubscription", ProgramSubscription.class).find(combine(eq("iduser", userid), eq("status", true))).projection(include("idprogram", "nbKataDone")); - ArrayList<ProgramShowCase> prgsc = new ArrayList<>(); - - MongoCollection<Program> cprograms = database.getCollection("Programs", Program.class); - s.forEach(x -> { - Program p = cprograms.find(eq("_id", x.getIdprogram())).first(); - prgsc.add(new ProgramShowCase(p.getTitle(), p.getSensei(), p.getLanguage(), p.getDescription(), p.getNbKata(), p.getTags(), p.getId(), x.getNbKataDone())); - }); - - return prgsc; - } - - public ArrayList<ProgramShowCase> getUserProgram(String userid) { - Iterable<Program> cprograms = database.getCollection("Programs", Program.class).find(eq("idsensei", userid)); - ArrayList<ProgramShowCase> prgsc = new ArrayList<>(); - - for (Program p : cprograms) - prgsc.add(new ProgramShowCase(p.getTitle(), p.getSensei(), p.getLanguage(), p.getDescription(), p.getNbKata(), p.getTags(), p.getId(), -1)); - - return prgsc; - } - - public ArrayList<KataSubscription> getKataSubscription(String programid, String userid) { - ArrayList<KataSubscription> s = database.getCollection("ProgramsSubscription", ProgramSubscription.class).find(combine(eq("iduser", userid), eq("programid", programid))).projection(include("katas")).first().getKatas(); - - return s; - } - - public KataSubscription getKataSubscriptionByID(String kataid, String programid, String userid) { -/* - ProgramSubscription p = database.getCollection("ProgramsSubscription", ProgramSubscription.class).find(combine(eq("iduser", userid), eq("idprogram", programid), eq("status", true),eq("katas._id",kataid ))).filter((); - return p == null ? new KataSubscription() : p.getKatas().get(0); - */ - ProgramSubscription s = database.getCollection("ProgramsSubscription", ProgramSubscription.class).find(combine(eq("iduser", userid), eq("idprogram", programid), eq("status", true))).projection(include("katas")).first(); - if (s == null) { - return new KataSubscription(); - } else - for (KataSubscription k : s.getKatas()) { - - if (k.getId().equals(kataid)) - return k; - } - return null; - } - - public void createKataSubscription(String kataid, String programid, String userid) { - ArrayList<KataSubscription> katas = database.getCollection("ProgramsSubscription", ProgramSubscription.class).find(combine(eq("iduser", userid), eq("idprogram", programid))).first().getKatas(); - katas.add(new KataSubscription(kataid, "ON-GOING", "", 0)); - - MongoCollection<ProgramSubscription> programs = database.getCollection("ProgramsSubscription", ProgramSubscription.class); - programs.updateOne(combine(eq("iduser", userid), eq("idprogram", programid)), set("katas", katas)); - } - - /** - * TODO trouver un moyen simple de rentrer dans la liste de kata avec mongo db, parce que la c'est vraiment très couteu à chaque appel. - * TODO voir si je peux pas transformer kataSubrription en une mongo collection dans ProgramSub.. et pourquoi pas - * TODO si 4a marche changer Arraylist kata en Mongo collection kata dans Program - * - * @param kataid - * @param programid - * @param userid - */ - public void incKataSubscriptionAttempt(String kataid, String programid, String userid) { - ArrayList<KataSubscription> katas = database.getCollection("ProgramsSubscription", ProgramSubscription.class).find(combine(eq("iduser", userid), eq("idprogram", programid))).first().getKatas(); - - for (KataSubscription k : katas) { - if (k.getId().equals(kataid)) { - k.setNbAttempt(k.getNbAttempt() + 1); - break; - } - } - - MongoCollection<ProgramSubscription> programs = database.getCollection("ProgramsSubscription", ProgramSubscription.class); - programs.updateOne(combine(eq("iduser", userid), eq("idprogram", programid)), set("katas", katas)); - } - - public void updateKataSubscription(String kataid, String programid, String userid, String sol, String status) { - ArrayList<KataSubscription> katas = database.getCollection("ProgramsSubscription", ProgramSubscription.class).find(combine(eq("iduser", userid), eq("idprogram", programid))).first().getKatas(); - - for (KataSubscription k : katas) { - if (k.getId().equals(kataid)) { - k.setStatus(status); - k.setMysol(sol); - break; - } - } - - MongoCollection<ProgramSubscription> programs = database.getCollection("ProgramsSubscription", ProgramSubscription.class); - programs.updateOne(combine(eq("iduser", userid), eq("idprogram", programid)), set("katas", katas)); - if (status.equals("RESOLVED")) - programs.updateOne(combine(eq("iduser", userid), eq("idprogram", programid)), inc("nbKataDone", 1)); - } - - public void deleteProgram(String programid) { - database.getCollection("Programs", Program.class).deleteMany(eq("_id", programid)); - database.getCollection("ProgramsSubscription", ProgramSubscription.class).deleteMany(eq("idprogram", programid)); - } - - public void createUser(MockUser u) { - database.getCollection("Users", MockUser.class).insertOne(u); - } - - public MockUser checkUser(String username, String password) { - MockUser u = database.getCollection("Users", MockUser.class).find(combine(eq("username", username), eq("password", password))).first(); - if (u == null) - return null; - return u; - } - - public boolean doUserExists(String username) { - MockUser u = database.getCollection("Users", MockUser.class).find(eq("username", username)).first(); - if (u == null) - return false; - return true; - } - -} diff --git a/gateway/src/main/java/ProgramShowCase.java b/gateway/src/main/java/ProgramShowCase.java deleted file mode 100644 index e5831a6c4eb3dca5b6fe1079416a8a5438f87022..0000000000000000000000000000000000000000 --- a/gateway/src/main/java/ProgramShowCase.java +++ /dev/null @@ -1,97 +0,0 @@ -import java.util.ArrayList; - -public class ProgramShowCase { - private String title, sensei, language, description, programID; - private int nbKata; - private ArrayList<String> tags; - private int nbKataDone; - - - public ProgramShowCase(String title, String sensei, String language, String description, int nbKata, ArrayList<String> tags, String programID, int nbKataDone) { - this.title = title; - this.sensei = sensei; - this.language = language; - this.description = description; - this.nbKata = nbKata; - this.tags = tags; - this.programID = programID; - this.nbKataDone = nbKataDone; - - - } - - public ProgramShowCase(String title, String sensei, String language, String description, int nbKata, ArrayList<String> tags, String programID) { - this.title = title; - this.sensei = sensei; - this.language = language; - this.description = description; - this.nbKata = nbKata; - this.tags = tags; - this.programID = programID; - } - - - public String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } - - public String getSensei() { - return sensei; - } - - public void setSensei(String sensei) { - this.sensei = sensei; - } - - public String getLanguage() { - return language; - } - - public void setLanguage(String language) { - this.language = language; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - public int getNbKata() { - return nbKata; - } - - public void setNbKata(int nbKata) { - this.nbKata = nbKata; - } - - public String getProgramID() { - return programID; - } - - public void setProgramID(String programID) { - this.programID = programID; - } - - public ArrayList<String> getTags() { - return tags; - } - - public void setTags(ArrayList<String> tags) { - this.tags = tags; - } - - public int getNbKataDone() { - return this.nbKataDone; - } - - public void setNbKataDone(int nbKataDone) { - this.nbKata = nbKataDone; - } -} diff --git a/gateway/src/main/java/ProgramSubscription.java b/gateway/src/main/java/ProgramSubscription.java deleted file mode 100644 index 0c400eed123a379394904e4f7829d578e077b6ed..0000000000000000000000000000000000000000 --- a/gateway/src/main/java/ProgramSubscription.java +++ /dev/null @@ -1,67 +0,0 @@ -import java.util.ArrayList; - -public class ProgramSubscription {// [iduser, idprogram : 234, status : 1 , katas [{id:1,status:"resolved",mysol:".."}],done : 1] - - private String _id,id, iduser, idprogram; - private boolean status; - private int nbKataDone; - private ArrayList<KataSubscription> katas; - - public String get_id() { - return _id; - } - - public void set_id(String _id) { - this._id = _id; - } - - public String getIduser() { - return iduser; - } - - public void setIduser(String iduser) { - this.iduser = iduser; - } - - public String getIdprogram() { - return idprogram; - } - - public void setIdprogram(String idprogram) { - this.idprogram = idprogram; - } - - public Boolean getStatus() { - return status; - } - - public void setStatus(Boolean status) { - this.status = status; - } - - - - public ArrayList<KataSubscription> getKatas() { - return katas; - } - - public void setKatas(ArrayList<KataSubscription> katas) { - this.katas = katas; - } - - public int getNbKataDone() { - return nbKataDone; - } - - public void setNbKataDone(int nbKataDone) { - this.nbKataDone = nbKataDone; - } - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } -} diff --git a/gateway/src/main/java/ProgramsDataBase.java b/gateway/src/main/java/ProgramsDataBase.java deleted file mode 100644 index 79301b4f9d97c0b39e9bfdf7acab8ffaf8c45dfd..0000000000000000000000000000000000000000 --- a/gateway/src/main/java/ProgramsDataBase.java +++ /dev/null @@ -1,46 +0,0 @@ -import java.util.ArrayList; - -public abstract class ProgramsDataBase { - public abstract void createProgram(Program prg); - - public abstract void createKata(Kata kata); - - public abstract ArrayList<ProgramShowCase> getProgramsDetails(); - - public abstract Kata getProgramKata(String programID, String kataID); - - public abstract ArrayList<KataShowCase> getProgramKatasDetails(String programID, String userid); - - public abstract ArrayList<String> getProgramDetailsByID(String id); - - public abstract ArrayList<ProgramShowCase> getProgramDetailsByResource(String type, String resource); - - public abstract ProgramSubscription getSubscriptionByID(String userid, String idrogram); - - public abstract void createProgramSubscritpion(ProgramSubscription p); - - public abstract void toggleSubscription(String userid, String idrogram); - - public abstract ArrayList<ProgramShowCase> getUserSubscription(String userid); - - public abstract ArrayList<ProgramShowCase> getUserProgram(String userid); - - public abstract ArrayList<KataSubscription> getKataSubscription(String programid, String userid); - - public abstract KataSubscription getKataSubscriptionByID(String kataid, String programid, String userid); - - public abstract void createKataSubscription(String kataid, String programid, String userid); - - public abstract void incKataSubscriptionAttempt(String kataid, String programid, String userid); - - public abstract void updateKataSubscription(String kataid, String programid, String userid, String sol, String status); - - public abstract void deleteProgram(String programid); - - public abstract void createUser(MockUser u); - - public abstract MockUser checkUser(String username, String password); - - public abstract boolean doUserExists(String username); - -} diff --git a/gateway/src/main/java/ch/hepia/repository/MongoDB.java b/gateway/src/main/java/ch/hepia/repository/MongoDB.java new file mode 100644 index 0000000000000000000000000000000000000000..c9e9086718a4f429009c637337d4c9905b0ad341 --- /dev/null +++ b/gateway/src/main/java/ch/hepia/repository/MongoDB.java @@ -0,0 +1,435 @@ +package ch.hepia.repository; + +import ch.hepia.repository.modals.kata.*; +import ch.hepia.repository.modals.program.*; + +import ch.hepia.repository.modals.user.User; +import com.mongodb.*; +import com.mongodb.client.AggregateIterable; +import com.mongodb.client.MongoCollection; +import com.mongodb.client.MongoDatabase; +import com.mongodb.client.model.Indexes; + +import com.mongodb.client.model.UpdateOptions; +import org.bson.Document; +import org.bson.codecs.configuration.CodecRegistry; +import org.bson.codecs.pojo.PojoCodecProvider; + +import java.util.*; +import java.util.regex.Pattern; + +import static com.mongodb.client.model.Aggregates.*; +import static com.mongodb.client.model.Filters.*; +import static com.mongodb.client.model.Updates.*; +import static com.mongodb.client.model.Projections.*; + +import static org.bson.codecs.configuration.CodecRegistries.fromProviders; +import static org.bson.codecs.configuration.CodecRegistries.fromRegistries; + +public class MongoDB implements ProgramsDataBase { + + private MongoClient mongoClient; + private MongoDatabase database; + + CodecRegistry pojoCodecRegistry = fromRegistries(MongoClient.getDefaultCodecRegistry(), + fromProviders(PojoCodecProvider.builder().automatic(true).build())); + + public MongoDB() { + MongoCredential credential = MongoCredential.createCredential("shodai", "DojoHepia", "shodai".toCharArray()); + this.mongoClient = new MongoClient(new ServerAddress("localhost", 27017), Arrays.asList(credential), MongoClientOptions.builder().codecRegistry(pojoCodecRegistry).build()); + this.database = mongoClient.getDatabase("DojoHepia"); + database.getCollection("Programs").createIndex(Indexes.ascending("title")); + + if (!isExisting("shodai")) { + create(new User("0", "shodai", "shodai", "d033e22ae348aeb5660fc2140aec35850c4da997")); + } + + } + + public void create(Program program) { + database.getCollection("Programs", Program.class).insertOne(program); + } + + public void create(Kata kata, String programid) { + database.getCollection("Programs").updateOne(eq("_id", programid), combine(inc("nbKata", 1), push("katas", kata))); + } + + public Optional<List<ProgramShowCase>> programsDetails() { + ArrayList<ProgramShowCase> p = new ArrayList<>(); + MongoCollection<Program> programs = database.getCollection("Programs", Program.class); + + // TODO voir si il y a pas moyen que je puisse aggregate et generer un programshowcase avec les project + + for (Program prg : programs.find()) + p.add(new ProgramShowCase(prg.getTitle(), prg.getSensei(), prg.getLanguage(), prg.getDescription(), prg.getNbKata(), prg.getTags(), prg.getId())); + + if (p == null) + return Optional.empty(); + else if (p.size() == 0) + return Optional.empty(); + else return Optional.of(p); + } + + public Optional<Kata> kata(String kataid) { + AggregateIterable<Kata> kata = database.getCollection("Programs", Kata.class).aggregate(Arrays.asList( + unwind("$katas"), + project( + fields(excludeId(), include("katas"))), + match(eq("katas._id", kataid)), + replaceRoot("$katas") + )); + + if (kata.iterator().hasNext()) + return Optional.of(kata.iterator().next()); + else + return Optional.empty(); + } + + public boolean isKataActivated(String kataid) { + return database.getCollection("Programs", Kata.class).aggregate(Arrays.asList( + unwind("$katas"), + project( + fields(excludeId(), include("katas"))), + match(eq("katas._id", kataid)), + replaceRoot("$katas") + )).iterator().next().isActivated(); + } + + public Optional<List<KataShowCase>> kataDetails(String programid, String userid) { + + AggregateIterable<Kata> kata = database.getCollection("Programs", Kata.class).aggregate(Arrays.asList( + unwind("$katas"), + match(eq("_id", programid)), + replaceRoot("$katas") + + )); + + ArrayList<KataShowCase> ktsc = new ArrayList<>(); + for (Kata x : kata) + ktsc.add(new KataShowCase(x.getTitle(), x.getDifficulty(), x.getId(), getKataStatus(x.getId(), programid, userid), x.isActivated())); + + return Optional.of(ktsc); + } + + private void decrementResolvedKata(String kataid) { + database.getCollection("Users").updateMany(eq("programSubscriptions.katas._id", kataid), inc("programSubscriptions.$[i].nbKataDone", -1), new UpdateOptions().arrayFilters(Arrays.asList( + eq("i.katas.status", "RESOLVED") + ))); + } + + private void incrementResolvedKata(String kataid) { + database.getCollection("Users").updateMany(eq("programSubscriptions.katas._id", kataid), inc("programSubscriptions.$[i].nbKataDone", 1), new UpdateOptions().arrayFilters(Arrays.asList( + eq("i.katas.status", "RESOLVED") + ))); + } + + private String getKataStatus(String kataid, String programid, String userid) { + + if (isSubscribed(userid, programid) || hasBeenSubscribed(userid, programid)) { + AggregateIterable<KataSubscription> kata = database.getCollection("Users", KataSubscription.class).aggregate(Arrays.asList( + match(combine(eq("_id", userid), eq("programSubscriptions.katas._id", kataid))), + unwind("$programSubscriptions"), + replaceRoot("$programSubscriptions"), + unwind("$katas"), + match(eq("katas._id", kataid)), + replaceRoot("$katas"), + project(fields(excludeId(), include("status"))) + )); + + try { + return kata.iterator().next().getStatus(); + } catch (NoSuchElementException e) { + return "TODO"; + } + + + } else + return "TODO"; + } + + public Optional<ProgramShowCase> programDetailsById(String id) { + ProgramShowCase p; + + try { + Program program = database.getCollection("Programs", Program.class).aggregate(Arrays.asList(match(eq("_id", id)))).iterator().next(); + p = new ProgramShowCase(program.getTitle(), program.getSensei(), program.getLanguage(), program.getDescription(), program.getNbKata(), program.getTags(), program.getId()); + + return Optional.of(p); + } catch (NoSuchElementException e) { + return Optional.empty(); + } + } + + public Optional<List<ProgramShowCase>> programDetailsFiltered(String type, String resource) { + ArrayList<ProgramShowCase> p = new ArrayList<>(); + + MongoCollection<Program> cprograms = database.getCollection("Programs", Program.class); + Pattern regex = Pattern.compile(resource, Pattern.CASE_INSENSITIVE); + Iterable<Program> programs = cprograms.find(eq(type, regex)); + + + programs.forEach(x -> { + p.add(new ProgramShowCase(x.getTitle(), x.getSensei(), x.getLanguage(), x.getDescription(), x.getNbKata(), x.getTags(), x.getId(), -1)); + }); + + if (p == null) + return Optional.empty(); + else if (p.size() == 0) + return Optional.empty(); + else return Optional.of(p); + } + + public Optional<ProgramSubscription> subscriptionByID(String userid, String idrogram) { + AggregateIterable<ProgramSubscription> prgsub = database.getCollection("Users", ProgramSubscription.class).aggregate(Arrays.asList( + match(eq("_id", userid)), + unwind("$programSubscriptions"), + project( + fields(excludeId(), include("programSubscriptions"))), + match(eq("programSubscriptions.idprogram", idrogram)), + replaceRoot("$programSubscriptions") + )); + + if (prgsub.iterator().hasNext()) + return Optional.of(prgsub.iterator().next()); + else + return Optional.empty(); + + } + + + public void create(String userid, ProgramSubscription p) { + database.getCollection("Users").updateOne(eq("_id", userid), push("programSubscriptions", p)); + } + + public void toggleSubscription(String userid, String idprogram) { + Document status = database.getCollection("Users").aggregate(Arrays.asList( + match(eq("_id", userid)), + unwind("$programSubscriptions"), + project( + fields(excludeId(), include("programSubscriptions"))), + match(eq("programSubscriptions.idprogram", idprogram)), + replaceRoot("$programSubscriptions"), + project( + fields(excludeId(), include("status"))) + )).iterator().next(); + + database.getCollection("Users").updateOne(eq("_id", userid), set("programSubscriptions.$[i].status", !status.getBoolean("status")), new UpdateOptions().arrayFilters(Arrays.asList( + eq("i.idprogram", idprogram) + ))); + } + + public void toggleKataActivation(String kataid) { + int number; + boolean isActivated = database.getCollection("Programs", Kata.class).aggregate(Arrays.asList( + project(fields(excludeId(), include("katas"))), + unwind("$katas"), + replaceRoot("$katas"), + match(eq("_id", kataid)) + + )).first().isActivated(); + + if (isActivated) { + decrementResolvedKata(kataid); + number = -1; + } else { + number = 1; + incrementResolvedKata(kataid); + } + + database.getCollection("Programs").updateOne(eq("katas._id", kataid), combine(inc("nbKata", number), set("katas.$[i].activated", !isActivated)), new UpdateOptions().arrayFilters(Arrays.asList( + eq("i._id", kataid) + ))); + } + + public Optional<List<ProgramShowCase>> userSubscriptions(String userid) { + + AggregateIterable<ProgramSubscription> programids = database.getCollection("Users", ProgramSubscription.class).aggregate(Arrays.asList( + match(eq("_id", userid)), + project( + fields(excludeId(), include("programSubscriptions"))), + unwind("$programSubscriptions"), + project( + fields(excludeId(), exclude("katas"))), + match(eq("programSubscriptions.status", true)), + replaceRoot("$programSubscriptions") + )); + + ArrayList<ProgramShowCase> prgsc = new ArrayList<>(); + MongoCollection<Program> cprograms = database.getCollection("Programs", Program.class); + + for (ProgramSubscription x : programids) { + Program p = cprograms.find(combine(eq("_id", x.idprogram), ne("idsensei", userid))).first(); + if (!(p == null)) + prgsc.add(new ProgramShowCase(p.getTitle(), p.getSensei(), p.getLanguage(), p.getDescription(), p.getNbKata(), p.getTags(), p.getId(), x.nbKataDone)); + } + if (prgsc == null) + return Optional.empty(); + else if (prgsc.size() == 0) + return Optional.empty(); + else return Optional.of(prgsc); + } + + public Optional<List<ProgramShowCase>> userPrograms(String userid) { + Iterable<Program> cprograms = database.getCollection("Programs", Program.class).find(eq("idsensei", userid)); + ArrayList<ProgramShowCase> prgsc = new ArrayList<>(); + + for (Program p : cprograms) + prgsc.add(new ProgramShowCase(p.getTitle(), p.getSensei(), p.getLanguage(), p.getDescription(), p.getNbKata(), p.getTags(), p.getId(), -1)); + + if (prgsc == null) + return Optional.empty(); + else if (prgsc.size() == 0) + return Optional.empty(); + else return Optional.of(prgsc); + } + + + public boolean isProgramOwner(String userid, String programid) { + try { + database.getCollection("Programs", Program.class).find(combine(eq("idsensei", userid), eq("_id", programid))).first().getId(); + return true; + } catch (NullPointerException e) { + return false; + } + } + + public boolean isKataOwner(String userid, String kataid) { + try { + database.getCollection("Programs", Program.class).find(combine(eq("idsensei", userid), eq("katas._id", kataid))).first().getId(); + return true; + } catch (NullPointerException e) { + return false; + } + } + + private boolean hasBeenSubscribed(String userid, String programid) { + try { + database.getCollection("Users").aggregate(Arrays.asList( + match(eq("_id", userid)), + unwind("$programSubscriptions"), + project( + fields(excludeId(), include("programSubscriptions"))), + match(eq("programSubscriptions.idprogram", programid)), + replaceRoot("$programSubscriptions"), + project( + fields(excludeId(), include("status"))) + )).iterator().next().getBoolean("status"); + return true; + } catch (NoSuchElementException e) { + return false; + } + } + + public boolean isSubscribed(String userid, String programid) { + try { + return database.getCollection("Users").aggregate(Arrays.asList( + match(eq("_id", userid)), + unwind("$programSubscriptions"), + project( + fields(excludeId(), include("programSubscriptions"))), + match(eq("programSubscriptions.idprogram", programid)), + replaceRoot("$programSubscriptions"), + project( + fields(excludeId(), include("status"))) + )).iterator().next().getBoolean("status"); + } catch (NoSuchElementException e) { + return false; + } + } + + public Optional<KataSubscription> kataSubscriptionById(String kataid, String programid, String userid) { + + AggregateIterable<KataSubscription> kata = database.getCollection("Users", KataSubscription.class).aggregate(Arrays.asList( + match(combine(eq("_id", userid), eq("programSubscriptions.katas._id", kataid))), + unwind("$programSubscriptions"), + replaceRoot("$programSubscriptions"), + project(fields(excludeId(), include("katas"))), + unwind("$katas"), + match(eq("katas._id", kataid)), + replaceRoot("$katas") + + )); + + if (kata.iterator().hasNext()) + return Optional.of(kata.iterator().next()); + else + return Optional.empty(); + } + + + public void createKataSubscription(String kataid, String programid, String userid) { + database.getCollection("Users").updateOne(eq("_id", userid), push("programSubscriptions.$[index].katas", new KataSubscription(kataid, "ONGOING", "", 0)), new UpdateOptions().arrayFilters(Arrays.asList( + eq("index.idprogram", programid) + ))); + } + + public void incrementKataSubscriptionAttempt(String kataid, String programid, String userid) { + database.getCollection("Users").updateOne(eq("_id", userid), inc("programSubscriptions.$[i].katas.$[j].nbAttempt", 1), new UpdateOptions().arrayFilters(Arrays.asList( + eq("i.idprogram", programid), + eq("j._id", kataid) + ))); + } + + public void updateKataSubscription(String kataid, String programid, String userid, String sol, String status) { + + database.getCollection("Users").updateOne(eq("_id", userid), combine( + set("programSubscriptions.$[i].katas.$[j].mysol", sol), + set("programSubscriptions.$[i].katas.$[j].status", status), + inc("programSubscriptions.$[i].nbKataDone", 1) + ), new UpdateOptions().arrayFilters(Arrays.asList( + eq("i.idprogram", programid), + eq("j._id", kataid) + ))); + } + + public void deleteProgram(String programid) { + database.getCollection("Users").updateMany(eq("programSubscriptions.idprogram", programid), pull("programSubscriptions", new BasicDBObject("idprogram", programid))); + database.getCollection("Programs").deleteOne(eq("_id", programid)); + } + + public void update(String programid, ProgramShowCase p) { + database.getCollection("Programs").updateOne(eq("_id", programid), combine( + set("title", p.title), + set("description", p.description), + set("tags", p.tags) + + )); + } + + public String update(Kata k) { + String programid = database.getCollection("Programs", Program.class).find(eq("katas._id", k.getId())).first().getId(); + deleteKata(k.getId()); + database.getCollection("Programs").updateOne(eq("_id", programid), push("katas", k)); + return programid; + } + + + public void create(User u) { + database.getCollection("Users", User.class).insertOne(u); + } + + public Optional<User> checkUserCredentials(String username, String password) { + User u = database.getCollection("Users", User.class).find(combine(eq("username", username), eq("password", password))).first(); + + if (u == null) + return Optional.empty(); + else + return Optional.of(u); + } + + public void deleteKata(String kataid) { + decrementResolvedKata(kataid); + database.getCollection("Users").updateMany(eq("programSubscriptions.katas._id", kataid), pull("programSubscriptions.$[].katas", new BasicDBObject("_id", kataid))); + database.getCollection("Programs").updateOne(eq("katas._id", kataid), pull("katas", new BasicDBObject("_id", kataid))); + database.getCollection("Programs").updateOne(combine(eq("katas._id", kataid), eq("katas.activated", "true")), inc("nbKata", -1)); + + } + + public boolean isExisting(String username) { + User u = database.getCollection("Users", User.class).find(eq("username", username)).first(); + if (u == null) + return false; + return true; + } + +} diff --git a/gateway/src/main/java/ch/hepia/repository/ProgramsDataBase.java b/gateway/src/main/java/ch/hepia/repository/ProgramsDataBase.java new file mode 100644 index 0000000000000000000000000000000000000000..e6cf4aa5142d97e352264043326fabab3168599e --- /dev/null +++ b/gateway/src/main/java/ch/hepia/repository/ProgramsDataBase.java @@ -0,0 +1,74 @@ +package ch.hepia.repository; + +import ch.hepia.repository.modals.kata.*; +import ch.hepia.repository.modals.program.*; +import ch.hepia.repository.modals.user.User; + + +import java.util.List; +import java.util.Optional; + +public interface ProgramsDataBase { + void create(Program program); + + void create(Kata kata, String programid); + + Optional<List<ProgramShowCase>> programsDetails(); + + Optional<Kata> kata(String kataid); + + Optional<List<KataShowCase>> kataDetails(String programID, String userid); + + Optional<ProgramShowCase> programDetailsById(String id); + + Optional<List<ProgramShowCase>> programDetailsFiltered(String type, String resource); + + Optional<ProgramSubscription> subscriptionByID(String userid, String idrogram); + + void create(String userid, ProgramSubscription p); + + void toggleSubscription(String userid, String idprogram); + + + Optional<KataSubscription> kataSubscriptionById(String kataid, String programid, String userid); + + void createKataSubscription(String kataid, String programid, String userid); + + + void deleteProgram(String programid); + + + void deleteKata(String kataid); + + boolean isProgramOwner(String userid, String programid); + + boolean isKataOwner(String userid, String kataid); + + void update(String programid, ProgramShowCase p); + + String update(Kata k); + + void toggleKataActivation(String kataid); + + boolean isKataActivated(String kataid); + + + + + void incrementKataSubscriptionAttempt(String kataid, String programid, String userid); + + void updateKataSubscription(String kataid, String programid, String userid, String sol, String status); + + boolean isSubscribed(String userid, String programid); + + Optional<List<ProgramShowCase>> userSubscriptions(String userid); + + Optional<List<ProgramShowCase>> userPrograms(String userid); + + void create(User u); + + boolean isExisting(String username); + + Optional<User> checkUserCredentials(String username, String password); + +} diff --git a/gateway/src/main/java/ch/hepia/repository/cursors/ProgramInterface.java b/gateway/src/main/java/ch/hepia/repository/cursors/ProgramInterface.java new file mode 100644 index 0000000000000000000000000000000000000000..05fd61a509c81aa9841a133734961ece9f70eb2f --- /dev/null +++ b/gateway/src/main/java/ch/hepia/repository/cursors/ProgramInterface.java @@ -0,0 +1,5 @@ +package ch.hepia.repository.cursors; + +public interface ProgramInterface { + +} diff --git a/gateway/src/main/java/ch/hepia/repository/cursors/Programs.java b/gateway/src/main/java/ch/hepia/repository/cursors/Programs.java new file mode 100644 index 0000000000000000000000000000000000000000..ee6ed10d79891e3382125a5b46a63c5625456c5b --- /dev/null +++ b/gateway/src/main/java/ch/hepia/repository/cursors/Programs.java @@ -0,0 +1,4 @@ +package ch.hepia.repository.cursors; + +public class Programs { +} diff --git a/gateway/src/main/java/ch/hepia/repository/cursors/UserInterface.java b/gateway/src/main/java/ch/hepia/repository/cursors/UserInterface.java new file mode 100644 index 0000000000000000000000000000000000000000..8de9345ffaff85c3d39451614b78c9dea2a720fc --- /dev/null +++ b/gateway/src/main/java/ch/hepia/repository/cursors/UserInterface.java @@ -0,0 +1,13 @@ +package ch.hepia.repository.cursors; + +import ch.hepia.repository.modals.user.User; + +import java.util.Optional; + +public interface UserInterface { + void create(User u); + + Optional<User> checkUserCredentials(String username, String password); + + boolean isExisting(String username); +} \ No newline at end of file diff --git a/gateway/src/main/java/ch/hepia/repository/cursors/Users.java b/gateway/src/main/java/ch/hepia/repository/cursors/Users.java new file mode 100644 index 0000000000000000000000000000000000000000..02d67a1e4c5b2c6e16d9087012520cf3da27b95e --- /dev/null +++ b/gateway/src/main/java/ch/hepia/repository/cursors/Users.java @@ -0,0 +1,9 @@ +package ch.hepia.repository.cursors; + +import ch.hepia.repository.modals.user.User; + +import java.util.Optional; + +public class Users { + +} diff --git a/gateway/src/main/java/Kata.java b/gateway/src/main/java/ch/hepia/repository/modals/kata/Kata.java similarity index 81% rename from gateway/src/main/java/Kata.java rename to gateway/src/main/java/ch/hepia/repository/modals/kata/Kata.java index 280b4b4876b7929f77d1a22e3620fc9f93898061..466c85f41ac011d69eafe377a590747d3264bf23 100644 --- a/gateway/src/main/java/Kata.java +++ b/gateway/src/main/java/ch/hepia/repository/modals/kata/Kata.java @@ -1,7 +1,9 @@ +package ch.hepia.repository.modals.kata; + public class Kata { - private String _id, id,title, canva, cassert, solution, rules,programID,difficulty,language; - private boolean keepAssert; - private int nbAttempt; + private String _id, id,title, canva, cassert, solution, rules,difficulty,language; + private boolean keepAssert,activated; + private double nbAttempt; @@ -54,23 +56,15 @@ public class Kata { this.rules = rules; } - public int getNbAttempt() { + public double getNbAttempt() { return nbAttempt; } - public void setNbAttempt(int nbAttempt) { + public void setNbAttempt(double nbAttempt) { this.nbAttempt = nbAttempt; } - public String getProgramID() { - return programID; - } - - public void setProgramID(String programID) { - this.programID = programID; - } - public String getDifficulty() { return difficulty; } @@ -102,4 +96,12 @@ public class Kata { public void setId(String id) { this.id = id; } + + public boolean isActivated() { + return activated; + } + + public void setActivated(boolean activated) { + this.activated = activated; + } } diff --git a/gateway/src/main/java/ch/hepia/repository/modals/kata/KataShowCase.java b/gateway/src/main/java/ch/hepia/repository/modals/kata/KataShowCase.java new file mode 100644 index 0000000000000000000000000000000000000000..64499ebc70547276d0d8dee666ebd5ccf720bb4e --- /dev/null +++ b/gateway/src/main/java/ch/hepia/repository/modals/kata/KataShowCase.java @@ -0,0 +1,14 @@ +package ch.hepia.repository.modals.kata; + +public class KataShowCase { + public String title,difficulty,id,status; + public boolean activated; + + public KataShowCase(String title, String difficulty, String id, String status, boolean activated){ + this.difficulty = difficulty; + this.title = title; + this.id = id; + this.status = status; + this.activated = activated; + } +} diff --git a/gateway/src/main/java/KataSubscription.java b/gateway/src/main/java/ch/hepia/repository/modals/kata/KataSubscription.java similarity index 96% rename from gateway/src/main/java/KataSubscription.java rename to gateway/src/main/java/ch/hepia/repository/modals/kata/KataSubscription.java index 2c1745951287e5cd0aa3011888a888617482b406..852a5895bc3c990c70da24c6eb0cd44893cad7a7 100644 --- a/gateway/src/main/java/KataSubscription.java +++ b/gateway/src/main/java/ch/hepia/repository/modals/kata/KataSubscription.java @@ -1,3 +1,5 @@ +package ch.hepia.repository.modals.kata; + public class KataSubscription { //katas [{id:1,status:"resolved",mysol:".."}] diff --git a/gateway/src/main/java/Program.java b/gateway/src/main/java/ch/hepia/repository/modals/program/Program.java similarity index 83% rename from gateway/src/main/java/Program.java rename to gateway/src/main/java/ch/hepia/repository/modals/program/Program.java index 7ffef7602c7354109ba75da1f14ebb6e6d80e22a..dcb755c4f636d75e4372f14a0a85e55c282be4b7 100644 --- a/gateway/src/main/java/Program.java +++ b/gateway/src/main/java/ch/hepia/repository/modals/program/Program.java @@ -1,3 +1,7 @@ +package ch.hepia.repository.modals.program; + +import ch.hepia.repository.modals.kata.Kata; + import java.util.ArrayList; public class Program { @@ -88,11 +92,11 @@ public class Program { this.idsensei = idsensei; } /* - public ArrayList<Kata> getKata() { - return kata; + public ArrayList<Kata.Kata> getKata() { + return ch.hepia.database.modal.kata; } - public void setKata(ArrayList<Kata> kata) { - this.kata = kata; + public void setKata(ArrayList<Kata.Kata> ch.hepia.database.modal.kata) { + this.ch.hepia.database.modal.kata = ch.hepia.database.modal.kata; }*/ } diff --git a/gateway/src/main/java/ch/hepia/repository/modals/program/ProgramShowCase.java b/gateway/src/main/java/ch/hepia/repository/modals/program/ProgramShowCase.java new file mode 100644 index 0000000000000000000000000000000000000000..6d7283a4f7aebaa5fcedc178643f3ccb5e31399f --- /dev/null +++ b/gateway/src/main/java/ch/hepia/repository/modals/program/ProgramShowCase.java @@ -0,0 +1,36 @@ +package ch.hepia.repository.modals.program; + +import java.util.ArrayList; + +public class ProgramShowCase { + public String title, sensei, language, description, id; + public int nbKata; + public ArrayList<String> tags; + public int nbKataDone; + + + public ProgramShowCase(String title, String sensei, String language, String description, int nbKata, ArrayList<String> tags, String id, int nbKataDone) { + this.title = title; + this.sensei = sensei; + this.language = language; + this.description = description; + this.nbKata = nbKata; + this.tags = tags; + this.id = id; + this.nbKataDone = nbKataDone; + + + } + + public ProgramShowCase(String title, String sensei, String language, String description, int nbKata, ArrayList<String> tags, String id) { + this.title = title; + this.sensei = sensei; + this.language = language; + this.description = description; + this.nbKata = nbKata; + this.tags = tags; + this.id = id; + } + + public ProgramShowCase(){}; +} diff --git a/gateway/src/main/java/ch/hepia/repository/modals/program/ProgramSubscription.java b/gateway/src/main/java/ch/hepia/repository/modals/program/ProgramSubscription.java new file mode 100644 index 0000000000000000000000000000000000000000..b982aa26938b65790a4f955fd93c68492e2b4cac --- /dev/null +++ b/gateway/src/main/java/ch/hepia/repository/modals/program/ProgramSubscription.java @@ -0,0 +1,13 @@ +package ch.hepia.repository.modals.program; + +import ch.hepia.repository.modals.kata.KataSubscription; + +import java.util.ArrayList; + +public class ProgramSubscription { + + public String _id,id, iduser, idprogram; + public boolean status; + public int nbKataDone; + public ArrayList<KataSubscription> katas; +} diff --git a/gateway/src/main/java/MockUser.java b/gateway/src/main/java/ch/hepia/repository/modals/user/User.java similarity index 59% rename from gateway/src/main/java/MockUser.java rename to gateway/src/main/java/ch/hepia/repository/modals/user/User.java index 7812029403afb5c1376dd2e4852c410fbcdf96ba..a57d163692c9560190449002e75e3c8171ab5e15 100644 --- a/gateway/src/main/java/MockUser.java +++ b/gateway/src/main/java/ch/hepia/repository/modals/user/User.java @@ -1,14 +1,21 @@ -public class MockUser { +package ch.hepia.repository.modals.user; + +import ch.hepia.repository.modals.program.ProgramSubscription; + +import java.util.ArrayList; + +public class User { private String id, _id, username, password, level; + private ArrayList<ProgramSubscription> programSubscriptions; - public MockUser(String id, String username, String level,String password) { + public User(String id, String username, String level, String password) { this.id = id; this.username = username; this.level = level; this.password = password; } - public MockUser(){} + public User(){} public String getId() { return id; @@ -51,4 +58,11 @@ public class MockUser { } + public ArrayList<ProgramSubscription> getProgramSubscriptions() { + return programSubscriptions; + } + + public void setProgramSubscriptions(ArrayList<ProgramSubscription> programSubscriptions) { + this.programSubscriptions = programSubscriptions; + } } \ No newline at end of file diff --git a/gateway/target/classes/Kata.class b/gateway/target/classes/Kata.class deleted file mode 100644 index 19e7b2c45129d7ab6919bd2def1a9070180f3bec..0000000000000000000000000000000000000000 Binary files a/gateway/target/classes/Kata.class and /dev/null differ diff --git a/gateway/target/classes/KataShowCase.class b/gateway/target/classes/KataShowCase.class deleted file mode 100644 index 0cd30bb503988e17695e5101e37861fec13e46c1..0000000000000000000000000000000000000000 Binary files a/gateway/target/classes/KataShowCase.class and /dev/null differ diff --git a/gateway/target/classes/KataSubscription.class b/gateway/target/classes/KataSubscription.class deleted file mode 100644 index 6afe70bbb7a9ed7a739d7c10f2b67abd4f00f572..0000000000000000000000000000000000000000 Binary files a/gateway/target/classes/KataSubscription.class and /dev/null differ diff --git a/gateway/target/classes/LiveDB.class b/gateway/target/classes/LiveDB.class deleted file mode 100644 index 13dceb1079bf4734755c0d11c47764b7e20d4f1e..0000000000000000000000000000000000000000 Binary files a/gateway/target/classes/LiveDB.class and /dev/null differ diff --git a/gateway/target/classes/META-INF/09.kotlin_module b/gateway/target/classes/META-INF/09.kotlin_module new file mode 100644 index 0000000000000000000000000000000000000000..8fb60192d378759239a3ecbf60eac8c8de446e9c Binary files /dev/null and b/gateway/target/classes/META-INF/09.kotlin_module differ diff --git a/gateway/target/classes/MockUser.class b/gateway/target/classes/MockUser.class deleted file mode 100644 index 5233ab9cfe462ae704441d3d485c0accd79cf37d..0000000000000000000000000000000000000000 Binary files a/gateway/target/classes/MockUser.class and /dev/null differ diff --git a/gateway/target/classes/MongoDB.class b/gateway/target/classes/MongoDB.class deleted file mode 100644 index 1690a6899501e0268151c890ff7c34d612d72f28..0000000000000000000000000000000000000000 Binary files a/gateway/target/classes/MongoDB.class and /dev/null differ diff --git a/gateway/target/classes/Program.class b/gateway/target/classes/Program.class deleted file mode 100644 index b90cce2a458199d8e1c735cdbcf628e1dc17f8f3..0000000000000000000000000000000000000000 Binary files a/gateway/target/classes/Program.class and /dev/null differ diff --git a/gateway/target/classes/ProgramShowCase.class b/gateway/target/classes/ProgramShowCase.class deleted file mode 100644 index c1a0eead2fdc0398e887c1f64269e64775af3475..0000000000000000000000000000000000000000 Binary files a/gateway/target/classes/ProgramShowCase.class and /dev/null differ diff --git a/gateway/target/classes/ProgramSubscription.class b/gateway/target/classes/ProgramSubscription.class deleted file mode 100644 index d854a98e25b5874cff272a34d0e9ea353d773f2b..0000000000000000000000000000000000000000 Binary files a/gateway/target/classes/ProgramSubscription.class and /dev/null differ diff --git a/gateway/target/classes/ProgramsDataBase.class b/gateway/target/classes/ProgramsDataBase.class deleted file mode 100644 index c0c01999d9fd0e6dc77addece7c813460d8734a8..0000000000000000000000000000000000000000 Binary files a/gateway/target/classes/ProgramsDataBase.class and /dev/null differ diff --git a/gateway/target/classes/app$Roles.class b/gateway/target/classes/app$Roles.class index 4b64a05c7994775255726b2a5f9f6333e54f31cb..c6cfe634d30caccd9e91517dd22f65ae2bf1258d 100644 Binary files a/gateway/target/classes/app$Roles.class and b/gateway/target/classes/app$Roles.class differ diff --git a/gateway/target/classes/app.class b/gateway/target/classes/app.class index 193a5635f2f7ac70e9b641ac1133076d2fe073d1..35c51b7800651d339570ddb154b6f03ea11e6415 100644 Binary files a/gateway/target/classes/app.class and b/gateway/target/classes/app.class differ diff --git a/gateway/target/classes/ch/hepia/repository/MongoDB.class b/gateway/target/classes/ch/hepia/repository/MongoDB.class new file mode 100644 index 0000000000000000000000000000000000000000..f906ef6731abb7dfcdb2326f16fd7db3d1e2e994 Binary files /dev/null and b/gateway/target/classes/ch/hepia/repository/MongoDB.class differ diff --git a/gateway/target/classes/ch/hepia/repository/ProgramsDataBase.class b/gateway/target/classes/ch/hepia/repository/ProgramsDataBase.class new file mode 100644 index 0000000000000000000000000000000000000000..b27cf42fdaed5c3f872c7f1cf414b751519e66df Binary files /dev/null and b/gateway/target/classes/ch/hepia/repository/ProgramsDataBase.class differ diff --git a/gateway/target/classes/ch/hepia/repository/cursors/ProgramInterface.class b/gateway/target/classes/ch/hepia/repository/cursors/ProgramInterface.class new file mode 100644 index 0000000000000000000000000000000000000000..dea1c6fd1e2f7afcfcdb1a168b16cf6bc8e42173 Binary files /dev/null and b/gateway/target/classes/ch/hepia/repository/cursors/ProgramInterface.class differ diff --git a/gateway/target/classes/ch/hepia/repository/cursors/Programs.class b/gateway/target/classes/ch/hepia/repository/cursors/Programs.class new file mode 100644 index 0000000000000000000000000000000000000000..eeb2e2f0e4fe6207e3ede676a899574db023218f Binary files /dev/null and b/gateway/target/classes/ch/hepia/repository/cursors/Programs.class differ diff --git a/gateway/target/classes/ch/hepia/repository/cursors/UserInterface.class b/gateway/target/classes/ch/hepia/repository/cursors/UserInterface.class new file mode 100644 index 0000000000000000000000000000000000000000..67f17a3990119a17eb87a5e34c514cb9a23346f6 Binary files /dev/null and b/gateway/target/classes/ch/hepia/repository/cursors/UserInterface.class differ diff --git a/gateway/target/classes/ch/hepia/repository/cursors/Users.class b/gateway/target/classes/ch/hepia/repository/cursors/Users.class new file mode 100644 index 0000000000000000000000000000000000000000..0eff0264c03c2134e1c8b6a2bf25e6df9c754c69 Binary files /dev/null and b/gateway/target/classes/ch/hepia/repository/cursors/Users.class differ diff --git a/gateway/target/classes/ch/hepia/repository/modals/kata/Kata.class b/gateway/target/classes/ch/hepia/repository/modals/kata/Kata.class new file mode 100644 index 0000000000000000000000000000000000000000..ce74a872b8318a9adbe2e640eb0184696ad1675b Binary files /dev/null and b/gateway/target/classes/ch/hepia/repository/modals/kata/Kata.class differ diff --git a/gateway/target/classes/ch/hepia/repository/modals/kata/KataShowCase.class b/gateway/target/classes/ch/hepia/repository/modals/kata/KataShowCase.class new file mode 100644 index 0000000000000000000000000000000000000000..2f9e40251ffb7cfe17b3ec02dd7aedb2e6e91a22 Binary files /dev/null and b/gateway/target/classes/ch/hepia/repository/modals/kata/KataShowCase.class differ diff --git a/gateway/target/classes/ch/hepia/repository/modals/kata/KataSubscription.class b/gateway/target/classes/ch/hepia/repository/modals/kata/KataSubscription.class new file mode 100644 index 0000000000000000000000000000000000000000..f3953f2f494b1194581f59a97fa0af1560052cb2 Binary files /dev/null and b/gateway/target/classes/ch/hepia/repository/modals/kata/KataSubscription.class differ diff --git a/gateway/target/classes/ch/hepia/repository/modals/program/Program.class b/gateway/target/classes/ch/hepia/repository/modals/program/Program.class new file mode 100644 index 0000000000000000000000000000000000000000..00e01509a7b59c86c686ccb37d29d0b05910d7ed Binary files /dev/null and b/gateway/target/classes/ch/hepia/repository/modals/program/Program.class differ diff --git a/gateway/target/classes/ch/hepia/repository/modals/program/ProgramShowCase.class b/gateway/target/classes/ch/hepia/repository/modals/program/ProgramShowCase.class new file mode 100644 index 0000000000000000000000000000000000000000..74d1073ec582dc3967dcb20a11db2347dc37dd30 Binary files /dev/null and b/gateway/target/classes/ch/hepia/repository/modals/program/ProgramShowCase.class differ diff --git a/gateway/target/classes/ch/hepia/repository/modals/program/ProgramSubscription.class b/gateway/target/classes/ch/hepia/repository/modals/program/ProgramSubscription.class new file mode 100644 index 0000000000000000000000000000000000000000..1a79fa5f2b7112afe16abdb4d59cb1e53980ec92 Binary files /dev/null and b/gateway/target/classes/ch/hepia/repository/modals/program/ProgramSubscription.class differ diff --git a/gateway/target/classes/ch/hepia/repository/modals/user/User.class b/gateway/target/classes/ch/hepia/repository/modals/user/User.class new file mode 100644 index 0000000000000000000000000000000000000000..210164fc333d77204be9f025611689de71b664e3 Binary files /dev/null and b/gateway/target/classes/ch/hepia/repository/modals/user/User.class differ diff --git a/mongodb/data/programs b/mongodb/data/programs deleted file mode 100644 index c5b23392504c91e38cecd18b4d21e0f38bc5e55c..0000000000000000000000000000000000000000 --- a/mongodb/data/programs +++ /dev/null @@ -1 +0,0 @@ -[{"_id":"baac03de-2816-470e-8789-3c10b438364f","description":"Let's play with arrays in python !","idsensei":"0","katas":[{"_id":"41ea64c1-0711-46a8-aece-fae593283ad1","canva":"def add(arr,m):","cassert":"from assertpy import assert_that\nimport sample as m\n\nassert_that(m.add([2,3,4],3)).is_equal_to([2,3,4,3])","difficulty":"Ceinture blanche","keepAssert":false,"language":"python","nbAttempt":3,"programID":"baac03de-2816-470e-8789-3c10b438364f","rules":"Add the given element to the given array\n\nexemple :\nafter you've added the number '3' to the array [2,3,4], it becomes [2,3,4,3]","solution":"def add(arr,m):\n arr.append(m)\n return arr","title":"Add element"},{"_id":"55501e10-12fe-446f-aea1-2d4db550f1f6","canva":"def mult(arr,n):\n # begin code here\n ","cassert":"from assertpy import assert_that\nimport sample as m\n\nassert_that(m.mult([2,3,4],2)).is_equal_to([4,6,8])\nassert_that(m.mult([2,3,4],5)).is_equal_to([10,15,20])","difficulty":"Ceinture blanche","keepAssert":true,"language":"python","nbAttempt":10,"programID":"baac03de-2816-470e-8789-3c10b438364f","rules":"You'll multiply each element of a given array by the given number.","solution":"def mult(arr,n):\n return [i * n for i in arr]","title":"Multiply elements"}],"language":"python","nbKata":2,"sensei":"shodai","tags":["arrays","hashmap","list"],"title":"Arrays"},{"_id":"26f8bb8a-e872-4b21-94a4-56308d500399","description":"Basics of the python language","idsensei":"0","katas":[{"_id":"4603ffd1-054f-4163-af51-d84a84c894e9","canva":"def ret(n):\n ","cassert":"from assertpy import assert_that\nimport sample as m\n\nassert_that(m.ret(5)).is_equal_to(5)\nassert_that(m.ret(4)).is_equal_to(4)","difficulty":"Ceinture blanche","keepAssert":false,"language":"python","nbAttempt":100,"programID":"26f8bb8a-e872-4b21-94a4-56308d500399","rules":"Just return the given value.","solution":"def ret(n):\n return n","title":"Return n"}],"language":"python","nbKata":1,"sensei":"shodai","tags":["basics","python"],"title":"Fundamentals"},{"_id":"86a3991a-a02e-4e0a-9323-7f4cedca2e3b","description":"Arrays in java are not that easy.","idsensei":"0","katas":[{"_id":"24ba470b-5678-482b-a888-95a02b6bf90e","canva":"import java.util.ArrayList;\n\npublic class Kata {\n public static int sum(ArrayList<Integer> list){\n \n }\n}\n","cassert":"import static org.junit.Assert.*;\nimport java.util.ArrayList;\n\npublic class Main {\n\n public static void main(String[] args) {\n\n ArrayList<Integer> mylist = new ArrayList<>();\n mylist.add(15);\n mylist.add(5);\n mylist.add(10);\n\n assertEquals(Kata.sum(mylist),30); \n\n }\n}","difficulty":"Ceinture blanche","keepAssert":true,"language":"java","nbAttempt":2,"programID":"86a3991a-a02e-4e0a-9323-7f4cedca2e3b","rules":"Return a sum of all element in an arraylist","solution":"import java.util.ArrayList;\n\npublic class Kata {\n public static int sum(ArrayList<Integer> list){\n int sum = 0;\n for(int n : list)\n sum += n;\n return sum;\n }\n}\n","title":"Sum up element"}],"language":"java","nbKata":1,"sensei":"shodai","tags":["arrays","arraylist","hashmap"],"title":"Arrays"}] diff --git a/mongodb/data/programssubscriptions b/mongodb/data/programssubscriptions deleted file mode 100644 index c433179607fa2b5645c44d3e7e42221df7beb7a4..0000000000000000000000000000000000000000 --- a/mongodb/data/programssubscriptions +++ /dev/null @@ -1,2 +0,0 @@ -[{"_id":"0a8e6a59-835c-4936-857d-4d10a8fea2c9","idprogram":"baac03de-2816-470e-8789-3c10b438364f","iduser":"0","katas":[{"_id":"41ea64c1-0711-46a8-aece-fae593283ad1","mysol":"def add(arr,m):\n arr.append(m)\n return arr","nbAttempt":1,"status":"RESOLVED"}],"nbKataDone":1,"status":true},{"_id":"95fe5168-f463-493d-8357-c05aee8caeb8","idprogram":"26f8bb8a-e872-4b21-94a4-56308d500399","iduser":"0","katas":[],"nbKataDone":0,"status":true},{"_id":"4863a985-ad1f-4de9-8ae9-98f4721d81d9","idprogram":"86a3991a-a02e-4e0a-9323-7f4cedca2e3b","iduser":"0","katas":[{"_id":"24ba470b-5678-482b-a888-95a02b6bf90e","mysol":"import java.util.ArrayList;\n\npublic class Kata {\n public static int sum(ArrayList<Integer> list){\n int sum = 0;\n for(int i = 0;i<list.size();i++)\n sum += list.get(i);\n return sum;\n }\n}\n","nbAttempt":3,"status":"RESOLVED"}],"nbKataDone":1,"status":true}] - diff --git a/mongodb/docker-compose.yml b/mongodb/docker-compose.yml index f9de26750b90905eb7238f171b09ac3f7901b1cf..39cff9ee37e659151ed6067b54e09cd435ccab69 100644 --- a/mongodb/docker-compose.yml +++ b/mongodb/docker-compose.yml @@ -3,15 +3,15 @@ version: '3.1' services: mongo: - image: mongo + build: ./mongo restart: always ports: - 27017:27017 environment: MONGO_INITDB_ROOT_USERNAME: root MONGO_INITDB_ROOT_PASSWORD: example - - + MONGO_INITDB_DATABASE: DojoHepia + mongo-express: image: mongo-express restart: always diff --git a/mongodb/mongo/Dockerfile b/mongodb/mongo/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..8f3e76c3d5fc37d18825fb6a87b8cd7e52f456cd --- /dev/null +++ b/mongodb/mongo/Dockerfile @@ -0,0 +1,3 @@ +FROM mongo + +COPY seed.js /docker-entrypoint-initdb.d \ No newline at end of file diff --git a/mongodb/mongo/seed.js b/mongodb/mongo/seed.js new file mode 100644 index 0000000000000000000000000000000000000000..abdff26919037397a176b734e4902004ecf8e70c --- /dev/null +++ b/mongodb/mongo/seed.js @@ -0,0 +1,15 @@ +conn = new Mongo(); +db = conn.getDB("DojoHepia"); + +db.createUser( + { + user: "shodai", + pwd: "shodai", + roles: [ + { role: "readWrite", db: "DojoHepia" } + ] + } +); + +db.Users.insertMany([{"_id":"0","level":"shodai","password":"d033e22ae348aeb5660fc2140aec35850c4da997","username":"shodai","programSubscriptions":[{"id":"0de80f4e-460f-40b7-910f-7ccb283a0f7c","idprogram":"97614887-c6d0-47ca-82a5-68de490add04","katas":[{"_id":"c954ebc1-2034-432e-9c89-622e45ac7b00","mysol":"","nbAttempt":0,"status":"ONGOING"},{"_id":"91fdb7f8-abca-48a1-b0f8-59eb3ad3468d","mysol":"","nbAttempt":0,"status":"ONGOING"}],"nbKataDone":0,"status":true},{"id":"47b702c8-6a17-48b1-b9ff-98fd574a56ea","idprogram":"01ae6952-0e75-42a2-a6bf-d042142ef6fd","katas":[{"_id":"cc7b69ec-32b1-4fff-8cc6-2e990d41102d","mysol":"","nbAttempt":1,"status":"ONGOING"}],"nbKataDone":0,"status":true},{"id":"82964c61-716f-4c2c-8fd6-3b159b295696","idprogram":"4193bb1f-ea80-422c-b31e-239e526ffb52","katas":[],"nbKataDone":0,"status":true}]},{"_id":"252600be-ae2e-4f79-a8e2-f64957ea607b","level":"monji","password":"34bcdf98deb05825ee8f40bad4b5912df89b0b95","username":"noob","programSubscriptions":[{"id":"845ac690-216b-4d82-85d4-95e335478742","idprogram":"4193bb1f-ea80-422c-b31e-239e526ffb52","katas":[{"_id":"56dc8061-9014-4416-89e8-489ee24a1e6e","mysol":"def ret(n):\n return n","nbAttempt":2,"status":"RESOLVED"}],"nbKataDone":1,"status":true},{"id":"3422f752-f1be-43f1-b777-c12b59844871","idprogram":"97614887-c6d0-47ca-82a5-68de490add04","katas":[{"_id":"c954ebc1-2034-432e-9c89-622e45ac7b00","mysol":"def mult(arr,n):\n return [i*n for i in arr]","nbAttempt":1,"status":"RESOLVED"},{"_id":"91fdb7f8-abca-48a1-b0f8-59eb3ad3468d","mysol":"def add(arr,m):\n arr.append(m)\n return arr","nbAttempt":2,"status":"FAILED"}],"nbKataDone":2,"status":true}]}]); +db.Programs.insertMany([{"_id":"97614887-c6d0-47ca-82a5-68de490add04","description":"Let's play with arrays in python.","idsensei":"0","katas":[{"_id":"c954ebc1-2034-432e-9c89-622e45ac7b00","activated":true,"canva":"def mult(arr,n):\n ","cassert":"from assertpy import assert_that\nimport sample as m\n\n\nassert_that(m.mult([1,2,3],6)).is_equal_to([6,12,18])\nassert_that(m.mult([5,10,20],10)).is_equal_to([50,100,200])","difficulty":"Ceinture blanche","keepAssert":true,"language":"python","nbAttempt":10,"rules":"#### Multiplication\n\nMultiply all given element by a given number\n\nExample :\n\n```python\ninput\n> print(m.mult([1,2,3],6))\n```\n\n```python\noutput\n> [6,12,18]\n```\n\nThe function has to be small as possible.","solution":"def mult(arr,n):\n return [i * n for i in arr]","title":"Multiply all elements"},{"_id":"91fdb7f8-abca-48a1-b0f8-59eb3ad3468d","activated":true,"canva":"def add(arr,m):\n # your code goes here :\n \n return arr","cassert":"from assertpy import assert_that\nimport sample as m\n\n\nassert_that(m.add([1,2,3],4)).is_equal_to([1,2,3,4])\nassert_that(m.add([1,2,3],5)).is_equal_to([1,2,3,5])","difficulty":"Ceinture blanche","keepAssert":false,"language":"python","nbAttempt":2,"rules":"#### What appended ?\n\nInsert a given element into a given array\n\n\nExample :\n\n```python\ninput\n> print(m.add([1,2,3],4))\n\noutput\n> [1,2,3,4]\n```\n","solution":"def add(arr,m):\n arr.append(m)\n return arr","title":"What appended ?"}],"language":"python","nbKata":2,"sensei":"shodai","tags":["array","hashmap","list"],"title":"Arrays !"},{"_id":"01ae6952-0e75-42a2-a6bf-d042142ef6fd","description":"Learn to play with numbers in java","idsensei":"0","katas":[{"_id":"13a0bd62-b426-43c8-8ed2-ed37f8c1190b","activated":false,"canva":"public class Kata {\n\n}\n","cassert":"import static org.junit.Assert.*;\n\npublic class Main {\n\n public static void main(String[] args) {\n\n// Example : \n// assertEquals(Kata.yourfunction(someValues,targetedValues)) \n\n }\n}","difficulty":"Ceinture blanche","keepAssert":true,"language":"java","nbAttempt":100,"rules":"### This kata is disabled","solution":"public class Kata {\n\n}\n","title":"disabled one"},{"_id":"cc7b69ec-32b1-4fff-8cc6-2e990d41102d","activated":true,"canva":"import java.util.ArrayList;\n\npublic class Kata {\n public static int sum(ArrayList<Integer> list){\n // your code goes here\n \n return sum;\n }\n}\n","cassert":"import static org.junit.Assert.*;\nimport java.util.ArrayList;\n\npublic class Main {\n\n public static void main(String[] args) {\n\n ArrayList<Integer> mylist = new ArrayList<>();\n \n mylist.add(15);\n mylist.add(5);\n mylist.add(10);\n \n assertEquals(Kata.sum(mylist),30);\n \n mylist.add(10);\n \n assertEquals(Kata.sum(mylist),40);\n }\n}","difficulty":"Ceinture blanche","keepAssert":true,"language":"java","nbAttempt":10,"rules":"#### Sum up !\n\nTargeted knowledge :\n\n- Learn to loop\n- Learn to be cool\n\n\nExample :\n\n```java\n> System.out.print(Kata.sum(new ArrayList<int>(1,2,3)));\n6\n\n> System.out.print(Kata.sum(new ArrayList<int>(1,2,10)));\n13\n```","solution":"import java.util.ArrayList;\n\npublic class Kata {\n public static int sum(ArrayList<Integer> list){\n int sum = 0;\n for(int n : list)\n sum += n;\n return sum;\n }\n}\n","title":"Sum up !"}],"language":"java","nbKata":1,"sensei":"shodai","tags":["number","loop"],"title":"Numbers"},{"_id":"4193bb1f-ea80-422c-b31e-239e526ffb52","description":"If you want to be the hero she deserves, you'll have to go through this program.","idsensei":"0","katas":[{"_id":"56dc8061-9014-4416-89e8-489ee24a1e6e","activated":true,"canva":"def ret(n):\n ","cassert":"from assertpy import assert_that\nimport sample as m\n\nassert_that(m.ret(5)).is_equal_to(5)\nassert_that(m.ret(\"Plop l'ami\")).is_equal_to(\"Plop l'ami\")","difficulty":"Ceinture blanche","keepAssert":false,"language":"python","nbAttempt":100,"rules":"#### Return n\n\nJust return the given value\n\nExample :\n\n```python\n> print(m.ret(5))\n5\n\n> print(m.ret(\"Even some text ! waw\"))\n\"Even some text ! waw\"\n```\n\nThis simple example works because python is a non typed language","solution":"def ret(n):\n return n","title":"Return n"}],"language":"python","nbKata":1,"sensei":"shodai","tags":["return","definition"],"title":"Fundamentals"}]); \ No newline at end of file diff --git a/mongodb/query/mongo-try-query.js b/mongodb/query/mongo-try-query.js new file mode 100644 index 0000000000000000000000000000000000000000..78655191ec6731ff87562f11d04f34ad1e60ce59 --- /dev/null +++ b/mongodb/query/mongo-try-query.js @@ -0,0 +1,259 @@ +db.ProgramsSubscription.find({"idprogram":"baac03de-2816-470e-8789-3c10b438364f","iduser":"0"}).map( + doc => {doc.katas = doc.katas.filter(x => x._id == "55501e10-12fe-446f-aea1-2d4db550f1f6")} + ) + + + + + + +db.ProgramsSubscription.find({"idprogram":"baac03de-2816-470e-8789-3c10b438364f","iduser":"0", "katas._id": "41ea64c1-0711-46a8-aece-fae593283ad1"}).pretty() + + + +db.ProgramsSubscription.aggregate( [ + {$match: {"iduser": "0", "idprogram": "baac03de-2816-470e-8789-3c10b438364f"}}, + {$unwind: "$katas"}, + {$match: {"katas._id": "41ea64c1-0711-46a8-aece-fae593283ad1"}}, + {$project: {"katas":true,"_id":false}} + + ]).pretty() + + +programs.aggregate(Arrays.asList(Aggregates.unwind("$katas"),Aggregates.project(Projections.fields(Projections.excludeId(),Projections.include("katas"))),Aggregates.match(eq("katas._id",kataid)))) + + +db.Programs.aggregate([ +{$unwind:"$katas"}, +{$project: {"katas":true,"_id":false}}, +{$match: {"katas._id": "41ea64c1-0711-46a8-aece-fae593283ad1"}}, +{$replaceRoot: {newRoot:"$katas"}} +]).pretty(); + + +database.getCollection("ProgramsSubscription").updateOne(combine(eq("_id",userid),eq("idprogram", programid)),push("katas",new KataSubscription(kataid, "ON-GOING", "", 0))); + +db.ProgramsSubscription.updateOne({_}) + +db.Users.aggregate([ +{$match: {"_id": "0"}}, +{$unwind:"$programSubscriptions"}, +{$project: {"programSubscriptions":true,"_id":false}}, +{$match: {"programSubscriptions.idprogram": "483685f4-aa41-4cf0-91cf-3e7ac467eea7"}}, +{$replaceRoot: {newRoot:"$programSubscriptions"}} +]).pretty(); + + +db.Programs.aggregate([ +{$match: {"_id": "0"}}, +{$unwind:"$programSubscriptions"}, +{$project: {"programSubscriptions":true,"_id":false}}, +]).pretty(); + +db.Programs.aggregate([ +{$match: {"_id": "0"}}, +]).pretty(); + + + + + + + database.getCollection("Users").updateOne(combine(eq("programSubscriptions.idprogram", idrogram), eq("iduser", userid)), bitwiseXor("programSubscriptions.status", 1)); + + + + + db.Users.updateOne(); + + + db.Users.aggregate( +{$match: {"_id": "d8412eff-dabb-4cd4-8c39-9cd336026195"}}, +{$unwind:"$programSubscriptions"}, +{$project: {"idprogram":true,"_id":false}}, +{$replaceRoot: {newRoot:"$programSubscriptions"}} + ); + + AggregateIterable<ProgramSubscription> kata = database.getCollection("Users", KataSubscription.class).aggregate(Arrays.asList( + match(combine(eq("_id", userid), eq("programSubscriptions.idprogram", programid),eq("programSubscriptions.status",true))), + unwind("$programSubscriptions"), + project( + fields(excludeId(), include("katas"))), + replaceRoot("$programSubscriptions") + )); + +,"programSubscriptions.idprogram":"0d02afc8-83ed-47fa-9269-3f02368f97ef","programSubscriptions.status":true + + db.Users.aggregate( +{$match: {"_id": "0","programSubscriptions.idprogram":"0d02afc8-83ed-47fa-9269-3f02368f97ef","programSubscriptions.status":true}} +).pretty + + db.Users.aggregate( +{$match: {"_id": "fd4c297b-44f6-4a0f-841a-40c606df6d47","programSubscriptions.katas._id":"6fee8e18-72b3-4ef8-8e14-e43ffbf0ec31"}}, +{$unwind:"$programSubscriptions"}, +{$replaceRoot: {newRoot:"$programSubscriptions"}}, +{$project: {"_id":false,"katas":true}}, +{$unwind:"$katas"}, +{$match :{"katas._id":"6fee8e18-72b3-4ef8-8e14-e43ffbf0ec31"}} +).pretty() + + + + + AggregateIterable<KataSubscription> kata = database.getCollection("Users", KataSubscription.class).aggregate(Arrays.asList( + match(combine(eq("_id", userid), eq("programSubscriptions.idprogram", programid), eq("programSubscriptions.status", true))), + unwind("$programSubscriptions"), + replaceRoot("$programSubscriptions"), + project( + fields(excludeId(), include("katas"))), + match(eq("_id", kataid)) + )); + + db.Users.aggregate( +{$match: {"_id": "0","programSubscriptions.katas._id":"52cde578-24c4-4397-a70c-1a66f63cf758"}}, +{$unwind:"$programSubscriptions"}, +{$replaceRoot: {newRoot:"$programSubscriptions"}}, +{$project: {"_id":false,"katas":true}}, +{$unwind:"$katas"}, +{$match :{"katas._id":"52cde578-24c4-4397-a70c-1a66f63cf758"}}, +{$replaceRoot: {newRoot:"$katas"}} +).pretty() + + +{$replaceRoot: {newRoot:"$programSubscriptions"}}, +{$project: {"katas":true,"_id":false}} +{$match } + +{$unwind:"$programSubscriptions"}, +{$project: {"programSubscriptions.katas":true,"_id":false}}, +{$unwind:"$programSubscriptions.katas"} + + + db.Users.update( + {}, + {"$pull": {"programSubscriptions":{"idprogram": "3a746466-2a15-492d-aa82-a85a26c084f6"} }}, + {multi:true} + ); +{"_id": "7a7fa27a-0a03-4c38-9ea6-ea8ce05ebb00","programSubscriptions.katas._id":"ec105da6-6ef7-4eeb-84c9-68be706f6ea8"}, + + db.Users.update( + {"_id": "7a7fa27a-0a03-4c38-9ea6-ea8ce05ebb00","programSubscriptions.katas._id":"ec105da6-6ef7-4eeb-84c9-68be706f6ea8"}, + {$inc: {"programSubscriptions.0.katas.$.nbAttempt": 1}} + ); + + + + db.Users.update( + {"_id":"0","programSubscriptions.katas._id":"a02aa850-1676-4b79-ad89-cc510d7c677a"}, + {$inc: {"programSubscriptions.$[i].katas.$[j].nbAttempt": 1.0}}, + {arrayFilters: [{"i" : {"i.idprogram":"2ce48559-404a-481a-9664-e05a23de66f8"}},{"j" : {"j._id":"a02aa850-1676-4b79-ad89-cc510d7c677a"}}]} + ); + + + + + + + + + db.Users.update( + {"_id":"0"}, + {$inc: {"programSubscriptions.$[i].katas.$[j].nbAttempt": 1.0}}, + {arrayFilters: [{"i.idprogram" : { $eq:"2ce48559-404a-481a-9664-e05a23de66f8"}},{"j._id" : {$eq:"6d33e758-adf6-4f1b-a089-30543dce9e3b"}}]} + ); + + + + + + + + + + + + AggregateIterable<ProgramSubscription> programids = database.getCollection("Users", ProgramSubscription.class).aggregate(Arrays.asList( + match(combine(eq("_id", userid), eq("programSubscriptions.status", true))), + unwind("$programSubscriptions"), + project( + fields(excludeId(), exclude("katas"))), + replaceRoot("$programSubscriptions") + )); + + + + +db.Users.aggregate( + {$match: {"_id":"29de7bfd-2304-489c-bd96-ec74127b76d5"}}, + {$project: {"_id":false,"programSubscriptions":true}}, + {$unwind: "$programSubscriptions"}, + {$match: {"programSubscriptions.status":true}}, + {$replaceRoot: {newRoot:"$programSubscriptions"}} + + ).pretty(); + +db.Users.updateMany({"programSubscriptions.idprogram":"c4f038b3-1f8f-412c-a13f-dc18d084c2ce"}, + {$pull: {"programSubscriptions": {"idprogram":"c4f038b3-1f8f-412c-a13f-dc18d084c2ce"}}}); + + + + + + +db.Users.aggregate( + {$match: {"_id":"0","programSubscriptions.katas._id":"c8f2535c-6731-46fb-a933-06ce578cd6e2"}}, + {$unwind: "$programSubscriptions"}, + {$replaceRoot: {newRoot:"$programSubscriptions"}}, + {$unwind: "$katas"}, + {$match: {"katas._id":"c8f2535c-6731-46fb-a933-06ce578cd6e2"}}, + {$replaceRoot: {newRoot:"$katas"}}, + {$project: {"_id":false,"status":true}} + ).pretty(); + + + + +db.Users.updateMany({}, + {$pull: {"programSubscriptions.$[].katas":{"_id":"c8f2535c-6731-46fb-a933-06ce578cd6e2"}}} + ); + + + + + + + + db.Users.update( + {"_id":"0"}, + {$inc: {"programSubscriptions.$[i].katas.$[j].nbAttempt": 1.0}}, + {arrayFilters: [{"i.idprogram" : { $eq:"2ce48559-404a-481a-9664-e05a23de66f8"}},{"j._id" : {$eq:"6d33e758-adf6-4f1b-a089-30543dce9e3b"}}]} + ); + + + +/*database.getCollection("Users").updateMany(eq("programSubscriptions.katas._id", kataid), inc("programSubscriptions.$[i].nbKataDone", -1),new UpdateOptions().arrayFilters(Arrays.asList( + eq("i.$[].katas.status","RESOLVED") + )));*/ + + + db.Users.updateMany( + {"programSubscriptions.katas._id": "c10f7aec-3417-49fb-a87b-7f227a5b5bb4"}, + {$inc:{"programSubscriptions.$[i].nbKataDone":-1}}, + {arrayFilters: [{"i.katas.status" : { $eq:"RESOLVED"}}]} + ); + + + db.Programs.aggregate( + {$project: {"_id":false,"katas":true}}, + {$unwind: "$katas"}, + {$replaceRoot: {newRoot:"$katas"}}, + {$match:{"katas._id":"6654cca8-6c5b-4dd8-8a7f-ad73daead8f6"}} + ).pretty() + + + + + + + +