Changeset 6b0fbbe


Ignore:
Timestamp:
10/27/21 21:48:47 (3 years ago)
Author:
Стојков Марко <mst@…>
Branches:
dev
Children:
2025810, 59d860c
Parents:
7899209 (diff), c152da1 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merged feature/ask-question-frontend into dev

Location:
src
Files:
10 added
1 deleted
19 edited
1 moved

Legend:

Unmodified
Added
Removed
  • src/Clients/Angular/finki-chattery/package-lock.json

    r7899209 r6b0fbbe  
    17461746      }
    17471747    },
     1748    "@tinymce/tinymce-angular": {
     1749      "version": "4.0.0",
     1750      "resolved": "https://registry.npmjs.org/@tinymce/tinymce-angular/-/tinymce-angular-4.0.0.tgz",
     1751      "integrity": "sha512-CmsKournkWWK5O7d8qgZQPvRC76z36GjeD3ZAHZEY/kUXKWAIXfbrHxxgQq9m7+wlfZq9QNgRx5ufN9y9N46DQ==",
     1752      "requires": {
     1753        "tslib": "^1.10.0"
     1754      },
     1755      "dependencies": {
     1756        "tslib": {
     1757          "version": "1.14.1",
     1758          "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
     1759          "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
     1760        }
     1761      }
     1762    },
    17481763    "@types/glob": {
    17491764      "version": "7.1.3",
  • src/Clients/Angular/finki-chattery/package.json

    r7899209 r6b0fbbe  
    2929    "@ngrx/store-devtools": "^11.0.1",
    3030    "@ngx-translate/core": "^13.0.0",
     31    "@tinymce/tinymce-angular": "^4.0.0",
    3132    "moment": "^2.29.1",
    3233    "ng2-file-upload": "^1.4.0",
  • src/Clients/Angular/finki-chattery/src/app/app-routing.module.ts

    r7899209 r6b0fbbe  
    66const routes: Routes = [
    77  {
     8    path: 'questioning',
     9    canActivate: [AuthorizedGuard],
     10    loadChildren: () => import('./modules/questioning/questioning.module').then((x) => x.QuestioningModule)
     11  },
     12  {
    813    path: 'auth-callback',
     14    pathMatch: 'full',
    915    component: AuthCallbackComponent
    1016  },
    1117  {
    12     path: 'questioning',
    13     canActivate: [AuthorizedGuard],
    14     loadChildren: () => import('./modules/questioning/questioning.module').then((x) => x.QuestioningModule)
     18    path: '',
     19    pathMatch: 'full',
     20    redirectTo: 'questioning/preview'
    1521  },
    1622  {
  • src/Clients/Angular/finki-chattery/src/app/core/core.module.ts

    r7899209 r6b0fbbe  
    99import { SharedMaterialModule } from '../shared-material/shared-material.module';
    1010import { COMPONENTS } from './components/components';
    11 import { GUARDS } from './guards/guards';
    1211import { LoaderInterceptor } from './interceptors/loader.interceptor';
    1312import { reducers } from './state';
     
    2019  declarations: [COMPONENTS],
    2120  providers: [
    22     GUARDS,
    2321    { provide: HTTP_INTERCEPTORS, useClass: LoaderInterceptor, multi: true },
    2422    { provide: HTTP_INTERCEPTORS, useClass: TokenInterceptor, multi: true }
  • src/Clients/Angular/finki-chattery/src/app/core/services/auth.service.ts

    r7899209 r6b0fbbe  
    11import { Injectable } from '@angular/core';
    2 import { User, UserManager } from 'oidc-client';
     2import { User, UserManager, WebStorageStateStore } from 'oidc-client';
    33import { Observable, of } from 'rxjs';
    44
    55import { environment } from '@env/environment';
    6 import { ApplicationUser, SelfUserResponse } from 'src/app/shared-app/models';
     6import { ApplicationUser, ApplicationUserType, SelfUserResponse } from 'src/app/shared-app/models';
    77import { BaseApiService } from 'src/app/shared-app/services/base-api.service';
    88
     
    1717    response_type: 'id_token token',
    1818    scope: 'openid app.api.finki-chattery profile',
    19     post_logout_redirect_uri: window.location.origin
     19    post_logout_redirect_uri: window.location.origin,
     20    filterProtocolClaims: true,
     21    loadUserInfo: true,
     22    userStore: new WebStorageStateStore({ store: window.localStorage })
    2023  });
    2124
     
    2326  public oidcUser: User | null = null;
    2427
    25   constructor(private baseApi: BaseApiService) {}
     28  constructor(private baseApi: BaseApiService) {
     29    this.userManager.getUser().then((user) => {
     30      this.oidcUser = user;
     31      this.user = new ApplicationUser(
     32        user?.profile.id,
     33        user?.profile.userType,
     34        user?.profile.emailAddress,
     35        user?.profile.username,
     36        user?.profile.isVerified
     37      );
     38    });
     39  }
    2640
    2741  public login(): void {
     
    3852    }
    3953    return false;
     54  }
     55
     56  public isStudent(): boolean {
     57    return this.user?.userType === ApplicationUserType.Student;
    4058  }
    4159
  • src/Clients/Angular/finki-chattery/src/app/modules/questioning/components/questioning-components.ts

    r7899209 r6b0fbbe  
    33import { QuestionsPreviewGeneralComponent } from './questions-preview-general/questions-preview-general.component';
    44import { QuestionsSearchComponent } from './questions-search/questions-search.component';
     5import { AskQuestionComponent } from './ask-question/ask-question.component';
    56
    67export const QUESTIONING_COMPONENTS: any[] = [
     
    89  QuestionsPreviewGeneralComponent,
    910  QuestioningGeneralComponent,
    10   QuestionsSearchComponent
     11  QuestionsSearchComponent,
     12  AskQuestionComponent
    1113];
  • src/Clients/Angular/finki-chattery/src/app/modules/questioning/components/questioning-general/questioning-general.component.ts

    r7899209 r6b0fbbe  
    11import { Component, OnInit } from '@angular/core';
     2import { CategoryFacadeService } from 'src/app/core/state/category-facade.service';
    23
    34@Component({
     
    78})
    89export class QuestioningGeneralComponent implements OnInit {
    9   constructor() {}
     10  constructor(private categoriesFacade: CategoryFacadeService) {}
    1011
    11   ngOnInit(): void {}
     12  ngOnInit(): void {
     13    this.categoriesFacade.fetchCategories();
     14  }
    1215}
  • src/Clients/Angular/finki-chattery/src/app/modules/questioning/components/questions-preview-general/questions-preview-general.component.ts

    r7899209 r6b0fbbe  
    1717  questionsSortByForm = new FormControl(PreviewQuestionsOrderEnum.Latest);
    1818
    19   constructor(private categoriesFacade: CategoryFacadeService, private questionFacade: QuestionFacadeService, private router: Router) {}
     19  constructor(private questionFacade: QuestionFacadeService, private router: Router) {}
    2020
    2121  ngOnInit(): void {
    22     this.categoriesFacade.fetchCategories();
    2322    this.questionFacade.fetchPreviewQuestions(PreviewQuestionsOrderEnum.Latest);
    2423    this.questionsSortByForm.valueChanges.subscribe((value: PreviewQuestionsOrderEnum) => {
  • src/Clients/Angular/finki-chattery/src/app/modules/questioning/questioning.routes.ts

    r7899209 r6b0fbbe  
    55import { QuestionsPreviewGeneralComponent } from './components/questions-preview-general/questions-preview-general.component';
    66import { QuestionsSearchComponent } from './components/questions-search/questions-search.component';
     7import { AuthorizedStudentGuard } from 'src/app/core/guards/authorized-student.guard';
     8import { AskQuestionComponent } from './components/ask-question/ask-question.component';
    79
    810const routes: Routes = [
     
    2224      },
    2325      {
     26        path: 'ask',
     27        pathMatch: 'full',
     28        component: AskQuestionComponent,
     29        canActivate: [AuthorizedStudentGuard]
     30      },
     31      {
    2432        path: ':questionUid',
    2533        component: QuestionPreviewGeneralComponent
  • src/Clients/Angular/finki-chattery/src/app/shared-app/components/components.ts

    r7899209 r6b0fbbe  
    44import { HeaderComponent } from './generic/header/header.component';
    55import { VoteComponent } from './generic/vote/vote.component';
     6import { AskQuestionSharedComponent } from './question/ask-question-shared/ask-question-shared.component';
    67import { PreviewQuestionDisplayComponent } from './question/preview-question-display/preview-question-display.component';
    78import { QuestionPreviewComponent } from './question/question-preview/question-preview.component';
     
    1819  HeaderComponent,
    1920  SearchQuestionComponent,
    20   PreviewQuestionDisplayComponent
     21  PreviewQuestionDisplayComponent,
     22  AskQuestionSharedComponent
    2123];
  • src/Clients/Angular/finki-chattery/src/app/shared-app/components/generic/header/header.component.html

    r7899209 r6b0fbbe  
    22  <span>FinkiChattery</span>
    33  <span class="right"></span>
    4   <app-button *ngIf="auth.isLoggedIn()" (action)="logout()" [buttonType]="ButtonType.CallToAction">Logout</app-button>
     4  <app-button class="margin-y-xs" *ngIf="auth.isStudent()" (action)="askQuestion()" [buttonType]="ButtonType.CallToAction">{{
     5    'header-ask-question' | translate
     6  }}</app-button>
     7  <app-button class="margin-y-xs" *ngIf="auth.isLoggedIn()" (action)="logout()" [buttonType]="ButtonType.Basic">{{
     8    'header-logout' | translate
     9  }}</app-button>
    510</mat-toolbar>
  • src/Clients/Angular/finki-chattery/src/app/shared-app/components/generic/header/header.component.ts

    r7899209 r6b0fbbe  
    11import { Component, OnInit } from '@angular/core';
     2import { Router } from '@angular/router';
    23import { AuthService } from 'src/app/core/services';
    34import { ButtonType } from '../button/button.models';
     
    1112  ButtonType = ButtonType;
    1213
    13   constructor(public auth: AuthService) {}
     14  constructor(public auth: AuthService, private router: Router) {}
    1415
    1516  ngOnInit(): void {}
     
    1819    this.auth.logout();
    1920  }
     21
     22  askQuestion(): void {
     23    this.router.navigateByUrl('questioning/ask');
     24  }
    2025}
  • src/Clients/Angular/finki-chattery/src/app/shared-app/components/question/question-preview/question-preview.component.html

    r7899209 r6b0fbbe  
    2020      </mat-chip-list>
    2121
    22       <div class="margin-top-lg" [innerHTML]="question.text"></div>
     22      <editor
     23        class="margin-x-sm"
     24        [init]="{
     25          apiKey: 'fx28x0d64jeufa35u7mcd80fgveayg5c4ap9gnr6posehzny',
     26          menubar: false,
     27          plugins: ['autoresize'],
     28          toolbar: ''
     29        }"
     30        [disabled]="true"
     31        [initialValue]="question.text"
     32      ></editor>
    2333      <div class="align-right">
    2434        <app-student-card
     
    4858          <app-vote [voteCount]="answer.upvotesCount" [correct]="answer.correctAnswer" fxFlex="6%"></app-vote>
    4959          <div fxFlex="92%">
    50             <div [innerHTML]="answer.text"></div>
     60            <editor
     61              class="margin-x-sm"
     62              [init]="{
     63                apiKey: 'fx28x0d64jeufa35u7mcd80fgveayg5c4ap9gnr6posehzny',
     64                menubar: false,
     65                plugins: ['autoresize'],
     66                toolbar: ''
     67              }"
     68              [disabled]="true"
     69              [initialValue]="answer.text"
     70            ></editor>
    5171            <div class="align-right">
    5272              <app-student-card
  • src/Clients/Angular/finki-chattery/src/app/shared-app/models/index.ts

    r7899209 r6b0fbbe  
    44export * from './category-state-view-models.models';
    55export * from './question-state-enums.models';
     6export * from './questioning-request.models';
  • src/Clients/Angular/finki-chattery/src/app/shared-app/shared-app.module.ts

    r7899209 r6b0fbbe  
    77import { NgxMaterialTimepickerModule } from 'ngx-material-timepicker';
    88import { FileUploadModule } from 'ng2-file-upload';
     9import { EditorModule } from '@tinymce/tinymce-angular';
    910
    1011import { COMPONENTS } from './components/components';
     
    2526    FlexLayoutModule,
    2627    FileUploadModule,
    27     NgxMaterialTimepickerModule
     28    NgxMaterialTimepickerModule,
     29    EditorModule
    2830  ],
    2931  exports: [
     
    3840    DIRECTIVES,
    3941    PIPES,
    40     SharedMaterialModule
     42    SharedMaterialModule,
     43    EditorModule
    4144  ]
    4245})
  • src/Clients/Angular/finki-chattery/src/assets/translations/en.json

    r7899209 r6b0fbbe  
    4444  "questions-preview-question-answers": "Answers",
    4545  "questions-preview-question-views": "Views",
    46   "questions-search-title": "Search results for: {{searchQuery}}"
     46  "questions-search-title": "Search results for: {{searchQuery}}",
     47  "ask-question-question-title": "Question title",
     48  "ask-question-categories": "Add categories to question",
     49  "ask-question-ask-button": "Ask question",
     50  "header-logout": "Logout",
     51  "header-ask-question": "Ask question"
    4752}
  • src/FinkiChattery/FinkiChattery.Api/Controllers/v1/QuestionsController.cs

    r7899209 r6b0fbbe  
    2929        public async Task<IActionResult> AskQuestion([FromBody] AskQuestionRequest request)
    3030        {
    31             await MediatorService.SendAsync(new AskQuestionCommand(request.Title, request.Text, request.Categories));
    32             return Ok();
     31            var questionUid = await MediatorService.SendAsync(new AskQuestionCommand(request.Title, request.Text, request.Categories));
     32            return Ok(questionUid);
    3333        }
    3434
  • src/FinkiChattery/FinkiChattery.Persistence/Configurations/QuestionConfig.cs

    r7899209 r6b0fbbe  
    2424            builder.Property(x => x.Views).HasColumnName(@"Views").HasColumnType("bigint").IsRequired().HasDefaultValue(0);
    2525            builder.Property(x => x.LastActiveOn).HasColumnName(@"LastActiveOn").HasColumnType("smalldatetime").IsRequired();
    26             builder.Property(x => x.Search).HasColumnType(@"Search").HasColumnType("nvarchar").HasMaxLength(4000).IsRequired();
     26            builder.Property(x => x.Search).HasComputedColumnSql(@"Search").HasColumnType("nvarchar").ValueGeneratedOnAddOrUpdate().HasMaxLength(4000).IsRequired();
    2727            builder.Property(x => x.AnswersCount).HasColumnType(@"AnswersCount").HasColumnType("bigint").IsRequired().HasDefaultValue(0);
    2828
  • src/FinkiChattery/FinkiChattery.Persistence/Models/Question.cs

    r7899209 r6b0fbbe  
    11using System;
    22using System.Collections.Generic;
     3using System.ComponentModel.DataAnnotations.Schema;
    34
    45namespace FinkiChattery.Persistence.Models
     
    3233        public DateTime LastActiveOn { get; set; }
    3334
     35        [DatabaseGenerated(DatabaseGeneratedOption.Computed)]
    3436        public string Search { get; set; }
    3537
Note: See TracChangeset for help on using the changeset viewer.