diff --git a/frontend/app/adapters/activity-block.js b/frontend/app/adapters/activity-block.ts similarity index 68% rename from frontend/app/adapters/activity-block.js rename to frontend/app/adapters/activity-block.ts index ae5488ce2..d1e7b36bc 100644 --- a/frontend/app/adapters/activity-block.js +++ b/frontend/app/adapters/activity-block.ts @@ -12,7 +12,7 @@ import ApplicationAdapter from "timed/adapters/application"; * @extends ApplicationAdapter * @public */ -export default ApplicationAdapter.extend({ +export default class ActivityBlockAdapter extends ApplicationAdapter { /** * Custom url for updating records * @@ -24,8 +24,8 @@ export default ApplicationAdapter.extend({ * @public */ urlForUpdateRecord(...args) { - return `${this._super(...args)}?include=activity`; - }, + return `${super.urlForUpdateRecord(...args)}?include=activity`; + } /** * Custom url for creating records @@ -38,6 +38,12 @@ export default ApplicationAdapter.extend({ * @public */ urlForCreateRecord(...args) { - return `${this._super(...args)}?include=activity`; - }, -}); + return `${super.urlForCreateRecord(...args)}?include=activity`; + } +} + +declare module "ember-data/types/registries/adapter" { + interface AdapterRegistry { + "activity-block": ActivityBlockAdapter; + } +} diff --git a/frontend/app/adapters/application.js b/frontend/app/adapters/application.ts similarity index 75% rename from frontend/app/adapters/application.js rename to frontend/app/adapters/application.ts index 326b5b5ac..c8696d328 100644 --- a/frontend/app/adapters/application.js +++ b/frontend/app/adapters/application.ts @@ -16,3 +16,9 @@ import OIDCJSONAPIAdapter from "ember-simple-auth-oidc/adapters/oidc-json-api-ad export default class ApplicationAdapter extends OIDCJSONAPIAdapter { namespace = "api/v1"; } + +declare module "ember-data/types/registries/adapter" { + interface AdapterRegistry { + application: ApplicationAdapter; + } +} diff --git a/frontend/app/models/absence-balance.js b/frontend/app/models/absence-balance.js deleted file mode 100644 index ad425b658..000000000 --- a/frontend/app/models/absence-balance.js +++ /dev/null @@ -1,12 +0,0 @@ -import Model, { attr, belongsTo, hasMany } from "@ember-data/model"; - -export default class AbsenceBalance extends Model { - @attr("number") credit; - @attr("number") usedDays; - @attr("django-duration") usedDuration; - @attr("number") balance; - @belongsTo("user", { async: false, inverse: "absenceBalances" }) user; - @belongsTo("absence-type", { async: false, inverse: "absenceBalances" }) - absenceType; - @hasMany("absence-credit", { async: true, inverse: null }) absenceCredits; -} diff --git a/frontend/app/models/absence-balance.ts b/frontend/app/models/absence-balance.ts new file mode 100644 index 000000000..25dbbc2be --- /dev/null +++ b/frontend/app/models/absence-balance.ts @@ -0,0 +1,29 @@ +import type { AsyncHasMany } from "@ember-data/model"; +import Model, { attr, belongsTo, hasMany } from "@ember-data/model"; +import type { Duration } from "moment"; +import type AbsenceCredit from "timed/models/absence-credit"; +import type AbsenceType from "timed/models/absence-type"; +import type User from "timed/models/user"; + +export default class AbsenceBalance extends Model { + @attr("number") + declare credit?: number; + @attr("number") + declare usedDays?: number; + @attr("django-duration") + declare usedDuration?: Duration; + @attr("number") + declare balance?: number; + @belongsTo("user", { async: false, inverse: "absenceBalances" }) + declare user: User; + @belongsTo("absence-type", { async: false, inverse: "absenceBalances" }) + declare absenceType: AbsenceType; + @hasMany("absence-credit", { async: true, inverse: null }) + declare absenceCredits: AsyncHasMany; +} + +declare module "ember-data/types/registries/model" { + interface ModelRegistry { + "absence-balance": AbsenceBalance; + } +} diff --git a/frontend/app/models/absence-credit.js b/frontend/app/models/absence-credit.ts similarity index 54% rename from frontend/app/models/absence-credit.js rename to frontend/app/models/absence-credit.ts index 417c3960c..38249ebff 100644 --- a/frontend/app/models/absence-credit.js +++ b/frontend/app/models/absence-credit.ts @@ -1,9 +1,12 @@ +import Model, { attr, belongsTo } from "@ember-data/model"; +import type { Moment } from "moment"; +import type AbsenceType from "timed/models/absence-type"; +import type User from "timed/models/user"; /** * @module timed * @submodule timed-models * @public */ -import Model, { attr, belongsTo } from "@ember-data/model"; /** * The absence credit model @@ -19,7 +22,8 @@ export default class AbsenceCredit extends Model { * @property {Number} days * @public */ - @attr("number") days; + @attr("number") + declare days?: number; /** * The date @@ -27,7 +31,8 @@ export default class AbsenceCredit extends Model { * @property {moment} date * @public */ - @attr("django-date") date; + @attr("django-date") + declare date?: Moment; /** * The comment @@ -35,7 +40,8 @@ export default class AbsenceCredit extends Model { * @property {String} comment * @public */ - @attr("string", { defaultValue: "" }) comment; + @attr("string", { defaultValue: "" }) + declare comment: string; /** * The absence type for which this credit counts @@ -43,7 +49,8 @@ export default class AbsenceCredit extends Model { * @property {AbsenceType} absenceType * @public */ - @belongsTo("absence-type", { async: false, inverse: null }) absenceType; + @belongsTo("absence-type", { async: false, inverse: null }) + declare absenceType: AbsenceType; /** * The user to which this credit belongs to @@ -51,5 +58,12 @@ export default class AbsenceCredit extends Model { * @property {User} user * @public */ - @belongsTo("user", { async: false, inverse: null }) user; + @belongsTo("user", { async: false, inverse: null }) + declare user: User; +} + +declare module "ember-data/types/registries/model" { + interface ModelRegistry { + "absence-credit": AbsenceCredit; + } } diff --git a/frontend/app/models/absence-type.js b/frontend/app/models/absence-type.ts similarity index 64% rename from frontend/app/models/absence-type.js rename to frontend/app/models/absence-type.ts index 21b97249e..6cf819835 100644 --- a/frontend/app/models/absence-type.js +++ b/frontend/app/models/absence-type.ts @@ -1,9 +1,11 @@ +import type { AsyncHasMany } from "@ember-data/model"; +import Model, { attr, hasMany } from "@ember-data/model"; +import type AbsenceBalance from "timed/models/absence-balance"; /** * @module timed * @submodule timed-models * @public */ -import Model, { attr, hasMany } from "@ember-data/model"; /** * The absence type model @@ -21,7 +23,8 @@ export default class AbsenceType extends Model { * @property {String} name * @public */ - @attr("string") name; + @attr("string") + declare name?: string; /** * Whether the absence type only fills the worktime @@ -29,7 +32,8 @@ export default class AbsenceType extends Model { * @property {Boolean} fillWorktime * @public */ - @attr("boolean") fillWorktime; + @attr("boolean") + declare fillWorktime?: boolean; /** * The balances for this type @@ -38,5 +42,11 @@ export default class AbsenceType extends Model { * @public */ @hasMany("absence-balance", { async: true, inverse: "absenceType" }) - absenceBalances; + declare absenceBalances: AsyncHasMany; +} + +declare module "ember-data/types/registries/model" { + interface ModelRegistry { + "absence-type": AbsenceType; + } } diff --git a/frontend/app/models/absence.js b/frontend/app/models/absence.ts similarity index 53% rename from frontend/app/models/absence.js rename to frontend/app/models/absence.ts index 630f1b91c..e95c2d5ca 100644 --- a/frontend/app/models/absence.js +++ b/frontend/app/models/absence.ts @@ -1,10 +1,14 @@ +import type { AsyncBelongsTo } from "@ember-data/model"; +import Model, { attr, belongsTo } from "@ember-data/model"; +import type { Duration, Moment } from "moment"; +import moment from "moment"; +import type AbsenceType from "timed/models/absence-type"; +import type User from "timed/models/user"; /** * @module timed * @submodule timed-models * @public */ -import Model, { attr, belongsTo } from "@ember-data/model"; -import moment from "moment"; /** * The report model @@ -20,7 +24,8 @@ export default class Absence extends Model { * @property {String} comment * @public */ - @attr("string", { defaultValue: "" }) comment; + @attr("string", { defaultValue: "" }) + declare comment: string; /** * The duration @@ -28,7 +33,8 @@ export default class Absence extends Model { * @property {moment.duration} duration * @public */ - @attr("django-duration", { defaultValue: () => moment.duration() }) duration; + @attr("django-duration", { defaultValue: () => moment.duration() }) + declare duration: Duration; /** * The date @@ -36,7 +42,8 @@ export default class Absence extends Model { * @property {moment} date * @public */ - @attr("django-date") date; + @attr("django-date") + declare date?: Moment; /** * The type of the absence @@ -44,7 +51,8 @@ export default class Absence extends Model { * @property {AbsenceType} absenceType * @public */ - @belongsTo("absence-type", { async: false, inverse: null }) absenceType; + @belongsTo("absence-type", { async: false, inverse: null }) + declare absenceType: AbsenceType; /** * The user @@ -52,5 +60,12 @@ export default class Absence extends Model { * @property {User} user * @public */ - @belongsTo("user", { async: true, inverse: null }) user; + @belongsTo("user", { async: true, inverse: null }) + declare user: AsyncBelongsTo; +} + +declare module "ember-data/types/registries/model" { + interface ModelRegistry { + absence: Absence; + } } diff --git a/frontend/app/models/activity.js b/frontend/app/models/activity.ts similarity index 72% rename from frontend/app/models/activity.js rename to frontend/app/models/activity.ts index e92782c43..e16285b97 100644 --- a/frontend/app/models/activity.js +++ b/frontend/app/models/activity.ts @@ -1,21 +1,36 @@ import { service } from "@ember/service"; +import type { AsyncBelongsTo } from "@ember-data/model"; import Model, { attr, belongsTo } from "@ember-data/model"; +import type StoreService from "@ember-data/store"; +import type NotifyService from "ember-notify"; +import type { Moment } from "moment"; import moment from "moment"; import { all } from "rsvp"; +import type Task from "timed/models/task"; +import type User from "timed/models/user"; export default class Activity extends Model { - @attr("django-time") fromTime; - @attr("django-time") toTime; - @attr("string", { defaultValue: "" }) comment; - @attr("django-date") date; - @attr("boolean", { defaultValue: false }) transferred; - @attr("boolean", { defaultValue: false }) review; - @attr("boolean", { defaultValue: false }) notBillable; - @belongsTo("task", { async: true, inverse: null }) task; - @belongsTo("user", { async: true, inverse: null }) user; - - @service notify; - @service store; + @attr("django-time") + declare fromTime?: Moment; + @attr("django-time") + declare toTime?: Moment; + @attr("string", { defaultValue: "" }) + declare comment: string; + @attr("django-date") + declare date?: Moment; + @attr("boolean", { defaultValue: false }) + declare transferred: boolean; + @attr("boolean", { defaultValue: false }) + declare review: boolean; + @attr("boolean", { defaultValue: false }) + declare notBillable: boolean; + @belongsTo("task", { async: true, inverse: null }) + declare task: AsyncBelongsTo; + @belongsTo("user", { async: true, inverse: null }) + declare user: AsyncBelongsTo; + + @service declare notify: NotifyService; + @service declare store: StoreService; get active() { return !this.toTime && !!this.id; @@ -137,3 +152,9 @@ export default class Activity extends Model { } } } + +declare module "ember-data/types/registries/model" { + interface ModelRegistry { + activity: Activity; + } +} diff --git a/frontend/app/models/attendance.js b/frontend/app/models/attendance.ts similarity index 68% rename from frontend/app/models/attendance.js rename to frontend/app/models/attendance.ts index 34a6e8acc..c9f7c449c 100644 --- a/frontend/app/models/attendance.js +++ b/frontend/app/models/attendance.ts @@ -1,10 +1,13 @@ +import type { AsyncBelongsTo } from "@ember-data/model"; /** * @module timed * @submodule timed-models * @public */ import Model, { attr, belongsTo } from "@ember-data/model"; +import type { Moment } from "moment"; import moment from "moment"; +import type User from "timed/models/user"; /** * The attendance model @@ -20,7 +23,8 @@ export default class Attendance extends Model { * @property {moment} date * @public */ - @attr("django-date") date; + @attr("django-date") + declare date?: Moment; /** * The start time @@ -28,7 +32,8 @@ export default class Attendance extends Model { * @property {moment} from * @public */ - @attr("django-time") from; + @attr("django-time") + declare from?: Moment; /** * The end time @@ -36,7 +41,8 @@ export default class Attendance extends Model { * @property {moment} to * @public */ - @attr("django-time") to; + @attr("django-time") + declare to?: Moment; /** * The user @@ -45,7 +51,8 @@ export default class Attendance extends Model { * @type {User} * @public */ - @belongsTo("user", { async: true, inverse: null }) user; + @belongsTo("user", { async: true, inverse: null }) + declare user: AsyncBelongsTo; /** * The duration between start and end time @@ -65,3 +72,9 @@ export default class Attendance extends Model { return moment.duration(calcTo.diff(this.from)); } } + +declare module "ember-data/types/registries/model" { + interface ModelRegistry { + attendance: Attendance; + } +} diff --git a/frontend/app/models/billing-type.js b/frontend/app/models/billing-type.ts similarity index 66% rename from frontend/app/models/billing-type.js rename to frontend/app/models/billing-type.ts index de59d7548..2c7a6fe8c 100644 --- a/frontend/app/models/billing-type.js +++ b/frontend/app/models/billing-type.ts @@ -19,5 +19,12 @@ export default class BillingType extends Model { * @property {String} name * @public */ - @attr("string") name; + @attr("string") + declare name?: string; +} + +declare module "ember-data/types/registries/model" { + interface ModelRegistry { + "billing-type": BillingType; + } } diff --git a/frontend/app/models/cost-center.js b/frontend/app/models/cost-center.js deleted file mode 100644 index a1b80fb56..000000000 --- a/frontend/app/models/cost-center.js +++ /dev/null @@ -1,6 +0,0 @@ -import Model, { attr } from "@ember-data/model"; - -export default class CostCenter extends Model { - @attr("string") name; - @attr("string") reference; -} diff --git a/frontend/app/models/cost-center.ts b/frontend/app/models/cost-center.ts new file mode 100644 index 000000000..0c32645b7 --- /dev/null +++ b/frontend/app/models/cost-center.ts @@ -0,0 +1,14 @@ +import Model, { attr } from "@ember-data/model"; + +export default class CostCenter extends Model { + @attr("string") + declare name?: string; + @attr("string") + declare reference?: string; +} + +declare module "ember-data/types/registries/model" { + interface ModelRegistry { + "cost-center": CostCenter; + } +} diff --git a/frontend/app/models/customer-assignee.js b/frontend/app/models/customer-assignee.ts similarity index 53% rename from frontend/app/models/customer-assignee.js rename to frontend/app/models/customer-assignee.ts index 678ea0ef4..3c85a229e 100644 --- a/frontend/app/models/customer-assignee.js +++ b/frontend/app/models/customer-assignee.ts @@ -1,9 +1,12 @@ +import type { AsyncBelongsTo } from "@ember-data/model"; +import Model, { attr, belongsTo } from "@ember-data/model"; +import type Customer from "timed/models/customer"; +import type User from "timed/models/user"; /** * @module timed * @submodule timed-models * @public */ -import Model, { attr, belongsTo } from "@ember-data/model"; /** * The customer assignee model @@ -20,7 +23,8 @@ export default class CustomerAssignee extends Model { * @type {Customer} * @public */ - @belongsTo("customer", { async: true, inverse: null }) customer; + @belongsTo("customer", { async: true, inverse: null }) + declare customer: AsyncBelongsTo; /** * The user * @@ -28,7 +32,8 @@ export default class CustomerAssignee extends Model { * @type {User} * @public */ - @belongsTo("user", { async: true, inverse: null }) user; + @belongsTo("user", { async: true, inverse: null }) + declare user: AsyncBelongsTo; /** * Whether the assignee is a reviewer @@ -37,7 +42,8 @@ export default class CustomerAssignee extends Model { * @type {Boolean} * @public */ - @attr("boolean", { defaultValue: false }) isReviewer; + @attr("boolean", { defaultValue: false }) + declare isReviewer: boolean; /** * Whether the assignee is a manager @@ -46,7 +52,8 @@ export default class CustomerAssignee extends Model { * @type {Boolean} * @public */ - @attr("boolean", { defaultValue: false }) isManager; + @attr("boolean", { defaultValue: false }) + declare isManager: boolean; /** * Whether the assignee is a resource @@ -55,5 +62,12 @@ export default class CustomerAssignee extends Model { * @type {Boolean} * @public */ - @attr("boolean", { defaultValue: false }) isResource; + @attr("boolean", { defaultValue: false }) + declare isResource: boolean; +} + +declare module "ember-data/types/registries/model" { + interface ModelRegistry { + "customer-assignee": CustomerAssignee; + } } diff --git a/frontend/app/models/customer-statistic.js b/frontend/app/models/customer-statistic.js deleted file mode 100644 index 315e0a950..000000000 --- a/frontend/app/models/customer-statistic.js +++ /dev/null @@ -1,6 +0,0 @@ -import Model, { attr } from "@ember-data/model"; - -export default class CustomerStatistics extends Model { - @attr("django-duration") duration; - @attr name; -} diff --git a/frontend/app/models/customer-statistic.ts b/frontend/app/models/customer-statistic.ts new file mode 100644 index 000000000..ef88ed8d2 --- /dev/null +++ b/frontend/app/models/customer-statistic.ts @@ -0,0 +1,15 @@ +import Model, { attr } from "@ember-data/model"; +import type { Duration } from "moment"; + +export default class CustomerStatistics extends Model { + @attr("django-duration") + declare duration?: Duration; + @attr + declare name?: string; +} + +declare module "ember-data/types/registries/model" { + interface ModelRegistry { + "customer-statistic": CustomerStatistics; + } +} diff --git a/frontend/app/models/customer.js b/frontend/app/models/customer.ts similarity index 57% rename from frontend/app/models/customer.js rename to frontend/app/models/customer.ts index 49444cf6f..8fd9ba334 100644 --- a/frontend/app/models/customer.js +++ b/frontend/app/models/customer.ts @@ -1,9 +1,12 @@ +import type { AsyncHasMany } from "@ember-data/model"; +import Model, { attr, hasMany } from "@ember-data/model"; +import type CustomerAssignee from "timed/models/customer-assignee"; +import type Project from "timed/models/project"; /** * @module timed * @submodule timed-models * @public */ -import Model, { attr, hasMany } from "@ember-data/model"; /** * The customer model @@ -20,7 +23,8 @@ export default class Customer extends Model { * @type {String} * @public */ - @attr("string", { defaultValue: "" }) name; + @attr("string", { defaultValue: "" }) + declare name: string; /** * Whether the project is archived @@ -29,7 +33,8 @@ export default class Customer extends Model { * @type {Boolean} * @public */ - @attr("boolean", { defaultValue: false }) archived; + @attr("boolean", { defaultValue: false }) + declare archived: boolean; /** * The projects @@ -38,7 +43,8 @@ export default class Customer extends Model { * @type {Project[]} * @public */ - @hasMany("project", { async: true, inverse: "customer" }) projects; + @hasMany("project", { async: true, inverse: "customer" }) + declare projects: AsyncHasMany; /** * Long name - alias for name, used for filtering in the customer box @@ -57,5 +63,12 @@ export default class Customer extends Model { * @type {CustomerAssignee[]} * @public */ - @hasMany("customer-assignee", { async: true, inverse: null }) assignees; + @hasMany("customer-assignee", { async: true, inverse: null }) + declare assignees: AsyncHasMany; +} + +declare module "ember-data/types/registries/model" { + interface ModelRegistry { + customer: Customer; + } } diff --git a/frontend/app/models/employment.js b/frontend/app/models/employment.ts similarity index 53% rename from frontend/app/models/employment.js rename to frontend/app/models/employment.ts index 560ce4013..1a1a8be5e 100644 --- a/frontend/app/models/employment.js +++ b/frontend/app/models/employment.ts @@ -1,9 +1,13 @@ +import type { AsyncBelongsTo } from "@ember-data/model"; +import Model, { attr, belongsTo } from "@ember-data/model"; +import type { Duration, Moment } from "moment"; +import type Location from "timed/models/location"; +import type User from "timed/models/user"; /** * @module timed * @submodule timed-models * @public */ -import Model, { attr, belongsTo } from "@ember-data/model"; /** * The employment model @@ -19,7 +23,8 @@ export default class Employment extends Model { * @property {Number} percentage * @public */ - @attr("number") percentage; + @attr("number") + declare percentage?: number; /** * The time the user has to work every day @@ -27,7 +32,8 @@ export default class Employment extends Model { * @property {moment.duration} worktimePerDay * @public */ - @attr("django-duration") worktimePerDay; + @attr("django-duration") + declare worktimePerDay?: Duration; /** * The start date @@ -35,7 +41,8 @@ export default class Employment extends Model { * @property {moment} start * @public */ - @attr("django-date") start; + @attr("django-date") + declare start?: Moment; /** * Whether the employment is of an external employee @@ -43,7 +50,8 @@ export default class Employment extends Model { * @property {Boolean} isExternal * @public */ - @attr("boolean", { defaultValue: false }) isExternal; + @attr("boolean", { defaultValue: false }) + declare isExternal: boolean; /** * The end date @@ -51,7 +59,8 @@ export default class Employment extends Model { * @property {moment} end * @public */ - @attr("django-date") end; + @attr("django-date") + declare end?: Moment; /** * The employed user @@ -59,7 +68,8 @@ export default class Employment extends Model { * @property {User} user * @public */ - @belongsTo("user", { async: true, inverse: "employments" }) user; + @belongsTo("user", { async: true, inverse: "employments" }) + declare user: AsyncBelongsTo; /** * The work location @@ -67,5 +77,12 @@ export default class Employment extends Model { * @property {Location} location * @public */ - @belongsTo("location", { async: true, inverse: null }) location; + @belongsTo("location", { async: true, inverse: null }) + declare location: AsyncBelongsTo; +} + +declare module "ember-data/types/registries/model" { + interface ModelRegistry { + employment: Employment; + } } diff --git a/frontend/app/models/location.js b/frontend/app/models/location.ts similarity index 67% rename from frontend/app/models/location.js rename to frontend/app/models/location.ts index fe7c35580..08cfd7a04 100644 --- a/frontend/app/models/location.js +++ b/frontend/app/models/location.ts @@ -19,7 +19,8 @@ export default class Location extends Model { * @property {String} name * @public */ - @attr("string") name; + @attr("string") + declare name?: string; /** * The days on which users in this location need to work @@ -27,5 +28,12 @@ export default class Location extends Model { * @property {Number[]} workdays * @public */ - @attr("django-workdays") workdays; + @attr("django-workdays") + declare workdays?: number[]; +} + +declare module "ember-data/types/registries/model" { + interface ModelRegistry { + location: Location; + } } diff --git a/frontend/app/models/month-statistic.js b/frontend/app/models/month-statistic.js deleted file mode 100644 index bd36d4ea6..000000000 --- a/frontend/app/models/month-statistic.js +++ /dev/null @@ -1,7 +0,0 @@ -import Model, { attr } from "@ember-data/model"; - -export default class MonthStatistic extends Model { - @attr("number") year; - @attr("number") month; - @attr("django-duration") duration; -} diff --git a/frontend/app/models/month-statistic.ts b/frontend/app/models/month-statistic.ts new file mode 100644 index 000000000..65f436c34 --- /dev/null +++ b/frontend/app/models/month-statistic.ts @@ -0,0 +1,17 @@ +import Model, { attr } from "@ember-data/model"; +import type { Duration } from "moment"; + +export default class MonthStatistic extends Model { + @attr("number") + declare year?: number; + @attr("number") + declare month?: number; + @attr("django-duration") + declare duration?: Duration; +} + +declare module "ember-data/types/registries/model" { + interface ModelRegistry { + "month-statistic": MonthStatistic; + } +} diff --git a/frontend/app/models/overtime-credit.js b/frontend/app/models/overtime-credit.js deleted file mode 100644 index ba06c6308..000000000 --- a/frontend/app/models/overtime-credit.js +++ /dev/null @@ -1,8 +0,0 @@ -import Model, { attr, belongsTo } from "@ember-data/model"; - -export default class OvertimeCredit extends Model { - @attr("django-date") date; - @attr("django-duration") duration; - @attr("string", { defaultValue: "" }) comment; - @belongsTo("user", { async: false, inverse: null }) user; -} diff --git a/frontend/app/models/overtime-credit.ts b/frontend/app/models/overtime-credit.ts new file mode 100644 index 000000000..22480db1b --- /dev/null +++ b/frontend/app/models/overtime-credit.ts @@ -0,0 +1,20 @@ +import Model, { attr, belongsTo } from "@ember-data/model"; +import type { Moment, Duration } from "moment"; +import type User from "timed/models/user"; + +export default class OvertimeCredit extends Model { + @attr("django-date") + declare date?: Moment; + @attr("django-duration") + declare duration?: Duration; + @attr("string", { defaultValue: "" }) + declare comment: string; + @belongsTo("user", { async: false, inverse: null }) + declare user: User; +} + +declare module "ember-data/types/registries/model" { + interface ModelRegistry { + "overtime-credit": OvertimeCredit; + } +} diff --git a/frontend/app/models/project-assignee.js b/frontend/app/models/project-assignee.ts similarity index 53% rename from frontend/app/models/project-assignee.js rename to frontend/app/models/project-assignee.ts index 58a3b844e..9f2b3f0d6 100644 --- a/frontend/app/models/project-assignee.js +++ b/frontend/app/models/project-assignee.ts @@ -1,9 +1,12 @@ +import type { AsyncBelongsTo } from "@ember-data/model"; /** * @module timed * @submodule timed-models * @public */ import Model, { attr, belongsTo } from "@ember-data/model"; +import type Project from "timed/models/project"; +import type User from "timed/models/user"; /** * The project assignee model @@ -20,7 +23,8 @@ export default class ProjectAssignee extends Model { * @type {Project} * @public */ - @belongsTo("project", { async: true, inverse: null }) project; + @belongsTo("project", { async: true, inverse: null }) + declare project: AsyncBelongsTo; /** * The user @@ -29,7 +33,8 @@ export default class ProjectAssignee extends Model { * @type {User} * @public */ - @belongsTo("user", { async: true, inverse: null }) user; + @belongsTo("user", { async: true, inverse: null }) + declare user: AsyncBelongsTo; /** * Whether the assignee is a reviewer @@ -38,7 +43,8 @@ export default class ProjectAssignee extends Model { * @type {Boolean} * @public */ - @attr("boolean", { defaultValue: false }) isReviewer; + @attr("boolean", { defaultValue: false }) + declare isReviewer: boolean; /** * Whether the assignee is a manager @@ -47,7 +53,8 @@ export default class ProjectAssignee extends Model { * @type {Boolean} * @public */ - @attr("boolean", { defaultValue: false }) isManager; + @attr("boolean", { defaultValue: false }) + declare isManager: boolean; /** * Whether the assignee is a resource @@ -56,5 +63,12 @@ export default class ProjectAssignee extends Model { * @type {Boolean} * @public */ - @attr("boolean", { defaultValue: false }) isResource; + @attr("boolean", { defaultValue: false }) + declare isResource: boolean; +} + +declare module "ember-data/types/registries/model" { + interface ModelRegistry { + "project-assignee": ProjectAssignee; + } } diff --git a/frontend/app/models/project-statistic.js b/frontend/app/models/project-statistic.js deleted file mode 100644 index 12a607a84..000000000 --- a/frontend/app/models/project-statistic.js +++ /dev/null @@ -1,9 +0,0 @@ -import Model, { attr, belongsTo } from "@ember-data/model"; - -export default class ProjectStatistics extends Model { - @attr name; - @attr("django-duration") estimatedTime; - @attr("django-duration") duration; - @attr("django-duration") totalRemainingEffort; - @belongsTo("customer", { async: true, inverse: null }) customer; -} diff --git a/frontend/app/models/project-statistic.ts b/frontend/app/models/project-statistic.ts new file mode 100644 index 000000000..b92357c1c --- /dev/null +++ b/frontend/app/models/project-statistic.ts @@ -0,0 +1,23 @@ +import type { AsyncBelongsTo } from "@ember-data/model"; +import Model, { attr, belongsTo } from "@ember-data/model"; +import type { Duration } from "moment"; +import type Customer from "timed/models/customer"; + +export default class ProjectStatistics extends Model { + @attr + declare name?: string; + @attr("django-duration") + declare estimatedTime?: Duration; + @attr("django-duration") + declare duration?: Duration; + @attr("django-duration") + declare totalRemainingEffort?: Duration; + @belongsTo("customer", { async: true, inverse: null }) + declare customer: AsyncBelongsTo; +} + +declare module "ember-data/types/registries/model" { + interface ModelRegistry { + "project-statistic": ProjectStatistics; + } +} diff --git a/frontend/app/models/project.js b/frontend/app/models/project.ts similarity index 51% rename from frontend/app/models/project.js rename to frontend/app/models/project.ts index a5a0bb80f..e4c52357d 100644 --- a/frontend/app/models/project.js +++ b/frontend/app/models/project.ts @@ -1,9 +1,15 @@ +import type { AsyncHasMany, AsyncBelongsTo } from "@ember-data/model"; /** * @module timed * @submodule timed-models * @public */ import Model, { attr, belongsTo, hasMany } from "@ember-data/model"; +import type { Duration } from "moment"; +import type BillingType from "timed/models/billing-type"; +import type Customer from "timed/models/customer"; +import type ProjectAssignee from "timed/models/project-assignee"; +import type Task from "timed/models/task"; /** * The project model @@ -20,7 +26,8 @@ export default class Project extends Model { * @type {String} * @public */ - @attr("string", { defaultValue: "" }) name; + @attr("string", { defaultValue: "" }) + declare name: string; /** * Whether the project is archived @@ -29,7 +36,8 @@ export default class Project extends Model { * @type {Boolean} * @public */ - @attr("boolean", { defaultValue: false }) archived; + @attr("boolean", { defaultValue: false }) + declare archived: boolean; /** * The estimated time for this project @@ -37,7 +45,8 @@ export default class Project extends Model { * @property {moment.duration} estimatedTime * @public */ - @attr("django-duration") estimatedTime; + @attr("django-duration") + declare estimatedTime?: Duration; /** * Boolean indicating if the remainig effort should be trackable @@ -45,14 +54,16 @@ export default class Project extends Model { * @type {Boolean} * @public */ - @attr("boolean", { defaultValue: false }) remainingEffortTracking; + @attr("boolean", { defaultValue: false }) + declare remainingEffortTracking: boolean; /** * Total remainig effort for this project * @property {moment.duration} estimatedtime * @public */ - @attr("django-duration") totalRemainingEffort; + @attr("django-duration") + declare totalRemainingEffort?: Duration; /** * The customer @@ -61,7 +72,8 @@ export default class Project extends Model { * @type {Customer} * @public */ - @belongsTo("customer", { async: true, inverse: "projects" }) customer; + @belongsTo("customer", { async: true, inverse: "projects" }) + declare customer: AsyncBelongsTo; /** * Whether the project's comments are visible to the customer @@ -70,7 +82,8 @@ export default class Project extends Model { * @type {Boolean} * @public */ - @attr("boolean", { defaultValue: false }) customerVisible; + @attr("boolean", { defaultValue: false }) + declare customerVisible: boolean; /** * The billing @@ -78,7 +91,8 @@ export default class Project extends Model { * @property {BillingType} billingType * @public */ - @belongsTo("billing-type", { async: false, inverse: null }) billingType; + @belongsTo("billing-type", { async: false, inverse: null }) + declare billingType: BillingType; /** * The tasks @@ -87,7 +101,8 @@ export default class Project extends Model { * @type {Task[]} * @public */ - @hasMany("task", { async: true, inverse: "project" }) tasks; + @hasMany("task", { async: true, inverse: "project" }) + declare tasks: AsyncHasMany; /** * Assigned users to this project @@ -96,5 +111,12 @@ export default class Project extends Model { * @type {ProjectAssignee[]} * @public */ - @hasMany("project-assignee", { async: true, inverse: null }) assignees; + @hasMany("project-assignee", { async: true, inverse: null }) + declare assignees: AsyncHasMany; +} + +declare module "ember-data/types/registries/model" { + interface ModelRegistry { + project: Project; + } } diff --git a/frontend/app/models/public-holiday.js b/frontend/app/models/public-holiday.ts similarity index 51% rename from frontend/app/models/public-holiday.js rename to frontend/app/models/public-holiday.ts index 2bca8babc..9eacb3218 100644 --- a/frontend/app/models/public-holiday.js +++ b/frontend/app/models/public-holiday.ts @@ -1,9 +1,12 @@ +import type { AsyncBelongsTo } from "@ember-data/model"; +import Model, { attr, belongsTo } from "@ember-data/model"; +import type { Moment } from "moment"; +import type Location from "timed/models/location"; /** * @module timed * @submodule timed-models * @public */ -import Model, { attr, belongsTo } from "@ember-data/model"; /** * The public holiday model @@ -19,7 +22,8 @@ export default class PublicHoliday extends Model { * @property {String} name * @public */ - @attr("string") name; + @attr("string") + declare name?: string; /** * The date @@ -27,7 +31,8 @@ export default class PublicHoliday extends Model { * @property {moment} date * @public */ - @attr("django-date") date; + @attr("django-date") + declare date?: Moment; /** * The location @@ -35,5 +40,12 @@ export default class PublicHoliday extends Model { * @property {Location} location * @public */ - @belongsTo("location", { async: true, inverse: null }) location; + @belongsTo("location", { async: true, inverse: null }) + declare location: AsyncBelongsTo; +} + +declare module "ember-data/types/registries/model" { + interface ModelRegistry { + "public-holiday": PublicHoliday; + } } diff --git a/frontend/app/models/report-intersection.js b/frontend/app/models/report-intersection.js deleted file mode 100644 index 8b3f2eb5c..000000000 --- a/frontend/app/models/report-intersection.js +++ /dev/null @@ -1,15 +0,0 @@ -import Model, { attr, belongsTo } from "@ember-data/model"; - -export default class ReportIntersection extends Model { - @attr("string") comment; - @attr("boolean", { allowNull: true, defaultValue: null }) notBillable; - @attr("boolean", { allowNull: true, defaultValue: false }) rejected; - @attr("boolean", { allowNull: true, defaultValue: null }) review; - @attr("boolean", { allowNull: true, defaultValue: null }) billed; - @attr("boolean", { allowNull: true, defaultValue: null }) verified; - - @belongsTo("customer", { async: true, inverse: null }) customer; - @belongsTo("project", { async: true, inverse: null }) project; - @belongsTo("task", { async: true, inverse: null }) task; - @belongsTo("user", { async: true, inverse: null }) user; -} diff --git a/frontend/app/models/report-intersection.ts b/frontend/app/models/report-intersection.ts new file mode 100644 index 000000000..48483b1a0 --- /dev/null +++ b/frontend/app/models/report-intersection.ts @@ -0,0 +1,36 @@ +import type { AsyncBelongsTo } from "@ember-data/model"; +import Model, { attr, belongsTo } from "@ember-data/model"; +import type Customer from "timed/models/customer"; +import type Project from "timed/models/project"; +import type Task from "timed/models/task"; +import type User from "timed/models/user"; + +export default class ReportIntersection extends Model { + @attr("string") + declare comment?: string; + @attr("boolean", { allowNull: true, defaultValue: null }) + declare notBillable: boolean | null; + @attr("boolean", { allowNull: true, defaultValue: false }) + declare rejected: boolean | null; + @attr("boolean", { allowNull: true, defaultValue: null }) + declare review: boolean | null; + @attr("boolean", { allowNull: true, defaultValue: null }) + declare billed: boolean | null; + @attr("boolean", { allowNull: true, defaultValue: null }) + declare verified: boolean | null; + + @belongsTo("customer", { async: true, inverse: null }) + declare customer: AsyncBelongsTo; + @belongsTo("project", { async: true, inverse: null }) + declare project: AsyncBelongsTo; + @belongsTo("task", { async: true, inverse: null }) + declare task: AsyncBelongsTo; + @belongsTo("user", { async: true, inverse: null }) + declare user: AsyncBelongsTo; +} + +declare module "ember-data/types/registries/model" { + interface ModelRegistry { + "report-intersection": ReportIntersection; + } +} diff --git a/frontend/app/models/report.js b/frontend/app/models/report.ts similarity index 59% rename from frontend/app/models/report.js rename to frontend/app/models/report.ts index 1407ecbff..2b8aefef9 100644 --- a/frontend/app/models/report.js +++ b/frontend/app/models/report.ts @@ -1,10 +1,14 @@ +import type { AsyncBelongsTo } from "@ember-data/model"; +import Model, { attr, belongsTo } from "@ember-data/model"; +import type { Duration, Moment } from "moment"; +import moment from "moment"; +import type Task from "timed/models/task"; +import type User from "timed/models/user"; /** * @module timed * @submodule timed-models * @public */ -import Model, { attr, belongsTo } from "@ember-data/model"; -import moment from "moment"; /** * The report model @@ -20,7 +24,8 @@ export default class Report extends Model { * @property {String} comment * @public */ - @attr("string", { defaultValue: "" }) comment; + @attr("string", { defaultValue: "" }) + declare comment: string; /** * The date @@ -28,7 +33,8 @@ export default class Report extends Model { * @property {moment} date * @public */ - @attr("django-date") date; + @attr("django-date") + declare date?: Moment; /** * The duration @@ -36,7 +42,8 @@ export default class Report extends Model { * @property {moment.duration} duration * @public */ - @attr("django-duration", { defaultValue: () => moment.duration() }) duration; + @attr("django-duration", { defaultValue: () => moment.duration() }) + declare duration: Duration; /** * The remaining effort for the underlying task @@ -46,7 +53,7 @@ export default class Report extends Model { */ @attr("django-duration", { defaultValue: () => moment.duration() }) - remainingEffort; + declare remainingEffort: Duration; /** * Whether the report needs to be reviewed @@ -54,7 +61,8 @@ export default class Report extends Model { * @property {Boolean} review * @public */ - @attr("boolean", { defaultValue: false }) review; + @attr("boolean", { defaultValue: false }) + declare review: boolean; /** * Whether the report got rejected by the reviewer @@ -62,7 +70,8 @@ export default class Report extends Model { * @property {Boolean} reject * @public */ - @attr("boolean", { defaultValue: false }) rejected; + @attr("boolean", { defaultValue: false }) + declare rejected: boolean; /** * Whether the report is not billable @@ -70,7 +79,8 @@ export default class Report extends Model { * @property {Boolean} notBillable * @public */ - @attr("boolean", { defaultValue: false }) notBillable; + @attr("boolean", { defaultValue: false }) + declare notBillable: boolean; /** * Whether the report has been marked as billed @@ -78,7 +88,8 @@ export default class Report extends Model { * @property {Boolean} billed * @public */ - @attr("boolean", { defaultValue: false }) billed; + @attr("boolean", { defaultValue: false }) + declare billed: boolean; /** * The task @@ -86,7 +97,8 @@ export default class Report extends Model { * @property {Task} task * @public */ - @belongsTo("task", { async: false, inverse: null }) task; + @belongsTo("task", { async: false, inverse: null }) + declare task: Task; /** * The user @@ -94,7 +106,8 @@ export default class Report extends Model { * @property {User} user * @public */ - @belongsTo("user", { async: false, inverse: null }) user; + @belongsTo("user", { async: false, inverse: null }) + declare user: User; /** * The user which verified this report @@ -102,5 +115,12 @@ export default class Report extends Model { * @property {User} verifiedBy * @public */ - @belongsTo("user", { async: true, inverse: null }) verifiedBy; + @belongsTo("user", { async: true, inverse: null }) + declare verifiedBy: AsyncBelongsTo; +} + +declare module "ember-data/types/registries/model" { + interface ModelRegistry { + report: Report; + } } diff --git a/frontend/app/models/task-assignee.js b/frontend/app/models/task-assignee.ts similarity index 53% rename from frontend/app/models/task-assignee.js rename to frontend/app/models/task-assignee.ts index 4f8a58bbe..816f7762f 100644 --- a/frontend/app/models/task-assignee.js +++ b/frontend/app/models/task-assignee.ts @@ -1,9 +1,12 @@ +import type { AsyncBelongsTo } from "@ember-data/model"; /** * @module timed * @submodule timed-models * @public */ import Model, { attr, belongsTo } from "@ember-data/model"; +import type Task from "timed/models/task"; +import type User from "timed/models/user"; /** * The task assignee model @@ -20,7 +23,8 @@ export default class TaskAssignee extends Model { * @type {Task} * @public */ - @belongsTo("task", { async: true, inverse: "assignees" }) task; + @belongsTo("task", { async: true, inverse: "assignees" }) + declare task: AsyncBelongsTo; /** * The user * @@ -28,7 +32,8 @@ export default class TaskAssignee extends Model { * @type {User} * @public */ - @belongsTo("user", { async: true, inverse: null }) user; + @belongsTo("user", { async: true, inverse: null }) + declare user: AsyncBelongsTo; /** * Whether the assignee is a reviewer @@ -37,7 +42,8 @@ export default class TaskAssignee extends Model { * @type {Boolean} * @public */ - @attr("boolean", { defaultValue: false }) isReviewer; + @attr("boolean", { defaultValue: false }) + declare isReviewer: boolean; /** * Whether the assignee is a manager @@ -46,7 +52,8 @@ export default class TaskAssignee extends Model { * @type {Boolean} * @public */ - @attr("boolean", { defaultValue: false }) isManager; + @attr("boolean", { defaultValue: false }) + declare isManager: boolean; /** * Whether the assignee is a resource @@ -55,5 +62,12 @@ export default class TaskAssignee extends Model { * @type {Boolean} * @public */ - @attr("boolean", { defaultValue: false }) isResource; + @attr("boolean", { defaultValue: false }) + declare isResource: boolean; +} + +declare module "ember-data/types/registries/model" { + interface ModelRegistry { + "task-assignee": TaskAssignee; + } } diff --git a/frontend/app/models/task-statistic.js b/frontend/app/models/task-statistic.js deleted file mode 100644 index b9a234e25..000000000 --- a/frontend/app/models/task-statistic.js +++ /dev/null @@ -1,9 +0,0 @@ -import Model, { attr, belongsTo } from "@ember-data/model"; - -export default class TaskStatistics extends Model { - @attr name; - @attr("django-duration") duration; - @attr("django-duration") estimatedTime; - @attr("django-duration") mostRecentRemainingEffort; - @belongsTo("project", { async: true, inverse: null }) project; -} diff --git a/frontend/app/models/task-statistic.ts b/frontend/app/models/task-statistic.ts new file mode 100644 index 000000000..e63d73b50 --- /dev/null +++ b/frontend/app/models/task-statistic.ts @@ -0,0 +1,23 @@ +import type { AsyncBelongsTo } from "@ember-data/model"; +import Model, { attr, belongsTo } from "@ember-data/model"; +import type { Duration } from "moment"; +import type Project from "timed/models/project"; + +export default class TaskStatistics extends Model { + @attr + declare name?: string; + @attr("django-duration") + declare duration?: Duration; + @attr("django-duration") + declare estimatedTime?: Duration; + @attr("django-duration") + declare mostRecentRemainingEffort?: Duration; + @belongsTo("project", { async: true, inverse: null }) + declare project: AsyncBelongsTo; +} + +declare module "ember-data/types/registries/model" { + interface ModelRegistry { + "task-statistic": TaskStatistics; + } +} diff --git a/frontend/app/models/task.js b/frontend/app/models/task.js deleted file mode 100644 index 9882f902b..000000000 --- a/frontend/app/models/task.js +++ /dev/null @@ -1,40 +0,0 @@ -import Model, { attr, belongsTo, hasMany } from "@ember-data/model"; - -export default class Task extends Model { - @attr("string", { defaultValue: "" }) name; - @attr("django-duration") estimatedTime; - @attr("django-duration") mostRecentRemainingEffort; - @attr("boolean", { defaultValue: false }) archived; - @attr("string", { defaultValue: "" }) reference; - - @belongsTo("project", { - async: true, - inverse: "tasks", - }) - project; - @hasMany("task-assignee", { - async: true, - inverse: "task", - }) - assignees; - - /** - * Flag saying that this is a task. - * Used in /app/customer-suggestion/template.hbs - * We're using this as a workaround for the fact that one - * can't seem to use helpers like "(eq" in inline templates - * - * @property project - * @type {Project} - * @public - */ - isTask = true; - - get longName() { - const taskName = this.name; - const projectName = this.project.get("name"); - const customerName = this.project.get("customer.name"); - - return `${customerName} > ${projectName} > ${taskName}`; - } -} diff --git a/frontend/app/models/task.ts b/frontend/app/models/task.ts new file mode 100644 index 000000000..147a10897 --- /dev/null +++ b/frontend/app/models/task.ts @@ -0,0 +1,49 @@ +import type { AsyncHasMany, AsyncBelongsTo } from "@ember-data/model"; +import Model, { attr, belongsTo, hasMany } from "@ember-data/model"; +import type { Duration } from "moment"; +import type Project from "timed/models/project"; +import type TaskAssignee from "timed/models/task-assignee"; + +export default class Task extends Model { + @attr("string", { defaultValue: "" }) + declare name: string; + @attr("django-duration") + declare estimatedTime?: Duration; + @attr("django-duration") + declare mostRecentRemainingEffort?: Duration; + @attr("boolean", { defaultValue: false }) + declare archived: boolean; + @attr("string", { defaultValue: "" }) + declare reference: string; + + @belongsTo("project", { async: true, inverse: "tasks" }) + declare project: AsyncBelongsTo; + @hasMany("task-assignee", { async: true, inverse: "task" }) + declare assignees: AsyncHasMany; + + /** + * Flag saying that this is a task. + * Used in /app/customer-suggestion/template.hbs + * We're using this as a workaround for the fact that one + * can't seem to use helpers like "(eq" in inline templates + * + * @property project + * @type {Project} + * @public + */ + isTask = true; + + get longName() { + const taskName = this.name; + const projectName = this.project.get("name"); + const customerName = this.project.get("customer.name"); + + return `${customerName} > ${projectName} > ${taskName}`; + } +} + +declare module "ember-data/types/registries/model" { + interface ModelRegistry { + task: Task; + } +} diff --git a/frontend/app/models/user-statistic.js b/frontend/app/models/user-statistic.js deleted file mode 100644 index 1785551fe..000000000 --- a/frontend/app/models/user-statistic.js +++ /dev/null @@ -1,7 +0,0 @@ -import Model, { attr, belongsTo } from "@ember-data/model"; - -export default class UserStatistic extends Model { - @attr("django-duration") duration; - - @belongsTo("user", { async: true, inverse: null }) user; -} diff --git a/frontend/app/models/user-statistic.ts b/frontend/app/models/user-statistic.ts new file mode 100644 index 000000000..514edf6dd --- /dev/null +++ b/frontend/app/models/user-statistic.ts @@ -0,0 +1,18 @@ +import type { AsyncBelongsTo } from "@ember-data/model"; +import Model, { attr, belongsTo } from "@ember-data/model"; +import type { Duration } from "moment"; +import type User from "timed/models/user"; + +export default class UserStatistic extends Model { + @attr("django-duration") + declare duration?: Duration; + + @belongsTo("user", { async: true, inverse: null }) + declare user: AsyncBelongsTo; +} + +declare module "ember-data/types/registries/model" { + interface ModelRegistry { + "user-statistic": UserStatistic; + } +} diff --git a/frontend/app/models/user.js b/frontend/app/models/user.ts similarity index 69% rename from frontend/app/models/user.js rename to frontend/app/models/user.ts index 3db1a1a6c..0313796b6 100644 --- a/frontend/app/models/user.js +++ b/frontend/app/models/user.ts @@ -1,11 +1,16 @@ +import { service } from "@ember/service"; +import type { SyncHasMany, AsyncHasMany } from "@ember-data/model"; +import Model, { attr, hasMany } from "@ember-data/model"; +import type StoreService from "@ember-data/store"; +import moment from "moment"; +import type AbsenceBalance from "timed/models/absence-balance"; +import type Employment from "timed/models/employment"; /** * @module timed * @submodule timed-models * @public */ -import { service } from "@ember/service"; -import Model, { attr, hasMany } from "@ember-data/model"; -import moment from "moment"; +import type WorktimeBalance from "timed/models/worktime-balance"; /** * The user model * @@ -14,14 +19,15 @@ import moment from "moment"; * @public */ export default class User extends Model { - @service store; + @service declare store: StoreService; /** * The username * * @property {String} username * @public */ - @attr("string") username; + @attr("string") + declare username?: string; /** * The first name @@ -29,7 +35,8 @@ export default class User extends Model { * @property {String} firstName * @public */ - @attr("string") firstName; + @attr("string") + declare firstName?: string; /** * The last name @@ -37,7 +44,8 @@ export default class User extends Model { * @property {String} lastName * @public */ - @attr("string") lastName; + @attr("string") + declare lastName?: string; /** * The email address @@ -45,7 +53,8 @@ export default class User extends Model { * @property {String} email * @public */ - @attr("string") email; + @attr("string") + declare email?: string; /** * Defines if the user is a superuser @@ -53,7 +62,8 @@ export default class User extends Model { * @property {Boolean} isSuperuser * @public */ - @attr("boolean") isSuperuser; + @attr("boolean") + declare isSuperuser?: boolean; /** * Whether a user is active @@ -61,7 +71,8 @@ export default class User extends Model { * @property {Boolean} isActive * @public */ - @attr("boolean") isActive; + @attr("boolean") + declare isActive?: boolean; /** * Whether the user is a reviewer in a project @@ -69,12 +80,14 @@ export default class User extends Model { * @property {Boolean} isReviewer * @public */ - @attr("boolean") isReviewer; + @attr("boolean") + declare isReviewer?: boolean; /** * Whether the user is an accountant */ - @attr("boolean", { defaultValue: false }) isAccountant; + @attr("boolean", { defaultValue: false }) + declare isAccountant: boolean; /** * Whether the user completed the app tour @@ -82,7 +95,8 @@ export default class User extends Model { * @property {Boolean} tourDone * @public */ - @attr("boolean") tourDone; + @attr("boolean") + declare tourDone?: boolean; /** * The users supervisors @@ -90,7 +104,8 @@ export default class User extends Model { * @property {User[]} supervisors * @public */ - @hasMany("user", { inverse: "supervisees", async: false }) supervisors; + @hasMany("user", { inverse: "supervisees", async: false }) + declare supervisors: SyncHasMany; /** * The users supervisees @@ -98,7 +113,8 @@ export default class User extends Model { * @property {User[]} supervisees * @public */ - @hasMany("user", { inverse: "supervisors", async: false }) supervisees; + @hasMany("user", { inverse: "supervisors", async: false }) + declare supervisees: SyncHasMany; /** * The users employments @@ -106,7 +122,8 @@ export default class User extends Model { * @property {Employment[]} employments * @public */ - @hasMany("employment", { async: true, inverse: "user" }) employments; + @hasMany("employment", { async: true, inverse: "user" }) + declare employments: AsyncHasMany; /** * The users worktime balances @@ -115,7 +132,7 @@ export default class User extends Model { * @public */ @hasMany("worktime-balances", { async: true, inverse: "user" }) - worktimeBalances; + declare worktimeBalances: AsyncHasMany; /** * The users absence balances @@ -123,7 +140,8 @@ export default class User extends Model { * @property {AbsenceBalance[]} absenceBalances * @public */ - @hasMany("absence-balance", { async: true, inverse: "user" }) absenceBalances; + @hasMany("absence-balance", { async: true, inverse: "user" }) + declare absenceBalances: AsyncHasMany; /** * The full name @@ -200,3 +218,9 @@ export default class User extends Model { }; } } + +declare module "ember-data/types/registries/model" { + interface ModelRegistry { + user: User; + } +} diff --git a/frontend/app/models/worktime-balance.js b/frontend/app/models/worktime-balance.js deleted file mode 100644 index f7cb73ead..000000000 --- a/frontend/app/models/worktime-balance.js +++ /dev/null @@ -1,7 +0,0 @@ -import Model, { attr, belongsTo } from "@ember-data/model"; - -export default class WorktimeBalance extends Model { - @attr("django-date") date; - @attr("django-duration") balance; - @belongsTo("user", { async: true, inverse: "worktimeBalances" }) user; -} diff --git a/frontend/app/models/worktime-balance.ts b/frontend/app/models/worktime-balance.ts new file mode 100644 index 000000000..881ebdd1a --- /dev/null +++ b/frontend/app/models/worktime-balance.ts @@ -0,0 +1,19 @@ +import type { AsyncBelongsTo } from "@ember-data/model"; +import Model, { attr, belongsTo } from "@ember-data/model"; +import type { Moment, Duration } from "moment"; +import type User from "timed/models/user"; + +export default class WorktimeBalance extends Model { + @attr("django-date") + declare date?: Moment; + @attr("django-duration") + declare balance?: Duration; + @belongsTo("user", { async: true, inverse: "worktimeBalances" }) + declare user: AsyncBelongsTo; +} + +declare module "ember-data/types/registries/model" { + interface ModelRegistry { + "worktime-balance": WorktimeBalance; + } +} diff --git a/frontend/app/models/year-statistic.js b/frontend/app/models/year-statistic.js deleted file mode 100644 index 54108d33d..000000000 --- a/frontend/app/models/year-statistic.js +++ /dev/null @@ -1,6 +0,0 @@ -import Model, { attr } from "@ember-data/model"; - -export default class YearStatistic extends Model { - @attr("number") year; - @attr("django-duration") duration; -} diff --git a/frontend/app/models/year-statistic.ts b/frontend/app/models/year-statistic.ts new file mode 100644 index 000000000..a2d59de19 --- /dev/null +++ b/frontend/app/models/year-statistic.ts @@ -0,0 +1,15 @@ +import Model, { attr } from "@ember-data/model"; +import type { Duration } from "moment"; + +export default class YearStatistic extends Model { + @attr("number") + declare year?: number; + @attr("django-duration") + declare duration?: Duration; +} + +declare module "ember-data/types/registries/model" { + interface ModelRegistry { + "year-statistic": YearStatistic; + } +} diff --git a/frontend/app/serializers/attendance.js b/frontend/app/serializers/attendance.js index d2ddaf624..2bbb80998 100644 --- a/frontend/app/serializers/attendance.js +++ b/frontend/app/serializers/attendance.js @@ -12,7 +12,7 @@ import ApplicationSerializer from "timed/serializers/application"; * @extends ApplicationSerializer * @public */ -export default ApplicationSerializer.extend({ +export default class AttendanceSerializer extends ApplicationSerializer { /** * The attribute mapping * @@ -24,8 +24,8 @@ export default ApplicationSerializer.extend({ * @property {String} to * @public */ - attrs: { + attrs = { from: "from-time", to: "to-time", - }, -}); + } +} diff --git a/frontend/app/serializers/employment.js b/frontend/app/serializers/employment.js index de54c6c2b..3ac3a3f1b 100644 --- a/frontend/app/serializers/employment.js +++ b/frontend/app/serializers/employment.js @@ -12,7 +12,7 @@ import ApplicationSerializer from "timed/serializers/application"; * @extends ApplicationSerializer * @public */ -export default ApplicationSerializer.extend({ +export default class EmploymentSerializer extends ApplicationSerializer{ /** * The attribute mapping * @@ -24,8 +24,8 @@ export default ApplicationSerializer.extend({ * @property {String} end * @public */ - attrs: { + attrs = { start: "start-date", end: "end-date", - }, -}); + } +} diff --git a/frontend/app/services/autostart-tour.js b/frontend/app/services/autostart-tour.ts similarity index 88% rename from frontend/app/services/autostart-tour.js rename to frontend/app/services/autostart-tour.ts index 65e326a6b..cbb4d433e 100644 --- a/frontend/app/services/autostart-tour.js +++ b/frontend/app/services/autostart-tour.ts @@ -37,3 +37,9 @@ export default class AutostartTourService extends Service { return this.undoneTours.length === 0; } } + +declare module "@ember/service" { + interface Registry { + "autostart-tour": AutostartTourService; + } +} diff --git a/frontend/app/services/current-user.js b/frontend/app/services/current-user.ts similarity index 62% rename from frontend/app/services/current-user.js rename to frontend/app/services/current-user.ts index d2e6524e2..2e5dc37f6 100644 --- a/frontend/app/services/current-user.js +++ b/frontend/app/services/current-user.ts @@ -1,11 +1,15 @@ +import type RouterService from "@ember/routing/router-service"; import Service, { service } from "@ember/service"; +import type StoreService from "@ember-data/store"; +import type SessionService from "ember-simple-auth-oidc/services/session"; import moment from "moment"; +import type FetchService from "timed/services/fetch"; export default class CurrentUserService extends Service { - @service session; - @service fetch; - @service store; - @service router; + @service declare session: SessionService; + @service declare fetch: FetchService; + @service declare store: StoreService; + @service declare router: RouterService; async load() { if (!this.session.isAuthenticated) { @@ -38,3 +42,9 @@ export default class CurrentUserService extends Service { this.user = usermodel; } } + +declare module "@ember/service" { + interface Registry { + "current-user": CurrentUserService; + } +} diff --git a/frontend/app/services/fetch.js b/frontend/app/services/fetch.ts similarity index 92% rename from frontend/app/services/fetch.js rename to frontend/app/services/fetch.ts index e950f900f..46e2f3ccb 100644 --- a/frontend/app/services/fetch.js +++ b/frontend/app/services/fetch.ts @@ -2,6 +2,7 @@ import Service, { service } from "@ember/service"; import { isEmpty } from "@ember/utils"; import { isUnauthorizedResponse } from "ember-fetch/errors"; import { handleUnauthorized } from "ember-simple-auth-oidc"; +import type SessionService from "ember-simple-auth-oidc/services/session"; import fetch from "fetch"; const CONTENT_TYPE = "application/vnd.api+json"; @@ -40,7 +41,7 @@ const stringifyBodyData = (obj) => { }; export default class FetchService extends Service { - @service session; + @service declare session: SessionService; async fetch(resource, init = {}) { await this.session.refreshAuthentication.perform(); @@ -97,3 +98,9 @@ export default class FetchService extends Service { }; } } + +declare module "@ember/service" { + interface Registry { + fetch: FetchService; + } +} diff --git a/frontend/app/services/metadata-fetcher.js b/frontend/app/services/metadata-fetcher.ts similarity index 92% rename from frontend/app/services/metadata-fetcher.js rename to frontend/app/services/metadata-fetcher.ts index eeb9f7429..7312781fa 100644 --- a/frontend/app/services/metadata-fetcher.js +++ b/frontend/app/services/metadata-fetcher.ts @@ -1,6 +1,7 @@ import Service, { service } from "@ember/service"; import { camelize, capitalize, dasherize } from "@ember/string"; import { restartableTask } from "ember-concurrency"; +import type FetchService from "timed/services/fetch"; import DjangoDurationTransform from "timed/transforms/django-duration"; const DJANGO_DURATION_TRANSFORM = DjangoDurationTransform.create(); @@ -45,7 +46,7 @@ export default class MetadataFetcherService extends Service { * @property {Emberfetch} fetch * @public */ - @service fetch; + @service declare fetch: FetchService; /** * Task to fetch a single records metadata @@ -95,3 +96,9 @@ export default class MetadataFetcherService extends Service { return { ...attributesValues, ...metaValues }; } } + +declare module "@ember/service" { + interface Registry { + "metadata-fetcher": MetadataFetcherService; + } +} diff --git a/frontend/app/services/rejected-reports.js b/frontend/app/services/rejected-reports.ts similarity index 73% rename from frontend/app/services/rejected-reports.js rename to frontend/app/services/rejected-reports.ts index 88197b3ae..06bbb9dc4 100644 --- a/frontend/app/services/rejected-reports.js +++ b/frontend/app/services/rejected-reports.ts @@ -1,15 +1,18 @@ import Service, { service } from "@ember/service"; +import type StoreService from "@ember-data/store"; import { macroCondition, isTesting } from "@embroider/macros"; import { tracked } from "@glimmer/tracking"; +import type NotifyService from "ember-notify"; +import type CurrentUserService from "timed/services/current-user"; const INTERVAL_DELAY = 10 * 60000; // 10 Minutes export default class RejectedReportsService extends Service { - @service store; + @service declare store: StoreService; - @service currentUser; + @service declare currentUser: CurrentUserService; - @service notify; + @service declare notify: NotifyService; @tracked amountReports = 0; @tracked intervalId; @@ -53,3 +56,9 @@ export default class RejectedReportsService extends Service { clearInterval(this.intervalId); } } + +declare module "@ember/service" { + interface Registry { + "rejected-reports": RejectedReportsService; + } +} diff --git a/frontend/app/services/tour.js b/frontend/app/services/tour.ts similarity index 87% rename from frontend/app/services/tour.js rename to frontend/app/services/tour.ts index d57f0ac1f..2d4f32200 100644 --- a/frontend/app/services/tour.js +++ b/frontend/app/services/tour.ts @@ -1,17 +1,21 @@ +import type RouterService from "@ember/routing/router-service"; import { schedule, later } from "@ember/runloop"; import { service } from "@ember/service"; import { waitFor } from "@ember/test-waiters"; import { isTesting, macroCondition } from "@embroider/macros"; import { tracked } from "@glimmer/tracking"; +import type NotifyService from "ember-notify"; import Tour from "ember-shepherd/services/tour"; +import type AutostartTourService from "timed/services/autostart-tour"; +import type MediaService from "timed/services/media"; import TOURS from "timed/tours"; import { cached } from "tracked-toolbox"; export default class TourService extends Tour { - @service notify; - @service media; - @service router; - @service autostartTour; + @service declare notify: NotifyService; + @service declare media: MediaService; + @service declare router: RouterService; + @service declare autostartTour: AutostartTourService; @tracked model; constructor(...args) { @@ -51,8 +55,7 @@ export default class TourService extends Tour { super.willDestroy(...args); } - @cached - get routeName() { + @cached get routeName() { return this.router.currentRouteName.replace(/\.index$/, ""); } @@ -132,8 +135,7 @@ export default class TourService extends Tour { } } - @waitFor - async startTour() { + @waitFor async startTour() { if (this._wantsTour && this.hasTourForRoute) { await this.prepareTourForCurrentRoute(); schedule("afterRender", this, () => { @@ -172,3 +174,9 @@ export default class TourService extends Tour { } } } + +declare module "@ember/service" { + interface Registry { + tour: TourService; + } +} diff --git a/frontend/app/services/tracking.js b/frontend/app/services/tracking.ts similarity index 96% rename from frontend/app/services/tracking.js rename to frontend/app/services/tracking.ts index 0df09deef..9f9569e5f 100644 --- a/frontend/app/services/tracking.js +++ b/frontend/app/services/tracking.ts @@ -2,9 +2,11 @@ import { getOwner } from "@ember/application"; import { scheduleOnce } from "@ember/runloop"; import Service, { service } from "@ember/service"; import { camelize, capitalize } from "@ember/string"; +import type StoreService from "@ember-data/store"; import { isTesting, macroCondition } from "@embroider/macros"; import { tracked } from "@glimmer/tracking"; import { dropTask, task, timeout } from "ember-concurrency"; +import type NotifyService from "ember-notify"; import { trackedTask } from "ember-resources/util/ember-concurrency"; import moment from "moment"; import formatDuration from "timed/utils/format-duration"; @@ -25,7 +27,7 @@ export default class TrackingService extends Service { * @property {Ember.Store} store * @public */ - @service store; + @service declare store: StoreService; /** * The notify service @@ -33,7 +35,7 @@ export default class TrackingService extends Service { * @property {EmberNotify.NotifyService} notify * @public */ - @service notify; + @service declare notify: NotifyService; /** * Flag indicating if the tracking reports is currently generated. @@ -363,3 +365,9 @@ export default class TrackingService extends Service { return; } } + +declare module "@ember/service" { + interface Registry { + tracking: TrackingService; + } +} diff --git a/frontend/app/services/unverified-reports.js b/frontend/app/services/unverified-reports.ts similarity index 77% rename from frontend/app/services/unverified-reports.js rename to frontend/app/services/unverified-reports.ts index b320b70e8..b6579c8d2 100644 --- a/frontend/app/services/unverified-reports.js +++ b/frontend/app/services/unverified-reports.ts @@ -1,7 +1,10 @@ import Service, { service } from "@ember/service"; +import type StoreService from "@ember-data/store"; import { isTesting, macroCondition } from "@embroider/macros"; import { tracked } from "@glimmer/tracking"; +import type NotifyService from "ember-notify"; import moment from "moment"; +import type CurrentUserService from "timed/services/current-user"; const INTERVAL_DELAY = 10 * 60000; // 10 Minutes @@ -16,11 +19,11 @@ const INTERVAL_DELAY = 10 * 60000; // 10 Minutes * @public */ export default class UnverifiedReportsService extends Service { - @service store; + @service declare store: StoreService; - @service currentUser; + @service declare currentUser: CurrentUserService; - @service notify; + @service declare notify: NotifyService; @tracked amountReports = 0; @@ -65,3 +68,9 @@ export default class UnverifiedReportsService extends Service { clearInterval(this.intervalId); } } + +declare module "@ember/service" { + interface Registry { + "unverified-reports": UnverifiedReportsService; + } +} diff --git a/frontend/app/transforms/django-date.js b/frontend/app/transforms/django-date.ts similarity index 74% rename from frontend/app/transforms/django-date.js rename to frontend/app/transforms/django-date.ts index 7d1764609..144d88dea 100644 --- a/frontend/app/transforms/django-date.js +++ b/frontend/app/transforms/django-date.ts @@ -18,3 +18,9 @@ export default class DjangoDateTransform extends MomentTransform { */ format = "YYYY-MM-DD"; } + +declare module "ember-data/types/registries/transform" { + interface TransformRegistry { + "django-date": DjangoDateTransform; + } +} diff --git a/frontend/app/transforms/django-datetime.js b/frontend/app/transforms/django-datetime.ts similarity index 74% rename from frontend/app/transforms/django-datetime.js rename to frontend/app/transforms/django-datetime.ts index fdbfd2ed5..1e81896ac 100644 --- a/frontend/app/transforms/django-datetime.js +++ b/frontend/app/transforms/django-datetime.ts @@ -18,3 +18,9 @@ export default class DjangoDatetimeTransform extends MomentTransform { */ format = "YYYY-MM-DDTHH:mm:ss.SSSSZ"; } + +declare module "ember-data/types/registries/transform" { + interface TransformRegistry { + "django-datetime": DjangoDatetimeTransform; + } +} diff --git a/frontend/app/transforms/django-duration.js b/frontend/app/transforms/django-duration.ts similarity index 90% rename from frontend/app/transforms/django-duration.js rename to frontend/app/transforms/django-duration.ts index c607ba709..925aaa3bd 100644 --- a/frontend/app/transforms/django-duration.js +++ b/frontend/app/transforms/django-duration.ts @@ -1,5 +1,5 @@ import Transform from "@ember-data/serializer/transform"; -import moment from "moment"; +import moment, { type Duration } from "moment"; import { pad2joincolon } from "timed/utils/pad"; import parseDjangoDuration from "timed/utils/parse-django-duration"; @@ -29,7 +29,7 @@ export default class DjangoDurationTransform extends Transform { * @return {moment.duration} The deserialized moment duration * @public */ - deserialize(serialized) { + deserialize(serialized: string) { return parseDjangoDuration(serialized); } @@ -69,7 +69,7 @@ export default class DjangoDurationTransform extends Transform { * @return {String} The serialized django duration * @public */ - serialize(deserialized) { + serialize(deserialized: Duration): string { if (!moment.isDuration(deserialized)) { return null; } @@ -90,3 +90,9 @@ export default class DjangoDurationTransform extends Transform { return string; } } + +declare module "ember-data/types/registries/transform" { + interface TransformRegistry { + "django-duration": DjangoDurationTransform; + } +} diff --git a/frontend/app/transforms/django-time.js b/frontend/app/transforms/django-time.ts similarity index 74% rename from frontend/app/transforms/django-time.js rename to frontend/app/transforms/django-time.ts index 465159bec..8852397e1 100644 --- a/frontend/app/transforms/django-time.js +++ b/frontend/app/transforms/django-time.ts @@ -18,3 +18,9 @@ export default class DjangoTimeTransform extends MomentTransform { */ format = "HH:mm:ss"; } + +declare module "ember-data/types/registries/transform" { + interface TransformRegistry { + "django-time": DjangoTimeTransform; + } +} diff --git a/frontend/app/transforms/django-workdays.js b/frontend/app/transforms/django-workdays.ts similarity index 79% rename from frontend/app/transforms/django-workdays.js rename to frontend/app/transforms/django-workdays.ts index 243146a30..b5ad782d3 100644 --- a/frontend/app/transforms/django-workdays.js +++ b/frontend/app/transforms/django-workdays.ts @@ -18,7 +18,7 @@ export default class DjangoWorkdaysTransform extends Transform { * @return {Number[]} The deserialized array * @public */ - deserialize(serialized) { + deserialize(serialized): number[] { return serialized.split(",").map(Number); } @@ -30,7 +30,13 @@ export default class DjangoWorkdaysTransform extends Transform { * @return {String} The serialized string * @public */ - serialize(deserialized) { + serialize(deserialized): string { return deserialized.join(); } } + +declare module "ember-data/types/registries/transform" { + interface TransformRegistry { + "django-workdays": DjangoWorkdaysTransform; + } +} diff --git a/frontend/app/transforms/moment.js b/frontend/app/transforms/moment.ts similarity index 80% rename from frontend/app/transforms/moment.js rename to frontend/app/transforms/moment.ts index 2720cd6fc..e6f74499c 100644 --- a/frontend/app/transforms/moment.js +++ b/frontend/app/transforms/moment.ts @@ -1,5 +1,5 @@ import Transform from "@ember-data/serializer/transform"; -import moment from "moment"; +import moment, { type Moment } from "moment"; /** * The moment transform @@ -27,7 +27,7 @@ export default class MomentTransform extends Transform { * @return {moment.duration} The deserialized moment object * @public */ - deserialize(serialized) { + deserialize(serialized): Moment { return serialized ? moment(serialized, this.format) : null; } @@ -39,9 +39,15 @@ export default class MomentTransform extends Transform { * @return {moment.duration} The serialized date string * @public */ - serialize(deserialized) { + serialize(deserialized): string { return deserialized && deserialized.isValid() ? deserialized.format(this.format) : null; } } + +declare module "ember-data/types/registries/transform" { + interface TransformRegistry { + moment: MomentTransform; + } +}