Add moderator module with routing, components, and API integration
This commit is contained in:
@@ -39,6 +39,12 @@
|
|||||||
User tools
|
User tools
|
||||||
</button>
|
</button>
|
||||||
}
|
}
|
||||||
|
@if (showModeratorBoard) {
|
||||||
|
<button mat-menu-item routerLink="moderator/moderator-welcome">
|
||||||
|
<mat-icon>space_dashboard</mat-icon>
|
||||||
|
Moderator board
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
|
||||||
<button mat-menu-item routerLink="profile">
|
<button mat-menu-item routerLink="profile">
|
||||||
<mat-icon>person</mat-icon>
|
<mat-icon>person</mat-icon>
|
||||||
|
|||||||
@@ -232,8 +232,7 @@ export class MainComponent implements OnInit{
|
|||||||
);
|
);
|
||||||
|
|
||||||
// do something here with the data
|
// do something here with the data
|
||||||
dialogloginSubscription.unsubscribe();
|
|
||||||
dialogSubmitSubscription.unsubscribe();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,11 @@ const MAIN_ROUTES: Routes =[
|
|||||||
loadChildren: () =>
|
loadChildren: () =>
|
||||||
import('../user-module/user.module').then((m) => m.UserModule),
|
import('../user-module/user.module').then((m) => m.UserModule),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'moderator',
|
||||||
|
loadChildren: () =>
|
||||||
|
import('../moderator-module/moderator.module').then((m) => m.ModeratorModule),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: 'home',
|
path: 'home',
|
||||||
component: HomeComponent
|
component: HomeComponent
|
||||||
|
|||||||
@@ -6,42 +6,8 @@ export class Tutorial {
|
|||||||
published?: boolean;
|
published?: boolean;
|
||||||
created?: Date;
|
created?: Date;
|
||||||
modified?: Date;
|
modified?: Date;
|
||||||
|
tobepublished?: boolean;
|
||||||
isEdit?: boolean;
|
isEdit?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const TutorialColumns = [
|
|
||||||
{
|
|
||||||
key: 'isSelected',
|
|
||||||
type: 'isSelected',
|
|
||||||
label: '',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'title',
|
|
||||||
type: 'text',
|
|
||||||
label: 'Title',
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'published',
|
|
||||||
type: 'boolean',
|
|
||||||
label: 'Is Published',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'created',
|
|
||||||
type: 'datetime',
|
|
||||||
label: 'Created Date',
|
|
||||||
required: true,
|
|
||||||
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'modified',
|
|
||||||
type: 'datetime',
|
|
||||||
label: 'Modified Date',
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'isEdit',
|
|
||||||
type: 'isEdit',
|
|
||||||
label: '',
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
import { TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { ModeratorApiService } from './moderator-api.service';
|
||||||
|
|
||||||
|
describe('ModeratorApiService', () => {
|
||||||
|
let service: ModeratorApiService;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({});
|
||||||
|
service = TestBed.inject(ModeratorApiService);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be created', () => {
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import {HttpClient, HttpHeaders} from '@angular/common/http';
|
||||||
|
import {Observable} from 'rxjs';
|
||||||
|
import {Tutorial} from '../models/tutorial.model';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class ModeratorApiService {
|
||||||
|
baseUrl = 'http://localhost:8080/api/moderator';
|
||||||
|
|
||||||
|
|
||||||
|
constructor(private http: HttpClient) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
getBePublishedTutorials(): Observable<Tutorial[]> {
|
||||||
|
return this.http.get<Tutorial[]>(`${this.baseUrl}/tutorials`);
|
||||||
|
}
|
||||||
|
|
||||||
|
getTutorial(id: string | null | undefined): Observable<Tutorial> {
|
||||||
|
return this.http.get<Tutorial>(`${this.baseUrl}/tutorial-get/${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
publish(id: any,data: any): Observable<any> {
|
||||||
|
return this.http.put(`${this.baseUrl}/tutorial-update/${id}`, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
<p>moderator-welcome.component works!</p>
|
||||||
+23
@@ -0,0 +1,23 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { ModeratorWelcomeComponent } from './moderator-welcome.component';
|
||||||
|
|
||||||
|
describe('ModeratorWelcomeComponent', () => {
|
||||||
|
let component: ModeratorWelcomeComponent;
|
||||||
|
let fixture: ComponentFixture<ModeratorWelcomeComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
imports: [ModeratorWelcomeComponent]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(ModeratorWelcomeComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
+11
@@ -0,0 +1,11 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-moderator-welcome.component',
|
||||||
|
imports: [],
|
||||||
|
templateUrl: './moderator-welcome.component.html',
|
||||||
|
styleUrl: './moderator-welcome.component.scss'
|
||||||
|
})
|
||||||
|
export class ModeratorWelcomeComponent {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
<app-side-bar-moderator class="pc-sidebar" ></app-side-bar-moderator>
|
||||||
|
<div class="pc-container">
|
||||||
|
<router-outlet></router-outlet>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
//---------------
|
||||||
|
.pc-sidebar{
|
||||||
|
top: 65px;
|
||||||
|
overflow-y: auto;
|
||||||
|
background-color: rgba(153, 153, 153, 0.16);
|
||||||
|
|
||||||
|
backdrop-filter: blur(8px);
|
||||||
|
}
|
||||||
|
.pc-container{
|
||||||
|
top: 0px;
|
||||||
|
padding-left: 5px;
|
||||||
|
padding-right: 5px;
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { ModeratorComponent } from './moderator.component';
|
||||||
|
|
||||||
|
describe('ModeratorComponent', () => {
|
||||||
|
let component: ModeratorComponent;
|
||||||
|
let fixture: ComponentFixture<ModeratorComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
imports: [ModeratorComponent]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(ModeratorComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
import {RouterOutlet} from '@angular/router';
|
||||||
|
import {SideBarModeratorComponent} from '../side-bar-moderator.component/side-bar-moderator.component';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-moderator.component',
|
||||||
|
imports: [
|
||||||
|
RouterOutlet,
|
||||||
|
SideBarModeratorComponent,
|
||||||
|
|
||||||
|
],
|
||||||
|
templateUrl: './moderator.component.html',
|
||||||
|
styleUrl: './moderator.component.scss'
|
||||||
|
})
|
||||||
|
export class ModeratorComponent {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import {moderatorRouting} from './moderator.routing';
|
||||||
|
import {ModeratorComponent} from './moderator.component/moderator.component';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: [],
|
||||||
|
imports: [
|
||||||
|
moderatorRouting,
|
||||||
|
ModeratorComponent,
|
||||||
|
CommonModule
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class ModeratorModule { }
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
import { ModeratorRouting } from './moderator.routing';
|
||||||
|
|
||||||
|
describe('ModeratorRouting', () => {
|
||||||
|
it('should create an instance', () => {
|
||||||
|
expect(new ModeratorRouting()).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import {RouterModule, Routes} from '@angular/router';
|
||||||
|
import {UserComponent} from '../user-module/user.component/user.component';
|
||||||
|
import {ModeratorComponent} from './moderator.component/moderator.component';
|
||||||
|
|
||||||
|
const MODERATOR_ROUTES: Routes = [
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
component: ModeratorComponent,
|
||||||
|
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: 'moderator-welcome',
|
||||||
|
loadComponent: () => import('../moderator-module/moderator-welcome.component/moderator-welcome.component').then((c) => c.ModeratorWelcomeComponent),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'tutorials-list',
|
||||||
|
loadComponent: () => import('../moderator-module/tutorials-list.component/tutorials-list.component').then((c) => c.TutorialsListComponent)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'tutorial-preview',
|
||||||
|
loadComponent: () => import('../moderator-module/tutorial-preview.component/tutorial-preview.component').then((c) => c.TutorialPreviewComponent)
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
export const moderatorRouting = RouterModule.forChild(MODERATOR_ROUTES);
|
||||||
+18
@@ -0,0 +1,18 @@
|
|||||||
|
<mat-nav-list>
|
||||||
|
<a mat-list-item routerLink="moderator-welcome">
|
||||||
|
<span class="entry">
|
||||||
|
<mat-icon>house</mat-icon>
|
||||||
|
@if (!isCollapsed) {
|
||||||
|
<span >Dashboard</span>
|
||||||
|
}
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
<a mat-list-item routerLink="tutorials-list">
|
||||||
|
<span class="entry">
|
||||||
|
<mat-icon>newspaper</mat-icon>
|
||||||
|
@if (!isCollapsed) {
|
||||||
|
<span >Tutorials</span>
|
||||||
|
}
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
</mat-nav-list>
|
||||||
+14
@@ -0,0 +1,14 @@
|
|||||||
|
.entry{
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 1rem;
|
||||||
|
padding:0.75rem;
|
||||||
|
color: rgba(24, 255, 255, 0.96);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
a.mdc-list-item
|
||||||
|
{
|
||||||
|
|
||||||
|
background-color: rgba(24,255,255,0.04);
|
||||||
|
}
|
||||||
+23
@@ -0,0 +1,23 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { SideBarModeratorComponent } from './side-bar-moderator.component';
|
||||||
|
|
||||||
|
describe('SideBarModeratorComponent', () => {
|
||||||
|
let component: SideBarModeratorComponent;
|
||||||
|
let fixture: ComponentFixture<SideBarModeratorComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
imports: [SideBarModeratorComponent]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(SideBarModeratorComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
+20
@@ -0,0 +1,20 @@
|
|||||||
|
import {Component, CUSTOM_ELEMENTS_SCHEMA} from '@angular/core';
|
||||||
|
import {MatIcon} from '@angular/material/icon';
|
||||||
|
import {MatListItem, MatNavList} from '@angular/material/list';
|
||||||
|
import {RouterLink} from '@angular/router';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-side-bar-moderator',
|
||||||
|
imports: [
|
||||||
|
MatIcon,
|
||||||
|
MatListItem,
|
||||||
|
MatNavList,
|
||||||
|
RouterLink
|
||||||
|
],
|
||||||
|
templateUrl: './side-bar-moderator.component.html',
|
||||||
|
styleUrl: './side-bar-moderator.component.scss',
|
||||||
|
schemas:[CUSTOM_ELEMENTS_SCHEMA]
|
||||||
|
})
|
||||||
|
export class SideBarModeratorComponent {
|
||||||
|
isCollapsed = false;
|
||||||
|
}
|
||||||
+43
@@ -0,0 +1,43 @@
|
|||||||
|
<mat-card appearance="outlined">
|
||||||
|
<mat-card-header>
|
||||||
|
<mat-card-title>Edit tutorial</mat-card-title>
|
||||||
|
</mat-card-header>
|
||||||
|
<mat-card-content >
|
||||||
|
<mat-form-field class="example-full-width">
|
||||||
|
<mat-label>Title</mat-label>
|
||||||
|
<input matInput required
|
||||||
|
[(ngModel)]="tutorial.title">
|
||||||
|
</mat-form-field>
|
||||||
|
<mat-tab-group>
|
||||||
|
<mat-tab label="Preview">
|
||||||
|
<markdown class="preview" [data]="tutorial.description"></markdown>
|
||||||
|
</mat-tab>
|
||||||
|
<mat-tab label="Edit">
|
||||||
|
<textarea class="variable-textarea" [(ngModel)]="tutorial.description"></textarea>
|
||||||
|
<markdown class="variable-binding" [data]="tutorial.description"></markdown>
|
||||||
|
</mat-tab>
|
||||||
|
|
||||||
|
<mat-tab label="Example">
|
||||||
|
<textarea class="variable-textarea" [(ngModel)]="markdown"></textarea>
|
||||||
|
<markdown class="variable-binding" [data]="markdown"></markdown>
|
||||||
|
</mat-tab>
|
||||||
|
</mat-tab-group>
|
||||||
|
</mat-card-content>
|
||||||
|
<mat-card-actions>
|
||||||
|
|
||||||
|
<button matButton (click)="publishTutorial()">Publicate</button>
|
||||||
|
@if (hasError){
|
||||||
|
<mat-error>
|
||||||
|
{{errorMessage}}
|
||||||
|
</mat-error>
|
||||||
|
}
|
||||||
|
@if(submitted) {
|
||||||
|
<h4>Tutorial was submitted successfully!</h4>
|
||||||
|
|
||||||
|
<button matButton routerLink="../tutorials-list">Back to list</button>
|
||||||
|
}
|
||||||
|
|
||||||
|
</mat-card-actions>
|
||||||
|
</mat-card>
|
||||||
|
|
||||||
|
|
||||||
+59
@@ -0,0 +1,59 @@
|
|||||||
|
.submit-form {
|
||||||
|
max-width: 400px;
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
mat-card{
|
||||||
|
//margin: 20px;
|
||||||
|
}
|
||||||
|
mat-card-title{
|
||||||
|
color: cyan;
|
||||||
|
}
|
||||||
|
|
||||||
|
.example-form {
|
||||||
|
min-width: 150px;
|
||||||
|
max-width: 500px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.example-full-width {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.variable-binding,
|
||||||
|
.variable-textarea {
|
||||||
|
width: 49%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.variable-textarea {
|
||||||
|
border-radius: 5px;
|
||||||
|
box-shadow: 0 1px 2px rgba(0,0,0,.07);
|
||||||
|
min-height: 420px;
|
||||||
|
padding: 8px;
|
||||||
|
transition: all 300ms ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.variable-textarea:hover {
|
||||||
|
box-shadow: 0 6px 12px 3px rgba(0,0,0,.09),
|
||||||
|
0 2px 3px 1px rgba(0,0,0,.06);
|
||||||
|
}
|
||||||
|
|
||||||
|
.variable-binding {
|
||||||
|
display: block;
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview {
|
||||||
|
/* display: block;
|
||||||
|
float: right;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
.mat-mdc-card-outlined {
|
||||||
|
background-color: var(--mat-card-outlined-container-color, var(--mat-sys-surface));
|
||||||
|
border-radius:0;
|
||||||
|
border-width: var(--mat-card-outlined-outline-width, 1px);
|
||||||
|
border-color: var(--mat-card-outlined-outline-color, var(--mat-sys-outline-variant));
|
||||||
|
box-shadow: var(--mat-card-outlined-container-elevation, var(--mat-sys-level0));
|
||||||
|
}
|
||||||
+23
@@ -0,0 +1,23 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { TutorialPreviewComponent } from './tutorial-preview.component';
|
||||||
|
|
||||||
|
describe('TutorialPreviewComponent', () => {
|
||||||
|
let component: TutorialPreviewComponent;
|
||||||
|
let fixture: ComponentFixture<TutorialPreviewComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
imports: [TutorialPreviewComponent]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(TutorialPreviewComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
+94
@@ -0,0 +1,94 @@
|
|||||||
|
import {Component, CUSTOM_ELEMENTS_SCHEMA} from '@angular/core';
|
||||||
|
import {FormsModule} from "@angular/forms";
|
||||||
|
import {MarkdownComponent} from "ngx-markdown";
|
||||||
|
import {MatButton} from "@angular/material/button";
|
||||||
|
import {MatCard, MatCardActions, MatCardContent, MatCardHeader} from "@angular/material/card";
|
||||||
|
import {MatError, MatFormField, MatInput, MatLabel} from "@angular/material/input";
|
||||||
|
import {MatTab, MatTabGroup} from "@angular/material/tabs";
|
||||||
|
import {ActivatedRoute, RouterLink} from "@angular/router";
|
||||||
|
import {Tutorial} from '../../models/tutorial.model';
|
||||||
|
import {UserApiService} from '../../user-module/user-api.service';
|
||||||
|
import {ModeratorApiService} from '../moderator-api.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-tutorial-preview.component',
|
||||||
|
imports: [
|
||||||
|
FormsModule,
|
||||||
|
MarkdownComponent,
|
||||||
|
MatButton,
|
||||||
|
MatCard,
|
||||||
|
MatCardActions,
|
||||||
|
MatCardContent,
|
||||||
|
MatCardHeader,
|
||||||
|
MatError,
|
||||||
|
MatFormField,
|
||||||
|
MatInput,
|
||||||
|
MatLabel,
|
||||||
|
MatTab,
|
||||||
|
MatTabGroup,
|
||||||
|
RouterLink,
|
||||||
|
MatError,
|
||||||
|
MatFormField
|
||||||
|
],
|
||||||
|
templateUrl: './tutorial-preview.component.html',
|
||||||
|
styleUrl: './tutorial-preview.component.scss',
|
||||||
|
schemas: [CUSTOM_ELEMENTS_SCHEMA]
|
||||||
|
})
|
||||||
|
export class TutorialPreviewComponent {
|
||||||
|
tutorial: Tutorial = new Tutorial();
|
||||||
|
submitted = false;
|
||||||
|
hasError = false;
|
||||||
|
errorMessage = '';
|
||||||
|
markdown = `## Markdown __rulez__!
|
||||||
|
---
|
||||||
|
|
||||||
|
### Syntax highlight
|
||||||
|
\`\`\`typescript
|
||||||
|
const language = 'typescript';
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
### Lists
|
||||||
|
1. Ordered list
|
||||||
|
2. Another bullet point
|
||||||
|
- Unordered list
|
||||||
|
- Another unordered bullet
|
||||||
|
|
||||||
|
### Blockquote
|
||||||
|
> Blockquote to the max`;
|
||||||
|
|
||||||
|
private id: string | null | undefined;
|
||||||
|
|
||||||
|
constructor(private moderatorApiService: ModeratorApiService, private route: ActivatedRoute) {
|
||||||
|
|
||||||
|
this.route.queryParams
|
||||||
|
.subscribe(params => {
|
||||||
|
console.log(params);
|
||||||
|
this.id = params['id'];
|
||||||
|
console.log(this.id);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.moderatorApiService.getTutorial(this.id).subscribe(
|
||||||
|
data=>{
|
||||||
|
this.tutorial = data;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
publishTutorial(): void {
|
||||||
|
this.tutorial.published = true;
|
||||||
|
this.moderatorApiService.publish(this.id, this.tutorial)
|
||||||
|
.subscribe(
|
||||||
|
response => {
|
||||||
|
console.log(response);
|
||||||
|
this.submitted = true;
|
||||||
|
this.hasError = false;
|
||||||
|
},
|
||||||
|
error => {
|
||||||
|
console.log(error);
|
||||||
|
|
||||||
|
this.errorMessage = error.error.message;
|
||||||
|
|
||||||
|
this.hasError = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
+44
@@ -0,0 +1,44 @@
|
|||||||
|
<table mat-table [dataSource]="dataSource">
|
||||||
|
@for (column of columnsSchema; track column){
|
||||||
|
<ng-container [matColumnDef]="column.key">
|
||||||
|
<th mat-header-cell *matHeaderCellDef>
|
||||||
|
{{column.label}}
|
||||||
|
</th>
|
||||||
|
<td mat-cell *matCellDef="let element">
|
||||||
|
@switch (column.type) {
|
||||||
|
|
||||||
|
@case('isEdit') {
|
||||||
|
<div class="btn-edit" >
|
||||||
|
<button mat-button routerLink='../tutorial-preview' [queryParams]="{id:element.id}" (click)="element.isEdit = !element.isEdit">
|
||||||
|
Preview
|
||||||
|
</button>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
@case ('boolean') {
|
||||||
|
<mat-slide-toggle
|
||||||
|
class="example-margin"
|
||||||
|
[checked]="element[column.key]"
|
||||||
|
|
||||||
|
(change)="publish(element, $event.checked)"
|
||||||
|
>
|
||||||
|
|
||||||
|
</mat-slide-toggle>
|
||||||
|
}
|
||||||
|
@case ('datetime') {
|
||||||
|
{{ element[column.key] | date: 'medium' }}
|
||||||
|
}
|
||||||
|
@default {
|
||||||
|
{{ element[column.key] }}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||||
|
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
+23
@@ -0,0 +1,23 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { TutorialsListComponent } from './tutorials-list.component';
|
||||||
|
|
||||||
|
describe('TutorialsListComponent', () => {
|
||||||
|
let component: TutorialsListComponent;
|
||||||
|
let fixture: ComponentFixture<TutorialsListComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
imports: [TutorialsListComponent]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(TutorialsListComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
+144
@@ -0,0 +1,144 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
import {DatePipe} from "@angular/common";
|
||||||
|
import {MatButton} from "@angular/material/button";
|
||||||
|
import {
|
||||||
|
MatCell,
|
||||||
|
MatCellDef, MatColumnDef,
|
||||||
|
MatHeaderCell, MatHeaderCellDef,
|
||||||
|
MatHeaderRow,
|
||||||
|
MatHeaderRowDef,
|
||||||
|
MatRow,
|
||||||
|
MatRowDef, MatTable, MatTableDataSource
|
||||||
|
} from "@angular/material/table";
|
||||||
|
import {MatCheckbox} from "@angular/material/checkbox";
|
||||||
|
import {MatSlideToggle} from "@angular/material/slide-toggle";
|
||||||
|
import {Router, RouterLink} from "@angular/router";
|
||||||
|
import {Tutorial} from '../../models/tutorial.model';
|
||||||
|
import {EventData} from '../../_shared/event.class';
|
||||||
|
import {ModeratorApiService} from '../moderator-api.service';
|
||||||
|
import {TokenStorageService} from '../../services/token-storage.service';
|
||||||
|
import {EventBusService} from '../../_shared/event-bus.service';
|
||||||
|
import {AuthService} from '../../services/auth.service';
|
||||||
|
import {HttpHeaders} from '@angular/common/http';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-tutorials-list.component',
|
||||||
|
imports: [
|
||||||
|
DatePipe,
|
||||||
|
MatButton,
|
||||||
|
MatCell,
|
||||||
|
MatCellDef,
|
||||||
|
MatHeaderCell,
|
||||||
|
MatHeaderRow,
|
||||||
|
MatHeaderRowDef,
|
||||||
|
MatRow,
|
||||||
|
MatRowDef,
|
||||||
|
MatSlideToggle,
|
||||||
|
MatTable,
|
||||||
|
RouterLink,
|
||||||
|
MatColumnDef,
|
||||||
|
MatHeaderCellDef
|
||||||
|
],
|
||||||
|
templateUrl: './tutorials-list.component.html',
|
||||||
|
styleUrl: './tutorials-list.component.scss'
|
||||||
|
})
|
||||||
|
export class TutorialsListComponent {
|
||||||
|
displayedColumns: string[] = TutorialColumns.map((col) => col.key)
|
||||||
|
columnsSchema: any = TutorialColumns
|
||||||
|
dataSource = new MatTableDataSource<Tutorial>()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
constructor(private moderatorApiService: ModeratorApiService,
|
||||||
|
private storageService: TokenStorageService,
|
||||||
|
private eventBusService: EventBusService,
|
||||||
|
private authService: AuthService,
|
||||||
|
private router: Router
|
||||||
|
) {
|
||||||
|
this.getTutorials();
|
||||||
|
}
|
||||||
|
getTutorials(): void {
|
||||||
|
this.moderatorApiService.getBePublishedTutorials()
|
||||||
|
.subscribe(( data:Tutorial[] ) => {
|
||||||
|
this.dataSource.data = data;
|
||||||
|
console.log(data);
|
||||||
|
},
|
||||||
|
error => {
|
||||||
|
console.log(error);
|
||||||
|
if (
|
||||||
|
(
|
||||||
|
error.status === 401
|
||||||
|
|
||||||
|
)
|
||||||
|
&& this.storageService.isLoggedIn()
|
||||||
|
) {
|
||||||
|
this.eventBusService.emit(new EventData('logout', null));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
publish(element: any, checked: boolean){
|
||||||
|
element.published = checked;
|
||||||
|
this.moderatorApiService.publish(element.id, element).subscribe(
|
||||||
|
response => {
|
||||||
|
console.log(response);
|
||||||
|
},
|
||||||
|
error => {
|
||||||
|
console.log(error);
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
logout(): void {
|
||||||
|
this.authService.logout().subscribe({
|
||||||
|
next: res => {
|
||||||
|
console.log(res);
|
||||||
|
this.storageService.clean();
|
||||||
|
|
||||||
|
//window.location.reload();
|
||||||
|
this.router.navigate(['main/generate-image']).then(() => {
|
||||||
|
//window.location.reload();
|
||||||
|
})
|
||||||
|
|
||||||
|
},
|
||||||
|
error: err => {
|
||||||
|
console.log(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const TutorialColumns = [
|
||||||
|
|
||||||
|
{
|
||||||
|
key: 'title',
|
||||||
|
type: 'text',
|
||||||
|
label: 'Title',
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'published',
|
||||||
|
type: 'boolean',
|
||||||
|
label: 'Is Published',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'created',
|
||||||
|
type: 'datetime',
|
||||||
|
label: 'Created Date',
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'modified',
|
||||||
|
type: 'datetime',
|
||||||
|
label: 'Modified Date',
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'isEdit',
|
||||||
|
type: 'isEdit',
|
||||||
|
label: '',
|
||||||
|
}
|
||||||
|
];
|
||||||
+8
-1
@@ -4,7 +4,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
mat-card{
|
mat-card{
|
||||||
margin: 20px;
|
//margin: 20px;
|
||||||
}
|
}
|
||||||
mat-card-title{
|
mat-card-title{
|
||||||
color: cyan;
|
color: cyan;
|
||||||
@@ -50,3 +50,10 @@ mat-card-title{
|
|||||||
float: right;*/
|
float: right;*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mat-mdc-card-outlined {
|
||||||
|
background-color: var(--mat-card-outlined-container-color, var(--mat-sys-surface));
|
||||||
|
border-radius:0;
|
||||||
|
border-width: var(--mat-card-outlined-outline-width, 1px);
|
||||||
|
border-color: var(--mat-card-outlined-outline-color, var(--mat-sys-outline-variant));
|
||||||
|
box-shadow: var(--mat-card-outlined-container-elevation, var(--mat-sys-level0));
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import {MatButton} from '@angular/material/button';
|
|||||||
import {MatCard, MatCardActions, MatCardContent, MatCardHeader} from '@angular/material/card';
|
import {MatCard, MatCardActions, MatCardContent, MatCardHeader} from '@angular/material/card';
|
||||||
import {MatError, MatFormField, MatInput, MatLabel} from '@angular/material/input';
|
import {MatError, MatFormField, MatInput, MatLabel} from '@angular/material/input';
|
||||||
import {MatTab, MatTabGroup} from '@angular/material/tabs';
|
import {MatTab, MatTabGroup} from '@angular/material/tabs';
|
||||||
import {NgIf} from '@angular/common';
|
|
||||||
import {FormsModule, ReactiveFormsModule} from '@angular/forms';
|
import {FormsModule, ReactiveFormsModule} from '@angular/forms';
|
||||||
import {Tutorial} from '../../models/tutorial.model';
|
import {Tutorial} from '../../models/tutorial.model';
|
||||||
import {UserApiService} from '../user-api.service';
|
import {UserApiService} from '../user-api.service';
|
||||||
|
|||||||
+3
-4
@@ -6,9 +6,6 @@
|
|||||||
>
|
>
|
||||||
Remove Rows
|
Remove Rows
|
||||||
</button>
|
</button>
|
||||||
<!--<button class="button-add-row" mat-button (click)="addRow()">
|
|
||||||
Add Row
|
|
||||||
</button>-->
|
|
||||||
<button mat-raised-button routerLink="../tutorial-add">Add tutorial</button>
|
<button mat-raised-button routerLink="../tutorial-add">Add tutorial</button>
|
||||||
|
|
||||||
</article>
|
</article>
|
||||||
@@ -56,7 +53,9 @@
|
|||||||
<mat-slide-toggle
|
<mat-slide-toggle
|
||||||
class="example-margin"
|
class="example-margin"
|
||||||
[checked]="element[column.key]"
|
[checked]="element[column.key]"
|
||||||
[disabled]="true">
|
[disabled]="column.key !== 'toBePublished'"
|
||||||
|
(change)="publish(element, $event.checked)"
|
||||||
|
>
|
||||||
|
|
||||||
</mat-slide-toggle>
|
</mat-slide-toggle>
|
||||||
}
|
}
|
||||||
|
|||||||
+56
-35
@@ -1,6 +1,6 @@
|
|||||||
import {Component, CUSTOM_ELEMENTS_SCHEMA, OnInit} from '@angular/core';
|
import {Component, CUSTOM_ELEMENTS_SCHEMA, OnInit} from '@angular/core';
|
||||||
import {MatList, MatListItem} from '@angular/material/list';
|
import {MatList, MatListItem} from '@angular/material/list';
|
||||||
import {Tutorial, TutorialColumns} from '../../models/tutorial.model';
|
import {Tutorial} from '../../models/tutorial.model';
|
||||||
import {TutorialService} from '../../services/tutorial.service';
|
import {TutorialService} from '../../services/tutorial.service';
|
||||||
import {UserApiService} from '../user-api.service';
|
import {UserApiService} from '../user-api.service';
|
||||||
import {MatButton} from '@angular/material/button';
|
import {MatButton} from '@angular/material/button';
|
||||||
@@ -23,22 +23,15 @@ import {
|
|||||||
MatTable,
|
MatTable,
|
||||||
MatTableDataSource
|
MatTableDataSource
|
||||||
} from '@angular/material/table';
|
} from '@angular/material/table';
|
||||||
import {MatFormField, MatInput} from '@angular/material/input';
|
import {DatePipe} from '@angular/common';
|
||||||
import {DatePipe, NgForOf, NgIf, NgSwitch, NgSwitchCase, NgSwitchDefault} from '@angular/common';
|
|
||||||
import {MatCheckbox} from '@angular/material/checkbox';
|
import {MatCheckbox} from '@angular/material/checkbox';
|
||||||
import {MatDatepicker, MatDatepickerInput, MatDatepickerToggle} from '@angular/material/datepicker';
|
|
||||||
import {MatSlideToggle} from '@angular/material/slide-toggle';
|
import {MatSlideToggle} from '@angular/material/slide-toggle';
|
||||||
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-tutorials-list.component',
|
selector: 'app-tutorials-list.component',
|
||||||
imports: [
|
imports: [
|
||||||
MatList,
|
|
||||||
MatListItem,
|
|
||||||
MatLine,
|
|
||||||
MatButton,
|
MatButton,
|
||||||
MatIcon,
|
|
||||||
MatOption,
|
|
||||||
RouterLink,
|
RouterLink,
|
||||||
ReactiveFormsModule,
|
ReactiveFormsModule,
|
||||||
MatTable,
|
MatTable,
|
||||||
@@ -47,22 +40,12 @@ import {MatSlideToggle} from '@angular/material/slide-toggle';
|
|||||||
MatRowDef,
|
MatRowDef,
|
||||||
MatRow,
|
MatRow,
|
||||||
FormsModule,
|
FormsModule,
|
||||||
MatInput,
|
|
||||||
MatFormField,
|
|
||||||
MatColumnDef,
|
MatColumnDef,
|
||||||
MatHeaderCell,
|
MatHeaderCell,
|
||||||
MatHeaderCellDef,
|
MatHeaderCellDef,
|
||||||
NgSwitch,
|
|
||||||
NgSwitchCase,
|
|
||||||
NgSwitchDefault,
|
|
||||||
MatCellDef,
|
MatCellDef,
|
||||||
MatCheckbox,
|
MatCheckbox,
|
||||||
MatDatepickerInput,
|
|
||||||
MatDatepickerToggle,
|
|
||||||
MatDatepicker,
|
|
||||||
DatePipe,
|
DatePipe,
|
||||||
NgIf,
|
|
||||||
NgForOf,
|
|
||||||
MatCell,
|
MatCell,
|
||||||
MatSlideToggle
|
MatSlideToggle
|
||||||
],
|
],
|
||||||
@@ -76,7 +59,7 @@ import {MatSlideToggle} from '@angular/material/slide-toggle';
|
|||||||
displayedColumns: string[] = TutorialColumns.map((col) => col.key)
|
displayedColumns: string[] = TutorialColumns.map((col) => col.key)
|
||||||
columnsSchema: any = TutorialColumns
|
columnsSchema: any = TutorialColumns
|
||||||
dataSource = new MatTableDataSource<Tutorial>()
|
dataSource = new MatTableDataSource<Tutorial>()
|
||||||
valid: any = {}
|
|
||||||
|
|
||||||
constructor(private userApiService: UserApiService,
|
constructor(private userApiService: UserApiService,
|
||||||
private storageService: TokenStorageService,
|
private storageService: TokenStorageService,
|
||||||
@@ -154,22 +137,16 @@ import {MatSlideToggle} from '@angular/material/slide-toggle';
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
editRow(row: Tutorial) {
|
publish(element: any, checked: boolean){
|
||||||
/*if (row.id === 0) {
|
element.tobepublished = checked;
|
||||||
this.userService.addUser(row).subscribe((newUser: User) => {
|
this.userApiService.update(element.id, element).subscribe(
|
||||||
row.id = newUser.id
|
response => {
|
||||||
row.isEdit = false
|
console.log(response);
|
||||||
})
|
},
|
||||||
} else {
|
error => {
|
||||||
this.userService.updateUser(row).subscribe(() => (row.isEdit = false))
|
console.log(error);
|
||||||
}*/
|
});
|
||||||
}
|
|
||||||
|
|
||||||
disableSubmit(id: number) {
|
|
||||||
if (this.valid[id]) {
|
|
||||||
return Object.values(this.valid[id]).some((item) => item === false)
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
logout(): void {
|
logout(): void {
|
||||||
@@ -191,3 +168,47 @@ import {MatSlideToggle} from '@angular/material/slide-toggle';
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const TutorialColumns = [
|
||||||
|
{
|
||||||
|
key: 'isSelected',
|
||||||
|
type: 'isSelected',
|
||||||
|
label: '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'title',
|
||||||
|
type: 'text',
|
||||||
|
label: 'Title',
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'published',
|
||||||
|
type: 'boolean',
|
||||||
|
label: 'Is Published',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'created',
|
||||||
|
type: 'datetime',
|
||||||
|
label: 'Created Date',
|
||||||
|
required: true,
|
||||||
|
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'modified',
|
||||||
|
type: 'datetime',
|
||||||
|
label: 'Modified Date',
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'toBePublished',
|
||||||
|
type: 'boolean',
|
||||||
|
label: 'To be published',
|
||||||
|
required: true
|
||||||
|
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'isEdit',
|
||||||
|
type: 'isEdit',
|
||||||
|
label: '',
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|||||||
@@ -9,16 +9,13 @@ import {HttpClient, HttpHeaders} from '@angular/common/http';
|
|||||||
export class UserApiService {
|
export class UserApiService {
|
||||||
baseUrl = 'http://localhost:8080/api/user';
|
baseUrl = 'http://localhost:8080/api/user';
|
||||||
|
|
||||||
httpOptions = {
|
|
||||||
headers: new HttpHeaders({ 'Content-Type': 'application/json' } )
|
|
||||||
};
|
|
||||||
|
|
||||||
constructor(private http: HttpClient) {
|
constructor(private http: HttpClient) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getUserAllTutorials(): Observable<Tutorial[]> {
|
getUserAllTutorials(): Observable<Tutorial[]> {
|
||||||
return this.http.get<Tutorial[]>(`${this.baseUrl}/tutorials`, this.httpOptions);
|
return this.http.get<Tutorial[]>(`${this.baseUrl}/tutorials`);
|
||||||
}
|
}
|
||||||
|
|
||||||
getTutorial(id: string | null | undefined): Observable<Tutorial> {
|
getTutorial(id: string | null | undefined): Observable<Tutorial> {
|
||||||
|
|||||||
@@ -66,31 +66,24 @@ public class TutorialController {
|
|||||||
try {
|
try {
|
||||||
List<Tutorial> tutorials = new ArrayList<Tutorial>();
|
List<Tutorial> tutorials = new ArrayList<Tutorial>();
|
||||||
|
|
||||||
/* Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
tutorialRepository.findByPublished(true).forEach(tutorials::add);
|
||||||
UserDetails userDetails = (UserDetails) authentication.getPrincipal();
|
|
||||||
String name = authenticationFacade.getAuthentication().getName();
|
|
||||||
|
|
||||||
User user = userRepository.findById(((UserDetailsImpl)userDetails).getId()).get();
|
|
||||||
if (user.getRoles().stream().anyMatch(role -> role.getName().name().equals("ROLE_ADMIN"))) {*/
|
|
||||||
/*
|
|
||||||
if (title == null)
|
|
||||||
tutorialRepository.findAll().forEach(tutorials::add);
|
|
||||||
else
|
|
||||||
tutorialRepository.findByTitleContaining(title).forEach(tutorials::add);
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* } else {
|
|
||||||
|
|
||||||
// If the user is not an admin, filter tutorials by user
|
|
||||||
tutorialRepository.findByUserId(user.getId()).forEach(tutorials::add);
|
|
||||||
if (tutorials.isEmpty()) {
|
if (tutorials.isEmpty()) {
|
||||||
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
|
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
|
||||||
}
|
}
|
||||||
return new ResponseEntity<>(tutorials, HttpStatus.OK);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
//all published tutorials without authentication
|
return new ResponseEntity<>(tutorials, HttpStatus.OK);
|
||||||
tutorialRepository.findByPublished(true).forEach(tutorials::add);
|
} catch (Exception e) {
|
||||||
|
return new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/moderator/tutorials")
|
||||||
|
public ResponseEntity<List<Tutorial>> getBePublishedTutorials(@RequestParam(required = false) String title) {
|
||||||
|
try {
|
||||||
|
List<Tutorial> tutorials = new ArrayList<Tutorial>();
|
||||||
|
|
||||||
|
tutorialRepository.findBytobepublished(true).forEach(tutorials::add);
|
||||||
|
|
||||||
if (tutorials.isEmpty()) {
|
if (tutorials.isEmpty()) {
|
||||||
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
|
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
|
||||||
@@ -111,8 +104,18 @@ public class TutorialController {
|
|||||||
User user = userRepository.findById(((UserDetailsImpl)userDetails).getId()).get();
|
User user = userRepository.findById(((UserDetailsImpl)userDetails).getId()).get();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
Tutorial newTutorial =new Tutorial(
|
||||||
|
tutorial.getTitle(),
|
||||||
|
tutorial.getDescription(),
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
user,
|
||||||
|
Timestamp.valueOf(LocalDateTime.now()),
|
||||||
|
Timestamp.valueOf(LocalDateTime.now())
|
||||||
|
);
|
||||||
|
|
||||||
Tutorial _tutorial = tutorialRepository
|
Tutorial _tutorial = tutorialRepository
|
||||||
.save(new Tutorial(tutorial.getTitle(), tutorial.getDescription(), false, user, Timestamp.valueOf(LocalDateTime.now()), Timestamp.valueOf(LocalDateTime.now())));
|
.save(newTutorial);
|
||||||
return new ResponseEntity<>(_tutorial, HttpStatus.CREATED);
|
return new ResponseEntity<>(_tutorial, HttpStatus.CREATED);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
return new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR);
|
return new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR);
|
||||||
@@ -131,6 +134,18 @@ public class TutorialController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("moderator/tutorial-get/{id}")
|
||||||
|
public ResponseEntity<Tutorial> getBePublishedTutorial(@PathVariable("id") long id) {
|
||||||
|
Optional<Tutorial> tutorialData = tutorialRepository.findById(id);
|
||||||
|
|
||||||
|
if (tutorialData.isPresent()) {
|
||||||
|
|
||||||
|
return new ResponseEntity<Tutorial>(tutorialData.get(), HttpStatus.OK);
|
||||||
|
} else {
|
||||||
|
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@PutMapping("user/tutorial-update/{id}")
|
@PutMapping("user/tutorial-update/{id}")
|
||||||
public ResponseEntity<?> updateTutorial(@PathVariable("id") long id, @RequestBody Tutorial tutorial) {
|
public ResponseEntity<?> updateTutorial(@PathVariable("id") long id, @RequestBody Tutorial tutorial) {
|
||||||
Optional<Tutorial> tutorialData = tutorialRepository.findById(id);
|
Optional<Tutorial> tutorialData = tutorialRepository.findById(id);
|
||||||
@@ -140,6 +155,31 @@ public class TutorialController {
|
|||||||
servTutorial.setTitle(tutorial.getTitle());
|
servTutorial.setTitle(tutorial.getTitle());
|
||||||
servTutorial.setDescription(tutorial.getDescription());
|
servTutorial.setDescription(tutorial.getDescription());
|
||||||
servTutorial.setPublished(tutorial.isPublished());
|
servTutorial.setPublished(tutorial.isPublished());
|
||||||
|
servTutorial.setTobepublished(tutorial.isTobepublished());
|
||||||
|
try {
|
||||||
|
servTutorial = tutorialRepository.save(servTutorial);
|
||||||
|
} catch (Exception e) {
|
||||||
|
|
||||||
|
map.put("status", 0);
|
||||||
|
map.put("message", e.getMessage());
|
||||||
|
return new ResponseEntity<>(map,HttpStatus.INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
|
return new ResponseEntity<>(servTutorial, HttpStatus.OK);
|
||||||
|
} else {
|
||||||
|
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping("moderator/tutorial-update/{id}")
|
||||||
|
public ResponseEntity<?> moderatorUpdateTutorial(@PathVariable("id") long id, @RequestBody Tutorial tutorial) {
|
||||||
|
Optional<Tutorial> tutorialData = tutorialRepository.findById(id);
|
||||||
|
Map<String, Object> map = new LinkedHashMap<String, Object>();
|
||||||
|
if (tutorialData.isPresent()) {
|
||||||
|
Tutorial servTutorial = tutorialData.get();
|
||||||
|
servTutorial.setTitle(tutorial.getTitle());
|
||||||
|
servTutorial.setDescription(tutorial.getDescription());
|
||||||
|
servTutorial.setPublished(tutorial.isPublished());
|
||||||
|
servTutorial.setTobepublished(tutorial.isTobepublished());
|
||||||
try {
|
try {
|
||||||
servTutorial = tutorialRepository.save(servTutorial);
|
servTutorial = tutorialRepository.save(servTutorial);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package com.jambotronGroup.jambotron.model;
|
|||||||
|
|
||||||
import jakarta.persistence.*;
|
import jakarta.persistence.*;
|
||||||
|
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@@ -21,6 +22,9 @@ public class Tutorial {
|
|||||||
@Column(name = "published")
|
@Column(name = "published")
|
||||||
private boolean published;
|
private boolean published;
|
||||||
|
|
||||||
|
@Column(name = "tobepublished")
|
||||||
|
private boolean tobepublished;
|
||||||
|
|
||||||
@ManyToOne(fetch = FetchType.LAZY, optional = false)
|
@ManyToOne(fetch = FetchType.LAZY, optional = false)
|
||||||
@JoinColumn(name = "userID", nullable = false)
|
@JoinColumn(name = "userID", nullable = false)
|
||||||
private User user;
|
private User user;
|
||||||
@@ -37,10 +41,11 @@ public class Tutorial {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Tutorial(String title, String description, boolean published, User user, java.sql.Timestamp created, java.sql.Timestamp modified) {
|
public Tutorial(String title, String description, boolean published, boolean tobepublished, User user, Timestamp created, Timestamp modified) {
|
||||||
this.title = title;
|
this.title = title;
|
||||||
this.description = description;
|
this.description = description;
|
||||||
this.published = published;
|
this.published = published;
|
||||||
|
this.tobepublished = tobepublished;
|
||||||
this.user = user;
|
this.user = user;
|
||||||
this.created = created;
|
this.created = created;
|
||||||
this.modified = modified;
|
this.modified = modified;
|
||||||
@@ -74,6 +79,14 @@ public class Tutorial {
|
|||||||
this.published = isPublished;
|
this.published = isPublished;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isTobepublished() {
|
||||||
|
return tobepublished;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTobepublished(boolean tobepublished) {
|
||||||
|
this.tobepublished = tobepublished;
|
||||||
|
}
|
||||||
|
|
||||||
public void setCreated(java.sql.Timestamp created) {
|
public void setCreated(java.sql.Timestamp created) {
|
||||||
this.created = created;
|
this.created = created;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import java.util.Set;
|
|||||||
public class User {
|
public class User {
|
||||||
@Id
|
@Id
|
||||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
@Column(name = "id")
|
||||||
private long id;
|
private long id;
|
||||||
|
|
||||||
@Column(name = "username")
|
@Column(name = "username")
|
||||||
|
|||||||
@@ -14,5 +14,7 @@ public interface TutorialRepository extends JpaRepository<Tutorial, Long> {
|
|||||||
List<Tutorial> findByUserId(Long userId);
|
List<Tutorial> findByUserId(Long userId);
|
||||||
List<Tutorial> findByUserIdAndTitle(Long userId, String title);
|
List<Tutorial> findByUserIdAndTitle(Long userId, String title);
|
||||||
List<Tutorial> findByPublished(boolean published);
|
List<Tutorial> findByPublished(boolean published);
|
||||||
|
List<Tutorial> findBytobepublished(boolean tobepublished);
|
||||||
|
List<Tutorial> findByIdAndTobepublished(Long id,boolean tobepublished);
|
||||||
List<Tutorial> findByTitleContaining(String title);
|
List<Tutorial> findByTitleContaining(String title);
|
||||||
}
|
}
|
||||||
@@ -140,7 +140,7 @@ public class WebSecurityConfig implements WebMvcConfigurer {// extends WebSecuri
|
|||||||
.requestMatchers("/api/public/tutorials/**").permitAll()
|
.requestMatchers("/api/public/tutorials/**").permitAll()
|
||||||
|
|
||||||
.requestMatchers("/api/user/**").permitAll()
|
.requestMatchers("/api/user/**").permitAll()
|
||||||
|
.requestMatchers("/api/moderator/**").permitAll()
|
||||||
.anyRequest().authenticated()
|
.anyRequest().authenticated()
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -160,6 +160,8 @@ public class WebSecurityConfig implements WebMvcConfigurer {// extends WebSecuri
|
|||||||
config.addAllowedHeader("*");
|
config.addAllowedHeader("*");
|
||||||
config.addAllowedMethod("*");
|
config.addAllowedMethod("*");
|
||||||
source.registerCorsConfiguration("/**", config);
|
source.registerCorsConfiguration("/**", config);
|
||||||
|
|
||||||
|
|
||||||
return new CorsFilter(source);
|
return new CorsFilter(source);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,6 +50,8 @@ app.origin=http://localhost:4200
|
|||||||
|
|
||||||
spring.mvc.throw-exception-if-no-handler-found=true
|
spring.mvc.throw-exception-if-no-handler-found=true
|
||||||
|
|
||||||
|
#spring.mvc.dispatch-options-request=true
|
||||||
|
|
||||||
# Disable the default mappings
|
# Disable the default mappings
|
||||||
#spring.resources.add-mappings=false
|
#spring.resources.add-mappings=false
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS roles
|
CREATE TABLE IF NOT EXISTS roles
|
||||||
(
|
(
|
||||||
id INT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
id INT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||||
name character varying(20) COLLATE pg_catalog."default"
|
name character varying(20)
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ CREATE TABLE tutorials
|
|||||||
(
|
(
|
||||||
id bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY ( INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 9223372036854775807 CACHE 1 ),
|
id bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY ( INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 9223372036854775807 CACHE 1 ),
|
||||||
published boolean,
|
published boolean,
|
||||||
|
tobepublished boolean,
|
||||||
title character varying(255) COLLATE pg_catalog."default",
|
title character varying(255) COLLATE pg_catalog."default",
|
||||||
userid bigint,
|
userid bigint,
|
||||||
created timestamp with time zone,
|
created timestamp with time zone,
|
||||||
|
|||||||
Reference in New Issue
Block a user