Add non-working days to datepicker

check if datepicker instance is defined then call its methods
pull/11980/head
Oliver Günther 2 years ago
parent fd60fe0475
commit efd3bc200f
  1. 7
      frontend/src/app/core/state/days/day.service.ts
  2. 7
      frontend/src/app/shared/components/datepicker/multi-date-modal/multi-date.modal.ts
  3. 5
      frontend/src/app/shared/components/datepicker/single-date-modal/single-date.modal.ts
  4. 7
      frontend/src/app/shared/components/op-date-picker/datepicker.ts
  5. 93
      spec/features/work_packages/datepicker/datepicker_non_working_day_spec.rb
  6. 8
      spec/support/components/datepicker/datepicker.rb

@ -2,6 +2,7 @@ import { Injectable } from '@angular/core';
import {
finalize,
map,
take,
tap,
} from 'rxjs/operators';
import { Observable } from 'rxjs';
@ -33,14 +34,16 @@ export class DayResourceService extends ResourceCollectionService<IDay> {
.path;
}
isNonWorkingDay$(input:Date):Observable<boolean> {
isNonWorkingDay$(input:Date):Promise<boolean> {
const date = moment(input).format('YYYY-MM-DD');
return this
.requireNonWorkingYear$(input)
.pipe(
map((days) => days.findIndex((day:IDay) => day.date === date) !== -1),
);
take(1),
)
.toPromise();
}
requireNonWorkingYear$(date:Date|string):Observable<IDay[]> {

@ -498,13 +498,14 @@ export class MultiDateModalComponent extends OpModalComponent implements AfterVi
this.toggleCurrentActivatedField();
}
},
onDayCreate: (dObj:Date[], dStr:string, fp:flatpickr.Instance, dayElem:DayElement) => {
// eslint-disable-next-line @typescript-eslint/no-misused-promises
onDayCreate: async (dObj:Date[], dStr:string, fp:flatpickr.Instance, dayElem:DayElement) => {
onDayCreate(
dayElem,
this.ignoreNonWorkingDays,
this.weekdayService.isNonWorkingDay(dayElem.dateObj),
await this.datePickerInstance?.isNonWorkingDay(dayElem.dateObj),
minimalDate,
this.isDayDisabled(dayElem, minimalDate),
this.dateModalScheduling.isDayDisabled(dayElem, minimalDate),
);
},
},

@ -281,11 +281,12 @@ export class SingleDateModalComponent extends OpModalComponent implements AfterV
this.onDataChange();
this.cdRef.detectChanges();
},
onDayCreate: (dObj:Date[], dStr:string, fp:flatpickr.Instance, dayElem:DayElement) => {
// eslint-disable-next-line @typescript-eslint/no-misused-promises
onDayCreate: async (dObj:Date[], dStr:string, fp:flatpickr.Instance, dayElem:DayElement) => {
onDayCreate(
dayElem,
this.ignoreNonWorkingDays,
this.datePickerInstance?.weekdaysService.isNonWorkingDay(dayElem.dateObj),
await this.datePickerInstance?.isNonWorkingDay(dayElem.dateObj),
minimalDate,
this.dateModalScheduling.isDayDisabled(dayElem, minimalDate),
);

@ -35,6 +35,7 @@ import { Injector } from '@angular/core';
import { InjectField } from 'core-app/shared/helpers/angular/inject-field.decorator';
import { WeekdayService } from 'core-app/core/days/weekday.service';
import DateOption = flatpickr.Options.DateOption;
import { DayResourceService } from 'core-app/core/state/days/day.service';
export class DatePicker {
private datepickerFormat = 'Y-m-d';
@ -49,6 +50,8 @@ export class DatePicker {
@InjectField() weekdaysService:WeekdayService;
@InjectField() daysService:DayResourceService;
@InjectField() I18n:I18nService;
private weekdaysPromise:Promise<unknown>;
@ -88,6 +91,10 @@ export class DatePicker {
document.addEventListener('scroll', this.hideDuringScroll, true);
}
public async isNonWorkingDay(day:Date):Promise<boolean> {
return this.weekdaysService.isNonWorkingDay(day) || await this.daysService.isNonWorkingDay$(day);
}
public clear():void {
this.datepickerInstance.clear();
}

@ -0,0 +1,93 @@
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2023 the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
#++
require 'spec_helper'
require 'support/edit_fields/edit_field'
describe 'Datepicker modal individual non working days (WP #44453)',
js: true,
with_settings: { date_format: '%Y-%m-%d' } do
shared_let(:user) { create(:admin) }
shared_let(:project) { create(:project) }
shared_let(:type_bug) { create(:type_bug) }
shared_let(:type_milestone) { create(:type_milestone) }
shared_let(:project) { create(:project, types: [type_bug, type_milestone]) }
shared_let(:bug_wp) { create(:work_package, project:, type: type_bug, ignore_non_working_days: false) }
shared_let(:milestone_wp) { create(:work_package, project:, type: type_milestone, ignore_non_working_days: false) }
shared_let(:non_working_day_this_week) do
create(:non_working_day,
date: Time.zone.today.beginning_of_week.next_occurring(:tuesday))
end
shared_let(:non_working_day_next_year) do
create(:non_working_day,
date: Time.zone.today.end_of_year.next_occurring(:tuesday))
end
shared_examples 'shows individual non working days' do
let(:work_packages_page) { Pages::FullWorkPackage.new(work_package, project) }
let(:date_field) { work_packages_page.edit_field(date_attribute) }
let(:datepicker) { date_field.datepicker }
it 'loads and shows individual non working days when navigating' do
login_as user
work_packages_page.visit!
work_packages_page.ensure_page_loaded
date_field.activate!
date_field.expect_active!
# Wait for the datepicker to be initialized
datepicker.expect_visible
datepicker.expect_non_working non_working_day_this_week.date
datepicker.select_year non_working_day_next_year.date.year
datepicker.select_month non_working_day_next_year.date.month
datepicker.expect_non_working non_working_day_next_year.date
end
end
context 'for multi date work package' do
let(:work_package) { bug_wp }
let(:date_attribute) { :combinedDate }
it_behaves_like 'shows individual non working days'
end
context 'for milestone work package' do
let(:work_package) { milestone_wp }
let(:date_attribute) { :date }
it_behaves_like 'shows individual non working days'
end
end

@ -109,5 +109,13 @@ module Components
expect_month(date.month)
expect_day(date.day)
end
##
# Expect the given date to be non working
def expect_non_working(date)
label = date.strftime('%B %-d, %Y')
expect(page).to have_selector(".flatpickr-day.flatpickr-non-working-day[aria-label='#{label}']",
wait: 20)
end
end
end

Loading…
Cancel
Save