• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

worktile / ngx-gantt / 30b6f0fd-8be6-4f56-81ac-1a22b8b3608e

17 Aug 2023 08:26AM UTC coverage: 72.137% (+0.6%) from 71.511%
30b6f0fd-8be6-4f56-81ac-1a22b8b3608e

push

circleci

web-flow
Merge pull request #414 from worktile/bumpAngular16

build: bump angular 16 #INFR-9186

342 of 593 branches covered (57.67%)

Branch coverage included in aggregate %.

1403 of 1826 relevant lines covered (76.83%)

862.3 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

60.98
/packages/gantt/src/root.component.ts
1
import {
2
    Component,
3
    OnInit,
4
    NgZone,
5
    ElementRef,
6
    Inject,
7
    ContentChild,
8
    TemplateRef,
9
    Input,
10
    Optional,
11
    OnDestroy,
12
    ViewChild,
13
    HostListener
14
} from '@angular/core';
15
import { GanttDomService, ScrollDirection } from './gantt-dom.service';
16
import { GanttDragContainer } from './gantt-drag-container';
17
import { take, takeUntil, startWith } from 'rxjs/operators';
18
import { from, Subject } from 'rxjs';
19
import { GanttUpper, GANTT_UPPER_TOKEN } from './gantt-upper';
20
import { GanttPrintService } from './gantt-print.service';
21
import { passiveListenerOptions } from './utils/passive-listeners';
22
import { GanttDragBackdropComponent } from './components/drag-backdrop/drag-backdrop.component';
23
import { GanttDate } from './utils/date';
24

25
@Component({
26
    selector: 'ngx-gantt-root',
27
    templateUrl: './root.component.html',
28
    providers: [GanttDomService, GanttDragContainer],
29
    host: {
30
        class: 'gantt'
31
    }
32
})
33
export class NgxGanttRootComponent implements OnInit, OnDestroy {
1✔
34
    @Input() sideWidth: number;
35

36
    @ContentChild('sideTemplate', { static: true }) sideTemplate: TemplateRef<any>;
37

38
    @ContentChild('mainTemplate', { static: true }) mainTemplate: TemplateRef<any>;
39

40
    /** The native `<gantt-drag-backdrop></gantt-drag-backdrop>` element. */
41
    @ViewChild(GanttDragBackdropComponent, { static: true, read: ElementRef }) backdrop: ElementRef<HTMLElement>;
42

43
    verticalScrollbarWidth = 0;
56✔
44

45
    horizontalScrollbarHeight = 0;
56✔
46

47
    private unsubscribe$ = new Subject<void>();
56✔
48

49
    private get view() {
50
        return this.ganttUpper.view;
57✔
51
    }
52

53
    @HostListener('window:resize')
54
    onWindowResize() {
55
        this.computeScrollBarOffset();
×
56
    }
57

58
    constructor(
59
        private elementRef: ElementRef<HTMLElement>,
56✔
60
        private ngZone: NgZone,
56✔
61
        private dom: GanttDomService,
56✔
62
        public dragContainer: GanttDragContainer,
56✔
63
        @Inject(GANTT_UPPER_TOKEN) public ganttUpper: GanttUpper,
56✔
64
        @Optional() private printService: GanttPrintService
56✔
65
    ) {
66
        this.ganttUpper.dragContainer = dragContainer;
56✔
67
    }
68

69
    ngOnInit() {
70
        // Note: the zone may be nooped through `BootstrapOptions` when bootstrapping the root module. This means
71
        // the `onStable` will never emit any value.
72
        const onStable$ = this.ngZone.isStable ? from(Promise.resolve()) : this.ngZone.onStable.pipe(take(1));
56!
73
        // Normally this isn't in the zone, but it can cause performance regressions for apps
74
        // using `zone-patch-rxjs` because it'll trigger a change detection when it unsubscribes.
75
        this.ngZone.runOutsideAngular(() => {
56✔
76
            onStable$.pipe(takeUntil(this.unsubscribe$)).subscribe(() => {
56✔
77
                this.dom.initialize(this.elementRef);
56✔
78

79
                if (this.printService) {
56✔
80
                    this.printService.register(this.elementRef);
33✔
81
                }
82
                this.setupScrollClass();
56✔
83
                this.setupResize();
56✔
84
                this.setupViewScroll();
56✔
85
                // 优化初始化时Scroll滚动体验问题,通过透明度解决,默认透明度为0,滚动结束后恢复
86
                this.elementRef.nativeElement.style.opacity = '1';
56✔
87
                this.ganttUpper.viewChange.pipe(startWith<null, null>(null), takeUntil(this.unsubscribe$)).subscribe(() => {
56✔
88
                    this.scrollToToday();
57✔
89
                });
90
                this.computeScrollBarOffset();
56✔
91
            });
92
        });
93
    }
94

95
    computeScrollBarOffset() {
96
        const ganttMainContainer = this.dom.mainContainer as HTMLElement;
56✔
97
        const ganttVerticalScrollContainer = this.dom.verticalScrollContainer as HTMLElement;
56✔
98

99
        let verticalScrollbarWidth = 0;
56✔
100
        if (ganttVerticalScrollContainer) {
56!
101
            verticalScrollbarWidth = ganttVerticalScrollContainer.offsetWidth - ganttVerticalScrollContainer.clientWidth;
56✔
102
        } else {
103
            verticalScrollbarWidth = ganttMainContainer?.offsetWidth - ganttMainContainer?.clientWidth;
×
104
        }
105
        const horizontalScrollbarHeight = ganttMainContainer?.offsetHeight - ganttMainContainer?.clientHeight;
56✔
106
        this.verticalScrollbarWidth = verticalScrollbarWidth;
56✔
107
        this.horizontalScrollbarHeight = horizontalScrollbarHeight;
56✔
108
    }
109

110
    ngOnDestroy(): void {
111
        this.unsubscribe$.next();
55✔
112
    }
113

114
    private setupViewScroll() {
115
        if (this.ganttUpper.disabledLoadOnScroll) {
56✔
116
            return;
7✔
117
        }
118
        this.dom
49✔
119
            .getViewerScroll(passiveListenerOptions)
120
            .pipe(takeUntil(this.unsubscribe$))
121
            .subscribe((event) => {
122
                if (event.direction === ScrollDirection.LEFT) {
×
123
                    const dates = this.view.addStartDate();
×
124
                    if (dates) {
×
125
                        event.target.scrollLeft += this.view.getDateRangeWidth(dates.start, dates.end);
×
126
                        if (this.ganttUpper.loadOnScroll.observers) {
×
127
                            this.ngZone.run(() =>
×
128
                                this.ganttUpper.loadOnScroll.emit({ start: dates.start.getUnixTime(), end: dates.end.getUnixTime() })
×
129
                            );
130
                        }
131
                    }
132
                }
133
                if (event.direction === ScrollDirection.RIGHT) {
×
134
                    const dates = this.view.addEndDate();
×
135
                    if (dates && this.ganttUpper.loadOnScroll.observers) {
×
136
                        this.ngZone.run(() =>
×
137
                            this.ganttUpper.loadOnScroll.emit({ start: dates.start.getUnixTime(), end: dates.end.getUnixTime() })
×
138
                        );
139
                    }
140
                }
141
            });
142
    }
143

144
    private setupResize() {
145
        this.dom
56✔
146
            .getResize()
147
            .pipe(takeUntil(this.unsubscribe$))
148
            .subscribe(() => {
149
                this.setupScrollClass();
×
150
            });
151
    }
152

153
    private setupScrollClass() {
154
        const mainContainer = this.dom.mainContainer as HTMLElement;
56✔
155
        const height = mainContainer.offsetHeight;
56✔
156
        const scrollHeight = mainContainer.scrollHeight;
56✔
157
        if (scrollHeight > height) {
56!
158
            this.elementRef.nativeElement.className = 'gantt gantt-scroll';
×
159
        } else {
160
            this.elementRef.nativeElement.className = 'gantt';
56✔
161
        }
162
    }
163

164
    public scrollToToday() {
165
        const x = this.view.getTodayXPoint();
57✔
166
        this.dom.scrollMainContainer(x);
57✔
167
    }
168

169
    public scrollToDate(date: number | GanttDate) {
170
        let x: number;
171
        if (typeof date === 'number') {
×
172
            x = this.view.getXPointByDate(new GanttDate(date));
×
173
        } else {
174
            x = this.view.getXPointByDate(date);
×
175
        }
176

177
        this.dom.scrollMainContainer(x);
×
178
    }
179
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc