From 812041366576ff881efb31ac2b5b5da2e07fd4c3 Mon Sep 17 00:00:00 2001 From: Ben Stein <115497763+sei-bstein@users.noreply.github.com> Date: Wed, 22 Jan 2025 09:44:26 -0500 Subject: [PATCH] v3.28.2 (#223) * WIP timeline updates * Add ticket stuff to timeline * Update tooltip markdown for timestamp * Fix ticket label picker modal search * Ticket details styling * Minor styling to ticket details, fix certificate stuff * Fix support pill --- .../src/app/api/certificates.service.ts | 1 + .../src/app/api/event-horizon.models.ts | 16 ++++++- .../src/app/api/event-horizon.service.ts | 12 ++++- .../src/app/components/nav/nav.component.html | 10 ++-- .../challenge-yaml-modal.component.html | 3 ++ .../challenge-yaml-modal.component.scss | 0 .../challenge-yaml-modal.component.ts | 20 ++++++++ .../team-event-horizon.component.scss | 20 +++++--- .../team-event-horizon.component.ts | 13 ++---- .../event-horizon-rendering.service.ts | 46 ++++++++++++++----- .../app/services/markdown-helpers.service.ts | 14 +++--- .../ticket-label-picker-modal.component.html | 12 +++-- .../ticket-label-picker-modal.component.scss | 3 -- .../support-pill/support-pill.component.html | 2 +- .../ticket-details.component.html | 36 ++++++++------- .../ticket-details.component.scss | 6 +++ .../inplace-editor.component.html | 35 ++++++++------ 17 files changed, 171 insertions(+), 78 deletions(-) create mode 100644 projects/gameboard-ui/src/app/core/components/challenge-yaml-modal/challenge-yaml-modal.component.html create mode 100644 projects/gameboard-ui/src/app/core/components/challenge-yaml-modal/challenge-yaml-modal.component.scss create mode 100644 projects/gameboard-ui/src/app/core/components/challenge-yaml-modal/challenge-yaml-modal.component.ts diff --git a/projects/gameboard-ui/src/app/api/certificates.service.ts b/projects/gameboard-ui/src/app/api/certificates.service.ts index e85ee6423..07467e290 100644 --- a/projects/gameboard-ui/src/app/api/certificates.service.ts +++ b/projects/gameboard-ui/src/app/api/certificates.service.ts @@ -38,6 +38,7 @@ export class CertificatesService { } getCompetitiveCertificates(userId: string): Promise { + console.log("getting certs", userId); return firstValueFrom(this.http.get(this.apiUrl.build(`user/${userId}/certificates/competitive`))); } diff --git a/projects/gameboard-ui/src/app/api/event-horizon.models.ts b/projects/gameboard-ui/src/app/api/event-horizon.models.ts index dd996aac9..01beaa474 100644 --- a/projects/gameboard-ui/src/app/api/event-horizon.models.ts +++ b/projects/gameboard-ui/src/app/api/event-horizon.models.ts @@ -5,7 +5,8 @@ export type EventHorizonEventType = "challengeStarted" | "gamespaceOnOff" | "solveComplete" | "submissionRejected" | - "submissionScored" + "submissionScored" | + "ticketOpenClose" export interface EventHorizonGenericEvent { id: string; @@ -35,7 +36,18 @@ export interface EventHorizonSolveCompleteEvent extends EventHorizonGenericEvent }; } -export type EventHorizonEvent = EventHorizonGenericEvent | EventHorizonGamespaceOnOffEvent | EventHorizonSubmissionScoredEvent | EventHorizonSolveCompleteEvent; +export interface EventHorizonTicketOpenCloseEvent extends EventHorizonGenericEvent { + eventData: { + closedAt?: DateTime; + ticketKey: string; + } +} + +export type EventHorizonEvent = EventHorizonGenericEvent | + EventHorizonGamespaceOnOffEvent | + EventHorizonSubmissionScoredEvent | + EventHorizonSolveCompleteEvent | + EventHorizonTicketOpenCloseEvent; export interface EventHorizonChallenge { id: string; diff --git a/projects/gameboard-ui/src/app/api/event-horizon.service.ts b/projects/gameboard-ui/src/app/api/event-horizon.service.ts index 6c105938a..9039b8a39 100644 --- a/projects/gameboard-ui/src/app/api/event-horizon.service.ts +++ b/projects/gameboard-ui/src/app/api/event-horizon.service.ts @@ -1,7 +1,7 @@ import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { firstValueFrom, map, of } from 'rxjs'; -import { EventHorizonEventType, EventHorizonEvent, TeamEventHorizonViewModel, EventHorizonChallengeSpec, EventHorizonGamespaceOnOffEvent } from './event-horizon.models'; +import { EventHorizonEventType, EventHorizonEvent, TeamEventHorizonViewModel, EventHorizonChallengeSpec, EventHorizonGamespaceOnOffEvent, EventHorizonTicketOpenCloseEvent } from './event-horizon.models'; import { ApiUrlService } from '@/services/api-url.service'; import { ApiDateTimeService } from '@/services/api-date-time.service'; import { LogService } from '@/services/log.service'; @@ -44,6 +44,13 @@ export class EventHorizonService { const offAtStamp = this.apiDateTimeService.toDateTime(asGamespaceEvent.eventData?.offAt as any); asGamespaceEvent.eventData.offAt = offAtStamp || undefined; } + + // also true of tickety events + const asTicketEvent = event as EventHorizonTicketOpenCloseEvent; + if (asTicketEvent.eventData?.closedAt) { + const closedAtStamp = this.apiDateTimeService.toDateTime(asTicketEvent.eventData.closedAt as any); + asTicketEvent.eventData.closedAt = closedAtStamp || undefined; + } } return timeline; @@ -67,7 +74,8 @@ export class EventHorizonService { "gamespaceOnOff", "solveComplete", "submissionRejected", - "submissionScored" + "submissionScored", + "ticketOpenClose" ]; } diff --git a/projects/gameboard-ui/src/app/components/nav/nav.component.html b/projects/gameboard-ui/src/app/components/nav/nav.component.html index fcd8ce120..a8135d988 100644 --- a/projects/gameboard-ui/src/app/components/nav/nav.component.html +++ b/projects/gameboard-ui/src/app/components/nav/nav.component.html @@ -6,13 +6,17 @@ {{t.display}} + Practice + - - Support +
+ + Support + - +
Profile diff --git a/projects/gameboard-ui/src/app/core/components/challenge-yaml-modal/challenge-yaml-modal.component.html b/projects/gameboard-ui/src/app/core/components/challenge-yaml-modal/challenge-yaml-modal.component.html new file mode 100644 index 000000000..6d6959712 --- /dev/null +++ b/projects/gameboard-ui/src/app/core/components/challenge-yaml-modal/challenge-yaml-modal.component.html @@ -0,0 +1,3 @@ + + + diff --git a/projects/gameboard-ui/src/app/core/components/challenge-yaml-modal/challenge-yaml-modal.component.scss b/projects/gameboard-ui/src/app/core/components/challenge-yaml-modal/challenge-yaml-modal.component.scss new file mode 100644 index 000000000..e69de29bb diff --git a/projects/gameboard-ui/src/app/core/components/challenge-yaml-modal/challenge-yaml-modal.component.ts b/projects/gameboard-ui/src/app/core/components/challenge-yaml-modal/challenge-yaml-modal.component.ts new file mode 100644 index 000000000..b5ca54c07 --- /dev/null +++ b/projects/gameboard-ui/src/app/core/components/challenge-yaml-modal/challenge-yaml-modal.component.ts @@ -0,0 +1,20 @@ +import { Component, OnInit } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { CoreModule } from "../../core.module"; + +@Component({ + selector: 'app-challenge-yaml-modal', + standalone: true, + imports: [CommonModule, CoreModule], + templateUrl: './challenge-yaml-modal.component.html', + styleUrls: ['./challenge-yaml-modal.component.scss'] +}) +export class ChallengeYamlModalComponent implements OnInit { + challengeId?: string; + + ngOnInit(): void { + if (!this.challengeId) { + throw new Error("challengeId is required."); + } + } +} diff --git a/projects/gameboard-ui/src/app/event-horizon/components/team-event-horizon/team-event-horizon.component.scss b/projects/gameboard-ui/src/app/event-horizon/components/team-event-horizon/team-event-horizon.component.scss index 6a7641090..2a11a7de7 100644 --- a/projects/gameboard-ui/src/app/event-horizon/components/team-event-horizon/team-event-horizon.component.scss +++ b/projects/gameboard-ui/src/app/event-horizon/components/team-event-horizon/team-event-horizon.component.scss @@ -6,20 +6,27 @@ } .eh-event-type-challenge-started { - background-color: #e7eaf6; + background-color: #9cdaa9; } - .eh-event-type-gamespace { - background-color: #a2a8d3; + .eh-event-type-gamespace-on-off { + background-color: #ceecd4; + font-weight: bold; + color: #eee; } .eh-event-type-solve-complete { - background-color: #38598b; + background-color: #41ad57; } .eh-event-type-submission-scored { - background-color: #113f67; - color: #e7eaf6; + background-color: #318241; + color: #eee; + } + + .eh-event-type-ticket-open-close { + background-color: $warning; + color: #fff; } .vis-label { @@ -29,6 +36,7 @@ font-size: 1rem !important; font-weight: bold; margin: 0; + padding: 0 1rem; } h2 { diff --git a/projects/gameboard-ui/src/app/event-horizon/components/team-event-horizon/team-event-horizon.component.ts b/projects/gameboard-ui/src/app/event-horizon/components/team-event-horizon/team-event-horizon.component.ts index d4d01f052..b1be7aba4 100644 --- a/projects/gameboard-ui/src/app/event-horizon/components/team-event-horizon/team-event-horizon.component.ts +++ b/projects/gameboard-ui/src/app/event-horizon/components/team-event-horizon/team-event-horizon.component.ts @@ -2,7 +2,6 @@ import { EventHorizonDataItem, EventHorizonEventType, TeamEventHorizonViewModel import { EventHorizonService } from '@/api/event-horizon.service'; import { EventHorizonRenderingService } from '@/services/event-horizon-rendering.service'; import { LogService } from '@/services/log.service'; -import { ModalConfirmService } from '@/services/modal-confirm.service'; import { ClipboardService } from '@/utility/services/clipboard.service'; import { ToastService } from '@/utility/services/toast.service'; import { AfterViewInit, Component, ElementRef, Input, OnDestroy, OnInit, ViewChild } from '@angular/core'; @@ -60,12 +59,9 @@ export class TeamEventHorizonComponent implements OnInit, AfterViewInit, OnDestr const teamChallengeInstance = this.timelineViewModel?.team.challenges.find(i => i.specId == c.id); return { id: c.id, - options: { - - }, title: c.name, content: ` -

${c.name}

+

${c.name}

${teamChallengeInstance ? `${teamChallengeInstance.id.substring(0, 6)} · ${teamChallengeInstance.score}/${c.maxPossibleScore} points` : "unlaunched"}

@@ -95,13 +91,14 @@ export class TeamEventHorizonComponent implements OnInit, AfterViewInit, OnDestr const timelineEvent = this.eventHorizonService.getEventId(eventId, this.timelineViewModel); const spec = this.eventHorizonService.getSpecForEventId(this.timelineViewModel, timelineEvent.id); - const bodyContent = this.eventHorizonRenderingService.toModalHtmlContent(timelineEvent, spec); + const bodyContent = this.eventHorizonRenderingService.toModalMarkdown(timelineEvent, spec); - if (!bodyContent) + if (!bodyContent) { return; + } await this.clipboardService.copy(bodyContent); - this.toastService.showMessage(`Copied this ** ${this.eventHorizonRenderingService.toFriendlyName(timelineEvent.type)}** event to your clipboard.`); + this.toastService.showMessage(`Copied this **${this.eventHorizonRenderingService.toFriendlyName(timelineEvent.type)}** event to your clipboard.`); } protected async handleEventTypeToggled(eventType: EventHorizonEventType) { diff --git a/projects/gameboard-ui/src/app/services/event-horizon-rendering.service.ts b/projects/gameboard-ui/src/app/services/event-horizon-rendering.service.ts index badf54979..53569288e 100644 --- a/projects/gameboard-ui/src/app/services/event-horizon-rendering.service.ts +++ b/projects/gameboard-ui/src/app/services/event-horizon-rendering.service.ts @@ -1,4 +1,4 @@ -import { EventHorizonDataItem, EventHorizonGenericEvent, EventHorizonEventType, EventHorizonSolveCompleteEvent, EventHorizonSubmissionScoredEvent, EventHorizonChallengeSpec, EventHorizonViewOptions, TeamEventHorizonViewModel, EventHorizonGamespaceOnOffEvent } from '@/api/event-horizon.models'; +import { EventHorizonDataItem, EventHorizonGenericEvent, EventHorizonEventType, EventHorizonSolveCompleteEvent, EventHorizonSubmissionScoredEvent, EventHorizonChallengeSpec, EventHorizonViewOptions, TeamEventHorizonViewModel, EventHorizonGamespaceOnOffEvent, EventHorizonTicketOpenCloseEvent } from '@/api/event-horizon.models'; import { Injectable } from '@angular/core'; import { DateTime } from 'luxon'; import { MarkdownHelpersService } from './markdown-helpers.service'; @@ -21,7 +21,7 @@ export class EventHorizonRenderingService { groupTemplate: (groupData: any, element: any) => this.toGroupTemplate(groupData), min: eventHorizonVm.team.session.start.toJSDate(), max: sessionEnd.toJSDate(), - selectable: true, + orientation: "top", stack: true, start: eventHorizonVm.team.session.start.toJSDate(), tooltip: { @@ -40,9 +40,10 @@ export class EventHorizonRenderingService { return this.toGamespaceOnOffDataItem(timelineEvent, challengeSpec); case "solveComplete": return this.toSolveCompleteDataItem(timelineEvent, challengeSpec); - case "submissionScored": { + case "submissionScored": return this.toSubmissionScoredDataItem(timelineEvent, challengeSpec); - } + case "ticketOpenClose": + return this.toTicketOpenCloseDataItem(timelineEvent as EventHorizonTicketOpenCloseEvent, challengeSpec); } throw new Error("Timeline event type not templated."); } @@ -59,8 +60,10 @@ export class EventHorizonRenderingService { return "Submission Rejected (Session Expired)"; case "submissionScored": return "Submission"; + case "ticketOpenClose": + return "Active Ticket"; default: - throw new Error(`Couldn't find a friendly name for event type "${eventType}".`); + return eventType; } } @@ -71,7 +74,7 @@ export class EventHorizonRenderingService { return `
${groupData.content}
`; } - public toModalHtmlContent(timelineEvent: EventHorizonGenericEvent, challengeSpec: EventHorizonChallengeSpec, includeClipboardPrompt?: boolean): string { + public toModalMarkdown(timelineEvent: EventHorizonGenericEvent, challengeSpec: EventHorizonChallengeSpec, includeClipboardPrompt?: boolean): string { if (!timelineEvent) return ""; @@ -88,6 +91,8 @@ export class EventHorizonRenderingService { case "submissionScored": detail = this.toSubmissionScoredMarkdown(timelineEvent as EventHorizonSubmissionScoredEvent, challengeSpec); break; + case "ticketOpenClose": + detail = this.toTicketOpenCloseMarkdown(timelineEvent as EventHorizonTicketOpenCloseEvent); } let retVal = header; @@ -115,8 +120,7 @@ export class EventHorizonRenderingService { if (challengeSpec.maxAttempts) attemptSummary = `${attemptSummary}/${challengeSpec.maxAttempts}`; - return ` -**Attempt:** ${attemptSummary} + return `**Attempt:** ${attemptSummary} **Points after this attempt:** ${timelineEvent.eventData.score}/${challengeSpec.maxPossibleScore} @@ -135,6 +139,13 @@ export class EventHorizonRenderingService { `.trim(); } + private toTicketOpenCloseMarkdown(timelineEvent: EventHorizonTicketOpenCloseEvent) { + let firstTicketText = `The team opened ticket **${timelineEvent.eventData.ticketKey}** here.`; + let closedInfo = timelineEvent.eventData.closedAt ? ` We fully closed it at ${timelineEvent.eventData.closedAt.toLocaleString(DateTime.DATETIME_MED)}.` : ""; + + return `${firstTicketText}${closedInfo}`; + } + private toGenericDataItem(timelineEvent: EventHorizonGenericEvent, challengeSpec: EventHorizonChallengeSpec, eventName: string, className: string, isClickable = false): EventHorizonDataItem { return { id: timelineEvent.id, @@ -143,13 +154,13 @@ export class EventHorizonRenderingService { content: eventName, className: `eh-event ${isClickable ? "eh-event-clickable" : ""} ${className}`, isClickable, - title: this.markdownHelpers.toHtml(this.toModalHtmlContent(timelineEvent, challengeSpec, true)), + title: this.markdownHelpers.toHtml(this.toModalMarkdown(timelineEvent, challengeSpec, true)), eventData: null }; } private toGamespaceOnOffDataItem(timelineEvent: EventHorizonGenericEvent, challengeSpec: EventHorizonChallengeSpec): EventHorizonDataItem { - const typedEvent = timelineEvent as unknown as EventHorizonGamespaceOnOffEvent; + const typedEvent = timelineEvent as EventHorizonGamespaceOnOffEvent; const baseItem = this.toGenericDataItem(timelineEvent, challengeSpec, "Gamespace On", "eh-event-type-gamespace-on-off", false); baseItem.end = typedEvent.eventData?.offAt ? typedEvent.eventData.offAt.toJSDate() : this.nowService.now(); @@ -160,7 +171,7 @@ export class EventHorizonRenderingService { } private toSolveCompleteDataItem(timelineEvent: EventHorizonGenericEvent, challengeSpec: EventHorizonChallengeSpec): EventHorizonDataItem { - const typedEvent = timelineEvent as unknown as EventHorizonSolveCompleteEvent; + const typedEvent = timelineEvent as EventHorizonSolveCompleteEvent; const baseItem = this.toGenericDataItem(timelineEvent, challengeSpec, "Completed", "eh-event-type-challenge-complete", true); baseItem.eventData = typedEvent; @@ -168,10 +179,21 @@ export class EventHorizonRenderingService { } private toSubmissionScoredDataItem(timelineEvent: EventHorizonGenericEvent, challengeSpec: EventHorizonChallengeSpec): EventHorizonDataItem { - const typedEvent = timelineEvent as unknown as EventHorizonSubmissionScoredEvent; + const typedEvent = timelineEvent as EventHorizonSubmissionScoredEvent; const baseItem = this.toGenericDataItem(timelineEvent, challengeSpec, "Submission", "eh-event-type-submission-scored", true); baseItem.eventData = typedEvent; return baseItem; } + + private toTicketOpenCloseDataItem(timelineEvent: EventHorizonTicketOpenCloseEvent, challengeSpec: EventHorizonChallengeSpec): EventHorizonDataItem { + const typedEvent = timelineEvent as EventHorizonTicketOpenCloseEvent; + const baseItem = this.toGenericDataItem(timelineEvent, challengeSpec, `Ticket ${timelineEvent.eventData.ticketKey}`, "eh-event-type-ticket-open-close", true); + + baseItem.end = typedEvent.eventData?.closedAt?.toJSDate() || this.nowService.now(); + baseItem.eventData = typedEvent; + baseItem.type = "range"; + + return baseItem; + } } diff --git a/projects/gameboard-ui/src/app/services/markdown-helpers.service.ts b/projects/gameboard-ui/src/app/services/markdown-helpers.service.ts index bc6ae5486..2f32594d5 100644 --- a/projects/gameboard-ui/src/app/services/markdown-helpers.service.ts +++ b/projects/gameboard-ui/src/app/services/markdown-helpers.service.ts @@ -1,9 +1,11 @@ -import { Injectable } from '@angular/core'; +import { inject, Injectable, SecurityContext } from '@angular/core'; +import { DomSanitizer, SafeHtml } from '@angular/platform-browser'; import { MarkdownService } from 'ngx-markdown'; @Injectable({ providedIn: 'root' }) export class MarkdownHelpersService { - constructor(private markdownService: MarkdownService) { } + private domSanitizer = inject(DomSanitizer); + private mdService = inject(MarkdownService); arrayToBulletList(items: string[]): string { return items.map(i => `\n - ${i}`).join(''); @@ -19,15 +21,15 @@ export class MarkdownHelpersService { getMarkdownPlaceholderHelp(header?: string): string { const paragraphs: string[] = []; - if (header) + if (header) { paragraphs.push(header); - + } paragraphs.push("This is a markdown field. You can surround text with _underscores_ to make it italic or double **asterisks** to make it bold. You can also [link to content using this syntax](https://google.com)."); return paragraphs.join("\n\n").trim(); } - toHtml(markdownContent: string) { - return this.markdownService.parse(markdownContent); + toHtml(markdownContent: string): string { + return this.domSanitizer.sanitize(SecurityContext.HTML, this.domSanitizer.bypassSecurityTrustHtml(this.mdService.parse(markdownContent, { disableSanitizer: true }))) || ""; } } diff --git a/projects/gameboard-ui/src/app/support/components/ticket-label-picker-modal/ticket-label-picker-modal.component.html b/projects/gameboard-ui/src/app/support/components/ticket-label-picker-modal/ticket-label-picker-modal.component.html index 720d8cf57..d1e316494 100644 --- a/projects/gameboard-ui/src/app/support/components/ticket-label-picker-modal/ticket-label-picker-modal.component.html +++ b/projects/gameboard-ui/src/app/support/components/ticket-label-picker-modal/ticket-label-picker-modal.component.html @@ -1,14 +1,16 @@ -
    -
  • - -
  • + +
  • + +
  • +

diff --git a/projects/gameboard-ui/src/app/support/components/ticket-label-picker-modal/ticket-label-picker-modal.component.scss b/projects/gameboard-ui/src/app/support/components/ticket-label-picker-modal/ticket-label-picker-modal.component.scss index f859b3577..e69de29bb 100644 --- a/projects/gameboard-ui/src/app/support/components/ticket-label-picker-modal/ticket-label-picker-modal.component.scss +++ b/projects/gameboard-ui/src/app/support/components/ticket-label-picker-modal/ticket-label-picker-modal.component.scss @@ -1,3 +0,0 @@ -li { - // flex-basis: 30%; -} diff --git a/projects/gameboard-ui/src/app/support/support-pill/support-pill.component.html b/projects/gameboard-ui/src/app/support/support-pill/support-pill.component.html index e3cafcbd2..66c844a62 100644 --- a/projects/gameboard-ui/src/app/support/support-pill/support-pill.component.html +++ b/projects/gameboard-ui/src/app/support/support-pill/support-pill.component.html @@ -1 +1 @@ - + diff --git a/projects/gameboard-ui/src/app/support/ticket-details/ticket-details.component.html b/projects/gameboard-ui/src/app/support/ticket-details/ticket-details.component.html index 0e39ce7e7..851f14b8e 100644 --- a/projects/gameboard-ui/src/app/support/ticket-details/ticket-details.component.html +++ b/projects/gameboard-ui/src/app/support/ticket-details/ticket-details.component.html @@ -206,7 +206,7 @@

- +
Status Changed to 
-
-
+
@@ -268,7 +268,7 @@

-
+
@@ -283,11 +283,11 @@

-
+
-

+

Support Code: @@ -296,21 +296,24 @@

-
-

Game Id: - {{changedTicket.player?.gameId | slice:0:16}}

+
+ {{ changedTicket.player?.gameId | slice:0:8 }} +
-
-
-

User Id: {{changedTicket.requesterId | - slice:0:16}}

+
+ {{changedTicket.requesterId | slice:0:8}}
-
-

+
+

{{ctx.ticket.creator?.name || 'None'}}

diff --git a/projects/gameboard-ui/src/app/support/ticket-details/ticket-details.component.scss b/projects/gameboard-ui/src/app/support/ticket-details/ticket-details.component.scss index bf3fe2004..8ce60824e 100644 --- a/projects/gameboard-ui/src/app/support/ticket-details/ticket-details.component.scss +++ b/projects/gameboard-ui/src/app/support/ticket-details/ticket-details.component.scss @@ -132,3 +132,9 @@ textarea { .copy-id-button { color: $success; } + +.ticket-field-label { + font-size: 0.9rem; + font-weight: bold; + text-transform: uppercase; +} diff --git a/projects/gameboard-ui/src/app/utility/components/inplace-editor/inplace-editor.component.html b/projects/gameboard-ui/src/app/utility/components/inplace-editor/inplace-editor.component.html index ea74598fc..ee29e28f0 100644 --- a/projects/gameboard-ui/src/app/utility/components/inplace-editor/inplace-editor.component.html +++ b/projects/gameboard-ui/src/app/utility/components/inplace-editor/inplace-editor.component.html @@ -1,18 +1,25 @@ -
-
- -
- -
-
-
-
- {{option.name}} {{option.secondary}} - -
+
+
+ +
+
-
- {{currentText}}   +
+
+ {{option.name}} {{option.secondary}} + +
+
+
+ {{currentText}}   +