Update Angular to v15 (#11778)

* Update angular to v15

Also bumps fullcalendar to v6-beta to be compatible

Bump fullcalendar to v6 final

* Fix accessing readOnly property that no longer exists

* Replace content projection

* Fix confusing duplicate variables scss, sass file

One can be imported by helpers, the other not
pull/11873/head
Oliver Günther 2 years ago committed by GitHub
parent cb60af9055
commit 39360ebde2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 5
      frontend/angular.json
  2. 7303
      frontend/package-lock.json
  3. 53
      frontend/package.json
  4. 3
      frontend/src/app/features/calendar/op-work-packages-calendar.service.ts
  5. 18
      frontend/src/app/features/calendar/wp-calendar/wp-calendar.component.ts
  6. 123
      frontend/src/app/features/team-planner/team-planner/planner/team-planner.component.html
  7. 31
      frontend/src/app/features/team-planner/team-planner/planner/team-planner.component.ts
  8. 2
      frontend/src/app/features/work-packages/routing/wp-view-base/view-services/wp-view-highlighting.service.ts
  9. 2
      frontend/src/app/features/work-packages/routing/wp-view-base/view-services/wp-view-order.service.ts
  10. 17
      frontend/src/app/shared/components/dynamic-forms/components/dynamic-inputs/formattable-textarea-input/components/formattable-control/formattable-control.component.ts
  11. 4
      frontend/src/app/shared/components/editor/components/ckeditor/ckeditor.types.ts
  12. 2
      frontend/src/app/shared/components/grids/openproject-grids.module.ts
  13. 2
      frontend/src/app/shared/components/modal/modal-banner/modal-banner.component.sass
  14. 6
      frontend/src/assets/sass/_helpers.sass
  15. 3
      frontend/src/global_styles/openproject/_variable_defaults.scss
  16. 4
      frontend/src/global_styles/openproject/_variables.sass
  17. 2
      frontend/src/styles.scss
  18. 7
      frontend/src/test.ts

@ -45,11 +45,6 @@
"node_modules/jquery-ui/themes/base/core.css", "node_modules/jquery-ui/themes/base/core.css",
"node_modules/jquery-ui/themes/base/datepicker.css", "node_modules/jquery-ui/themes/base/datepicker.css",
"node_modules/jquery-ui/themes/base/dialog.css", "node_modules/jquery-ui/themes/base/dialog.css",
"node_modules/@fullcalendar/common/main.css",
"node_modules/@fullcalendar/daygrid/main.css",
"node_modules/@fullcalendar/timegrid/main.css",
"node_modules/@fullcalendar/timeline/main.css",
"node_modules/@fullcalendar/resource-timeline/main.css",
"node_modules/flatpickr/dist/flatpickr.min.css" "node_modules/flatpickr/dist/flatpickr.min.css"
], ],
"stylePreprocessorOptions": { "stylePreprocessorOptions": {

File diff suppressed because it is too large Load Diff

@ -5,13 +5,13 @@
"version": "0.1.0", "version": "0.1.0",
"private": true, "private": true,
"devDependencies": { "devDependencies": {
"@angular-devkit/build-angular": "^14.2.5", "@angular-devkit/build-angular": "^15.0.2",
"@angular-eslint/builder": "^13.2.1", "@angular-eslint/builder": "^15.1.0",
"@angular-eslint/eslint-plugin": "^13.2.1", "@angular-eslint/eslint-plugin": "^13.2.1",
"@angular-eslint/eslint-plugin-template": "^13.2.1", "@angular-eslint/eslint-plugin-template": "^13.2.1",
"@angular-eslint/schematics": "13.2.1", "@angular-eslint/schematics": "13.2.1",
"@angular-eslint/template-parser": "^13.2.1", "@angular-eslint/template-parser": "^13.2.1",
"@angular/language-service": "14.0.2", "@angular/language-service": "15.0.2",
"@babel/core": "^7.18.5", "@babel/core": "^7.18.5",
"@compodoc/compodoc": "^1.1.19", "@compodoc/compodoc": "^1.1.19",
"@html-eslint/eslint-plugin": "^0.13.1", "@html-eslint/eslint-plugin": "^0.13.1",
@ -47,7 +47,7 @@
"@typescript-eslint/eslint-plugin": "4.23.0", "@typescript-eslint/eslint-plugin": "4.23.0",
"@typescript-eslint/parser": "4.23.0", "@typescript-eslint/parser": "4.23.0",
"babel-loader": "^8.2.5", "babel-loader": "^8.2.5",
"browserslist": "^4.9.1", "browserslist": "^4.8.7",
"codelyzer": "^6.0.0", "codelyzer": "^6.0.0",
"css-loader": "^6.7.1", "css-loader": "^6.7.1",
"eslint": "^7.26.0", "eslint": "^7.26.0",
@ -79,41 +79,42 @@
"style-loader": "^3.3.1", "style-loader": "^3.3.1",
"theo": "^8.1.5", "theo": "^8.1.5",
"ts-node": "~8.3.0", "ts-node": "~8.3.0",
"typescript": "~4.7.4", "typescript": "4.8",
"webpack-bundle-analyzer": "^4.4.2" "webpack-bundle-analyzer": "^4.4.2"
}, },
"dependencies": { "dependencies": {
"@angular/animations": "^14.2.5", "@angular/animations": "^15.0.2",
"@angular/cdk": "^14.2.4", "@angular/cdk": "^15.0.1",
"@angular/cli": "^14.2.5", "@angular/cli": "^15.0.2",
"@angular/common": "^14.2.5", "@angular/common": "^15.0.2",
"@angular/compiler": "^14.2.5", "@angular/compiler": "^15.0.2",
"@angular/compiler-cli": "^14.2.5", "@angular/compiler-cli": "^15.0.2",
"@angular/core": "^14.2.5", "@angular/core": "^15.0.2",
"@angular/forms": "^14.2.5", "@angular/forms": "^15.0.2",
"@angular/platform-browser": "^14.2.5", "@angular/platform-browser": "^15.0.2",
"@angular/platform-browser-dynamic": "^14.2.5", "@angular/platform-browser-dynamic": "^15.0.2",
"@angular/router": "^14.2.5", "@angular/router": "^15.0.2",
"@appsignal/javascript": "^1.3.23", "@appsignal/javascript": "^1.3.23",
"@appsignal/plugin-breadcrumbs-console": "^1.1.24", "@appsignal/plugin-breadcrumbs-console": "^1.1.24",
"@appsignal/plugin-breadcrumbs-network": "^1.1.21", "@appsignal/plugin-breadcrumbs-network": "^1.1.21",
"@datorama/akita": "^6.2.0", "@datorama/akita": "^6.2.0",
"@fullcalendar/angular": "5.10.1", "@fullcalendar/angular": "^6.0.2",
"@fullcalendar/common": "^5.10.1", "@fullcalendar/common": "^6.0.0-beta.1",
"@fullcalendar/core": "5.10.1", "@fullcalendar/core": "^6.0.2",
"@fullcalendar/daygrid": "5.10.1", "@fullcalendar/daygrid": "^6.0.2",
"@fullcalendar/interaction": "5.10.1", "@fullcalendar/interaction": "^6.0.2",
"@fullcalendar/resource-common": "^5.10.1", "@fullcalendar/resource": "^6.0.2",
"@fullcalendar/resource-timeline": "5.10.1", "@fullcalendar/resource-common": "^6.0.0-beta.1",
"@fullcalendar/timegrid": "5.10.1", "@fullcalendar/resource-timeline": "^6.0.2",
"@fullcalendar/timegrid": "^6.0.2",
"@kolkov/ngx-gallery": "^1.0.11", "@kolkov/ngx-gallery": "^1.0.11",
"@ng-select/ng-option-highlight": "0.0.5", "@ng-select/ng-option-highlight": "0.0.5",
"@ng-select/ng-select": "^4.0.4", "@ng-select/ng-select": "^4.0.4",
"@ngneat/content-loader": "^6.1.0", "@ngneat/content-loader": "^6.1.0",
"@ngx-formly/core": "^5.10.19", "@ngx-formly/core": "^5.10.19",
"@uirouter/angular": "^9.1.0", "@uirouter/angular": "^10.0.0",
"@uirouter/core": "^6.0.8", "@uirouter/core": "^6.0.8",
"@uirouter/rx": "^0.6.5", "@uirouter/rx": "^1.0.0",
"@w11k/ngx-componentdestroyed": "^5.0.2", "@w11k/ngx-componentdestroyed": "^5.0.2",
"@xeokit/xeokit-bim-viewer": "2.3.10", "@xeokit/xeokit-bim-viewer": "2.3.10",
"autoprefixer": "^9.6.1", "autoprefixer": "^9.6.1",

@ -409,7 +409,8 @@ export class OpWorkPackagesCalendarService extends UntilDestroyedMixin {
'.', '.',
{ {
cdate: this.timezoneService.formattedISODate(dates.view.currentStart), cdate: this.timezoneService.formattedISODate(dates.view.currentStart),
cview: dates.view.type, // v6.beta3 fails to have type on the ViewAPI
cview: (dates.view as unknown as { type:string }).type,
}, },
{ {
custom: { notify: false }, custom: { notify: false },

@ -37,10 +37,12 @@ import {
import { import {
CalendarOptions, CalendarOptions,
DateSelectArg, DateSelectArg,
EventClickArg,
EventDropArg, EventDropArg,
EventInput, EventInput,
ToolbarInput,
} from '@fullcalendar/core'; } from '@fullcalendar/core';
import { EventClickArg, FullCalendarComponent, ToolbarInput } from '@fullcalendar/angular'; import { FullCalendarComponent } from '@fullcalendar/angular';
import dayGridPlugin from '@fullcalendar/daygrid'; import dayGridPlugin from '@fullcalendar/daygrid';
import * as moment from 'moment'; import * as moment from 'moment';
import { Subject } from 'rxjs'; import { Subject } from 'rxjs';
@ -50,9 +52,7 @@ import { States } from 'core-app/core/states/states.service';
import { IsolatedQuerySpace } from 'core-app/features/work-packages/directives/query-space/isolated-query-space'; import { IsolatedQuerySpace } from 'core-app/features/work-packages/directives/query-space/isolated-query-space';
import { WorkPackageResource } from 'core-app/features/hal/resources/work-package-resource'; import { WorkPackageResource } from 'core-app/features/hal/resources/work-package-resource';
import { WorkPackageCollectionResource } from 'core-app/features/hal/resources/wp-collection-resource'; import { WorkPackageCollectionResource } from 'core-app/features/hal/resources/wp-collection-resource';
import { import { WorkPackageViewFiltersService } from 'core-app/features/work-packages/routing/wp-view-base/view-services/wp-view-filters.service';
WorkPackageViewFiltersService,
} from 'core-app/features/work-packages/routing/wp-view-base/view-services/wp-view-filters.service';
import { WorkPackagesListService } from 'core-app/features/work-packages/components/wp-list/wp-list.service'; import { WorkPackagesListService } from 'core-app/features/work-packages/components/wp-list/wp-list.service';
import { StateService } from '@uirouter/core'; import { StateService } from '@uirouter/core';
import { I18nService } from 'core-app/core/i18n/i18n.service'; import { I18nService } from 'core-app/core/i18n/i18n.service';
@ -62,10 +62,12 @@ import { ConfigurationService } from 'core-app/core/config/configuration.service
import { UntilDestroyedMixin } from 'core-app/shared/helpers/angular/until-destroyed.mixin'; import { UntilDestroyedMixin } from 'core-app/shared/helpers/angular/until-destroyed.mixin';
import { SchemaCacheService } from 'core-app/core/schemas/schema-cache.service'; import { SchemaCacheService } from 'core-app/core/schemas/schema-cache.service';
import { CurrentProjectService } from 'core-app/core/current-project/current-project.service'; import { CurrentProjectService } from 'core-app/core/current-project/current-project.service';
import interactionPlugin, { EventDragStartArg, EventDragStopArg, EventResizeDoneArg } from '@fullcalendar/interaction'; import interactionPlugin, {
import { EventDragStartArg,
HalResourceEditingService, EventDragStopArg,
} from 'core-app/shared/components/fields/edit/services/hal-resource-editing.service'; EventResizeDoneArg,
} from '@fullcalendar/interaction';
import { HalResourceEditingService } from 'core-app/shared/components/fields/edit/services/hal-resource-editing.service';
import { HalResourceNotificationService } from 'core-app/features/hal/services/hal-resource-notification.service'; import { HalResourceNotificationService } from 'core-app/features/hal/services/hal-resource-notification.service';
import { splitViewRoute } from 'core-app/features/work-packages/routing/split-view-routes.helper'; import { splitViewRoute } from 'core-app/features/work-packages/routing/split-view-routes.helper';
import { import {

@ -55,7 +55,68 @@
[options]="calendarOptions" [options]="calendarOptions"
class="op-team-planner--calendar fc-scroller" class="op-team-planner--calendar fc-scroller"
[ngClass]="{'op-team-planner--calendar_empty': (isEmpty$ | async)}" [ngClass]="{'op-team-planner--calendar_empty': (isEmpty$ | async)}"
></full-calendar> >
<ng-template #resourceLabelContent let-resource="$implicit.resource">
<div
*ngIf="resource && resource.extendedProps.principal"
class="tp-assignee"
>
<op-principal
[principal]="resource.extendedProps.principal"
class="tp-assignee--principal op-principal_wrapped"
[hideName]="isMobile"
></op-principal>
<button
type="button"
class="tp-assignee--remove"
(click)="removeAssignee(resource.id)"
[attr.aria-label]="text.remove_assignee"
[attr.data-qa-remove-assignee]="resource.extendedProps.principal.id"
>
<op-icon icon-classes="icon-remove"></op-icon>
</button>
</div>
<op-principal-loading-skeleton
*ngIf="resource && !resource.extendedProps.principal && resource.id.startsWith('skeleton')"
></op-principal-loading-skeleton>
<op-tp-add-assignee
*ngIf="resource && !resource.extendedProps.principal && !resource.id.startsWith('skeleton')"
(selectAssignee)="addAssignee($event)"
[alreadySelected]="principalIds$ | async"
></op-tp-add-assignee>
</ng-template>
<ng-template #eventContent let-event="$implicit.event">
<op-wp-loading-skeleton
[viewBox]="event.extendedProps.viewBox"
class="op-team-planner--wp-loading-skeleton"
*ngIf="event.source && event.source.id === 'skeleton'"
></op-wp-loading-skeleton>
<wp-single-card
*ngIf="(!event.source || event.source.id === 'work_packages') && event.extendedProps.workPackage as wp"
[workPackage]="wp"
[selectedWhenOpen]="true"
[orientation]="'horizontal'"
[highlightingMode]="'type'"
[showInfoButton]="true"
[disabledInfo]="showDisabledText(wp)"
[isClosed]="isStatusClosed(wp)"
[showAsGhost]="shouldShowAsGhost(wp.id, (globalDraggingItem$ | async))"
[showAsInlineCard]="true"
[showStartDate]="!isWpStartDateInCurrentView(wp)"
[showEndDate]="!isWpEndDateInCurrentView(wp)"
(stateLinkClicked)="openStateLink($event)"
(cardClicked)="workPackagesCalendar.onCardClicked($event)"
(cardDblClicked)="workPackagesCalendar.onCardDblClicked($event)"
(cardContextMenu)="workPackagesCalendar.showEventContextMenu($event)"
></wp-single-card>
</ng-template>
</full-calendar>
<div <div
[textContent]="workPackagesCalendar.tooManyResultsText" [textContent]="workPackagesCalendar.tooManyResultsText"
@ -78,66 +139,6 @@
</div> </div>
</ng-container> </ng-container>
<ng-template #resourceContent let-resource="resource">
<div
*ngIf="resource && resource.extendedProps.principal"
class="tp-assignee"
>
<op-principal
[principal]="resource.extendedProps.principal"
class="tp-assignee--principal op-principal_wrapped"
[hideName]="isMobile"
></op-principal>
<button
type="button"
class="tp-assignee--remove"
(click)="removeAssignee(resource.id)"
[attr.aria-label]="text.remove_assignee"
[attr.data-qa-remove-assignee]="resource.extendedProps.principal.id"
>
<op-icon icon-classes="icon-remove"></op-icon>
</button>
</div>
<op-principal-loading-skeleton
*ngIf="resource && !resource.extendedProps.principal && resource.id.startsWith('skeleton')"
></op-principal-loading-skeleton>
<op-tp-add-assignee
*ngIf="resource && !resource.extendedProps.principal && !resource.id.startsWith('skeleton')"
(selectAssignee)="addAssignee($event)"
[alreadySelected]="principalIds$ | async"
></op-tp-add-assignee>
</ng-template>
<ng-template #eventContent let-event="event">
<op-wp-loading-skeleton
[viewBox]="event.extendedProps.viewBox"
class="op-team-planner--wp-loading-skeleton"
*ngIf="event.source && event.source.id === 'skeleton'"
></op-wp-loading-skeleton>
<wp-single-card
*ngIf="(!event.source || event.source.id === 'work_packages') && event.extendedProps.workPackage as wp"
[workPackage]="wp"
[selectedWhenOpen]="true"
[orientation]="'horizontal'"
[highlightingMode]="'type'"
[showInfoButton]="true"
[disabledInfo]="showDisabledText(wp)"
[isClosed]="isStatusClosed(wp)"
[showAsGhost]="shouldShowAsGhost(wp.id, (globalDraggingItem$ | async))"
[showAsInlineCard]="true"
[showStartDate]="!isWpStartDateInCurrentView(wp)"
[showEndDate]="!isWpEndDateInCurrentView(wp)"
(stateLinkClicked)="openStateLink($event)"
(cardClicked)="workPackagesCalendar.onCardClicked($event)"
(cardDblClicked)="workPackagesCalendar.onCardDblClicked($event)"
(cardContextMenu)="workPackagesCalendar.showEventContextMenu($event)"
></wp-single-card>
</ng-template>
<div class="op-team-planner--footer" data-qa-selector="op-team-planner-footer"> <div class="op-team-planner--footer" data-qa-selector="op-team-planner-footer">
<div <div
class="op-team-planner--add-assignee" class="op-team-planner--add-assignee"

@ -44,8 +44,6 @@ import {
EventContentArg, EventContentArg,
EventDropArg, EventDropArg,
EventInput, EventInput,
RawOptionsFromRefiners,
ViewOptionRefiners,
} from '@fullcalendar/core'; } from '@fullcalendar/core';
import { import {
BehaviorSubject, BehaviorSubject,
@ -118,8 +116,11 @@ import { LoadingIndicatorService } from 'core-app/core/loading-indicator/loading
import { OpWorkPackagesCalendarService } from 'core-app/features/calendar/op-work-packages-calendar.service'; import { OpWorkPackagesCalendarService } from 'core-app/features/calendar/op-work-packages-calendar.service';
import { DeviceService } from 'core-app/core/browser/device.service'; import { DeviceService } from 'core-app/core/browser/device.service';
import { WeekdayService } from 'core-app/core/days/weekday.service'; import { WeekdayService } from 'core-app/core/days/weekday.service';
import { RawOptionsFromRefiners } from '@fullcalendar/core/internal';
import { ViewOptionRefiners } from '@fullcalendar/common';
import { ResourceApi } from '@fullcalendar/resource';
export type TeamPlannerViewOptionKey = 'resourceTimelineWorkWeek' | 'resourceTimelineWeek' | 'resourceTimelineTwoWeeks'; export type TeamPlannerViewOptionKey = 'resourceTimelineWorkWeek'|'resourceTimelineWeek'|'resourceTimelineTwoWeeks';
export type TeamPlannerViewOptions = { [K in TeamPlannerViewOptionKey]:RawOptionsFromRefiners<Required<ViewOptionRefiners>> }; export type TeamPlannerViewOptions = { [K in TeamPlannerViewOptionKey]:RawOptionsFromRefiners<Required<ViewOptionRefiners>> };
@Component({ @Component({
@ -139,8 +140,6 @@ export class TeamPlannerComponent extends UntilDestroyedMixin implements OnInit,
this.calendar.resizeObserver(v); this.calendar.resizeObserver(v);
} }
@ViewChild('eventContent') eventContent:TemplateRef<unknown>;
@ViewChild('resourceContent') resourceContent:TemplateRef<unknown>; @ViewChild('resourceContent') resourceContent:TemplateRef<unknown>;
@ViewChild('assigneeAutocompleter') assigneeAutocompleter:TemplateRef<unknown>; @ViewChild('assigneeAutocompleter') assigneeAutocompleter:TemplateRef<unknown>;
@ -430,7 +429,7 @@ export class TeamPlannerComponent extends UntilDestroyedMixin implements OnInit,
const api = this.ucCalendar.getApi(); const api = this.ucCalendar.getApi();
// This also removes the skeleton resources that are rendered initially // This also removes the skeleton resources that are rendered initially
api.getResources().forEach((resource) => resource.remove()); api.getResources().forEach((resource:ResourceApi) => resource.remove());
principals.forEach((principal) => { principals.forEach((principal) => {
const id = principal._links.self.href; const id = principal._links.self.href;
@ -522,8 +521,6 @@ export class TeamPlannerComponent extends UntilDestroyedMixin implements OnInit,
resources: skeletonResources, resources: skeletonResources,
resourceAreaWidth: this.isMobile ? '60px' : '180px', resourceAreaWidth: this.isMobile ? '60px' : '180px',
select: this.handleDateClicked.bind(this) as unknown, select: this.handleDateClicked.bind(this) as unknown,
resourceLabelContent: (data:ResourceLabelContentArg) => this.renderTemplate(this.resourceContent, data.resource.id, data),
resourceLabelWillUnmount: (data:ResourceLabelContentArg) => this.unrenderTemplate(data.resource.id),
// DnD configuration // DnD configuration
editable: true, editable: true,
droppable: true, droppable: true,
@ -582,24 +579,6 @@ export class TeamPlannerComponent extends UntilDestroyedMixin implements OnInit,
await this.updateEvent(dropInfo, true); await this.updateEvent(dropInfo, true);
this.actions$.dispatch(teamPlannerEventAdded({ workPackage: wp.id as string })); this.actions$.dispatch(teamPlannerEventAdded({ workPackage: wp.id as string }));
}, },
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
eventContent: (data:EventContentArg):{ domNodes:unknown[] }|undefined => {
// Let FC handle the background events
if (data.event.source?.id === 'background') {
return undefined;
}
return this.renderTemplate(this.eventContent, this.eventId(data), data);
},
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
eventWillUnmount: (data:EventContentArg) => {
// Nothing to do for background events
if (data.event.source?.id === 'background') {
return;
}
this.unrenderTemplate(this.eventId(data));
},
} as CalendarOptions), } as CalendarOptions),
); );
}); });

@ -33,7 +33,7 @@ export class WorkPackageViewHighlightingService extends WorkPackageQueryStateSer
} }
// 2. Is selected attributes === undefined or empty Array? // 2. Is selected attributes === undefined or empty Array?
if (this.current.selectedAttributes === undefined || this.current.selectedAttributes === []) { if (this.current.selectedAttributes?.length === 0) {
return true; return true;
} }

@ -169,7 +169,7 @@ export class WorkPackageViewOrderService extends WorkPackageQueryStateService<Qu
const { value } = this.positions; const { value } = this.positions;
// Remove empty or stale values given we can reload them // Remove empty or stale values given we can reload them
if ((value === {} || this.positions.isValueOlderThan(60000))) { if ((_.isEmpty(value) || this.positions.isValueOlderThan(60000))) {
this.positions.clear('Clearing old positions value'); this.positions.clear('Clearing old positions value');
} }

@ -77,7 +77,8 @@ export class FormattableControlComponent implements ControlValueAccessor, OnInit
setDisabledState(disabled:boolean):void { setDisabledState(disabled:boolean):void {
this.disabled = disabled; this.disabled = disabled;
this.editor.ckEditorInstance.isReadOnly = disabled;
this.syncCKEditorReadonlyMode();
} }
onContentChange(value:string) { onContentChange(value:string) {
@ -87,7 +88,21 @@ export class FormattableControlComponent implements ControlValueAccessor, OnInit
this.onChange(valueToEmit); this.onChange(valueToEmit);
} }
syncCKEditorReadonlyMode() {
const { ckEditorInstance } = this.editor;
if (!ckEditorInstance) {
return;
}
if (this.disabled) {
ckEditorInstance.enableReadOnlyMode('formattable-control');
} else {
ckEditorInstance.disableReadOnlyMode('formattable-control');
}
}
onCkeditorSetup(_editor:ICKEditorInstance) { onCkeditorSetup(_editor:ICKEditorInstance) {
this.syncCKEditorReadonlyMode();
this.editor.ckEditorInstance.ui.focusTracker.on( this.editor.ckEditorInstance.ui.focusTracker.on(
'change:isFocused', 'change:isFocused',
(evt:unknown, name:unknown, isFocused:unknown) => { (evt:unknown, name:unknown, isFocused:unknown) => {

@ -11,6 +11,9 @@ export interface ICKEditorInstance {
destroy():void; destroy():void;
enableReadOnlyMode(lockId:string):void;
disableReadOnlyMode(lockId:string):void;
on(event:string, callback:() => unknown):void; on(event:string, callback:() => unknown):void;
model:any; model:any;
@ -18,7 +21,6 @@ export interface ICKEditorInstance {
config:any; config:any;
ui:any; ui:any;
element:HTMLElement; element:HTMLElement;
isReadOnly:boolean;
} }
export interface ICKEditorStatic { export interface ICKEditorStatic {

@ -32,7 +32,6 @@ import { HookService } from 'core-app/features/plugins/hook-service';
import { OPSharedModule } from 'core-app/shared/shared.module'; import { OPSharedModule } from 'core-app/shared/shared.module';
import { OpenprojectModalModule } from 'core-app/shared/components/modal/modal.module'; import { OpenprojectModalModule } from 'core-app/shared/components/modal/modal.module';
import { OpenprojectCalendarModule } from 'core-app/features/calendar/openproject-calendar.module'; import { OpenprojectCalendarModule } from 'core-app/features/calendar/openproject-calendar.module';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms'; import { FormsModule } from '@angular/forms';
import { DragDropModule } from '@angular/cdk/drag-drop'; import { DragDropModule } from '@angular/cdk/drag-drop';
import { OpenprojectWorkPackagesModule } from 'core-app/features/work-packages/openproject-work-packages.module'; import { OpenprojectWorkPackagesModule } from 'core-app/features/work-packages/openproject-work-packages.module';
@ -70,7 +69,6 @@ import { TimeEntriesCurrentUserConfigurationModalComponent } from './widgets/tim
@NgModule({ @NgModule({
imports: [ imports: [
BrowserModule,
FormsModule, FormsModule,
DragDropModule, DragDropModule,

@ -1,4 +1,4 @@
@import '~app/spot/styles/sass/variables' @import 'helpers'
.op-modal-banner .op-modal-banner
display: grid display: grid

@ -3,7 +3,7 @@
* as all CSS output will be duplicated in EVERY component * as all CSS output will be duplicated in EVERY component
* importing these helpers! * importing these helpers!
*/ */
@import "~global_styles/openproject/_mixins" @import "../../global_styles/openproject/_mixins"
@import "~global_styles/openproject/_variables" @import "../../global_styles/openproject/_variables"
@import "~global_styles/content/drag_and_drop" @import "../../global_styles/content/drag_and_drop"
@import "../../app/spot/styles/sass/variables" @import "../../app/spot/styles/sass/variables"

@ -226,6 +226,3 @@
--hamburger-width: 50px; --hamburger-width: 50px;
} }
// SCSS variables needed for foundation, but that are set in css variables now only
// which cannot be set to sass unfortunately
$secondary-color: #bfbfbf;

@ -1,2 +1,6 @@
// SCSS variables needed for foundation, but that are set in css variables now only
// which cannot be set to sass unfortunately
$secondary-color: #bfbfbf
// A selector that checks whether we are running in a test environment // A selector that checks whether we are running in a test environment
$spec-active-selector: '.env-test' $spec-active-selector: '.env-test'

@ -2,7 +2,7 @@
@import "~@ng-select/ng-select/themes/default.theme.css"; @import "~@ng-select/ng-select/themes/default.theme.css";
// Variables // Variables
@import "global_styles/openproject/_variables.scss"; @import "global_styles/openproject/_variable_defaults.scss";
// Foundation variables // Foundation variables
@import "global_styles/openproject/_settings.scss"; @import "global_styles/openproject/_settings.scss";

@ -17,8 +17,6 @@ import { I18nShim } from './test/i18n-shim';
(window as any).global = window; (window as any).global = window;
require('expose-loader?_!lodash'); require('expose-loader?_!lodash');
declare const require:any;
declare global { declare global {
export interface Window { export interface Window {
I18n:GlobalI18n; I18n:GlobalI18n;
@ -36,8 +34,3 @@ getTestBed().initTestEnvironment(
teardown: { destroyAfterEach: false }, teardown: { destroyAfterEach: false },
}, },
); );
// Then we find all the tests.
const context = require.context('./', true, /\.spec\.ts$/);
// And load the modules.
context.keys().map(context);

Loading…
Cancel
Save