Skip to content

Commit

Permalink
Make old feedback config yaml visible on game center settings screen
Browse files Browse the repository at this point in the history
  • Loading branch information
sei-bstein committed Dec 12, 2024
1 parent 3622fb1 commit 074d60c
Show file tree
Hide file tree
Showing 5 changed files with 21 additions and 123 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,12 @@
<label class="d-block" for="feedbackConfig-input">Feedback Questions</label>
<div class="my-2 p-1 badge badge-warning">DEPRECATED</div>
<textarea rows="11" type="text" class="form-control font-fixed-width" id="feedbackConfig-input"
name="feedbackConfig" [(ngModel)]="boundYaml" (input)="updateYaml(boundYaml)" [placeholder]="sampleConfig"
[readOnly]="true" [disabled]="true"></textarea>
name="feedbackConfig" [(ngModel)]="boundYaml" [placeholder]="sampleConfig" [readOnly]="true"
[disabled]="true"></textarea>

<div class="d-flex align-items-center mt-3">
<div *ngIf="feedbackTemplate" class="flex-grow-1">
<ng-container *ngIf="feedbackTemplate.game?.length || feedbackTemplate.challenge?.length">
<ng-container *ngIf="feedbackTemplate.game?.length">
<strong class="text-success">{{feedbackTemplate.game.length}}</strong>
game questions
</ng-container>
<span *ngIf="feedbackTemplate?.game?.length && feedbackTemplate?.challenge?.length"> // </span>
<ng-container *ngIf="feedbackTemplate.challenge?.length">
<strong class="text-success">{{feedbackTemplate.challenge.length}}</strong>
challenge questions
</ng-container>
</ng-container>
</div>

<button *ngIf="feedbackTemplate" type="button" class="btn btn-success ml-2 flex-basis-50"
[disabled]="!sampleConfig" [appCopyOnClick]="feedbackTemplate.content">
<button *ngIf="feedbackConfig" type="button" class="btn btn-success ml-2 flex-basis-50"
[appCopyOnClick]="boundYaml">
Copy Deprecated Template to Clipboard
</button>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { ModalConfirmService } from '@/services/modal-confirm.service';
providers: [UnsubscriberService]
})
export class FeedbackEditorComponent implements OnInit {
@Input() feedbackTemplate?: FeedbackTemplate;
@Input() feedbackConfig = "";
@Output() templateChange = new EventEmitter<FeedbackTemplate | null>();

protected boundYaml = "";
Expand All @@ -40,14 +40,7 @@ export class FeedbackEditorComponent implements OnInit {
}

async ngOnInit() {
this.sampleConfig = await this.feedbackService.getSampleYaml() || "";

if (!this.feedbackTemplate) {
this.updateYaml("");
return;
}

this.updateYaml(this.yamlService.render(this.feedbackTemplate || ""));
this.boundYaml = this.feedbackConfig;
}

protected handleAboutFeedbackClick() {
Expand All @@ -72,95 +65,4 @@ Depending on the value of **type**, additional configuration may be required. Fo
title: "About feedback templates"
});
}

protected handlePasteSample(): void {
if (this.sampleConfig && this.boundYaml) {
this.modalService.openConfirm({
title: "Paste a sample feedback configuration",
bodyContent: `Are you sure you want to replace your current feedback configuration (**${this.feedbackTemplate?.game?.length || 0}** game questions and **${this.feedbackTemplate?.challenge?.length}** challenge questions)?`,
renderBodyAsMarkdown: true,
onConfirm: () => this.updateYaml(this.sampleConfig || "")
});

return;
}

if (this.sampleConfig) {
this.updateYaml(this.sampleConfig);
}
}

protected updateYaml(yamlConfig: string) {
// if blank, delete the configuration
if (!yamlConfig) {
this.update(undefined);
return;
}

// otherwise, only send updates when the config is valid
this.boundYaml = yamlConfig;
const feedbackTemplate = this.validateInput(yamlConfig);

if (feedbackTemplate && !this.validationMessages.length) {
try {
this.update(feedbackTemplate);
}
catch (err: any) {
this.validationMessages.push(err);
}
}
}

private update(template?: FeedbackTemplate) {
this.feedbackTemplate = template;
this.templateChangeSubject$.next(template || null);
}

private validateInput(input: string): FeedbackTemplate | undefined {
this.validationMessages = [];

let parsed: FeedbackTemplate | undefined = undefined;
const invalidYaml = "This isn't a valid YAML document. Try pasting the example configuration to get started.";

if (!input)
return parsed;

try {
parsed = this.yamlService.parse<FeedbackTemplate>(input);

if (!isObject(parsed)) {
this.validationMessages.push(invalidYaml);
return undefined;
}
}
catch (err) {
if (err instanceof YAMLParseError) {
this.validationMessages.push(invalidYaml);
return undefined;
}
}

if (parsed) {
this.validationMessages = this.validationMessages.concat(this.feedbackService.validateConfig(parsed));

// don't bother converting IDs if we're not going to pass validation
if (!this.validationMessages.length) {
// workaround for a funky thing: if the value supplied for a question's "Id" property can be evaluated
// as an integer, then the yaml library parses it as an integer, even if the typescript type is different
// (e.g. string). This just forces all IDs to be strings, which is the correct type.
if (parsed?.game)
for (const gameQuestion of parsed.game) {
gameQuestion.id = gameQuestion?.id?.toString() || gameQuestion.id;
}

if (parsed?.challenge) {
for (const challengeQuestion of parsed.challenge) {
challengeQuestion.id = challengeQuestion?.id?.toString() || challengeQuestion.id;
}
}
}
}

return parsed;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@
(select)="handleChallengesFeedbackTemplateChanged($event)"></app-feedback-template-picker>

<app-feedback-editor *ngIf="game.feedbackConfig"
[feedbackTemplate]="game.feedbackTemplate"></app-feedback-editor>
[feedbackConfig]="game.feedbackConfig"></app-feedback-editor>
</div>

<div class="col-12 mt-5">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,7 @@ export class GameCenterSettingsComponent implements AfterViewInit {
private practiceService: PracticeService,
private route: ActivatedRoute,
private toastService: ToastService,
private unsub: UnsubscriberService,
private yamlService: YamlService) {
private unsub: UnsubscriberService) {
this.unsub.add(this.route.data.subscribe(d => this.handleGameChange(d.gameId)));
}

Expand Down
15 changes: 13 additions & 2 deletions projects/gameboard-ui/src/app/api/game.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import { ChallengeGate } from './board-models';
import { ChangedGame, Game, GameGroup, NewGame, SessionForecast, UploadedFile } from './game-models';
import { TimeWindow } from './player-models';
import { Spec } from './spec-models';
import { YamlService } from '@/services/yaml.service';
import { FeedbackTemplate } from './feedback-models';

@Injectable({ providedIn: 'root' })
export class GameService {
Expand All @@ -23,7 +25,8 @@ export class GameService {

constructor(
private http: HttpClient,
private config: ConfigService
private config: ConfigService,
private yamlService: YamlService
) {
this.url = config.apphost + 'api';
}
Expand Down Expand Up @@ -168,7 +171,15 @@ export class GameService {

game.session = new TimeWindow(game.gameStart, game.gameEnd);
game.registration = new TimeWindow(game.registrationOpen, game.registrationClose);

try {
if (game.feedbackConfig) {
game.feedbackTemplate = this.yamlService.parse<FeedbackTemplate>(game.feedbackConfig);
console.log("loaded game template", game.feedbackTemplate);
}
}
catch {
game.feedbackTemplate = undefined;
}
return game;
}

Expand Down

0 comments on commit 074d60c

Please sign in to comment.