converts poll/participation and poll/evaluation controllers to TypeScript (#724)
This commit is contained in:
parent
386910bdd3
commit
bf87f6f305
18 changed files with 135 additions and 173 deletions
|
@ -14,21 +14,7 @@
|
||||||
is not sure about it.
|
is not sure about it.
|
||||||
}}
|
}}
|
||||||
<th colspan={{count}}>
|
<th colspan={{count}}>
|
||||||
{{!
|
{{format-date jsDate dateStyle="full" timeZone=@timeZone}}
|
||||||
TODO: Simplify to dateStyle="full" after upgrading to Ember Intl v6
|
|
||||||
|
|
||||||
Cannot use optionGroup.value because that's a ISO8601 day string
|
|
||||||
(e.g. "2023-10-01"), which is parsed by browsers in UTC and not
|
|
||||||
locale time zone. Therefore we need parse a JS Date representation
|
|
||||||
of that string, which has been parsed by Luxon in correct timezone.
|
|
||||||
}}
|
|
||||||
{{format-date
|
|
||||||
jsDate
|
|
||||||
weekday="long"
|
|
||||||
day="numeric"
|
|
||||||
month="long"
|
|
||||||
year="numeric"
|
|
||||||
}}
|
|
||||||
</th>
|
</th>
|
||||||
{{/each-in}}
|
{{/each-in}}
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -49,7 +35,11 @@
|
||||||
But TypeScript does not support narrowing through a chain of getters
|
But TypeScript does not support narrowing through a chain of getters
|
||||||
currently.
|
currently.
|
||||||
}}
|
}}
|
||||||
{{format-date option.jsDate timeStyle="short"}}
|
{{! @glint-ignore }}{{! prettier-ignore }}
|
||||||
|
{{format-date option.jsDate
|
||||||
|
timeStyle="short"
|
||||||
|
timeZone=@timeZone
|
||||||
|
}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{else if @poll.isFindADate}}
|
{{else if @poll.isFindADate}}
|
||||||
{{!
|
{{!
|
||||||
|
@ -59,7 +49,7 @@
|
||||||
But TypeScript does not support narrowing through a chain of getters
|
But TypeScript does not support narrowing through a chain of getters
|
||||||
currently.
|
currently.
|
||||||
}}
|
}}
|
||||||
{{format-date option.jsDate dateStyle="full"}}
|
{{format-date option.jsDate dateStyle="full" timeZone=@timeZone}}
|
||||||
{{else}}
|
{{else}}
|
||||||
{{option.title}}
|
{{option.title}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import { DateTime } from 'luxon';
|
||||||
export interface PollEvaluationParticipantsTableSignature {
|
export interface PollEvaluationParticipantsTableSignature {
|
||||||
Args: {
|
Args: {
|
||||||
poll: Poll;
|
poll: Poll;
|
||||||
|
timeZone: string | undefined;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ interface PollEvaluationSummaryOptionSignature {
|
||||||
Named: {
|
Named: {
|
||||||
evaluationBestOption: BestOption;
|
evaluationBestOption: BestOption;
|
||||||
isFindADate: boolean;
|
isFindADate: boolean;
|
||||||
timeZone: string | null | undefined;
|
timeZone: string | undefined;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
Element: HTMLButtonElement;
|
Element: HTMLButtonElement;
|
||||||
|
|
|
@ -3,12 +3,12 @@ import { inject as service } from '@ember/service';
|
||||||
import { action } from '@ember/object';
|
import { action } from '@ember/object';
|
||||||
import type RouterService from '@ember/routing/router-service';
|
import type RouterService from '@ember/routing/router-service';
|
||||||
import type Transition from '@ember/routing/transition';
|
import type Transition from '@ember/routing/transition';
|
||||||
import type { CreateRouteIndexModel } from 'croodle/routes/create/index';
|
import type { CreateIndexRouteModel } from 'croodle/routes/create/index';
|
||||||
|
|
||||||
export default class CreateIndex extends Controller {
|
export default class CreateIndex extends Controller {
|
||||||
@service declare router: RouterService;
|
@service declare router: RouterService;
|
||||||
|
|
||||||
declare model: CreateRouteIndexModel;
|
declare model: CreateIndexRouteModel;
|
||||||
|
|
||||||
@action
|
@action
|
||||||
submit() {
|
submit() {
|
||||||
|
|
|
@ -63,7 +63,7 @@ export default class PollController extends Controller {
|
||||||
get timezone() {
|
get timezone() {
|
||||||
const { model: poll, shouldUseLocalTimezone } = this;
|
const { model: poll, shouldUseLocalTimezone } = this;
|
||||||
|
|
||||||
return shouldUseLocalTimezone ? undefined : poll.timezone;
|
return shouldUseLocalTimezone || !poll.timezone ? undefined : poll.timezone;
|
||||||
}
|
}
|
||||||
|
|
||||||
@action
|
@action
|
||||||
|
|
|
@ -1,84 +0,0 @@
|
||||||
import Controller, { inject as controller } from '@ember/controller';
|
|
||||||
import { inject as service } from '@ember/service';
|
|
||||||
|
|
||||||
export default class PollEvaluationController extends Controller {
|
|
||||||
@service intl;
|
|
||||||
|
|
||||||
@controller('poll') pollController;
|
|
||||||
|
|
||||||
get isEvaluable() {
|
|
||||||
const { model: poll } = this;
|
|
||||||
const { isFreeText, users } = poll;
|
|
||||||
const hasUsers = users.length > 0;
|
|
||||||
|
|
||||||
return hasUsers && !isFreeText;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* evaluates poll data
|
|
||||||
* if free text answers are allowed evaluation is disabled
|
|
||||||
*/
|
|
||||||
get evaluation() {
|
|
||||||
if (!this.isEvaluable) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
const { model: poll } = this;
|
|
||||||
|
|
||||||
let evaluation = [];
|
|
||||||
let options = [];
|
|
||||||
let lookup = [];
|
|
||||||
|
|
||||||
// init options array
|
|
||||||
poll.options.forEach((option, index) => {
|
|
||||||
options[index] = 0;
|
|
||||||
});
|
|
||||||
|
|
||||||
// init array of evalutation objects
|
|
||||||
// create object for every possible answer
|
|
||||||
poll.answers.forEach((answer) => {
|
|
||||||
evaluation.push({
|
|
||||||
id: answer.label,
|
|
||||||
label: answer.label,
|
|
||||||
options: [...options],
|
|
||||||
});
|
|
||||||
});
|
|
||||||
// create object for no answer if answers are not forced
|
|
||||||
if (!poll.forceAnswer) {
|
|
||||||
evaluation.push({
|
|
||||||
id: null,
|
|
||||||
label: 'no answer',
|
|
||||||
options: [...options],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// create lookup array
|
|
||||||
evaluation.forEach(function (value, index) {
|
|
||||||
lookup[value.id] = index;
|
|
||||||
});
|
|
||||||
|
|
||||||
// loop over all users
|
|
||||||
poll.users.forEach((user) => {
|
|
||||||
// loop over all selections of the user
|
|
||||||
user.selections.forEach(function (selection, optionIndex) {
|
|
||||||
let answerIndex;
|
|
||||||
|
|
||||||
// get answer index by lookup array
|
|
||||||
if (typeof lookup[selection.value.label] === 'undefined') {
|
|
||||||
answerIndex = lookup[null];
|
|
||||||
} else {
|
|
||||||
answerIndex = lookup[selection.get('value.label')];
|
|
||||||
}
|
|
||||||
|
|
||||||
// increment counter
|
|
||||||
try {
|
|
||||||
evaluation[answerIndex].options[optionIndex]++;
|
|
||||||
} catch (e) {
|
|
||||||
// ToDo: Throw an error
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
return evaluation;
|
|
||||||
}
|
|
||||||
}
|
|
21
app/controllers/poll/evaluation.ts
Normal file
21
app/controllers/poll/evaluation.ts
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
import Controller, { inject as controller } from '@ember/controller';
|
||||||
|
import { inject as service } from '@ember/service';
|
||||||
|
import type IntlService from 'ember-intl/services/intl';
|
||||||
|
import type PollController from '../poll';
|
||||||
|
import type { PollEvaluationRouteModel } from 'croodle/routes/poll/evaluation';
|
||||||
|
|
||||||
|
export default class PollEvaluationController extends Controller {
|
||||||
|
@service declare intl: IntlService;
|
||||||
|
|
||||||
|
@controller('poll') declare pollController: PollController;
|
||||||
|
|
||||||
|
declare model: PollEvaluationRouteModel;
|
||||||
|
|
||||||
|
get isEvaluable() {
|
||||||
|
const { model: poll } = this;
|
||||||
|
const { isFreeText, users } = poll;
|
||||||
|
const hasUsers = users.length > 0;
|
||||||
|
|
||||||
|
return hasUsers && !isFreeText;
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,16 +3,28 @@ import User from '../../models/user';
|
||||||
import { inject as service } from '@ember/service';
|
import { inject as service } from '@ember/service';
|
||||||
import { action } from '@ember/object';
|
import { action } from '@ember/object';
|
||||||
import { tracked } from '@glimmer/tracking';
|
import { tracked } from '@glimmer/tracking';
|
||||||
|
import type RouterService from '@ember/routing/router-service';
|
||||||
|
import type PollController from '../poll';
|
||||||
|
import type { PollParticipationRouteModel } from 'croodle/routes/poll/participation';
|
||||||
|
import type Poll from 'croodle/models/poll';
|
||||||
|
import type { SelectionInput } from 'croodle/models/selection';
|
||||||
|
|
||||||
export default class PollParticipationController extends Controller {
|
export default class PollParticipationController extends Controller {
|
||||||
@service router;
|
@service declare router: RouterService;
|
||||||
|
|
||||||
@controller('poll')
|
@controller('poll') declare pollController: PollController;
|
||||||
pollController;
|
|
||||||
|
declare model: PollParticipationRouteModel;
|
||||||
|
|
||||||
@tracked name = '';
|
@tracked name = '';
|
||||||
@tracked savingFailed = false;
|
@tracked savingFailed = false;
|
||||||
|
|
||||||
|
newUserData: {
|
||||||
|
name: string | null;
|
||||||
|
poll: Poll;
|
||||||
|
selections: SelectionInput[];
|
||||||
|
} | null = null;
|
||||||
|
|
||||||
@action
|
@action
|
||||||
async submit() {
|
async submit() {
|
||||||
const { formData, poll } = this.model;
|
const { formData, poll } = this.model;
|
||||||
|
@ -30,18 +42,21 @@ export default class PollParticipationController extends Controller {
|
||||||
}
|
}
|
||||||
|
|
||||||
// map selection to answer if it's not freetext
|
// map selection to answer if it's not freetext
|
||||||
let answer = answers.find(({ type }) => type === value);
|
const answer = answers.find(({ type }) => type === value);
|
||||||
let { icon, label, labelTranslation, type } = answer;
|
if (!answer) {
|
||||||
|
throw new Error('Mapping selection to answer failed');
|
||||||
|
}
|
||||||
|
|
||||||
|
const { icon, labelTranslation, type } = answer;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
icon,
|
icon,
|
||||||
label,
|
|
||||||
labelTranslation,
|
labelTranslation,
|
||||||
type,
|
type,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
this.newUserRecord = {
|
this.newUserData = {
|
||||||
name,
|
name,
|
||||||
poll,
|
poll,
|
||||||
selections,
|
selections,
|
||||||
|
@ -51,12 +66,24 @@ export default class PollParticipationController extends Controller {
|
||||||
|
|
||||||
@action
|
@action
|
||||||
async save() {
|
async save() {
|
||||||
const { model, newUserRecord: user } = this;
|
const { model, newUserData: userData } = this;
|
||||||
const { poll } = model;
|
const { poll } = model;
|
||||||
const { encryptionKey } = this.router.currentRoute.parent.queryParams;
|
// As know that the route is `poll.participation`, which means that there
|
||||||
|
// is a parent `poll` for sure.
|
||||||
|
const { encryptionKey } = this.router.currentRoute.parent!.queryParams;
|
||||||
|
|
||||||
|
if (!userData) {
|
||||||
|
throw new Error(
|
||||||
|
'save method called before submit method has set the user data',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!encryptionKey) {
|
||||||
|
throw new Error('Can not lookup encryption key');
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await User.create(user, encryptionKey);
|
await User.create(userData, encryptionKey);
|
||||||
|
|
||||||
this.savingFailed = false;
|
this.savingFailed = false;
|
||||||
} catch (error) {
|
} catch (error) {
|
|
@ -182,7 +182,7 @@ export default class Poll {
|
||||||
id: payload.poll.id,
|
id: payload.poll.id,
|
||||||
options: decrypt(payload.poll.options, passphrase) as OptionInput,
|
options: decrypt(payload.poll.options, passphrase) as OptionInput,
|
||||||
pollType: decrypt(payload.poll.pollType, passphrase) as PollType,
|
pollType: decrypt(payload.poll.pollType, passphrase) as PollType,
|
||||||
timezone: decrypt(payload.poll.timezone, passphrase) as string,
|
timezone: decrypt(payload.poll.timezone, passphrase) as string | null,
|
||||||
title: decrypt(payload.poll.title, passphrase) as string,
|
title: decrypt(payload.poll.title, passphrase) as string,
|
||||||
users: payload.poll.users.map((user) => {
|
users: payload.poll.users.map((user) => {
|
||||||
return new User({
|
return new User({
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
export type SelectionInput = {
|
export type SelectionInput = {
|
||||||
icon: string;
|
icon?: string;
|
||||||
label: string;
|
label?: string;
|
||||||
labelTranslation: string;
|
labelTranslation?: string;
|
||||||
type: string;
|
type?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default class Selection {
|
export default class Selection {
|
||||||
icon: string;
|
icon?: string;
|
||||||
label: string;
|
label?: string;
|
||||||
labelTranslation: string;
|
labelTranslation?: string;
|
||||||
type: string;
|
type?: string;
|
||||||
|
|
||||||
constructor({ icon, label, labelTranslation, type }: SelectionInput) {
|
constructor({ icon, label, labelTranslation, type }: SelectionInput) {
|
||||||
this.icon = icon;
|
this.icon = icon;
|
||||||
|
|
|
@ -8,7 +8,7 @@ import type Poll from './poll';
|
||||||
type UserInput = {
|
type UserInput = {
|
||||||
creationDate: string;
|
creationDate: string;
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string | null;
|
||||||
selections: SelectionInput[];
|
selections: SelectionInput[];
|
||||||
version: string;
|
version: string;
|
||||||
};
|
};
|
||||||
|
@ -20,7 +20,7 @@ export default class User {
|
||||||
id: string;
|
id: string;
|
||||||
|
|
||||||
// user name
|
// user name
|
||||||
name: string;
|
name: string | null;
|
||||||
|
|
||||||
// array of users selections
|
// array of users selections
|
||||||
// must be in same order as options property of poll
|
// must be in same order as options property of poll
|
||||||
|
@ -42,7 +42,7 @@ export default class User {
|
||||||
name,
|
name,
|
||||||
poll,
|
poll,
|
||||||
selections,
|
selections,
|
||||||
}: { name: string; poll: Poll; selections: SelectionInput[] },
|
}: { name: string | null; poll: Poll; selections: SelectionInput[] },
|
||||||
passphrase: string,
|
passphrase: string,
|
||||||
) {
|
) {
|
||||||
const creationDate = new Date().toISOString();
|
const creationDate = new Date().toISOString();
|
||||||
|
|
|
@ -23,6 +23,6 @@ export default class CreateIndexRoute extends Route {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Resolved<P> = P extends Promise<infer T> ? T : P;
|
type Resolved<P> = P extends Promise<infer T> ? T : P;
|
||||||
export type CreateRouteIndexModel = Resolved<
|
export type CreateIndexRouteModel = Resolved<
|
||||||
ReturnType<CreateIndexRoute['model']>
|
ReturnType<CreateIndexRoute['model']>
|
||||||
>;
|
>;
|
||||||
|
|
|
@ -1,7 +1,13 @@
|
||||||
import Route from '@ember/routing/route';
|
import Route from '@ember/routing/route';
|
||||||
|
import type { PollRouteModel } from '../poll';
|
||||||
|
|
||||||
export default class EvaluationRoute extends Route {
|
export default class PollEvaluationRoute extends Route {
|
||||||
model() {
|
model() {
|
||||||
return this.modelFor('poll');
|
return this.modelFor('poll') as PollRouteModel;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Resolved<P> = P extends Promise<infer T> ? T : P;
|
||||||
|
export type PollEvaluationRouteModel = Resolved<
|
||||||
|
ReturnType<PollEvaluationRoute['model']>
|
||||||
|
>;
|
||||||
|
|
|
@ -78,13 +78,15 @@ class FormData {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class ParticipationRoute extends Route {
|
export default class PollParticipationRoute extends Route {
|
||||||
model() {
|
model() {
|
||||||
const poll = this.modelFor('poll') as Poll;
|
const poll = this.modelFor('poll') as Poll;
|
||||||
const { anonymousUser, forceAnswer, options, users } = poll;
|
const { anonymousUser, forceAnswer, options, users } = poll;
|
||||||
const formData = new FormData(options, {
|
const formData = new FormData(options, {
|
||||||
nameIsRequired: !anonymousUser,
|
nameIsRequired: !anonymousUser,
|
||||||
namesTaken: users.map(({ name }) => name),
|
namesTaken: users
|
||||||
|
.map(({ name }) => name)
|
||||||
|
.filter((_) => _ !== null) as string[],
|
||||||
selectionIsRequired: forceAnswer,
|
selectionIsRequired: forceAnswer,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -94,3 +96,8 @@ export default class ParticipationRoute extends Route {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Resolved<P> = P extends Promise<infer T> ? T : P;
|
||||||
|
export type PollParticipationRouteModel = Resolved<
|
||||||
|
ReturnType<PollParticipationRoute['model']>
|
||||||
|
>;
|
||||||
|
|
|
@ -31,26 +31,18 @@
|
||||||
as |shouldShowDate|
|
as |shouldShowDate|
|
||||||
}}
|
}}
|
||||||
{{#if @model.poll.isFreeText}}
|
{{#if @model.poll.isFreeText}}
|
||||||
|
{{! prettier-ignore }}
|
||||||
<form.element
|
<form.element
|
||||||
@controlType="text"
|
@controlType="text"
|
||||||
{{!
|
{{!
|
||||||
TODO: Simplify date formating to dateStyle="full" and timeStyle="short" after upgrading to Ember Intl v6
|
@glint-ignore
|
||||||
|
We know that jsDate is not null if `poll.isFindADate` is `true`.
|
||||||
|
But Glint does not understand that.
|
||||||
}}
|
}}
|
||||||
@label={{if
|
@label={{if @model.poll.isFindADate (format-date option.jsDate
|
||||||
@model.poll.isFindADate
|
dateStyle=(if shouldShowDate "full" undefined)
|
||||||
(format-date
|
timeStyle=(if option.hasTime "short" undefined)
|
||||||
option.jsDate
|
timeZone=this.pollController.timezone
|
||||||
weekday=(if shouldShowDate "long" undefined)
|
|
||||||
day=(if shouldShowDate "numeric" undefined)
|
|
||||||
month=(if shouldShowDate "long" undefined)
|
|
||||||
year=(if shouldShowDate "numeric" undefined)
|
|
||||||
hour=(if option.hasTime "numeric" undefined)
|
|
||||||
minute=(if option.hasTime "numeric" undefined)
|
|
||||||
timeZone=(if
|
|
||||||
this.pollController.timezone
|
|
||||||
this.pollController.timezone
|
|
||||||
undefined
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
option.title
|
option.title
|
||||||
}}
|
}}
|
||||||
|
@ -59,25 +51,17 @@
|
||||||
data-test-form-element={{concat "option-" option.title}}
|
data-test-form-element={{concat "option-" option.title}}
|
||||||
/>
|
/>
|
||||||
{{else}}
|
{{else}}
|
||||||
|
{{! prettier-ignore }}
|
||||||
<form.element
|
<form.element
|
||||||
{{!
|
{{!
|
||||||
TODO: Simplify date formating to dateStyle="full" and timeStyle="short" after upgrading to Ember Intl v6
|
@glint-ignore
|
||||||
|
We know that jsDate is not null if `poll.isFindADate` is `true`.
|
||||||
|
But Glint does not understand that.
|
||||||
}}
|
}}
|
||||||
@label={{if
|
@label={{if @model.poll.isFindADate (format-date option.jsDate
|
||||||
@model.poll.isFindADate
|
dateStyle=(if shouldShowDate "full" undefined)
|
||||||
(format-date
|
timeStyle=(if option.hasTime "short" undefined)
|
||||||
option.jsDate
|
timeZone=this.pollController.timezone
|
||||||
weekday=(if shouldShowDate "long" undefined)
|
|
||||||
day=(if shouldShowDate "numeric" undefined)
|
|
||||||
month=(if shouldShowDate "long" undefined)
|
|
||||||
year=(if shouldShowDate "numeric" undefined)
|
|
||||||
hour=(if option.hasTime "numeric" undefined)
|
|
||||||
minute=(if option.hasTime "numeric" undefined)
|
|
||||||
timeZone=(if
|
|
||||||
this.pollController.timezone
|
|
||||||
this.pollController.timezone
|
|
||||||
undefined
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
option.title
|
option.title
|
||||||
}}
|
}}
|
||||||
|
|
|
@ -21,7 +21,7 @@ export default Factory.extend({
|
||||||
],
|
],
|
||||||
pollType: 'FindADate',
|
pollType: 'FindADate',
|
||||||
title: 'default title',
|
title: 'default title',
|
||||||
timezone: '',
|
timezone: null,
|
||||||
version: 'v0.3',
|
version: 'v0.3',
|
||||||
|
|
||||||
afterCreate(poll, server) {
|
afterCreate(poll, server) {
|
||||||
|
|
20
types/ember-bootstrap/components/bs-modal.d.ts
vendored
20
types/ember-bootstrap/components/bs-modal.d.ts
vendored
|
@ -5,12 +5,14 @@ declare module '@glint/environment-ember-loose/registry' {
|
||||||
BsModal: ComponentLike<{
|
BsModal: ComponentLike<{
|
||||||
Args: {
|
Args: {
|
||||||
Named: {
|
Named: {
|
||||||
autoClose: boolean;
|
autoClose?: boolean;
|
||||||
closeButton: boolean;
|
closeButton?: boolean;
|
||||||
footer: boolean;
|
footer?: boolean;
|
||||||
keyboard: boolean;
|
keyboard?: boolean;
|
||||||
|
onHidden?: () => void;
|
||||||
|
onSubmit?: () => void;
|
||||||
open: boolean;
|
open: boolean;
|
||||||
title: string;
|
title?: string;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
Blocks: {
|
Blocks: {
|
||||||
|
@ -21,11 +23,19 @@ declare module '@glint/environment-ember-loose/registry' {
|
||||||
default: [];
|
default: [];
|
||||||
};
|
};
|
||||||
}>;
|
}>;
|
||||||
|
close: () => void;
|
||||||
|
header: ComponentLike<{
|
||||||
|
Args: {
|
||||||
|
closeButton: boolean;
|
||||||
|
title: string;
|
||||||
|
};
|
||||||
|
}>;
|
||||||
footer: ComponentLike<{
|
footer: ComponentLike<{
|
||||||
Blocks: {
|
Blocks: {
|
||||||
default: [];
|
default: [];
|
||||||
};
|
};
|
||||||
}>;
|
}>;
|
||||||
|
submit: () => void;
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
2
types/ember-intl/helpers/format-date.d.ts
vendored
2
types/ember-intl/helpers/format-date.d.ts
vendored
|
@ -10,7 +10,7 @@ declare module '@glint/environment-ember-loose/registry' {
|
||||||
'format-date': HelperLike<{
|
'format-date': HelperLike<{
|
||||||
Args: {
|
Args: {
|
||||||
Positional: [Date | string];
|
Positional: [Date | string];
|
||||||
Named: Record<string, unknown>;
|
Named: Intl.DateTimeFormatOptions;
|
||||||
};
|
};
|
||||||
Return: string;
|
Return: string;
|
||||||
}>;
|
}>;
|
||||||
|
|
Loading…
Reference in a new issue