Merge pull request #11934 from opf/44455-replace-weekdays-api-with-individual-nwd-days-api-in-gantt

dev
Oliver Günther 2 years ago committed by GitHub
commit b16b138a7f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 11
      frontend/src/app/core/state/days/day.service.ts
  2. 7
      frontend/src/app/features/work-packages/components/wp-table/timeline/cells/timeline-cell-renderer.ts
  3. 31
      frontend/src/app/features/work-packages/components/wp-table/timeline/container/wp-timeline-container.directive.ts
  4. 3
      frontend/src/app/features/work-packages/components/wp-table/timeline/grid/wp-timeline-grid.directive.ts
  5. 21
      spec/features/work_packages/timeline/timeline_dates_spec.rb

@ -57,6 +57,17 @@ export class DayResourceService extends ResourceCollectionService<IDay> {
return this.require({ filters }); return this.require({ filters });
} }
requireNonWorkingYears$(start:Date|string, end:Date|string):Observable<IDay[]> {
const from = moment(start).startOf('year').format('YYYY-MM-DD');
const to = moment(end).endOf('year').format('YYYY-MM-DD');
const filters:ApiV3ListFilter[] = [
['date', '<>d', [from, to]],
];
return this.require({ filters });
}
fetchCollection(params:ApiV3ListParameters):Observable<IHALCollection<IDay>> { fetchCollection(params:ApiV3ListParameters):Observable<IHALCollection<IDay>> {
const collectionURL = collectionKey(params); const collectionURL = collectionKey(params);

@ -321,7 +321,7 @@ export class TimelineCellRenderer {
break; break;
} }
// Extend the duration if the currentDate is non-working // Extend the duration if the currentDate is non-working
if (this.weekdayService.isNonWorkingDay(currentDate.toDate())) { if (this.weekdayService.isNonWorkingDay(currentDate.toDate() || this.workPackageTimeline.isNonWorkingDay(currentDate.toDate()))) {
duration += 1; duration += 1;
} }
} }
@ -472,10 +472,11 @@ export class TimelineCellRenderer {
const dates = (evOrDates instanceof MouseEvent) const dates = (evOrDates instanceof MouseEvent)
? [this.cursorDateAndDayOffset(evOrDates, renderInfo)[0]] ? [this.cursorDateAndDayOffset(evOrDates, renderInfo)[0]]
: evOrDates; : evOrDates;
if (!renderInfo.workPackage.ignoreNonWorkingDays && direction === 'both' && this.weekdayService.isNonWorkingDay(dates[dates.length - 1].toDate())) { if (!renderInfo.workPackage.ignoreNonWorkingDays && direction === 'both'
&& (this.weekdayService.isNonWorkingDay(dates[dates.length - 1].toDate() || this.workPackageTimeline.isNonWorkingDay(dates[dates.length - 1].toDate())))) {
return false; return false;
} }
return dates.some((date) => this.weekdayService.isNonWorkingDay(date.toDate())); return dates.some((date) => (this.weekdayService.isNonWorkingDay(date.toDate()) || this.workPackageTimeline.isNonWorkingDay(date.toDate())));
} }
/** /**

@ -34,7 +34,7 @@ import { IToast, ToastService } from 'core-app/shared/components/toaster/toast.s
import { WorkPackageResource } from 'core-app/features/hal/resources/work-package-resource'; import { WorkPackageResource } from 'core-app/features/hal/resources/work-package-resource';
import * as moment from 'moment'; import * as moment from 'moment';
import { Moment } from 'moment'; import { Moment } from 'moment';
import { filter, takeUntil } from 'rxjs/operators'; import { filter, takeUntil, take } from 'rxjs/operators';
import { input, InputState } from 'reactivestates'; import { input, InputState } from 'reactivestates';
import { WorkPackageTable } from 'core-app/features/work-packages/components/wp-fast-table/wp-fast-table'; import { WorkPackageTable } from 'core-app/features/work-packages/components/wp-fast-table/wp-fast-table';
import { WorkPackageTimelineCellsRenderer } from 'core-app/features/work-packages/components/wp-table/timeline/cells/wp-timeline-cells-renderer'; import { WorkPackageTimelineCellsRenderer } from 'core-app/features/work-packages/components/wp-table/timeline/cells/wp-timeline-cells-renderer';
@ -68,6 +68,8 @@ import {
} from '../wp-timeline'; } from '../wp-timeline';
import { WeekdayService } from 'core-app/core/days/weekday.service'; import { WeekdayService } from 'core-app/core/days/weekday.service';
import * as Mousetrap from 'mousetrap'; import * as Mousetrap from 'mousetrap';
import { DayResourceService } from 'core-app/core/state/days/day.service';
import { IDay } from 'core-app/core/state/days/day.model';
@Component({ @Component({
selector: 'wp-timeline-container', selector: 'wp-timeline-container',
@ -137,6 +139,7 @@ export class WorkPackageTimelineTableController extends UntilDestroyedMixin impl
readonly I18n:I18nService, readonly I18n:I18nService,
private workPackageViewCollapsedGroupsService:WorkPackageViewCollapsedGroupsService, private workPackageViewCollapsedGroupsService:WorkPackageViewCollapsedGroupsService,
private weekdaysService:WeekdayService, private weekdaysService:WeekdayService,
private daysService:DayResourceService,
) { ) {
super(); super();
} }
@ -144,6 +147,13 @@ export class WorkPackageTimelineTableController extends UntilDestroyedMixin impl
ngAfterViewInit() { ngAfterViewInit() {
this.$element = jQuery(this.elementRef.nativeElement); this.$element = jQuery(this.elementRef.nativeElement);
const scrollBar = document.querySelector('.work-packages-tabletimeline--timeline-side');
if (scrollBar) {
scrollBar.addEventListener('scroll', () => {
this.requireNonWorkingDays(this.getFirstDayInViewport().format('YYYY-MM-DD'), this.getLastDayInViewport().format('YYYY-MM-DD'));
});
}
this.text = { this.text = {
selectionMode: this.I18n.t('js.timelines.selection_mode.notification'), selectionMode: this.I18n.t('js.timelines.selection_mode.notification'),
}; };
@ -176,6 +186,8 @@ export class WorkPackageTimelineTableController extends UntilDestroyedMixin impl
this.setupManageCollapsedGroupHeaderCells(); this.setupManageCollapsedGroupHeaderCells();
} }
public nonWorkingDays:IDay[] = [];
workPackageCells(wpId:string):WorkPackageTimelineCell[] { workPackageCells(wpId:string):WorkPackageTimelineCell[] {
return this.cellsRenderer.getCellsFor(wpId); return this.cellsRenderer.getCellsFor(wpId);
} }
@ -225,12 +237,14 @@ export class WorkPackageTimelineTableController extends UntilDestroyedMixin impl
this.wpTableTimeline.appliedZoomLevel = this.wpTableTimeline.zoomLevel; this.wpTableTimeline.appliedZoomLevel = this.wpTableTimeline.zoomLevel;
} }
timeOutput('refreshView() in timeline container', () => { timeOutput('refreshView() in timeline container', async () => {
// Reset the width of the outer container if its content shrinks // Reset the width of the outer container if its content shrinks
this.outerContainer.css('width', 'auto'); this.outerContainer.css('width', 'auto');
this.calculateViewParams(this._viewParameters); this.calculateViewParams(this._viewParameters);
await this.requireNonWorkingDays(this.getFirstDayInViewport().format('YYYY-MM-DD'), this.getLastDayInViewport().format('YYYY-MM-DD'));
// Update all cells // Update all cells
this.cellsRenderer.refreshAllCells(); this.cellsRenderer.refreshAllCells();
@ -348,6 +362,19 @@ export class WorkPackageTimelineTableController extends UntilDestroyedMixin impl
this.refreshView(); this.refreshView();
} }
async requireNonWorkingDays(start:Date|string, end:Date|string) {
this.nonWorkingDays = await this
.daysService
.requireNonWorkingYears$(start, end)
.pipe(take(1))
.toPromise();
}
isNonWorkingDay(date:Date|string):boolean {
const formatted = moment(date).format('YYYY-MM-DD');
return (this.nonWorkingDays.findIndex((el) => el.date === formatted) !== -1);
}
private calculateViewParams(currentParams:TimelineViewParameters):boolean { private calculateViewParams(currentParams:TimelineViewParameters):boolean {
if (this.disableViewParamsCalculation) { if (this.disableViewParamsCalculation) {
return false; return false;

@ -187,8 +187,7 @@ export class WorkPackageTableTimelineGrid implements AfterViewInit {
private checkForNonWorkingDayHighlight(date:Moment, cell:HTMLElement) { private checkForNonWorkingDayHighlight(date:Moment, cell:HTMLElement) {
const day = date.toDate(); const day = date.toDate();
if (this.weekdaysService.isNonWorkingDay(day) || this.wpTimeline.isNonWorkingDay(day)) {
if (this.weekdaysService.isNonWorkingDay(day)) {
cell.classList.add('wp-timeline--non-working-day'); cell.classList.add('wp-timeline--non-working-day');
cell.dataset.qaSelector = `wp-timeline--non-working-day_${day.getDate()}-${day.getMonth() + 1}-${day.getFullYear()}`; cell.dataset.qaSelector = `wp-timeline--non-working-day_${day.getDate()}-${day.getMonth() + 1}-${day.getFullYear()}`;
} }

@ -125,14 +125,18 @@ RSpec.describe 'Work package timeline date formatting',
let(:current_user) { create :admin, language: 'en' } let(:current_user) { create :admin, language: 'en' }
shared_let(:week_days) { week_with_saturday_and_sunday_as_weekend } shared_let(:week_days) { week_with_saturday_and_sunday_as_weekend }
shared_let(:non_working_day) do
create(:non_working_day,
date: '28-12-2020')
end
it 'shows them as disabled' do it 'shows them as disabled' do
expect_date_week work_package.start_date.iso8601, '01' expect_date_week work_package.start_date.iso8601, '01'
expect(page).to have_selector('[data-qa-selector="wp-timeline--non-working-day_27-12-2020"]') expect(page).to have_selector('[data-qa-selector="wp-timeline--non-working-day_27-12-2020"]')
expect(page).to have_selector('[data-qa-selector="wp-timeline--non-working-day_2-1-2021"]') expect(page).to have_selector('[data-qa-selector="wp-timeline--non-working-day_2-1-2021"]')
expect(page).to have_selector('[data-qa-selector="wp-timeline--non-working-day_28-12-2020"]')
expect(page).to have_no_selector('[data-qa-selector="wp-timeline--non-working-day_28-12-2020"]')
expect(page).to have_no_selector('[data-qa-selector="wp-timeline--non-working-day_29-12-2020"]') expect(page).to have_no_selector('[data-qa-selector="wp-timeline--non-working-day_29-12-2020"]')
expect(page).to have_no_selector('[data-qa-selector="wp-timeline--non-working-day_30-12-2020"]') expect(page).to have_no_selector('[data-qa-selector="wp-timeline--non-working-day_30-12-2020"]')
expect(page).to have_no_selector('[data-qa-selector="wp-timeline--non-working-day_31-12-2020"]') expect(page).to have_no_selector('[data-qa-selector="wp-timeline--non-working-day_31-12-2020"]')
@ -171,6 +175,11 @@ RSpec.describe 'Work package timeline date formatting',
let(:current_user) { create :admin } let(:current_user) { create :admin }
let(:row) { wp_timeline.timeline_row work_package_with_non_working_days.id } let(:row) { wp_timeline.timeline_row work_package_with_non_working_days.id }
shared_let(:non_working_day) do
create(:non_working_day,
date: '06-01-2021')
end
shared_examples "sets dates, duration and displays bar" do shared_examples "sets dates, duration and displays bar" do
it 'sets dates, duration and duration bar' do it 'sets dates, duration and duration bar' do
subject subject
@ -224,7 +233,7 @@ RSpec.describe 'Work package timeline date formatting',
let(:expected_bar_duration) { work_package_with_non_working_days.duration } let(:expected_bar_duration) { work_package_with_non_working_days.duration }
let(:expected_start_date) { Date.parse('2021-01-04') } let(:expected_start_date) { Date.parse('2021-01-04') }
let(:expected_due_date) { Date.parse('2021-01-08') } let(:expected_due_date) { Date.parse('2021-01-08') }
let(:expected_duration) { 5 } let(:expected_duration) { 4 }
let(:expected_label) { work_package_with_non_working_days.subject } let(:expected_label) { work_package_with_non_working_days.subject }
end end
end end
@ -237,7 +246,7 @@ RSpec.describe 'Work package timeline date formatting',
let(:expected_bar_duration) { work_package_with_non_working_days.duration + 2 } let(:expected_bar_duration) { work_package_with_non_working_days.duration + 2 }
let(:expected_start_date) { Date.parse('2021-01-05') } let(:expected_start_date) { Date.parse('2021-01-05') }
let(:expected_due_date) { Date.parse('2021-01-11') } let(:expected_due_date) { Date.parse('2021-01-11') }
let(:expected_duration) { 5 } let(:expected_duration) { 4 }
let(:expected_label) { work_package_with_non_working_days.subject } let(:expected_label) { work_package_with_non_working_days.subject }
end end
end end
@ -250,7 +259,7 @@ RSpec.describe 'Work package timeline date formatting',
let(:expected_bar_duration) { work_package_with_non_working_days.duration } let(:expected_bar_duration) { work_package_with_non_working_days.duration }
let(:expected_start_date) { Date.parse('2021-01-04') } let(:expected_start_date) { Date.parse('2021-01-04') }
let(:expected_due_date) { Date.parse('2021-01-08') } let(:expected_due_date) { Date.parse('2021-01-08') }
let(:expected_duration) { 5 } let(:expected_duration) { 4 }
let(:expected_label) { work_package_with_non_working_days.subject } let(:expected_label) { work_package_with_non_working_days.subject }
end end
end end
@ -263,7 +272,7 @@ RSpec.describe 'Work package timeline date formatting',
let(:expected_bar_duration) { work_package_with_non_working_days.duration + 2 } let(:expected_bar_duration) { work_package_with_non_working_days.duration + 2 }
let(:expected_start_date) { Date.parse('2021-01-05') } let(:expected_start_date) { Date.parse('2021-01-05') }
let(:expected_due_date) { Date.parse('2021-01-11') } let(:expected_due_date) { Date.parse('2021-01-11') }
let(:expected_duration) { 5 } let(:expected_duration) { 4 }
let(:expected_label) { work_package_with_non_working_days.subject } let(:expected_label) { work_package_with_non_working_days.subject }
end end
end end
@ -276,7 +285,7 @@ RSpec.describe 'Work package timeline date formatting',
let(:expected_bar_duration) { work_package_with_non_working_days.duration + 3 } let(:expected_bar_duration) { work_package_with_non_working_days.duration + 3 }
let(:expected_start_date) { Date.parse('2021-01-05') } let(:expected_start_date) { Date.parse('2021-01-05') }
let(:expected_due_date) { Date.parse('2021-01-12') } let(:expected_due_date) { Date.parse('2021-01-12') }
let(:expected_duration) { 6 } let(:expected_duration) { 5 }
let(:expected_label) { work_package_with_non_working_days.subject } let(:expected_label) { work_package_with_non_working_days.subject }
end end
end end

Loading…
Cancel
Save