Modernize angular bootstrap

This commit is contained in:
David Burke committed 2025-06-04 13:29:03 -04:00
1 parent dc833b2eb2
commit 5d540a0761
15 files changed
+102 -333

No files matched your search

-12
View File
@@ -71,12 +71,6 @@
},
"configurations": {
"prod-no-static": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
],
"outputHashing": "all"
},
"production": {
@@ -92,12 +86,6 @@
"maximumError": "6kb"
}
],
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
],
"optimization": {
"styles": {
"inlineCritical": false
-155
View File
@@ -91,7 +91,6 @@
"ts-node": "~7.0.0",
"typescript": "^5.8.2",
"wait-on": "^5.3.0",
"webpack-bundle-analyzer": "^4.10.2",
"xliff": "^6.2.1"
}
},
@@ -6553,13 +6552,6 @@
"node": ">=14"
}
},
"node_modules/@polka/url": {
"version": "1.0.0-next.28",
"resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.28.tgz",
"integrity": "sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw==",
"dev": true,
"license": "MIT"
},
"node_modules/@redocly/ajv": {
"version": "8.11.2",
"resolved": "https://registry.npmjs.org/@redocly/ajv/-/ajv-8.11.2.tgz",
@@ -8652,19 +8644,6 @@
"acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
}
},
"node_modules/acorn-walk": {
"version": "8.3.4",
"resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz",
"integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==",
"dev": true,
"license": "MIT",
"dependencies": {
"acorn": "^8.11.0"
},
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/adjust-sourcemap-loader": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/adjust-sourcemap-loader/-/adjust-sourcemap-loader-4.0.0.tgz",
@@ -11650,13 +11629,6 @@
"devOptional": true,
"license": "MIT"
},
"node_modules/debounce": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz",
"integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==",
"dev": true,
"license": "MIT"
},
"node_modules/debug": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
@@ -12016,13 +11988,6 @@
"node": ">= 0.4"
}
},
"node_modules/duplexer": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz",
"integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==",
"dev": true,
"license": "MIT"
},
"node_modules/eastasianwidth": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
@@ -13837,22 +13802,6 @@
"dev": true,
"license": "MIT"
},
"node_modules/gzip-size": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz",
"integrity": "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==",
"dev": true,
"license": "MIT",
"dependencies": {
"duplexer": "^0.1.2"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/hachure-fill": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/hachure-fill/-/hachure-fill-0.5.2.tgz",
@@ -17469,16 +17418,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/opener": {
"version": "1.5.2",
"resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz",
"integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==",
"dev": true,
"license": "(WTFPL OR MIT)",
"bin": {
"opener": "bin/opener-bin.js"
}
},
"node_modules/optionator": {
"version": "0.9.4",
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
@@ -19816,21 +19755,6 @@
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/sirv": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.4.tgz",
"integrity": "sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@polka/url": "^1.0.0-next.24",
"mrmime": "^2.0.0",
"totalist": "^3.0.0"
},
"engines": {
"node": ">= 10"
}
},
"node_modules/slice-ansi": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz",
@@ -21017,16 +20941,6 @@
"node": ">=0.6"
}
},
"node_modules/totalist": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz",
"integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=6"
}
},
"node_modules/tough-cookie": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.0.0.tgz",
@@ -21758,75 +21672,6 @@
}
}
},
"node_modules/webpack-bundle-analyzer": {
"version": "4.10.2",
"resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.10.2.tgz",
"integrity": "sha512-vJptkMm9pk5si4Bv922ZbKLV8UTT4zib4FPgXMhgzUny0bfDDkLXAVQs3ly3fS4/TN9ROFtb0NFrm04UXFE/Vw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@discoveryjs/json-ext": "0.5.7",
"acorn": "^8.0.4",
"acorn-walk": "^8.0.0",
"commander": "^7.2.0",
"debounce": "^1.2.1",
"escape-string-regexp": "^4.0.0",
"gzip-size": "^6.0.0",
"html-escaper": "^2.0.2",
"opener": "^1.5.2",
"picocolors": "^1.0.0",
"sirv": "^2.0.3",
"ws": "^7.3.1"
},
"bin": {
"webpack-bundle-analyzer": "lib/bin/analyzer.js"
},
"engines": {
"node": ">= 10.13.0"
}
},
"node_modules/webpack-bundle-analyzer/node_modules/@discoveryjs/json-ext": {
"version": "0.5.7",
"resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz",
"integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/webpack-bundle-analyzer/node_modules/commander": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
"integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 10"
}
},
"node_modules/webpack-bundle-analyzer/node_modules/ws": {
"version": "7.5.10",
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz",
"integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=8.3.0"
},
"peerDependencies": {
"bufferutil": "^4.0.1",
"utf-8-validate": "^5.0.2"
},
"peerDependenciesMeta": {
"bufferutil": {
"optional": true
},
"utf-8-validate": {
"optional": true
}
}
},
"node_modules/webpack-dev-middleware": {
"version": "7.4.2",
"resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-7.4.2.tgz",
+1 -2
View File
@@ -17,7 +17,7 @@
"cy:openscreenshot": "cypress open --env screenshot=true",
"cy:run": "cypress run",
"e2e": "concurrently \"npm run start -- --no-hmr\" \"wait-on http-get://localhost:4200 && npm run cy:run\" --kill-others --success first",
"build-stats": "ng build --stats-json",
"build-stats": "ng build -c production --stats-json",
"analyze": "webpack-bundle-analyzer dist/glitchtip-frontend/stats.json",
"docs:json": "compodoc -p ./tsconfig.json -e json -d .",
"extract-i18n": "ng extract-i18n",
@@ -111,7 +111,6 @@
"ts-node": "~7.0.0",
"typescript": "^5.8.2",
"wait-on": "^5.3.0",
"webpack-bundle-analyzer": "^4.10.2",
"xliff": "^6.2.1"
},
"overrides": {
+28 -28
View File
@@ -3017,10 +3017,10 @@ export interface components {
/** Status */
status: string;
project: components["schemas"]["ProjectReference"];
/** Short Id */
short_id: string;
/** Num Comments */
num_comments: number;
/** Shortid */
shortId: string;
/** Numcomments */
numComments: number;
/**
* Stats
* @default {
@@ -3055,24 +3055,24 @@ export interface components {
user_count: number | null;
/** Matching Event Id */
matching_event_id?: string | null;
/**
* Firstseen
* Format: date-time
*/
firstSeen: string;
/**
* Lastseen
* Format: date-time
*/
lastSeen: string;
/** Title */
title: string;
/** Metadata */
metadata: Record<string, unknown>;
/** Culprit */
culprit?: string | null;
/**
* First Seen
* Format: date-time
*/
first_seen?: string;
/**
* Last Seen
* Format: date-time
*/
last_seen?: string;
/** User Report Count */
user_report_count: number;
/** Userreportcount */
userReportCount: number;
};
/** ProjectReference */
ProjectReference: {
@@ -3132,8 +3132,8 @@ export interface components {
project: components["schemas"]["ProjectReference"];
/** Short Id Display */
short_id_display: string;
/** Numcomments */
numComments: number;
/** Num Comments */
num_comments: number;
/**
* Stats
* @default {
@@ -3168,22 +3168,22 @@ export interface components {
userCount: number | null;
/** Matchingeventid */
matchingEventId?: string | null;
/**
* First Seen
* Format: date-time
*/
first_seen: string;
/**
* Last Seen
* Format: date-time
*/
last_seen: string;
/** Title */
title: string;
/** Metadata */
metadata: Record<string, unknown>;
/** Culprit */
culprit?: string | null;
/**
* First Seen
* Format: date-time
*/
firstSeen?: string;
/**
* Last Seen
* Format: date-time
*/
lastSeen?: string;
};
/** IssueTagSchema */
IssueTagSchema: {
+2 -9
View File
@@ -1,15 +1,13 @@
import { Injectable, inject } from "@angular/core";
import { HttpClient, HttpParams } from "@angular/common/http";
import { EMPTY, map } from "rxjs";
import { EMPTY } from "rxjs";
import { baseUrl } from "../../constants";
import { APIBaseService } from "../api-base.service";
import {
IssueDetail,
IssueStatus,
IssueTags,
UpdateStatusResponse,
} from "src/app/issues/interfaces";
import { normalizeID } from "../shared-api.utils";
@Injectable({
providedIn: "root",
@@ -31,12 +29,7 @@ export class IssuesAPIService extends APIBaseService {
}
retrieve(id: string) {
return this.http.get<IssueDetail>(this.detailURL(id)).pipe(
map((issueDetail) => {
issueDetail.project.id = normalizeID(issueDetail.project.id);
return issueDetail;
}),
);
return EMPTY;
}
update(status: IssueStatus, orgSlug: string, id: number) {
@@ -37,7 +37,7 @@ export class UserReportsService extends PaginationStatefulService<UserReportsSta
super(initialState);
}
getReportsForIssue(issue: number, cursor?: string | null) {
getReportsForIssue(issue: string, cursor?: string | null) {
this.setLoadingReports(true);
this.resetUserReports();
this.getIssueReports(issue, cursor)
@@ -60,7 +60,7 @@ export class UserReportsService extends PaginationStatefulService<UserReportsSta
.subscribe();
}
private getIssueReports(issueId: number, cursor?: string | null) {
private getIssueReports(issueId: string, cursor?: string | null) {
let httpParams = new HttpParams();
if (cursor) {
httpParams = httpParams.set("cursor", cursor);
@@ -3,7 +3,6 @@ import {
ChangeDetectionStrategy,
inject,
input,
effect,
computed,
} from "@angular/core";
import { RouterLink } from "@angular/router";
@@ -56,12 +55,6 @@ export class EventDetailComponent {
nextEventUrl = this.issueService.nextEventUrl;
previousEventUrl = this.issueService.previousEventUrl;
constructor() {
effect(() => {
this.issueService.setParams(this.issueID(), this.eventID());
});
}
/** TODO fix these types */
generateQuery(tag: { [key: string]: string | null }) {
// Assume unresolved if not present; tag overrides query otherwise
@@ -5,6 +5,7 @@ import {
inject,
computed,
input,
effect,
} from "@angular/core";
import { FormControl, FormGroup } from "@angular/forms";
import { ActivatedRoute, RouterModule } from "@angular/router";
@@ -47,7 +48,7 @@ export class IssueDetailComponent implements OnInit {
issue = this.issueService.issue;
issueTitle = computed(() => {
const issue = this.issue();
if (issue === null || issue.metadata === null) {
if (!issue || issue.metadata === null) {
return ["", null] as [string, string | null];
}
const metadata = issue.metadata;
@@ -75,23 +76,23 @@ export class IssueDetailComponent implements OnInit {
return [metadata.title!, null] as [string, string | null];
}
});
issueSubtitle = computed(() => {
issueSubtitle = computed<string>(() => {
const issue = this.issue();
if (issue === null || issue.metadata === null) {
if (!issue || issue.metadata === null) {
return "";
}
const metadata = issue.metadata;
switch (issue.type) {
case "error":
return metadata.value;
return metadata.value as string;
case "csp":
return metadata.message;
return metadata.message as string;
case "expectct":
case "expectstaple":
case "hpkp":
return "";
default:
return issue.culprit;
return issue.culprit as string;
}
});
initialLoadComplete = this.issueService.issueInitialLoadComplete;
@@ -99,6 +100,7 @@ export class IssueDetailComponent implements OnInit {
assignee: new FormControl(""),
});
issueID = input.required<string>({ alias: "issue-id" });
eventID = input<string | null>(null, { alias: "event-id" });
organization = this.organizationsService.activeOrganization;
participantCountPluralMapping: { [k: string]: string } = {
"=0": "No Participants",
@@ -106,11 +108,14 @@ export class IssueDetailComponent implements OnInit {
other: "# Participants",
};
constructor() {
effect(() => {
this.issueService.setParams(this.issueID(), this.eventID());
});
}
ngOnInit() {
this.issueService.clearState();
const issueID = this.issueID();
// Consider moving to effect once ported to resource
this.issueService.retrieveIssue(+issueID).toPromise();
}
markResolved() {
@@ -137,7 +142,7 @@ export class IssueDetailComponent implements OnInit {
}
}
generateBackLink(projectId: number) {
generateBackLink(projectId: string) {
return {
...this.route.snapshot.queryParams,
project: projectId,
@@ -1,11 +1,9 @@
import { HttpErrorResponse } from "@angular/common/http";
import { Injectable, computed, inject, resource, signal } from "@angular/core";
import { Router } from "@angular/router";
import { MatSnackBar } from "@angular/material/snack-bar";
import { EMPTY, lastValueFrom } from "rxjs";
import { catchError, filter, take, tap, withLatestFrom } from "rxjs/operators";
import { EMPTY } from "rxjs";
import { catchError, tap, withLatestFrom } from "rxjs/operators";
import {
IssueDetail,
IssueStatus,
ExceptionValueData,
Request,
@@ -28,23 +26,18 @@ import { client } from "src/app/api/api";
import { components } from "src/app/api/api-schema";
type EventDetail = components["schemas"]["IssueEventDetailSchema"];
type IssueDetail = components["schemas"]["IssueDetailSchema"];
interface IssueDetailState {
issue: IssueDetail | null;
issueLoading: boolean;
issueInitialLoadComplete: boolean;
tags: IssueTags[] | null;
isReversed: boolean;
showShowMore: boolean;
}
const initialState: IssueDetailState = {
issue: null,
tags: null,
isReversed: true,
showShowMore: false,
issueLoading: false,
issueInitialLoadComplete: false,
};
@Injectable({
@@ -56,9 +49,9 @@ export class IssueDetailService extends StatefulService<IssueDetailState> {
private snackBar = inject(MatSnackBar);
private router = inject(Router);
readonly issue = computed(() => this.state().issue);
readonly issueInitialLoadComplete = computed(
() => this.state().issueInitialLoadComplete,
readonly issue = computed(() => this.#issueResource.value());
readonly issueInitialLoadComplete = computed(() =>
this.#issueResource.hasValue(),
);
readonly event = computed(() => this.#eventResource.value());
readonly tags = computed(() => {
@@ -82,7 +75,7 @@ export class IssueDetailService extends StatefulService<IssueDetailState> {
const event = this.event();
if (event && event.nextEventID) {
return this.eventUrl(orgSlug, issue, event.nextEventID);
return this.eventUrl(orgSlug, issue!, event.nextEventID);
}
return null;
});
@@ -92,7 +85,7 @@ export class IssueDetailService extends StatefulService<IssueDetailState> {
const event = this.event();
if (event && event.previousEventID) {
return this.eventUrl(orgSlug, issue, event.previousEventID);
return this.eventUrl(orgSlug, issue!, event.previousEventID);
}
return null;
});
@@ -131,6 +124,18 @@ export class IssueDetailService extends StatefulService<IssueDetailState> {
issueID: "",
eventID: "",
});
#issueResource = resource({
params: () => ({ issueID: this.#params().issueID }),
loader: async ({ params }) => {
if (!params.issueID) {
return;
}
const { data } = await client.GET("/api/0/issues/{issue_id}/", {
params: { path: { issue_id: parseInt(params.issueID) } },
});
return data;
},
});
#eventResource = resource({
params: () => ({ params: this.#params() }),
loader: async ({ params }) => {
@@ -164,27 +169,6 @@ export class IssueDetailService extends StatefulService<IssueDetailState> {
super(initialState);
}
retrieveIssue(id: number) {
this.setState({ issueLoading: true });
return this.issuesAPIService.retrieve(id.toString()).pipe(
tap((issue) => this.setIssue(issue)),
catchError((error) => {
if (error instanceof HttpErrorResponse && error.status === 404) {
this.clearIssue();
}
return EMPTY;
}),
);
}
setIssue(issue: IssueDetail) {
this.setState({
issue,
issueLoading: false,
issueInitialLoadComplete: true,
});
}
setParams(issueID: string, eventID: string | null) {
this.#params.set({ issueID, eventID });
}
@@ -205,24 +189,24 @@ export class IssueDetailService extends StatefulService<IssueDetailState> {
this.setState({ showShowMore: value });
}
setStatus(status: IssueStatus) {
const issue = this.state().issue;
async setStatus(status: IssueStatus) {
const issue = this.issue();
if (issue) {
lastValueFrom(
this.organization.activeOrganizationSlug$.pipe(
filter((slug) => !!slug),
take(1),
tap((slug) => {
if (slug) {
lastValueFrom(
this.issuesAPIService
.update(status, slug, issue.id)
.pipe(tap((resp) => this.setIssueStatus(resp.status))),
);
}
}),
),
const { data } = await client.PUT(
"/api/0/organizations/{organization_slug}/issues/{issue_id}/",
{
params: {
path: {
organization_slug: this.organization.activeOrganizationSlug(),
issue_id: parseInt(this.#params().issueID),
},
},
body: { status: status as any },
},
);
if (data) {
this.setIssueStatus(data.status as IssueStatus);
}
}
}
@@ -287,31 +271,14 @@ export class IssueDetailService extends StatefulService<IssueDetailState> {
/** Set local state issue state */
private setIssueStatus(status: IssueStatus) {
const state = this.state();
if (state.issue) {
const issue = { ...state.issue, status };
this.setState({ issue });
}
}
private clearIssue() {
this.setState({
issue: null,
issueLoading: false,
issueInitialLoadComplete: true,
});
this.#issueResource.update((issue) => ({ ...issue!, status }));
}
private setUpdatedCommentCount(num: number) {
const state = this.state();
if (state.issue) {
this.setState({
issue: {
...state.issue,
numComments: state.issue.numComments + num,
},
});
}
this.#issueResource.update((issue) => ({
...issue!,
numComments: issue!.numComments + num,
}));
}
setTags(tags: IssueTags[]) {
@@ -15,7 +15,7 @@ export class SlugifyDirective {
return true;
}
@HostListener("paste", ["$event"]) blockPaste(event: KeyboardEvent) {
@HostListener("paste", ["$event"]) blockPaste(event: ClipboardEvent) {
this.validateFields();
}
-4
View File
@@ -1,4 +0,0 @@
export const environment = {
production: true,
billingEmail: "sales@glitchtip.com",
};
-1
View File
@@ -3,6 +3,5 @@
// The list of file replacements can be found in `angular.json`.
export const environment = {
production: false,
billingEmail: "sales@glitchtip.com",
};
+5 -18
View File
@@ -1,21 +1,14 @@
import {
enableProdMode,
ErrorHandler,
importProvidersFrom,
inject,
provideZonelessChangeDetection,
Provider,
} from "@angular/core";
import { loadTranslations } from "@angular/localize";
import { environment } from "./environments/environment";
import { AppComponent } from "./app/app.component";
import { MicroSentryModule } from "@micro-sentry/angular";
import {
MAT_SNACK_BAR_DEFAULT_OPTIONS,
MatSnackBarModule,
} from "@angular/material/snack-bar";
import { provideAnimationsAsync } from "@angular/platform-browser/animations/async";
import { provideMicroSentry } from "@micro-sentry/angular";
import { MAT_SNACK_BAR_DEFAULT_OPTIONS } from "@angular/material/snack-bar";
import { routes, TemplatePageTitleStrategy } from "./app/app.routes";
import { bootstrapApplication } from "@angular/platform-browser";
import { LessAnnoyingErrorStateMatcher } from "./app/shared/less-annoying-error-state-matcher";
@@ -50,10 +43,6 @@ if (window.Cypress) {
}
const serverErrorsRegex = new RegExp(`403 Forbidden|404 OK`, "mi");
if (environment.production) {
enableProdMode();
}
// First locale is default, add additional after it
const availableLocales = ["en", "fr", "nb"];
// Direct macrolanguages to specific ones. Example: Norwegian becomes Bokmål
@@ -108,10 +97,9 @@ const bootstrap = () =>
}),
),
provideMarkdown(),
importProvidersFrom(
MatSnackBarModule,
MicroSentryModule.forRoot({ ignoreErrors: [serverErrorsRegex] }),
),
provideMicroSentry({
ignoreErrors: [serverErrorsRegex],
}),
{
provide: MAT_SNACK_BAR_DEFAULT_OPTIONS,
useValue: { duration: snackBarDuration },
@@ -122,7 +110,6 @@ const bootstrap = () =>
provide: ErrorStateMatcher,
useClass: LessAnnoyingErrorStateMatcher,
},
provideAnimationsAsync(),
provideHttpClient(
withFetch(),
withXsrfConfiguration({
+2 -6
View File
@@ -4,12 +4,8 @@
"outDir": "./out-tsc/app",
"types": []
},
"files": [
"src/main.ts",
],
"include": [
"src/**/*.d.ts"
],
"files": ["src/main.ts"],
"include": ["src/**/*.d.ts"],
"exclude": [
"src/test.ts",
"src/**/*.spec.ts",
+5 -4
View File
@@ -9,7 +9,7 @@
"declaration": false,
"experimentalDecorators": true,
"forceConsistentCasingInFileNames": true,
"module": "ES2022",
"module": "preserve",
"moduleResolution": "bundler",
"noUnusedLocals": true,
"noImplicitReturns": true,
@@ -25,8 +25,9 @@
},
"angularCompilerOptions": {
"enableI18nLegacyMessageIdFormat": false,
"fullTemplateTypeCheck": true,
"strictTemplates": true,
"strictInjectionParameters": true
"strictInjectionParameters": true,
"strictInputAccessModifiers": true,
"typeCheckHostBindings": true,
"strictTemplates": true
}
}