Changeset 59d860c for src/Clients


Ignore:
Timestamp:
10/28/21 16:21:38 (3 years ago)
Author:
Стојков Марко <mst@…>
Branches:
dev
Children:
2025810
Parents:
6b0fbbe
Message:

Asking question has a steper to preview the question

Location:
src/Clients/Angular/finki-chattery/src
Files:
8 added
12 edited

Legend:

Unmodified
Added
Removed
  • src/Clients/Angular/finki-chattery/src/app/core/services/auth.service.ts

    r6b0fbbe r59d860c  
    11import { Injectable } from '@angular/core';
    2 import { User, UserManager, WebStorageStateStore } from 'oidc-client';
     2import { User, UserManager } from 'oidc-client';
    33import { Observable, of } from 'rxjs';
    44
     
    1919    post_logout_redirect_uri: window.location.origin,
    2020    filterProtocolClaims: true,
    21     loadUserInfo: true,
    22     userStore: new WebStorageStateStore({ store: window.localStorage })
     21    loadUserInfo: true
    2322  });
    2423
     
    5554
    5655  public isStudent(): boolean {
    57     return this.user?.userType === ApplicationUserType.Student;
     56    return this.user !== null && this.user.userType === ApplicationUserType.Student;
    5857  }
    5958
  • src/Clients/Angular/finki-chattery/src/app/core/state/question-state/question.effects.ts

    r6b0fbbe r59d860c  
    3939      switchMap((action) => {
    4040        return this.api.get<QuestionStateResponse>(`v1/questions/${action.questionUid}`).pipe(
    41           switchMap((state) => [new GetQuestionStateSuccess(QuestionMapper.ToQuestionStateViewModel(state)), new EffectFinishedWorking()]),
     41          switchMap((state) => [
     42            new GetQuestionStateSuccess(QuestionMapper.ToQuestionStateViewModel(state, this.translate)),
     43            new EffectFinishedWorking()
     44          ]),
    4245          catchError((err) => [new EffectFinishedWorkingError(err)])
    4346        );
  • src/Clients/Angular/finki-chattery/src/app/core/state/question-state/question.mapper.ts

    r6b0fbbe r59d860c  
    1313} from 'src/app/shared-app/models';
    1414import { TranslateFromJsonService } from 'src/app/shared-app/services';
    15 import { PreviewQuestionCategoryResponse, PreviewQuestionResponse, QuestionStateResponse } from './question-state.models';
     15import { PreviewQuestionResponse, QuestionStateResponse } from './question-state.models';
    1616
    1717export class QuestionMapper {
    18   public static ToQuestionStateViewModel(questionStateResponse: QuestionStateResponse): QuestionStateViewModel {
     18  public static ToQuestionStateViewModel(
     19    questionStateResponse: QuestionStateResponse,
     20    translate: TranslateFromJsonService
     21  ): QuestionStateViewModel {
    1922    let answers: AnswerQuestionStateViewModel[] = [];
    2023
     
    5861
    5962    if (questionStateResponse.categoriesResponse.length > 0) {
    60       categories = questionStateResponse.categoriesResponse.map((x) => new QuestionCategoryQuestionStateViewModel(x.uid, x.name));
     63      categories = questionStateResponse.categoriesResponse.map(
     64        (x) => new QuestionCategoryQuestionStateViewModel(x.uid, x.name, translate.instant(x.name))
     65      );
    6166    }
    6267
  • src/Clients/Angular/finki-chattery/src/app/shared-app/components/components.ts

    r6b0fbbe r59d860c  
    33import { FormErrorComponent } from './generic/form-error/form-error.component';
    44import { HeaderComponent } from './generic/header/header.component';
     5import { TextEditorComponent } from './generic/text-editor/text-editor.component';
    56import { VoteComponent } from './generic/vote/vote.component';
    67import { AskQuestionSharedComponent } from './question/ask-question-shared/ask-question-shared.component';
    78import { PreviewQuestionDisplayComponent } from './question/preview-question-display/preview-question-display.component';
     9import { PreviewQuestionFullComponent } from './question/preview-question-full/preview-question-full.component';
    810import { QuestionPreviewComponent } from './question/question-preview/question-preview.component';
    911import { SearchQuestionComponent } from './question/search-question/search-question.component';
     
    2022  SearchQuestionComponent,
    2123  PreviewQuestionDisplayComponent,
    22   AskQuestionSharedComponent
     24  AskQuestionSharedComponent,
     25  PreviewQuestionFullComponent,
     26  TextEditorComponent
    2327];
  • src/Clients/Angular/finki-chattery/src/app/shared-app/components/question/ask-question-shared/ask-question-shared.component.html

    r6b0fbbe r59d860c  
    1 <form [formGroup]="questionFormGroup">
    2   <mat-form-field class="full-width margin-bottom-sm" appearance="fill" appHandleInputFormErrors>
    3     <mat-label>{{ 'ask-question-question-title' | translate }}</mat-label>
    4     <input matInput [formControl]="titleForm" />
    5   </mat-form-field>
     1<mat-horizontal-stepper linear #stepper>
     2  <mat-step [stepControl]="questionFormGroup">
     3    <ng-template matStepLabel>{{ 'ask-question-stepper-ask' | translate }}</ng-template>
     4    <form [formGroup]="questionFormGroup">
     5      <mat-form-field class="full-width margin-bottom-sm" appearance="fill" appHandleInputFormErrors>
     6        <mat-label>{{ 'ask-question-question-title' | translate }}</mat-label>
     7        <input matInput [formControl]="titleForm" />
     8      </mat-form-field>
    69
    7   <editor
    8     matInput
    9     class="margin-bottom-sm"
    10     [formControl]="textForm"
    11     [init]="{
    12       apiKey: 'fx28x0d64jeufa35u7mcd80fgveayg5c4ap9gnr6posehzny',
    13       menubar: false,
    14       plugins: [
    15         'advlist autolink lists link image charmap print preview anchor',
    16         'searchreplace visualblocks code fullscreen',
    17         'insertdatetime media table paste code help wordcount'
    18       ],
    19       toolbar:
    20         'undo redo | formatselect | bold italic backcolor | code | \
    21         alignleft aligncenter alignright alignjustify | \
    22         bullist numlist outdent indent | removeformat | help'
    23     }"
    24   ></editor>
    25   <mat-error *ngIf="textForm?.touched && textForm?.errors?.required">{{ 'not-found' | translate }}</mat-error>
    26   <mat-error *ngIf="textForm?.touched && textForm?.errors?.maxlength">{{
    27     'error-message-max-length' | translate: { maxlength: textForm?.errors?.maxlength?.requiredLength }
    28   }}</mat-error>
     10      <app-text-editor [textForm]="textForm"></app-text-editor>
    2911
    30   <mat-form-field class="full-width margin-bottom-sm" appearance="fill" appHandleInputFormErrors>
    31     <mat-label>{{ 'ask-question-categories' | translate }}</mat-label>
    32     <mat-select [formControl]="categoriesForm" multiple>
    33       <mat-option *ngFor="let category of categoriesList$ | async" [value]="category.uid">{{ category.translatedName }}</mat-option>
    34     </mat-select>
    35   </mat-form-field>
     12      <mat-form-field class="full-width margin-bottom-sm" appearance="fill" appHandleInputFormErrors>
     13        <mat-label>{{ 'ask-question-categories' | translate }}</mat-label>
     14        <mat-select [formControl]="categoriesForm" multiple>
     15          <mat-option *ngFor="let category of categoriesList$ | async" [value]="category">{{ category.translatedName }}</mat-option>
     16        </mat-select>
     17      </mat-form-field>
    3618
    37   <app-button [disabled]="questionFormGroup.invalid" [buttonType]="ButtonType.CallToAction" (action)="askQuestionEmit()">
    38     {{ 'ask-question-ask-button' | translate }}
    39   </app-button>
    40 </form>
     19      <button mat-button [disabled]="questionFormGroup.invalid" matStepperNext>
     20        {{ 'ask-question-ask-button-preview' | translate }}
     21      </button>
     22    </form>
     23  </mat-step>
     24  <mat-step>
     25    <ng-template matStepLabel>{{ 'ask-question-stepper-preview' | translate }}</ng-template>
     26    <app-preview-question-full [question]="previewQuestion"></app-preview-question-full>
     27    <div>
     28      <button class="margin-y-xs" mat-button [disabled]="questionFormGroup.invalid" matStepperPrevious>
     29        {{ 'ask-question-ask-button-back' | translate }}
     30      </button>
     31      <app-button
     32        class="margin-y-xs"
     33        [disabled]="questionFormGroup.invalid"
     34        [buttonType]="ButtonType.CallToAction"
     35        (action)="askQuestionEmit()"
     36      >
     37        {{ 'ask-question-ask-button' | translate }}
     38      </app-button>
     39    </div>
     40  </mat-step>
     41</mat-horizontal-stepper>
  • src/Clients/Angular/finki-chattery/src/app/shared-app/components/question/ask-question-shared/ask-question-shared.component.scss

    r6b0fbbe r59d860c  
     1::ng-deep .mat-horizontal-content-container {
     2  padding: 0 !important;
     3}
     4
     5::ng-deep mat-card {
     6  margin: 5px !important;
     7}
  • src/Clients/Angular/finki-chattery/src/app/shared-app/components/question/ask-question-shared/ask-question-shared.component.ts

    r6b0fbbe r59d860c  
    11import { Component, EventEmitter, OnInit, Output } from '@angular/core';
    22import { FormControl, FormGroup, Validators } from '@angular/forms';
     3import * as moment from 'moment';
    34
    45import { CategoryFacadeService } from 'src/app/core/state/category-facade.service';
    56import { ButtonType } from 'src/app/shared-app/components/generic/button/button.models';
    6 import { AskQuestionRequest } from 'src/app/shared-app/models';
     7import {
     8  AskQuestionRequest,
     9  QuestionCategoryQuestionStateViewModel,
     10  QuestionStateViewModel,
     11  StudentQuestionStateViewModel
     12} from 'src/app/shared-app/models';
    713
    814@Component({
     
    1319export class AskQuestionSharedComponent implements OnInit {
    1420  @Output() askQuestion = new EventEmitter<AskQuestionRequest>();
     21
     22  public previewQuestion?: QuestionStateViewModel;
    1523
    1624  public titleForm = new FormControl('', [Validators.required, Validators.maxLength(500)]);
     
    2937  }
    3038
    31   ngOnInit(): void {}
     39  ngOnInit(): void {
     40    this.questionFormGroup.valueChanges.subscribe((x) => {
     41      const student = new StudentQuestionStateViewModel('', '', '', 0);
     42      const categories = this.categoriesForm.value.map(
     43        (category: any) => new QuestionCategoryQuestionStateViewModel('', category.name, category.translatedName)
     44      );
     45
     46      this.previewQuestion = new QuestionStateViewModel(
     47        '',
     48        this.titleForm.value,
     49        this.textForm.value,
     50        moment(),
     51        0,
     52        moment(),
     53        student,
     54        [],
     55        categories,
     56        null
     57      );
     58    });
     59  }
    3260
    3361  public askQuestionEmit(): void {
    34     this.askQuestion.emit(new AskQuestionRequest(this.titleForm.value, this.textForm.value, this.categoriesForm.value));
     62    this.askQuestion.emit(
     63      new AskQuestionRequest(
     64        this.titleForm.value,
     65        this.textForm.value,
     66        this.categoriesForm.value.map((x: any) => x.uid)
     67      )
     68    );
    3569  }
    3670}
  • src/Clients/Angular/finki-chattery/src/app/shared-app/components/question/question-preview/question-preview.component.html

    r6b0fbbe r59d860c  
    11<div *ngIf="!working">
    2   <mat-card appHoverElevation class="margin-bottom-xl">
    3     <mat-card-title>{{ question.title }}</mat-card-title>
    4     <mat-card-subtitle
    5       [innerHTML]="
    6         'question-preview-subtitle'
    7           | translate
    8             : {
    9                 createdOn: question.createdOn | momentDate: 'LLLL',
    10                 lastActive: question.lastActiveOn | momentDate: 'LLLL',
    11                 views: question.views
    12               }
    13       "
    14     ></mat-card-subtitle>
    15     <mat-card-content>
    16       <mat-chip-list>
    17         <mat-chip *ngFor="let category of question.categories">
    18           {{ category.name }}
    19         </mat-chip>
    20       </mat-chip-list>
    21 
    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>
    33       <div class="align-right">
    34         <app-student-card
    35           [indexNumber]="question.student.index"
    36           [imageUrl]="question.student.imageUrl"
    37           [uid]="question.student.uid"
    38           [reputation]="question.student.reputation"
    39           [subtitle]="'question-asked-by-subtitle' | translate: { date: question.createdOn | momentDate: 'LL' }"
    40         ></app-student-card>
    41       </div>
    42     </mat-card-content>
    43     <mat-card-actions>
    44       <app-button appShareLink [buttonType]="ButtonType.Basic">{{ 'share-link' | translate }}</app-button>
    45     </mat-card-actions>
    46   </mat-card>
     2  <div class="margin-bottom-xl">
     3    <app-preview-question-full [question]="question"></app-preview-question-full>
     4  </div>
    475
    486  <h1 class="mat-headline">{{ 'question-answers' | translate: { answerCount: question.answers.length } }}</h1>
     
    5816          <app-vote [voteCount]="answer.upvotesCount" [correct]="answer.correctAnswer" fxFlex="6%"></app-vote>
    5917          <div fxFlex="92%">
    60             <editor
    61               class="margin-x-sm"
    62               [init]="{
    63                 apiKey: 'fx28x0d64jeufa35u7mcd80fgveayg5c4ap9gnr6posehzny',
     18            <app-text-editor
     19              [text]="answer.text"
     20              [configuration]="{
    6421                menubar: false,
    6522                plugins: ['autoresize'],
    6623                toolbar: ''
    6724              }"
    68               [disabled]="true"
    69               [initialValue]="answer.text"
    70             ></editor>
     25              [readonly]="true"
     26            ></app-text-editor>
    7127            <div class="align-right">
    7228              <app-student-card
  • src/Clients/Angular/finki-chattery/src/app/shared-app/components/question/student-card/student-card.component.ts

    r6b0fbbe r59d860c  
    99  @Input() imageUrl: string | undefined;
    1010  @Input() indexNumber: string | undefined;
    11   @Input() uid!: string;
     11  @Input() uid?: string;
    1212  @Input() reputation: number | undefined;
    1313  @Input() subtitle: string | undefined;
  • src/Clients/Angular/finki-chattery/src/app/shared-app/models/question-state-view-models.models.ts

    r6b0fbbe r59d860c  
    2323
    2424export class QuestionCategoryQuestionStateViewModel {
    25   constructor(public uid: string, public name: string) {}
     25  constructor(public uid: string, public name: string, public translatedName: string) {}
    2626}
    2727
  • src/Clients/Angular/finki-chattery/src/app/shared-material/shared-material.module.ts

    r6b0fbbe r59d860c  
    2424import { MatButtonToggleModule } from '@angular/material/button-toggle';
    2525import { MatBadgeModule } from '@angular/material/badge';
     26import { MatStepperModule } from '@angular/material/stepper';
    2627
    2728@NgModule({
     
    4950    MatTooltipModule,
    5051    MatButtonToggleModule,
    51     MatBadgeModule
     52    MatBadgeModule,
     53    MatStepperModule
    5254  ],
    5355  exports: [
     
    7375    MatTooltipModule,
    7476    MatButtonToggleModule,
    75     MatBadgeModule
     77    MatBadgeModule,
     78    MatStepperModule
    7679  ]
    7780})
  • src/Clients/Angular/finki-chattery/src/assets/translations/en.json

    r6b0fbbe r59d860c  
    4747  "ask-question-question-title": "Question title",
    4848  "ask-question-categories": "Add categories to question",
    49   "ask-question-ask-button": "Ask question",
     49  "ask-question-ask-button-preview": "Preview question",
    5050  "header-logout": "Logout",
    51   "header-ask-question": "Ask question"
     51  "header-ask-question": "Ask question",
     52  "ask-question-stepper-preview": "Preview question",
     53  "ask-question-stepper-ask": "Ask question",
     54  "ask-question-ask-button-back": "Edit question",
     55  "ask-question-ask-button": "Ask question"
    5256}
Note: See TracChangeset for help on using the changeset viewer.