Skip to content

Commit

Permalink
feat: gantt component support footer template #INFR-8626 (#394)
Browse files Browse the repository at this point in the history
* feat: gantt component support footer template #INFR-8626

* fix: fix sync scroll
  • Loading branch information
HandsomeButterball authored Jul 18, 2023
1 parent 1f5fdca commit c437b0c
Show file tree
Hide file tree
Showing 14 changed files with 208 additions and 39 deletions.
18 changes: 14 additions & 4 deletions example/src/app/configuration/parameters/api/zh-cn.js
Original file line number Diff line number Diff line change
Expand Up @@ -185,13 +185,13 @@ module.exports = [
type: 'TemplateRef<any>'
},
{
name: '#tableEmpty',
description: `设置空表格模板`,
name: '#toolbar',
description: `工具栏自定义模版`,
type: 'TemplateRef<any>'
},
{
name: '#toolbar',
description: `工具栏自定义模版`,
name: '#tableFooter',
description: `设置底部模板`,
type: 'TemplateRef<any>'
}
]
Expand Down Expand Up @@ -246,6 +246,16 @@ module.exports = [
name: '#rowAfterSlot',
description: `设置表格中每行的后置自定义渲染模板`,
type: 'TemplateRef<any>'
},
{
name: '#tableEmpty',
description: `设置空表格模板`,
type: 'TemplateRef<any>'
},
{
name: '#tableFooter',
description: `设置表格底部模板`,
type: 'TemplateRef<any>'
}
]
},
Expand Down
6 changes: 1 addition & 5 deletions example/src/app/gantt-custom-view/gantt.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ registerView(customViewType, GanttViewCustom);
selector: 'app-gantt-custom-view-example',
templateUrl: './gantt.component.html'
})
export class AppGanttCustomViewExampleComponent implements OnInit, AfterViewInit {
export class AppGanttCustomViewExampleComponent implements OnInit {
viewType = customViewType;

showWeekend = true;
Expand Down Expand Up @@ -78,10 +78,6 @@ export class AppGanttCustomViewExampleComponent implements OnInit, AfterViewInit

ngOnInit(): void {}

ngAfterViewInit() {
setTimeout(() => this.ganttComponent.scrollToDate(1627729997), 200);
}

barClick(event: GanttBarClickEvent) {
this.thyNotify.info('Event: barClick', `你点击了 [${event.item.title}]`);
}
Expand Down
38 changes: 32 additions & 6 deletions example/src/app/gantt-virtual-scroll/gantt.component.html
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
<div style="line-height: 30px; padding: 15px; display: flex">
<div style="flex: 1">
<span class="text-primary">NgxGantt</span>
默认开启了虚拟滚动功能,如需关闭该功能设置 virtualScrollEnabled 参数为 false 即可。
</div>
</div>
<thy-layout>
<thy-header class="header-with-baseline">
<ng-template #headerContent>
<span class="text-primary">NgxGantt</span>
&nbsp;&nbsp;默认开启了虚拟滚动功能,如需关闭该功能设置 virtualScrollEnabled 参数为 false 即可。
</ng-template>
</thy-header>
<thy-content>
<ngx-gantt #gantt [items]="items" [virtualScrollEnabled]="true">
<ngx-gantt-table>
Expand All @@ -21,11 +21,37 @@
{{ item.end * 1000 | date : 'yyyy-MM-dd' }}
</ng-template>
</ngx-gantt-column>

<ng-template #tableFooter let-columns="columns">
<div class="table-footer">
<div class="gantt-table-column" *ngFor="let column of columns; let i = index" [style.width]="column.columnWidth">
{{ column.name }}
</div>
</div>
</ng-template>
</ngx-gantt-table>

<ng-template #bar let-item="item">
<span style="color: #fff">&nbsp;&nbsp;{{ item.title }} </span>
</ng-template>

<ng-template #footer>
<div class="footer-container" [style.width.px]="gantt?.view.width">
<div
class="footer-item"
*ngFor="let day of gantt?.view.secondaryDatePoints"
[style.left.px]="day.x - gantt?.view.options.cellWidth / 2"
[style.width.px]="gantt?.view.options.cellWidth"
>
<ng-container *ngIf="false; else empty">
<div class="stat stat-fill"></div>
</ng-container>
<ng-template #empty>
<div class="stat stat-empty">0</div>
</ng-template>
</div>
</div>
</ng-template>
</ngx-gantt>
</thy-content>
</thy-layout>
6 changes: 1 addition & 5 deletions example/src/app/gantt-virtual-scroll/gantt.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { randomItems, random } from '../helper';
templateUrl: './gantt.component.html',
providers: [GanttPrintService]
})
export class AppGanttVirtualScrollExampleComponent implements OnInit, AfterViewInit {
export class AppGanttVirtualScrollExampleComponent implements OnInit {
items: GanttItem[] = randomItems(10000);

@HostBinding('class.gantt-example-component') class = true;
Expand All @@ -24,8 +24,4 @@ export class AppGanttVirtualScrollExampleComponent implements OnInit, AfterViewI
}
});
}

ngAfterViewInit() {
setTimeout(() => this.ganttComponent.scrollToDate(1627729997), 200);
}
}
3 changes: 0 additions & 3 deletions example/src/app/gantt/gantt.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,6 @@
<ng-template #bar let-item="item">
<span style="color: #fff">&nbsp;&nbsp;{{ item.title }} </span>
</ng-template>
<!-- <ng-template #toolbar>
<span>test</span>
</ng-template> -->
</ngx-gantt>
</thy-content>
</thy-layout>
1 change: 1 addition & 0 deletions example/src/app/gantt/gantt.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { randomItems, random } from '../helper';
@Component({
selector: 'app-gantt-example',
templateUrl: './gantt.component.html',
styleUrls: ['./gantt.scss'],
providers: [GanttPrintService]
})
export class AppGanttExampleComponent implements OnInit, AfterViewInit {
Expand Down
Empty file.
26 changes: 26 additions & 0 deletions example/src/styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,32 @@ $primary: #6698ff;
}
ngx-gantt-root {
border: 1px solid #eee;
.table-footer {
display: flex;
.gantt-table-column {
overflow: hidden;
border-right: 1px solid #eee;
box-sizing: border-box;
padding: 0 15px;
line-height: 44px;

&:last-child {
border-right: none;
}
}
}
.footer-container {
display: flex;
position: relative;
height: 100%;
.footer-item {
border-right: 1px solid #eee;
line-height: 44px;
&:last-child {
border-right: none;
}
}
}
}
}
}
49 changes: 38 additions & 11 deletions packages/gantt/src/gantt-dom.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,25 @@ export class GanttDomService implements OnDestroy {

public linksOverlay: Element;

private mainFooter: Element;

private mainScrollbar: Element;

private unsubscribe$ = new Subject<void>();

constructor(private ngZone: NgZone, @Inject(PLATFORM_ID) private platformId: string) {}

private monitorScrollChange() {
const scrollObservers = [
fromEvent(this.mainContainer, 'scroll', passiveListenerOptions),
fromEvent(this.sideContainer, 'scroll', passiveListenerOptions)
];

this.mainFooter && scrollObservers.push(fromEvent(this.mainFooter, 'scroll', passiveListenerOptions));
this.mainScrollbar && scrollObservers.push(fromEvent(this.mainScrollbar, 'scroll', passiveListenerOptions));

this.ngZone.runOutsideAngular(() =>
merge(
fromEvent(this.mainContainer, 'scroll', passiveListenerOptions),
fromEvent(this.sideContainer, 'scroll', passiveListenerOptions)
)
merge(...scrollObservers)
.pipe(takeUntil(this.unsubscribe$))
.subscribe((event) => {
this.syncScroll(event);
Expand All @@ -59,11 +68,22 @@ export class GanttDomService implements OnDestroy {

private syncScroll(event: Event) {
const target = event.currentTarget as HTMLElement;
this.calendarHeader.scrollLeft = this.mainContainer.scrollLeft;
this.calendarOverlay.scrollLeft = this.mainContainer.scrollLeft;

this.sideContainer.scrollTop = target.scrollTop;
this.mainContainer.scrollTop = target.scrollTop;
const classList = target.classList;

if (!classList.contains('gantt-side-container')) {
this.mainContainer.scrollLeft = target.scrollLeft;
this.calendarHeader.scrollLeft = target.scrollLeft;
this.calendarOverlay.scrollLeft = target.scrollLeft;
this.mainScrollbar && (this.mainScrollbar.scrollLeft = target.scrollLeft);
this.mainFooter && (this.mainFooter.scrollLeft = target.scrollLeft);
if (classList.contains('gantt-main-container')) {
this.sideContainer.scrollTop = target.scrollTop;
this.mainContainer.scrollTop = target.scrollTop;
}
} else {
this.sideContainer.scrollTop = target.scrollTop;
this.mainContainer.scrollTop = target.scrollTop;
}
}

private disableBrowserWheelEvent() {
Expand Down Expand Up @@ -92,10 +112,11 @@ export class GanttDomService implements OnDestroy {
this.container = this.root.getElementsByClassName('gantt-container')[0];
this.sideContainer = this.root.getElementsByClassName('gantt-side-container')[0];
this.mainContainer = this.root.getElementsByClassName('gantt-main-container')[0];
this.mainScrollbar = this.root.getElementsByClassName('gantt-main-scrollbar')[0];
this.mainFooter = this.root.getElementsByClassName('gantt-container-footer')[0];
this.verticalScrollContainer = this.root.getElementsByClassName('gantt-scroll-container')[0];
const mainItems = this.mainContainer.getElementsByClassName('gantt-main-items')[0];
const mainGroups = this.mainContainer.getElementsByClassName('gantt-main-groups')[0];

this.mainItems = mainItems || mainGroups;
this.calendarHeader = this.root.getElementsByClassName('gantt-calendar-header')[0];
this.calendarOverlay = this.root.getElementsByClassName('gantt-calendar-grid')[0];
Expand All @@ -109,9 +130,13 @@ export class GanttDomService implements OnDestroy {
* to run the change detection if needed.
*/
getViewerScroll(options?: AddEventListenerOptions): Observable<ScrollEvent> {
const scrollObservers = [fromEvent(this.mainContainer, 'scroll', options)];
this.mainFooter && scrollObservers.push(fromEvent(this.mainFooter, 'scroll', options));
this.mainScrollbar && scrollObservers.push(fromEvent(this.mainScrollbar, 'scroll', options));

return new Observable<ScrollEvent>((subscriber) =>
this.ngZone.runOutsideAngular(() =>
fromEvent(this.mainContainer, 'scroll', options)
merge(...scrollObservers)
.pipe(
map(() => this.mainContainer.scrollLeft),
pairwise(),
Expand Down Expand Up @@ -151,6 +176,8 @@ export class GanttDomService implements OnDestroy {
this.mainContainer.scrollLeft = scrollLeft > scrollThreshold ? scrollLeft : 0;
this.calendarHeader.scrollLeft = this.mainContainer.scrollLeft;
this.calendarOverlay.scrollLeft = this.mainContainer.scrollLeft;
this.mainScrollbar && (this.mainScrollbar.scrollLeft = this.mainContainer.scrollLeft);
this.mainFooter && (this.mainFooter.scrollLeft = this.mainContainer.scrollLeft);
}
}

Expand Down
32 changes: 30 additions & 2 deletions packages/gantt/src/gantt.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@

<cdk-virtual-scroll-viewport
class="gantt-virtual-scroll-viewport"
[ngClass]="{ 'gantt-normal-viewport': !virtualScrollEnabled, 'gantt-scroll-container': virtualScrollEnabled }"
[ngClass]="{
'gantt-normal-viewport': !virtualScrollEnabled,
'gantt-scroll-container': virtualScrollEnabled,
'with-footer': table?.tableFooterTemplate || footerTemplate
}"
[itemSize]="styles.lineHeight"
[minBufferPx]="styles.lineHeight * 10"
[maxBufferPx]="styles.lineHeight * 20"
Expand All @@ -23,7 +27,7 @@
[viewportItems]="viewportItems"
[columns]="columns"
[groupTemplate]="groupTemplate"
[emptyTemplate]="tableEmptyTemplate"
[emptyTemplate]="table.tableEmptyTemplate || tableEmptyTemplate"
[rowBeforeTemplate]="table?.rowBeforeTemplate"
[rowAfterTemplate]="table?.rowAfterTemplate"
[draggable]="table.draggable"
Expand Down Expand Up @@ -59,4 +63,28 @@
</cdk-virtual-scroll-viewport>

<gantt-drag-backdrop [style.left.px]="tableHeader.tableWidth + 1"></gantt-drag-backdrop>

<div
class="gantt-scrollbar"
[style.height.px]="ganttRoot.horizontalScrollbarHeight + 1"
[style.right.px]="ganttRoot.verticalScrollbarWidth"
>
<div
[style.width.px]="tableHeader.tableWidth"
class="gantt-table-scrollbar"
[class.with-scrollbar]="ganttRoot.horizontalScrollbarHeight"
></div>
<div class="gantt-main-scrollbar">
<div class="h-100" [style.width.px]="view.width"></div>
</div>
</div>

<div class="gantt-footer" [style.right.px]="ganttRoot.verticalScrollbarWidth" [style.bottom.px]="ganttRoot.horizontalScrollbarHeight">
<div class="gantt-table-footer" [style.width.px]="tableHeader.tableWidth + 1" *ngIf="table?.tableFooterTemplate">
<ng-template [ngTemplateOutlet]="table?.tableFooterTemplate" [ngTemplateOutletContext]="{ columns: columns }"> </ng-template>
</div>
<div class="gantt-container-footer" *ngIf="footerTemplate">
<ng-template [ngTemplateOutlet]="footerTemplate"> </ng-template>
</div>
</div>
</ngx-gantt-root>
Loading

0 comments on commit c437b0c

Please sign in to comment.