Skip to content

Commit

Permalink
v3.24.3 (#206)
Browse files Browse the repository at this point in the history
* WIP feedback stuff

* Hide label filter for non-admins in ticket list
  • Loading branch information
sei-bstein authored Nov 15, 2024
1 parent c6de2b6 commit ee561df
Show file tree
Hide file tree
Showing 10 changed files with 123 additions and 210 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -248,8 +248,7 @@
</div>
<small>
If Synchronized Start is enabled, all players will need to ready up before playing. The session will
start
automatically when everyone is ready.
start automatically when everyone is ready.
</small>
</div>

Expand Down Expand Up @@ -309,6 +308,7 @@ <h4>Execution</h4>
<small>duration of game session in minutes</small>
</div>


<div class="form-group pb-0 pt-1">
<label for="sessionLimit-input">Session Limit</label>
<input type="number" class="form-control" id="sessionLimit-input" name="sessionLimit"
Expand Down
103 changes: 2 additions & 101 deletions projects/gameboard-ui/src/app/api/feedback.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,103 +24,6 @@ export class FeedbackService {
this.url = config.apphost + 'api';
}

private dummyTemplate = {
id: "c1c81543-a7f8-4146-b647-2ad5f80cd821",
content: `
- type: selectOne
required: true
min: 1
max: 0
options:
- Cyber Defense Incident Responder
- Cyber Defense Forensics Analyst
- Network Operations Specialist
- Cyber Defense Analyst
- Exploitation Analyst
- Cyber Operator
- Research and Development Specialist
- Vulnerability Assessment Analyst
- Data Analyst
- Threat/Warning Analyst
- Other
display: dropdown
id: q1
prompt: Which NICE Work Role best aligns with your position?
shortName: nice
- type: selectOne
required: true
min: 1
max: 0
options:
- High School Diploma/GED
- Associate Degree
- Bachelor's Degree
- Master's Degree
- PhD
- Other
specify:
key: Other
prompt: ""
id: q2
prompt: Please Indicate your highest level of education.
shortName: education
- type: selectOne
required: true
min: 1
max: 0
options:
- 1-5
- 5-10
- 15+
- None (N/A)
id: q3
prompt: How many years of cybersecurity experience do you have?
shortName: experience
- type: selectMany
required: true
min: 1
max: 0
options:
- Promotional messages about the President’s Cup (emails, social media,
presentation, etc.)
- Word-of-Mouth (a supervisor, colleague or friend encouraged me to
register)
- Returning participant (enjoyed the event and wanted to participate in it
again)
- Professional development (a chance to grow my cybersecurity skills)
- Other
specify:
key: Other
prompt: ""
id: q4
prompt: What made you decide to participate?
shortName: decide
- type: selectOne
required: true
min: 1
max: 0
options:
- Yes
- No
- Unsure
id: q5
prompt: Will you participate again next year if your schedule permits?
shortName: again
- type: text
required: false
min: 1
max: 0
id: q6
prompt: How can we improve the next President’s Cup? Please provide any other
feedback you would like to share.
shortName: improve
`.trim(),
createdBy: { id: "5a6bfb3f-a2e3-4629-9014-acc4d3f22935", name: "Ben" },
helpText: "Tell us how you really feel.",
name: "My Cool Template",
responseCount: 12
};

public async createTemplate(template: CreateFeedbackTemplate) {
return await firstValueFrom(this.http.post<FeedbackTemplateView>(`${this.url}/feedback/template`, template));
}
Expand All @@ -129,10 +32,8 @@ export class FeedbackService {
return await firstValueFrom(this.http.delete(`${this.url}/feedback/template/${template.id}`));
}

public getTemplates(): Promise<ListFeedbackTemplatesResponse> {
return firstValueFrom(of({
templates: [this.dummyTemplate]
}));
public async getTemplates(): Promise<ListFeedbackTemplatesResponse> {
return await firstValueFrom(this.http.get<ListFeedbackTemplatesResponse>(`${this.url}/feedback/template`));
}

public getRequiredProperties(): string[] {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ <h5 *ngIf="subSubtitle" class="text-muted">
[class.btn-success]="!isDangerConfirm" [disabled]="confirmDisabled" (click)="handleConfirm()">
{{ confirmButtonText || 'OK' }}
</button>

</div>
</div>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { ModalConfirmConfig } from '@/core/components/modal/modal.models';
</div>
<div class="modal-body" *ngIf="!context.renderBodyAsMarkdown; else markdownBodyContent" [innerHTML]="context.bodyContent.trim()"></div>
<div class="modal-footer">
<button type="button" *ngIf="context.hideCancel !== true" class="btn btn-link" (click)="cancel()">{{ context.cancelButtonText || "Cancel" }}</button>
<button type="button" *ngIf="context.hideCancel !== true" class="btn btn-link text-muted" (click)="cancel()">{{ context.cancelButtonText || "Cancel" }}</button>
<button type="button" class="btn btn-danger" [class.btn-danger]="!context.hideCancel" [class.btn-success]="context.hideCancel" (click)="confirm()">{{ context.confirmButtonText || 'OK' }}</button>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ <h3 class="m-0 p-0 flex-grow-1">{{ctx.canManage ? 'Tickets' : 'My Tickets'}}</h3
</select>
</div>
<div class="ml-2">
<app-ticket-label-picker (selectionChanged)="handleLabelSelectionChanged($event)"></app-ticket-label-picker>
<app-ticket-label-picker *ngIf="ctx.canManage"
(selectionChanged)="handleLabelSelectionChanged($event)"></app-ticket-label-picker>
</div>
</div>
<div class="input-group input-group-sm col-4">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
<button type="button" class="btn btn-success btn-sm">
<fa-icon [icon]="fa.eye"></fa-icon>
</button>
<button type="button" class="btn btn-success btn-sm">
<button type="button" class="btn btn-success btn-sm" (click)="handleEdit(gameFeedbackTemplate)">
<fa-icon [icon]="fa.edit"></fa-icon>
</button>
<button type="button" class="btn btn-danger btn-sm" (click)="handleDelete(gameFeedbackTemplate)">
Expand Down Expand Up @@ -52,7 +52,8 @@
<button type="button" class="btn btn-success btn-sm">
<fa-icon [icon]="fa.eye"></fa-icon>
</button>
<button type="button" class="btn btn-success btn-sm">
<button type="button" class="btn btn-success btn-sm"
(click)="handleEdit(challengeSpecFeedbackTemplate)">
<fa-icon [icon]="fa.edit"></fa-icon>
</button>
<button type="button" class="btn btn-danger btn-sm"
Expand All @@ -69,9 +70,86 @@

</ng-template>

<ng-template #createTemplate>
<app-modal-content title="Create Feedback Template" [confirmDisabled]="!!!createEditTemplateForm.valid">
<ng-container *ngTemplateOutlet="createEditTemplate"></ng-container>
<ng-template #createEditModalTemplate>
<app-modal-content title="{{ createEditTemplateForm.value.id ? 'Edit' : 'Create' }} Template"
[confirmDisabled]="!!!createEditTemplateForm.valid" [subtitle]="createEditTemplateForm.value.name || ''"
(confirm)="handleCreateEditSubmit(createEditTemplateForm.value)">

<form [formGroup]="createEditTemplateForm">
<input type="hidden" formControlName="id">
<div class="form-group">
<label for="name" class="form-label">Name</label>
<input type="text" class="form-control" formControlName="name" required
placeholder="Enter a name for your feedback template (like &quot;Hackathon Feedback&quot;)">
</div>

<div class="form-group">
<label for="helpText" class="form-label">Help Text</label>
<input type="text" class="form-control" formControlName="helpText"
placeholder="Shown at the top of the form (optional)">
</div>

<div class="form-group">
<label for="content" class="form-label">Template</label>
<textarea type="text" class="form-control font-fixed-width" formControlName="content" required rows="10"
placeholder="Enter a feedback template here. You can also click the button below to paste an example feedback configuration or use the other controls to copy an existing template.">
</textarea>
</div>
</form>

<ng-container
*ngIf="(createEditTemplateForm.controls['name'].touched && !createEditTemplateForm.controls['name'].valid) || createEditTemplateForm.controls['content'].touched && !createEditTemplateForm.controls['content'].valid">
<alert type="warning" class="my-2">
<h5>Oops. A thing or two to sort out here...</h5>
<ul class="my-2 ml-2 li-style-type-circle">
<li
*ngIf="createEditTemplateForm.controls['name'].touched && createEditTemplateForm.controls['name'].hasError('required')">
Your template needs a name so you can find it later. How about "Hacktacular Survey"?
</li>
<li
*ngIf="createEditTemplateForm.controls['content'].touched && createEditTemplateForm.controls['content'].hasError('required')">
Questions are critical to the feedback process. Why not enter a few above?
</li>
<li
*ngIf="createEditTemplateForm.controls['content'].touched && createEditTemplateForm.controls['content'].hasError('questionValidation')">
Whuh-oh. It looks like your question schema isn't quite right:

<ul>
<li class="ml-2"
*ngFor="let error of createEditTemplateForm.controls['content'].getError('questionValidation').errors">
- {{ error }}
</li>
</ul>
</li>
</ul>
</alert>
</ng-container>

<div class="d-flex align-items-center">
<button type="button" class="btn btn-sm btn-success d-block mr-2" [disabled]="!sampleConfig"
(click)="handlePasteSample()">
Paste Example Configuration
</button>

<div class="d-flex align-items-center flex-grow-1 mr-2">
<label class="copy-from-label d-block text-muted mr-2 mb-0">Copy from: </label>

<div class="input-group">
<select class="form-control custom-select custom-select-sm" #copyTemplateContentSelect>
<option value="">[Choose a template to copy from]</option>
<option *ngFor="let template of templates" [value]="template.id">{{ template.name }}</option>
</select>

<div class="input-group-append">
<button type="button" class="btn btn-sm btn-warning"
(click)="handleCopyFromTemplate(copyTemplateContentSelect.value)"
[disabled]="!copyTemplateContentSelect.value">
<fa-icon [icon]="fa.copy"></fa-icon>
</button>
</div>
</div>
</div>
</div>

<div footer>
<a href="https://cmu-sei.github.io/foundry-docs/gameboard/admin-feedback-form/#configuration-yaml"
Expand All @@ -81,93 +159,3 @@
</div>
</app-modal-content>
</ng-template>

<ng-template #editTemplate>
<app-modal-content title="Edit Feedback Template" [subtitle]="editingTemplate?.name">

</app-modal-content>

<div footer>
<a href="https://cmu-sei.github.io/foundry-docs/gameboard/admin-feedback-form/#configuration-yaml"
target="_blank">
About feedback templates
</a>
</div>
</ng-template>

<ng-template #createEditTemplate>
<form [formGroup]="createEditTemplateForm" (ngSubmit)="handleCreateEditSubmit(createEditTemplateForm.value)">
<div class="form-group">
<label for="name" class="form-label">Name</label>
<input type="text" class="form-control" formControlName="name" required
placeholder="Enter a name for your feedback template (like &quot;Hackathon Feedback&quot;)">
</div>

<div class="form-group">
<label for="helpText" class="form-label">Help Text</label>
<input type="text" class="form-control" formControlName="helpText"
placeholder="Shown at the top of the form (optional)">
</div>

<div class="form-group">
<label for="content" class="form-label">Template</label>
<textarea type="text" class="form-control font-fixed-width" formControlName="content" required rows="10"
placeholder="Enter a feedback template here. You can also click the button below to paste an example feedback configuration or use the other controls to copy an existing template.">
</textarea>
</div>
</form>

<ng-container
*ngIf="(createEditTemplateForm.controls['name'].touched && !createEditTemplateForm.controls['name'].valid) || createEditTemplateForm.controls['content'].touched && !createEditTemplateForm.controls['content'].valid">
<alert type="warning" class="my-2">
<h5>Oops. A thing or two to sort out here...</h5>
<ul class="my-2 ml-2 li-style-type-circle">
<li
*ngIf="createEditTemplateForm.controls['name'].dirty && createEditTemplateForm.controls['name'].hasError('required')">
Your template needs a name so you can find it later. How about "Hacktacular Survey"?
</li>
<li
*ngIf="createEditTemplateForm.controls['content'].dirty && createEditTemplateForm.controls['content'].hasError('required')">
Questions are critical to the feedback process. Why not enter a few above?
</li>
<li
*ngIf="createEditTemplateForm.controls['content'].dirty && createEditTemplateForm.controls['content'].hasError('questionValidation')">
Whuh-oh. It looks like your question schema isn't quite right:

<ul>
<li class="ml-2"
*ngFor="let error of createEditTemplateForm.controls['content'].getError('questionValidation').errors">
- {{ error }}
</li>
</ul>
</li>
</ul>
</alert>
</ng-container>

<div class="d-flex align-items-center">
<button type="button" class="btn btn-sm btn-success d-block mr-2" [disabled]="!sampleConfig"
(click)="handlePasteSample()">
Paste Example Configuration
</button>

<div class="d-flex align-items-center flex-grow-1 mr-2">
<label class="copy-from-label d-block text-muted mr-2 mb-0">Copy from: </label>

<div class="input-group">
<select class="form-control custom-select custom-select-sm" #copyTemplateContentSelect>
<option value="">[Choose a template to copy from]</option>
<option *ngFor="let template of templates" [value]="template.id">{{ template.name }}</option>
</select>

<div class="input-group-append">
<button type="button" class="btn btn-sm btn-warning"
(click)="handleCopyFromTemplate(copyTemplateContentSelect.value)"
[disabled]="!copyTemplateContentSelect.value">
<fa-icon [icon]="fa.copy"></fa-icon>
</button>
</div>
</div>
</div>
</div>
</ng-template>
Loading

0 comments on commit ee561df

Please sign in to comment.