Compare commits

..

5 Commits

64 changed files with 5385 additions and 1585 deletions

4
.gitignore vendored
View File

@ -4,3 +4,7 @@ node_modules
build
docs
target
switch_git.bat
arm-git.zip
fid-git.zip

Binary file not shown.

View File

@ -50,6 +50,7 @@
"@isp/xdce-arch-core": "1.50.30",
"@isp/xdce-arch-core-base": "1.21.8",
"@isp/xdce-widget": "1.125.2",
"@ng-bootstrap/ng-bootstrap": "4.0.0",
"ag-grid-angular": "22.1.1",
"ag-grid-community": "22.1.1",
"@ag-grid-community/all-modules": "22.1.1",

View File

@ -10,8 +10,7 @@ $btn-map: (
secondary-bg-color: map-get($white-palette, 100),
secondary-border-color: map-get($orange-palette, 100),
secondary-color: map-get($orange-palette, 100),
secondary-bg-color-h: map-get($orange-palette, 100),
secondary-color-h: map-get($white-palette, 100),
secondary-bg-color-h: map-get($gray-palette, 100),
);
$checkbox-map: (
@ -83,10 +82,10 @@ body {
@include isp-button-colors("secondary",
map-get($btn-map, "secondary-bg-color"), map-get($btn-map, "secondary-border-color"), map-get($btn-map, "secondary-color"),
map-get($btn-map, "secondary-bg-color-h"), map-get($btn-map, "secondary-border-color"), map-get($btn-map, "secondary-color-h"),
map-get($btn-map, "secondary-bg-color-h"), map-get($btn-map, "secondary-border-color"), map-get($btn-map, "secondary-color-h"),
map-get($btn-map, "secondary-bg-color-h"), map-get($btn-map, "secondary-border-color"), map-get($btn-map, "secondary-color"),
map-get($btn-map, "secondary-bg-color-h"), map-get($btn-map, "secondary-border-color"), map-get($btn-map, "secondary-color"),
map-get($btn-map, "secondary-bg-color"), map-get($btn-map, "secondary-border-color"), map-get($btn-map, "secondary-color"),
map-get($btn-map, "secondary-bg-color-h"), map-get($btn-map, "secondary-border-color"), map-get($btn-map, "secondary-color-h"), );
map-get($btn-map, "secondary-bg-color-h"), map-get($btn-map, "secondary-border-color"), map-get($btn-map, "secondary-color"), );
}
nbp-button {
@ -255,7 +254,7 @@ body {
nbp-modal .isp-corporate-mode-wrapper {
.isp-modal-close {
color: map-get($orange-palette, 100);
color: map-get($blue-palette, 100);
}
.isp-modal-container {

View File

@ -43,7 +43,6 @@ body {
outline: none !important;
-o-transition: all 0.1s;
transition: all 0.1s;
border-radius: 0.20rem !important;
}
}
@ -222,15 +221,6 @@ body {
.isp-modal-close {
padding: 14px;
.isp-font-comuni-chiudi::before {
content: $fa-var-times;
font: 14px / 1 FontAwesome !important;
}
span {
position: relative;
z-index: 1000;
}
}
.cursor-pointer {
@ -239,7 +229,6 @@ body {
.isp-modal-content {
padding: unset;
max-height: 94vh !important;
&>div:nth-child(2) {
&>* {
@ -1191,10 +1180,6 @@ body {
}
}
rpl-calendar-noa11y.isp-corporate-mode-wrapper.invisible {
position: fixed;
}
.ag-theme-balham {
.ag-header-cell::after,

View File

@ -1,61 +1,67 @@
import { ModuleWithProviders, NgModule } from '@angular/core';
import { XdceArchModule } from '@isp/xdce-arch-core';
import { NbpModule } from '@isp/xdce-widget';
import { NbpBreadCrumbsComponent } from './widgetfideuram/components/nbp-bread-crumbs/nbp-bread-crumbs.component';
export { NbpBreadCrumbsComponent } from './widgetfideuram/components/nbp-bread-crumbs/nbp-bread-crumbs.component';
import { NbpFidBarChartComponent } from './widgetfideuram/components/nbp-fid-bar-chart/nbp-fid-bar-chart.component';
export { NbpFidBarChartComponent } from './widgetfideuram/components/nbp-fid-bar-chart/nbp-fid-bar-chart.component';
import { NbpFidButtonBarComponent } from './widgetfideuram/components/nbp-fid-button-bar/nbp-fid-button-bar.component';
export { NbpFidButtonBarComponent } from './widgetfideuram/components/nbp-fid-button-bar/nbp-fid-button-bar.component';
import { NbpFidDonutChartComponent } from './widgetfideuram/components/nbp-fid-donut-chart/nbp-fid-donut-chart.component';
export { NbpFidDonutChartComponent } from './widgetfideuram/components/nbp-fid-donut-chart/nbp-fid-donut-chart.component';
import { NbpFidPyramidChartComponent } from './widgetfideuram/components/nbp-fid-pyramid-chart/nbp-fid-pyramid-chart.component';
export { NbpFidPyramidChartComponent } from './widgetfideuram/components/nbp-fid-pyramid-chart/nbp-fid-pyramid-chart.component';
import { NbpFidSidePopupComponent } from './widgetfideuram/components/nbp-fid-side-popup/nbp-fid-side-popup.component';
export { NbpFidSidePopupComponent } from './widgetfideuram/components/nbp-fid-side-popup/nbp-fid-side-popup.component';
import { NbpFidTableComponent } from './widgetfideuram/components/nbp-fid-table/nbp-fid-table.component';
export { NbpFidTableComponent } from './widgetfideuram/components/nbp-fid-table/nbp-fid-table.component';
import { NbpFidToggleTabComponentA11Y } from './widgetfideuram/components/nbp-fid-toggle-tabset/nbp-fid-toggle-tab.component.a11y';
export { NbpFidToggleTabComponentA11Y } from './widgetfideuram/components/nbp-fid-toggle-tabset/nbp-fid-toggle-tab.component.a11y';
import { NbpFidToggleTabComponentNOA11Y } from './widgetfideuram/components/nbp-fid-toggle-tabset/nbp-fid-toggle-tab.component.noa11y';
export { NbpFidToggleTabComponentNOA11Y } from './widgetfideuram/components/nbp-fid-toggle-tabset/nbp-fid-toggle-tab.component.noa11y';
import { NbpFidToggleTabComponent } from './widgetfideuram/components/nbp-fid-toggle-tabset/nbp-fid-toggle-tab.component';
export { NbpFidToggleTabComponent } from './widgetfideuram/components/nbp-fid-toggle-tabset/nbp-fid-toggle-tab.component';
import { NbpFidToggleTabsetComponentA11Y } from './widgetfideuram/components/nbp-fid-toggle-tabset/nbp-fid-toggle-tabset.component.a11y';
export { NbpFidToggleTabsetComponentA11Y } from './widgetfideuram/components/nbp-fid-toggle-tabset/nbp-fid-toggle-tabset.component.a11y';
import { NbpFidToggleTabsetComponentNOA11Y } from './widgetfideuram/components/nbp-fid-toggle-tabset/nbp-fid-toggle-tabset.component.noa11y';
export { NbpFidToggleTabsetComponentNOA11Y } from './widgetfideuram/components/nbp-fid-toggle-tabset/nbp-fid-toggle-tabset.component.noa11y';
import { NbpFidToggleTabsetComponent } from './widgetfideuram/components/nbp-fid-toggle-tabset/nbp-fid-toggle-tabset.component';
export { NbpFidToggleTabsetComponent } from './widgetfideuram/components/nbp-fid-toggle-tabset/nbp-fid-toggle-tabset.component';
import { NbpFidComboComponent } from './widgetfideuram/components/nbp-fid-combo/nbp-fid-combo.component';
export { NbpFidComboComponent } from './widgetfideuram/components/nbp-fid-combo/nbp-fid-combo.component';
import { ShowcaseComponent } from './widgetfideuram/components/showcase/showcase.component';
export { ShowcaseComponent } from './widgetfideuram/components/showcase/showcase.component';
import { Showcase1Component } from './widgetfideuram/components/showcase/showcase1.component';
export { Showcase1Component } from './widgetfideuram/components/showcase/showcase1.component';
import { WidgetFideuramShowcaseComponent } from './widgetfideuram/components/widget-fideuram-showcase/widget-fideuram-showcase.component';
export { WidgetFideuramShowcaseComponent } from './widgetfideuram/components/widget-fideuram-showcase/widget-fideuram-showcase.component';
import { AgGridModule, AngularFrameworkComponentWrapper, AngularFrameworkOverrides } from 'ag-grid-angular';
import { FormsModule } from '@angular/forms';
import { NbpFidCalendarGenericComponent } from './widgetfideuram/components/nbp-fid-calendar-generic/nbp-fid-calendar-generic.component';
import { CommonModule } from "@angular/common";
import { ModuleWithProviders, NgModule, } from "@angular/core";
import { FormsModule } from "@angular/forms";
import { XdceArchModule } from "@isp/xdce-arch-core";
import { NbpModule } from "@isp/xdce-widget";
import { NgbModule } from "@ng-bootstrap/ng-bootstrap";
import { TranslateModule } from '@ngx-translate/core';
export { NbpFidCalendarGenericComponent } from './widgetfideuram/components/nbp-fid-calendar-generic/nbp-fid-calendar-generic.component';
export { AgGridModule } from 'ag-grid-angular';
import {
AgGridModule,
AngularFrameworkComponentWrapper,
AngularFrameworkOverrides,
} from "ag-grid-angular";
import { NbpBreadCrumbsComponent } from "./widgetfideuram/components/nbp-bread-crumbs/nbp-bread-crumbs.component";
import { NbpFidBarChartComponent } from "./widgetfideuram/components/nbp-fid-bar-chart/nbp-fid-bar-chart.component";
import { NbpFidButtonBarComponent } from "./widgetfideuram/components/nbp-fid-button-bar/nbp-fid-button-bar.component";
import { RplDeclarations, RplEntryComponents, RplExports, RplRootProviders } from './widgetfideuram/components/nbp-fid-calendar-generic/@ng-bootstrap-noa11y/datepicker/datepicker-reply.module';
import { NbpFidCalendarGenericComponent } from "./widgetfideuram/components/nbp-fid-calendar-generic/nbp-fid-calendar-generic.component";
import { NbpFidComboComponent } from "./widgetfideuram/components/nbp-fid-combo/nbp-fid-combo.component";
import { NbpFidDonutChartComponent } from "./widgetfideuram/components/nbp-fid-donut-chart/nbp-fid-donut-chart.component";
import { NbpFidPyramidChartComponent } from "./widgetfideuram/components/nbp-fid-pyramid-chart/nbp-fid-pyramid-chart.component";
import { NbpFidSidePopupComponent } from "./widgetfideuram/components/nbp-fid-side-popup/nbp-fid-side-popup.component";
import { NbpFidTableComponent } from "./widgetfideuram/components/nbp-fid-table/nbp-fid-table.component";
import { NbpFidToggleTabComponent } from "./widgetfideuram/components/nbp-fid-toggle-tabset/nbp-fid-toggle-tab.component";
import { NbpFidToggleTabComponentA11Y } from "./widgetfideuram/components/nbp-fid-toggle-tabset/nbp-fid-toggle-tab.component.a11y";
import { NbpFidToggleTabComponentNOA11Y } from "./widgetfideuram/components/nbp-fid-toggle-tabset/nbp-fid-toggle-tab.component.noa11y";
import { NbpFidToggleTabsetComponent } from "./widgetfideuram/components/nbp-fid-toggle-tabset/nbp-fid-toggle-tabset.component";
import { NbpFidToggleTabsetComponentA11Y } from "./widgetfideuram/components/nbp-fid-toggle-tabset/nbp-fid-toggle-tabset.component.a11y";
import { NbpFidToggleTabsetComponentNOA11Y } from "./widgetfideuram/components/nbp-fid-toggle-tabset/nbp-fid-toggle-tabset.component.noa11y";
import { ShowcaseComponent } from "./widgetfideuram/components/showcase/showcase.component";
import { Showcase1Component } from "./widgetfideuram/components/showcase/showcase1.component";
import { WidgetFideuramShowcaseComponent } from "./widgetfideuram/components/widget-fideuram-showcase/widget-fideuram-showcase.component";
export { AgGridModule } from "ag-grid-angular";
export * from "./widgetfideuram/components/nbp-bread-crumbs/nbp-bread-crumbs.component";
export * from "./widgetfideuram/components/nbp-fid-bar-chart/nbp-fid-bar-chart.component";
export * from "./widgetfideuram/components/nbp-fid-button-bar/nbp-fid-button-bar.component";
export * from "./widgetfideuram/components/nbp-fid-calendar-generic/@ng-bootstrap-noa11y/datepicker/datepicker";
export * from "./widgetfideuram/components/nbp-fid-calendar-generic/@ng-bootstrap-noa11y/datepicker/datepicker-day-view";
export * from "./widgetfideuram/components/nbp-fid-calendar-generic/@ng-bootstrap-noa11y/datepicker/datepicker-input";
export * from "./widgetfideuram/components/nbp-fid-calendar-generic/@ng-bootstrap-noa11y/datepicker/datepicker-navigation";
export * from "./widgetfideuram/components/nbp-fid-calendar-generic/@ng-bootstrap-noa11y/datepicker/datepicker-reply-month-view";
export * from "./widgetfideuram/components/nbp-fid-calendar-generic/@ng-bootstrap-noa11y/datepicker/datepicker-reply-years-view";
export * from './widgetfideuram/components/nbp-fid-calendar-generic/@ng-bootstrap-noa11y/datepicker/datepicker-reply.module';
export * from "./widgetfideuram/components/nbp-fid-calendar-generic/nbp-fid-calendar-generic.component";
export { NbpFidCalendarGenericComponent } from "./widgetfideuram/components/nbp-fid-calendar-generic/nbp-fid-calendar-generic.component";
export * from "./widgetfideuram/components/nbp-fid-combo/nbp-fid-combo.component";
export * from "./widgetfideuram/components/nbp-fid-donut-chart/nbp-fid-donut-chart.component";
export * from "./widgetfideuram/components/nbp-fid-pyramid-chart/nbp-fid-pyramid-chart.component";
export * from "./widgetfideuram/components/nbp-fid-side-popup/nbp-fid-side-popup.component";
export * from "./widgetfideuram/components/nbp-fid-table/nbp-fid-table.component";
export * from "./widgetfideuram/components/nbp-fid-toggle-tabset/nbp-fid-toggle-tab.component";
export * from "./widgetfideuram/components/nbp-fid-toggle-tabset/nbp-fid-toggle-tab.component.a11y";
export * from "./widgetfideuram/components/nbp-fid-toggle-tabset/nbp-fid-toggle-tab.component.noa11y";
export * from "./widgetfideuram/components/nbp-fid-toggle-tabset/nbp-fid-toggle-tabset.component";
export * from "./widgetfideuram/components/nbp-fid-toggle-tabset/nbp-fid-toggle-tabset.component.a11y";
export * from "./widgetfideuram/components/nbp-fid-toggle-tabset/nbp-fid-toggle-tabset.component.noa11y";
export * from "./widgetfideuram/components/showcase/showcase.component";
export * from "./widgetfideuram/components/showcase/showcase1.component";
export * from "./widgetfideuram/components/widget-fideuram-showcase/widget-fideuram-showcase.component";
export { DATE_STRING_FORMAT, formatDate, formatNumber, setSpinnerMessage, clearSpinnerMessage } from './widgetfideuram/Utils';
export * from "./widgetfideuram/Utils";
@NgModule({
imports: [
XdceArchModule,
NbpModule,
AgGridModule,
FormsModule,
TranslateModule
],
imports: [XdceArchModule, NbpModule, AgGridModule, FormsModule, NgbModule, TranslateModule, CommonModule],
declarations: [
NbpBreadCrumbsComponent,
NbpFidBarChartComponent,
@ -74,7 +80,8 @@ export { DATE_STRING_FORMAT, formatDate, formatNumber, setSpinnerMessage, clearS
ShowcaseComponent,
Showcase1Component,
WidgetFideuramShowcaseComponent,
NbpFidCalendarGenericComponent
NbpFidCalendarGenericComponent,
...RplDeclarations
],
exports: [
NbpBreadCrumbsComponent,
@ -95,11 +102,12 @@ export { DATE_STRING_FORMAT, formatDate, formatNumber, setSpinnerMessage, clearS
Showcase1Component,
WidgetFideuramShowcaseComponent,
AgGridModule,
NbpFidCalendarGenericComponent
NbpFidCalendarGenericComponent,
...RplExports
],
providers: [
AngularFrameworkOverrides,
AngularFrameworkComponentWrapper
AngularFrameworkComponentWrapper,
],
entryComponents: [
NbpFidToggleTabComponentA11Y,
@ -107,14 +115,15 @@ export { DATE_STRING_FORMAT, formatDate, formatNumber, setSpinnerMessage, clearS
NbpFidToggleTabsetComponentA11Y,
NbpFidToggleTabsetComponentNOA11Y,
NbpFidToggleTabComponent,
NbpFidToggleTabsetComponent
]
NbpFidToggleTabsetComponent,
...RplEntryComponents
],
})
export class XdceWidgetFideuramModule {
static forRoot(): ModuleWithProviders {
return {
ngModule: XdceWidgetFideuramModule,
providers: []
providers: [...RplRootProviders],
};
}
}

View File

@ -0,0 +1,26 @@
import {Injectable, TemplateRef} from '@angular/core';
import {DayTemplateContextNOA11Y} from './datepicker-day-template-context';
import {NgbDateStruct} from './ngb-date-struct';
/**
* Configuration service for the NgbDatepicker component.
* You can inject this service, typically in your root component, and customize the values of its properties in
* order to provide default values for all the datepickers used in the application.
*/
@Injectable()
export class NgbDatepickerConfigNOA11Y {
dayTemplate: TemplateRef<DayTemplateContextNOA11Y>;
displayMonths = 1;
firstDayOfWeek = 1;
markDisabled: (date: NgbDateStruct, current: {year: number, month: number}) => boolean;
minDate: NgbDateStruct;
maxDate: NgbDateStruct;
navigation: 'select' | 'arrows' | 'none' = 'select';
outsideDays: 'visible' | 'collapsed' | 'hidden' = 'visible';
showWeekdays = true;
showWeekNumbers = false;
startDate: {year: number, month: number};
disabledWeekend: boolean;
holidays: Array<NgbDateStruct>;
taxDeadlines: Array<NgbDateStruct>;
}

View File

@ -0,0 +1,56 @@
import {NgbDateStruct} from './ngb-date-struct';
/**
* Context for the datepicker 'day' template in case you want to override the default one
*/
export interface DayTemplateContextNOA11Y {
/**
* Month currently displayed by the datepicker
*/
currentMonth: number;
/**
* Date that corresponds to the template
*/
date: NgbDateStruct;
/**
* True if current date is disabled
*/
disabled: boolean;
/**
* True if current date is focused
*/
focused: boolean;
/**
* True if current date is selected
*/
selected: boolean;
/**
* True if current date is today
*/
isToday: boolean;
/**
* True if current date is a weekend day
*/
isWeekend: boolean;
/**
* True if current date is a weekend day
*/
isDayPast: boolean;
/**
* True if current date is a tax deadlines
*/
isFiscalDay: boolean;
/**
* True if current date is an holiday
*/
isHoliday?: boolean;
}

View File

@ -0,0 +1,4 @@
<div [ngClass]=" abilitaGiorni(date) ? 'ngbdatepickerdayview' : 'ngbdatepickerdayviewdisabled'">
<span [attr.role]="'button'" [attr.aria-label]="' '" [attr.aria.labelledby]="' '" [attr.aria-describedby]="labelDay(date)">{{ date.day }}</span>
<div *ngIf="isFiscalDay" class="is-fiscal"></div>
</div>

View File

@ -0,0 +1,32 @@
.ngbdatepickerdayview {
border-radius: 0!important;
box-sizing: border-box;
text-align: center;
width: inherit!important;
height: inherit!important;
line-height: 2.6875rem!important;
vertical-align: middle;
}
.ngbdatepickerdayviewdisabled {
box-sizing: border-box;
text-align: center;
width: inherit!important;
height: inherit!important;
line-height: 2.6875rem!important;
vertical-align: middle;
cursor: default;
}
.is-fiscal {
// Triangolo bianco
border-bottom-width: 0.5rem;
border-bottom-style: solid;
border-left: 0.5rem solid transparent;
border-right: 0.5rem solid transparent;
transform: rotate(45deg);
transform-origin: top;
position: absolute;
top: 0;
right: -0.5rem;
}

View File

@ -0,0 +1,71 @@
import {ChangeDetectionStrategy, Component, Input} from '@angular/core';
import {NgbDateStruct} from './ngb-date-struct';
@Component({
selector: '[ngbFidDatepickerDayView]',
changeDetection: ChangeDetectionStrategy.OnPush,
host: {
'class': 'btn-secondary',
'[class.bg-primary]': 'selected',
'[class.text-white]': 'selected',
'[class.text-muted]': 'isMuted()',
'[class.outside]': 'isMuted()',
'[class.active]': 'focused',
'[class.is-today]': 'isToday',
'[class.is-holiday]' : 'isHoliday',
'[class.is-weekend]': 'isWeekend',
'[class.is-daypast]': 'isDayPast',
'[class.is-fiscal]' : 'isFiscalDay'
},
templateUrl: './datepicker-day-view.html',
styleUrls: ['./datepicker-day-view.scss'],
})
export class NgbDatepickerDayViewNOA11Y {
@Input() currentMonth: number;
@Input() date: NgbDateStruct;
@Input() disabled: boolean;
@Input() focused: boolean;
@Input() selected: boolean;
@Input() startDateEnabled: any;
@Input() endDateEnabled: any;
@Input() isToday: boolean;
@Input() isWeekend: boolean;
@Input() isDayPast: boolean;
@Input() taxDeadlines: any;
@Input() isFiscalDay: boolean;
@Input() isHoliday : boolean;
isMuted() { return !this.selected && (this.date.month !== this.currentMonth || this.disabled); }
abilitaGiorni(data) {
let startDate, endDate;
let buffer = new Date(data.year, data.month - 1, data.day);
if (this.startDateEnabled instanceof Date) {
startDate = new Date(this.startDateEnabled.getFullYear(), this.startDateEnabled.getMonth(), this.startDateEnabled.getDate());
endDate = new Date(this.endDateEnabled.getFullYear(), this.endDateEnabled.getMonth(), this.endDateEnabled.getDate());
} else {
startDate = new Date(this.startDateEnabled.year, this.startDateEnabled.month - 1, this.startDateEnabled.day);
endDate = new Date(this.endDateEnabled.year, this.endDateEnabled.month - 1, this.endDateEnabled.day);
}
if (startDate && endDate) {
return (startDate <= buffer && buffer <= endDate);
} else {
return true;
}
}
labelDay(data){
let result;
let weekdays = ['Domenica', 'Lunedì', 'Martedì', 'Mercoledì', 'Giovedì', 'Venerdì', 'Sabato'];
result = weekdays[new Date(data.year, data.month - 1, data.day).getDay()] + ' ' + data.day;
return result;
}
}

View File

@ -0,0 +1,47 @@
import {Injectable} from '@angular/core';
import { NgbDateStruct } from '@ng-bootstrap/ng-bootstrap';
const WEEKDAYS_SHORT = ['Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa', 'Su'];
const MONTHS_SHORT = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
const MONTHS_FULL = [
'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November',
'December'
];
/**
* Type of the service supplying month and weekday names to to NgbDatepicker component.
* See the i18n demo for how to extend this class and define a custom provider for i18n.
*/
@Injectable()
export abstract class NgbDatepickerI18nNOA11Y {
/**
* Returns the short weekday name to display in the heading of the month view.
* With default calendar we use ISO 8601: 'weekday' is 1=Mon ... 7=Sun
*/
abstract getWeekdayShortName(weekday: number): string;
/**
* Returns the short month name to display in the date picker navigation.
* With default calendar we use ISO 8601: 'month' is 1=Jan ... 12=Dec
*/
abstract getMonthShortName(month: number): string;
/**
* Returns the full month name to display in the date picker navigation.
* With default calendar we use ISO 8601: 'month' is 1=January ... 12=December
*/
abstract getMonthFullName(month: number): string;
abstract getDayAriaLabel(date: NgbDateStruct): string;
}
@Injectable()
export class NgbDatepickerI18nDefaultNOA11Y extends NgbDatepickerI18nNOA11Y {
getWeekdayShortName(weekday: number): string { return WEEKDAYS_SHORT[weekday - 1]; }
getMonthShortName(month: number): string { return MONTHS_SHORT[month - 1]; }
getMonthFullName(month: number): string { return MONTHS_FULL[month - 1]; }
getDayAriaLabel(date: NgbDateStruct): string { return `${date.day} ${MONTHS_FULL[date.month-1]} ${date.year}`}
}

View File

@ -0,0 +1,509 @@
import {
Directive,
Input,
ComponentRef,
ElementRef,
ViewContainerRef,
Renderer2,
ComponentFactoryResolver,
NgZone,
TemplateRef,
forwardRef,
EventEmitter,
Output,
OnChanges,
OnDestroy,
SimpleChanges, QueryList
} from '@angular/core';
import { AbstractControl, ControlValueAccessor, Validator, NG_VALUE_ACCESSOR, NG_VALIDATORS } from '@angular/forms';
import { NgbDate } from './ngb-date';
import { RplCalendarNOA11Y, NgbDatepickerNavigateEventNOA11Y } from './datepicker';
import { DayTemplateContextNOA11Y } from './datepicker-day-template-context';
import { NgbDateParserFormatterNOA11Y } from './ngb-date-parser-formatter';
import { Positioning } from '../util/positioning';
import { NgbDateStruct } from './ngb-date-struct';
import { NgbCalendarNOA11Y } from './ngb-calendar';
import { NgbDatepickerServiceNOA11Y } from './datepicker-service';
import {NbpCalendarPattern, NbpCalendarPosition, NbpDateSeparator} from '../../nbp-calendar-generic.enum';
import {EventManager, NATIVE_CONNECTOR} from '@isp/xdce-arch-core-base';
import {take} from 'rxjs/operators';
const NGB_DATEPICKER_VALUE_ACCESSOR = {
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => NgbInputDatepickerNOA11Y),
multi: true
};
const NGB_DATEPICKER_VALIDATOR = {
provide: NG_VALIDATORS,
useExisting: forwardRef(() => NgbInputDatepickerNOA11Y),
multi: true
};
/**
* A directive that makes it possible to have datepickers on input fields.
* Manages integration with the input field itself (data entry) and ngModel (validation etc.).
*/
@Directive({
selector: 'input[rplFidCalendarNOA11Y]',
exportAs: 'rplFidCalendarNOA11Y',
host: {
'(input)': 'waitForFormat($event.target.value)',
'(change)': 'manualDateChange($event.target.value, true)',
'(keyup.esc)': 'close()',
'(blur)': 'onBlur()',
'(document:click)':'onFocusOut($event)'
},
providers: [NGB_DATEPICKER_VALUE_ACCESSOR, NGB_DATEPICKER_VALIDATOR, NgbDatepickerServiceNOA11Y]
})
export class NgbInputDatepickerNOA11Y implements OnChanges,
OnDestroy, ControlValueAccessor, Validator {
private _cRef: ComponentRef<RplCalendarNOA11Y> = null;
private _model: NgbDate;
private _zoneSubscription: any;
opened: boolean;
dataBeforeChange;
/**
* Reference for the custom template for the day display
*/
@Input() dayTemplate: TemplateRef<DayTemplateContextNOA11Y>;
/**
* Number of months to display
*/
@Input() displayMonths: number;
/**
* First day of the week. With default calendar we use ISO 8601: 1=Mon ... 7=Sun
*/
@Input() firstDayOfWeek: number;
/**
* Callback to mark a given date as disabled.
* 'Current' contains the month that will be displayed in the view
*/
@Input() markDisabled: (date: NgbDateStruct, current: { year: number, month: number }) => boolean;
/**
* Min date for the navigation. If not provided will be 10 years before today or `startDate`
*/
_minDate: NgbDateStruct;
@Input()
get minDate() {
return this._minDate;
}
set minDate(minDate: NgbDateStruct) {
this._minDate = minDate;
}
/**
* Max date for the navigation. If not provided will be 10 years from today or `startDate`
*/
_maxDate: NgbDateStruct;
@Input()
get maxDate() {
return this._maxDate;
}
set maxDate(maxDate: NgbDateStruct) {
this._maxDate = maxDate;
}
/**
* Navigation type: `select` (default with select boxes for month and year), `arrows`
* (without select boxes, only navigation arrows) or `none` (no navigation at all)
*/
@Input() navigation: 'select' | 'arrows' | 'none';
/**
* The way to display days that don't belong to current month: `visible` (default),
* `hidden` (not displayed) or `collapsed` (not displayed with empty space collapsed)
*/
@Input() outsideDays: 'visible' | 'collapsed' | 'hidden';
/**
* Placement of a datepicker popup. Accepts: "top", "bottom", "left", "right", "bottom-left",
* "bottom-right" etc.
*/
@Input() placement = 'bottom-left';
/**
* Whether to display days of the week
*/
@Input() showWeekdays: boolean;
/**
* Whether to display week numbers
*/
@Input() showWeekNumbers: boolean;
/**
* Date to open calendar with.
* With default calendar we use ISO 8601: 'month' is 1=Jan ... 12=Dec.
* If nothing or invalid date provided, calendar will open with current month.
* Use 'navigateTo(date)' as an alternative
*/
@Input() startDate: { year: number, month: number };
@Input() disabledWeekend: boolean;
@Input() holidays: Array<NgbDateStruct>;
@Input() taxDeadlines: Array<NgbDateStruct>;
/**
* input for unifiedVg
*/
@Input() isUnifiedVg: boolean;
private _pattern: any = NbpCalendarPattern;
@Input() nbpLabelPattern: NbpCalendarPattern = this._pattern.GGMMAAAA;
private _separator = NbpDateSeparator;
@Input() nbpDateSeparator: NbpDateSeparator = this._separator.DOT;
/**
* An event fired when navigation happens and currently displayed month changes.
* See NgbDatepickerNavigateEvent for the payload info.
*/
@Output() navigate = new EventEmitter<NgbDatepickerNavigateEventNOA11Y>();
private _onChange = (_: any) => { };
private _onTouched = () => { };
private _validatorChange = () => { };
private _placement: any = NbpCalendarPosition;
private positionService: Positioning;
private get isInModal(): boolean {
let el: HTMLElement = (<HTMLElement> this._elRef.nativeElement);
if (!el || !el.parentElement || !el.parentElement.tagName) {
return false;
}
let tagName: string = el.parentElement.tagName;
while (!tagName.match(/modal/i) && !tagName.match(/body/i)) {
el = el.parentElement;
tagName = el.parentElement && el.parentElement.tagName ? el.parentElement.tagName : '';
}
return tagName && !!tagName.match(/modal/i);
}
private get isCorporate(): boolean {
return this._cRef.location.nativeElement.classList.contains('isp-corporate-mode-wrapper');
}
get _isNative(): boolean {
return /(ip(a|o)d|iphone|android)/ig.test(window.navigator.userAgent)
}
constructor(
private _parserFormatter: NgbDateParserFormatterNOA11Y, private _elRef: ElementRef, private _vcRef: ViewContainerRef,
private _renderer: Renderer2, private _cfr: ComponentFactoryResolver, ngZone: NgZone,
private _service: NgbDatepickerServiceNOA11Y, private _calendar: NgbCalendarNOA11Y,
private eventManager: EventManager
) {
this.positionService = new Positioning();
this._zoneSubscription = ngZone.onStable.subscribe(() => this.setDatepickerPosition());
}
setDatepickerPosition() {
if (!this._cRef || !this._elRef) {
return;
}
const calendar: HTMLElement = this._cRef.location.nativeElement;
const datepickerInput: HTMLElement = this._elRef.nativeElement;
const calendarClone: HTMLElement = (<HTMLElement>calendar.cloneNode(true));
this._renderer.removeClass(calendarClone.querySelector('.isp-main-datepicker'), 'd-none');
this._renderer.addClass(calendarClone, 'invisible');
window.document.body.appendChild(calendarClone);
const navigation: number = calendarClone.querySelector(".isp-datepicker-navigation")['offsetHeight'];
const routingView: number = calendarClone.querySelector(".isp-datepicker-routing-view")['offsetHeight'];
const position: ClientRect = this.positionService.positionElements(datepickerInput, calendarClone, this.placement);
this._renderer.removeChild(calendarClone.parentElement, calendarClone);
switch (this.placement) {
case this._placement.TOP:
case this._placement.TOP_RIGHT:
case this._placement.TOP_LEFT:
position.top = this.isCorporate ? (-navigation - routingView) : (-navigation - routingView - 3);
break;
case this._placement.RIGHT:
case this._placement.LEFT:
position.top = (-navigation - (routingView / 2));
break;
}
calendar.style.top = `${position.top}px`;
calendar.style.left = `${position.left}px`;
this._renderer.removeClass(calendar.querySelector('.isp-main-datepicker'), 'd-none');
}
registerOnChange(fn: (value: any) => any): void { this._onChange = fn; }
registerOnTouched(fn: () => any): void { this._onTouched = fn; }
registerOnValidatorChange(fn: () => void): void { this._validatorChange = fn; };
setDisabledState(isDisabled: boolean): void {
this._renderer.setProperty(this._elRef.nativeElement, 'disabled', isDisabled);
if (this.isOpen()) {
this._cRef.instance.setDisabledState(isDisabled);
}
}
validate(c: AbstractControl): { [key: string]: any } {
const value = c.value;
if (value === null || value === undefined) {
return null;
}
if (typeof value === 'string') {
let newValue: NgbDate;
newValue = new NgbDate(parseInt(value.substring(0, 4), 10),
parseInt(value.substring(5, 7), 10),
parseInt(value.substring(8, 10), 10));
if (!this._calendar.isValid(newValue)) {
return { 'ngbDate': { invalid: c.value } };
}
if (this.minDate && NgbDate.from(newValue).before(NgbDate.from(this.minDate))) {
return { 'ngbDate': { requiredBefore: this.minDate } };
}
if (this.maxDate && NgbDate.from(newValue).after(NgbDate.from(this.maxDate))) {
return { 'ngbDate': { requiredAfter: this.maxDate } };
}
} else {
if (!this._calendar.isValid(value)) {
return { 'ngbDate': { invalid: c.value } };
}
if (this.minDate && NgbDate.from(value).before(NgbDate.from(this.minDate))) {
return { 'ngbDate': { requiredBefore: this.minDate } };
}
if (this.maxDate && NgbDate.from(value).after(NgbDate.from(this.maxDate))) {
return { 'ngbDate': { requiredAfter: this.maxDate } };
}
}
}
writeValue(value: any) {
const ngbDate = value ? new NgbDate(value.year, value.month, value.day) : null;
this._model = this._calendar.isValid(value) ? ngbDate : null;
this._writeModelValue(this._model);
}
waitForFormat(value: string, updateView = false) {
this.dataBeforeChange = value;
let actualValue = value;
setTimeout(() => {
if (actualValue === this.dataBeforeChange) {
this.manualDateChange(actualValue, updateView);
}
}, 2000);
}
manualDateChange(value: string, updateView = false) {
let datesplitted = value.split(/[./-]/g);
if(this.nbpLabelPattern == this._pattern.MMAAAA && datesplitted.length < 3 && datesplitted.length > 1)
{
value = '01.' + value;
}
let [year, month, day] = value.split('-');
if (this.isUnifiedVg && this._isNative) {
if (year && month && day) {
// value = day + '.' + month + '.' + year;
}
}
this._model = this._service.toValidDate(this._parserFormatter.parse(value, this.nbpLabelPattern), null);
this._onChange(this._model ? this._model.toStruct() : (value === '' ? null : value));
if (updateView && this._model) {
this._writeModelValue(this._model);
}
}
isOpen() { return !!this._cRef; }
/**
* Opens the datepicker with the selected date indicated by the ngModel value.
*/
open(mode: boolean) {
if (!this.isOpen()) {
if (this._model && (this.minDate || this.maxDate)) {
if ((this.minDate && NgbDate.from(this._model).before(NgbDate.from(this.minDate))) || (this.maxDate && NgbDate.from(this._model).after(NgbDate.from(this.maxDate)))) {
this._model = null;
}
}
const cf = this._cfr.resolveComponentFactory(RplCalendarNOA11Y);
this._cRef = this._vcRef.createComponent(cf);
this._applyPopupStyling(this._cRef.location.nativeElement);
this._cRef.instance.writeValue(this._model);
this._applyDatepickerInputs(this._cRef.instance);
this._subscribeForDatepickerOutputs(this._cRef.instance);
this._cRef.instance.disabledWeekend = this.disabledWeekend;
this._cRef.instance.holidays = this.holidays;
this._cRef.instance.taxDeadlines = this.taxDeadlines;
if (mode){
this._renderer.addClass(this._cRef.location.nativeElement, 'isp-corporate-mode-wrapper');
}
this._cRef.instance.ngOnInit();
// date selection event handling
this._cRef.instance.registerOnChange((selectedDate) => {
this.writeValue(selectedDate);
this._onChange(selectedDate);
if (!this.opened) {
this.close();
}
});
// focus handling
this._cRef.instance.focus();
}
}
/**
* Closes the datepicker popup.
*/
close() {
if (this.isOpen()) {
this._vcRef.remove(this._vcRef.indexOf(this._cRef.hostView));
this._cRef = null;
this.eventManager.emit('DATEPICKER_CLOSE', true);
}
}
/**
* Toggles the datepicker popup (opens when closed and closes when opened).
*/
toggle(mode: boolean) {
if (this.isOpen()) {
this.close();
} else {
this.open(mode);
}
}
addMargin(value: string) {
if (this._cRef) {
this._renderer.setStyle(this._cRef.location.nativeElement, "margin-top", value);
}
}
onFocusOut($event) {
const parent: HTMLElement = this._elRef.nativeElement.parentElement;
const icon: HTMLElement = parent.querySelector('i');
if(this.isOpen() && !(event.target === icon || this._elRef.nativeElement.contains($event.target) || this._cRef.location.nativeElement.contains($event.target))) {
this._cRef.instance.focusOutComponent($event);
console.info('onfocusout close');
this.close();
if (this.eventManager) {
this.eventManager.emit('HANDLER_CALENDAR', {});
}
}
}
/**
* Navigates current view to provided date.
* With default calendar we use ISO 8601: 'month' is 1=Jan ... 12=Dec.
* If nothing or invalid date provided calendar will open current month.
* Use 'startDate' input as an alternative
*/
navigateTo(date?: { year: number, month: number }) {
if (this.isOpen()) {
this._cRef.instance.navigateTo(date);
}
}
onBlur() { this._onTouched(); }
ngOnChanges(changes: SimpleChanges) {
if (changes['minDate'] || changes['maxDate']) {
this._validatorChange();
}
}
ngOnDestroy() {
this.close();
this._zoneSubscription.unsubscribe();
}
getCalendarHeight() {
if (this._cRef && this._cRef.instance.datepickerRoutingView) {
return this._cRef.instance.datepickerRoutingView.getRoutingViewHeight();
}
return 0;
}
getCalendarWidth() {
if (this._cRef && this._cRef.instance.datepickerRoutingView) {
return this._cRef.instance.datepickerRoutingView.getRoutingViewWidth();
}
return 0;
}
getInputHeight() {
if (this._elRef) {
return this._elRef.nativeElement.offsetHeight;
}
return 0;
}
private _applyDatepickerInputs(datepickerInstance: RplCalendarNOA11Y): void {
['dayTemplate', 'displayMonths', 'firstDayOfWeek', 'markDisabled', 'minDate', 'maxDate', 'navigation',
'outsideDays', 'showNavigation', 'showWeekdays', 'showWeekNumbers']
.forEach((optionName: string) => {
if ((this as any)[optionName] !== undefined) {
(datepickerInstance as any)[optionName] = (this as any)[optionName];
}
});
datepickerInstance.startDate = this.startDate || this._model;
}
private _applyPopupStyling(nativeElement: any) {
this._renderer.addClass(nativeElement, 'dropdown-menu');
this._renderer.setStyle(nativeElement, 'padding', '0');
}
private _subscribeForDatepickerOutputs(datepickerInstance: RplCalendarNOA11Y) {
datepickerInstance.navigate.subscribe((date: any) => this.navigate.emit(date));
}
private _writeModelValue(model: NgbDate) {
if (model) {
const { day, month, year } = model;
if(this.nbpLabelPattern == this._pattern.MMAAAA) {
this._renderer.setProperty(this._elRef.nativeElement, 'value', this._parserFormatter.format({year, month, day: 0}, this.nbpLabelPattern, this.nbpDateSeparator));
}
else {
this._renderer.setProperty(this._elRef.nativeElement, 'value', this._parserFormatter.format({year, month, day}, this.nbpLabelPattern, this.nbpDateSeparator));
}
} else {
this._renderer.setProperty(this._elRef.nativeElement, 'value', this._parserFormatter.format(model, this.nbpLabelPattern, this.nbpDateSeparator));
}
if (this.isOpen()) {
this._cRef.instance.writeValue(model);
this._onTouched();
}
}
}

View File

@ -0,0 +1,75 @@
import {Injectable} from '@angular/core';
import {NgbDatepickerServiceNOA11Y} from './datepicker-service';
import {NgbCalendarNOA11Y} from './ngb-calendar';
import {toString} from '../util/util';
import {NgbDate} from './ngb-date';
enum Key {
Enter = 13,
Space = 32,
PageUp = 33,
PageDown = 34,
End = 35,
Home = 36,
ArrowLeft = 37,
ArrowUp = 38,
ArrowRight = 39,
ArrowDown = 40
}
@Injectable()
export class NgbDatepickerKeyMapServiceNOA11Y {
private _minDate: NgbDate;
private _maxDate: NgbDate;
private _firstViewDate: NgbDate;
private _lastViewDate: NgbDate;
constructor(private _service: NgbDatepickerServiceNOA11Y, private _calendar: NgbCalendarNOA11Y) {
_service.model$.subscribe(model => {
this._minDate = model.minDate;
this._maxDate = model.maxDate;
this._firstViewDate = model.firstDate;
this._lastViewDate = model.lastDate;
});
}
processKey(event: KeyboardEvent) {
if (Key[toString(event.which)]) {
switch (event.which) {
case Key.PageUp:
this._service.focusMove(event.shiftKey ? 'y' : 'm', -1);
break;
case Key.PageDown:
this._service.focusMove(event.shiftKey ? 'y' : 'm', 1);
break;
case Key.End:
this._service.focus(event.shiftKey ? this._maxDate : this._lastViewDate);
break;
case Key.Home:
this._service.focus(event.shiftKey ? this._minDate : this._firstViewDate);
break;
case Key.ArrowLeft:
this._service.focusMove('d', -1);
break;
case Key.ArrowUp:
this._service.focusMove('d', -this._calendar.getDaysPerWeek());
break;
case Key.ArrowRight:
this._service.focusMove('d', 1);
break;
case Key.ArrowDown:
this._service.focusMove('d', this._calendar.getDaysPerWeek());
break;
case Key.Enter:
case Key.Space:
this._service.focusSelect();
break;
default:
return;
}
event.preventDefault();
event.stopPropagation();
}
}
}

View File

@ -0,0 +1,8 @@
<select [disabled]="disabled" class="custom-select d-inline-block" [value]="date?.month" (change)="changeMonth($event.target.value)"
tabindex="-1">
<option *ngFor="let m of months" [value]="m">{{ i18n.getMonthShortName(m) }}</option>
</select>
<select [disabled]="disabled" class="custom-select d-inline-block" [value]="date?.year" (change)="changeYear($event.target.value)"
tabindex="-1">
<option *ngFor="let y of years" [value]="y">{{ y }}</option>
</select>

View File

@ -0,0 +1,41 @@
select {
font-family: sans-serif;
margin: 0;
padding: 0.25rem 0.5rem;
font-size: 0.875rem;
line-height: 1.25;
height: inherit;
width: 50%;
-ms-touch-action: manipulation;
touch-action: manipulation;
text-transform: none;
.custom-select {
display: inline-block;
max-width: 100%;
height: calc(2.25rem + 0.125rem);
padding: .375rem 1.75rem .375rem .75rem;
line-height: 1.25;
vertical-align: middle;
border-width: 0.0625rem;
border-style: solid;
border-radius: .25rem;
-moz-appearance: none;
-webkit-appearance: none;
}
.d-inline-block {
display: inline-block !important;
}
}
optgroup {
font-family: sans-serif;
font-size: 100%;
line-height: 1.15;
margin: 0;
}
/* mounth and Year*/
ngb-datepicker-navigation-select.d-block {
width: 9rem !important;
}

View File

@ -0,0 +1,55 @@
import { Component, Input, Output, EventEmitter, OnChanges, SimpleChanges, ChangeDetectionStrategy } from '@angular/core';
import { NgbDate } from './ngb-date';
import { toInteger } from '../util/util';
import { NgbDatepickerI18nNOA11Y } from './datepicker-i18n';
import { NgbCalendarNOA11Y } from './ngb-calendar';
@Component({
selector: 'ngb-fid-datepicker-navigation-select',
changeDetection: ChangeDetectionStrategy.OnPush,
templateUrl: './datepicker-navigation-select.html',
styleUrls: ['./datepicker-navigation-select.scss'],
})
export class NgbDatepickerNavigationSelectNOA11Y implements OnChanges {
months: number[];
years: number[] = [];
@Input() date: NgbDate;
@Input() disabled: boolean;
@Input() maxDate: NgbDate;
@Input() minDate: NgbDate;
@Output() select = new EventEmitter<NgbDate>();
constructor(public i18n: NgbDatepickerI18nNOA11Y, private calendar: NgbCalendarNOA11Y) { this.months = calendar.getMonths(); }
ngOnChanges(changes: SimpleChanges) {
if (changes['maxDate'] || changes['minDate'] || changes['date']) {
this._generateYears();
this._generateMonths();
}
}
changeMonth(month: string) { this.select.emit(new NgbDate(this.date.year, toInteger(month), 1)); }
changeYear(year: string) { this.select.emit(new NgbDate(toInteger(year), this.date.month, 1)); }
private _generateMonths() {
this.months = this.calendar.getMonths();
if (this.date && this.date.year === this.minDate.year) {
const index = this.months.findIndex(month => month === this.minDate.month);
this.months = this.months.slice(index);
}
if (this.date && this.date.year === this.maxDate.year) {
const index = this.months.findIndex(month => month === this.maxDate.month);
this.months = this.months.slice(0, index + 1);
}
}
private _generateYears() {
this.years = Array.from({ length: this.maxDate.year - this.minDate.year + 1 }, (e, i) => this.minDate.year + i);
}
}

View File

@ -0,0 +1,58 @@
<ng-template #retail>
<div class="isp-datepicker-navigation">
<span>
<!-- Bottone mensile ad una freccia -->
<button type='button' class='btn btn-sm btn-link camillo' (click)='!!doNavigate(navigation.PREV)'
[disabled]='prevDisabled()' tabindex='-1'
[attr.role]="'button'" [attr.aria-label]="' '">
<span class='ngb-dp-navigation-chevron camillo'></span>
</button>
</span>
<div class="header-navigation-date" (click)="setTemplate()">
<ngb-fid-datepicker-navigation-select *ngIf='showSelect' class='d-block' [style.width.rem]='months * 9' [date]='date'
[minDate]='minDate'
[maxDate]='maxDate' [disabled]='disabled'
(select)='selectDate($event)'></ngb-fid-datepicker-navigation-select>
</div>
<span>
<!-- Bottone mensile ad una freccia -->
<button type='button' class='btn btn-sm btn-link camillo' (click)='!!doNavigate(navigation.NEXT)'
[disabled]='nextDisabled()' tabindex='-1'
[attr.role]="'button'" [attr.aria-label]="' '">
<span class='ngb-dp-navigation-chevron right camillo'></span>
</button>
</span>
</div>
</ng-template>
<ng-template #corporate>
<div class="isp-datepicker-navigation">
<span>
<!-- Bottone mensile ad una freccia -->
<button type='button' class='btn btn-sm btn-link camillo' (click)='!!doNavigate(navigation.PREV)'
[disabled]='prevDisabled()' tabindex='-1'
[attr.role]="'button'" [attr.aria-label]="' '">
<span class='icomoon-Simboli_Risorsa-12 camillo'></span>
</button>
</span>
<div class="header-navigation-date" (click)="setTemplate()">
<ngb-fid-datepicker-navigation-select *ngIf='showSelect' class='d-block' [style.width.rem]='months * 9' [date]='date'
[minDate]='minDate'
[maxDate]='maxDate' [disabled]='disabled'
(select)='selectDate($event)'></ngb-fid-datepicker-navigation-select>
</div>
<span>
<!-- Bottone mensile ad una freccia -->
<button type='button' class='btn btn-sm btn-link camillo' (click)='!!doNavigate(navigation.NEXT)'
[disabled]='nextDisabled()' tabindex='-1'
[attr.role]="'button'" [attr.aria-label]="' '">
<span class='icomoon-Simboli_Risorsa-13 right camillo'></span>
</button>
</span>
</div>
</ng-template>
<ng-container [ngTemplateOutlet]="widgetTemplate"></ng-container>

View File

@ -0,0 +1,108 @@
:host(.isp-corporate-mode-wrapper) {
.isp-datepicker-navigation {
span button {
&.btn-link {
span.icomoon-Simboli_Risorsa-13, span.icomoon-Simboli_Risorsa-12 {
&::before {
border: none;
transform: none;
margin: 0;
font-weight: bold!important;
display: inline-block;
height: 0.75rem;
width: 0.75rem;
}
&.right {
&::before {
transform: none;
display: inline-block;
height: 0.75rem;
width: 0.75rem;
}
}
}
}
}
}
}
.isp-datepicker-navigation {
width: 100%;
height: 3.125rem;
line-height: 1.85rem;
-webkit-box-pack: justify !important;
-ms-flex-pack: justify !important;
justify-content: space-between !important;
display: -webkit-box !important;
display: -ms-flexbox !important;
display: flex !important;
border-top-width: 0.0625rem;
border-top-style: solid;
span button {
text-decoration: none;
font-family: sans-serif;
font-size: 100%;
line-height: 1.15;
margin: 0;
text-transform: none;
overflow: visible;
-webkit-appearance: button;
-ms-touch-action: manipulation;
touch-action: manipulation;
&.btn-link {
width: 3.3125rem;
min-height: 100% !important;
cursor: pointer;
border-style: solid;
border-width: 0.0625rem !important;
font-weight: 400;
border-radius: 0;
span.ngb-dp-navigation-chevron {
&::before {
border-style: solid;
border-width: 0.125rem 0.125rem 0rem 0rem;
content: '';
display: inline-block;
height: 0.75rem;
transform: rotate(-135deg);
-webkit-transform: rotate(-135deg);
-ms-transform: rotate(-135deg);
width: 0.75rem;
margin: 0 0 0 0.5rem;
}
&.right {
&::before {
-webkit-transform: rotate(45deg);
-ms-transform: rotate(45deg);
transform: rotate(45deg);
margin: 0 0.5rem 0 0;
}
}
}
}
&.camillo {
display: inline-block;
margin: 0;
padding: 0;
border-top: none;
border-bottom: none;
border-left-width: 0.0625rem;
border-left-style: solid;
border-right-width: 0.0625rem;
border-right-style: solid;
}
}
.header-navigation-date {
min-width: 8.3125rem;
min-height: 100%;
cursor: pointer;
}
}
table, caption, tbody, tfoot, thead, tr, th, td {
margin: 0;
padding: 0;
border: 0;
outline: 0;
font-size: 100%;
vertical-align: baseline;
}

View File

@ -0,0 +1,87 @@
import { Component, Input, Output, EventEmitter, ChangeDetectionStrategy, Injector } from '@angular/core';
import { NavigationEvent } from './datepicker-view-model';
import { NgbDate } from './ngb-date';
import { NgbDatepickerI18nNOA11Y } from './datepicker-i18n';
import { NgbCalendarNOA11Y } from './ngb-calendar';
import { NgbDateStruct } from './ngb-date-struct';
import { NbpBaseComponent } from '@isp/xdce-widget/base';
import { CalendarItemNOA11Y } from './datepicker';
@Component({
selector: 'ngb-fid-datepicker-navigation',
changeDetection: ChangeDetectionStrategy.OnPush,
host: { 'class': 'd-flex justify-content-between', '[class.collapsed]': '!showSelect' },
templateUrl: './datepicker-navigation.html',
styleUrls: ['./datepicker-navigation.scss'],
})
export class NgbDatepickerNavigationNOA11Y extends NbpBaseComponent{
navigation = NavigationEvent;
@Input() date: NgbDate;
@Input() disabled: boolean;
@Input() months: number;
@Input() years: CalendarItemNOA11Y [][];
@Input() showSelect: boolean;
@Input() showWeekNumbers: boolean;
@Input() template: number = 0;
@Input() disabledWeekend: boolean;
@Input() holidays: Array<NgbDateStruct>
@Input() taxDeadlines: Array<NgbDateStruct>
@Output() navigate = new EventEmitter<NavigationEvent>();
@Output() select = new EventEmitter<NgbDate>();
@Output() newTemplate = new EventEmitter<number>();
_minDate: NgbDate;
@Input()
get minDate() {
return this._minDate;
}
set minDate(minDate: NgbDate) {
this._minDate = minDate;
}
_maxDate: NgbDate;
@Input()
get maxDate() {
return this._maxDate;
}
set maxDate(maxDate: NgbDate) {
this._maxDate = maxDate;
}
constructor(public i18n: NgbDatepickerI18nNOA11Y, private _calendar: NgbCalendarNOA11Y, private injector : Injector) {
super(injector);
}
doNavigate(event: NavigationEvent) {
this.navigate.emit(event);
}
nextDisabled() {
let yearsSize = 0;
this.years.forEach(row => yearsSize += row.length);
return this.disabled || (this.maxDate && ((this.template == 0 && this._calendar.getNext(this.date, 'm').after(this.maxDate))
|| (this.template == 1 && this.date.year + 1 > this.maxDate.year)
|| (this.template == 2 && this.years[0][0].number + yearsSize > this.maxDate.year)));
}
prevDisabled() {
let prevMonthDate = new Date(this.date.year, this.date.month + 1, 0);
let prevMonth = new NgbDate(prevMonthDate.getFullYear(), prevMonthDate.getMonth() - 1, prevMonthDate.getDate());
return this.disabled || (this.minDate && ((this.template == 0 && prevMonth.before(this.minDate))
|| (this.template == 1 && this.date.year - 1 < this.minDate.year)
|| (this.template == 2 && this.years[0][0].number - 1 < this.minDate.year)));
}
selectDate(date: NgbDate) {
this.select.emit(date);
}
setTemplate() {
this.template = (this.template + 1) % 3;
this.newTemplate.emit(this.template);
}
}

View File

@ -0,0 +1,3 @@
<div [ngClass]=" abilitaMesi(mese) ? 'ngbdatepickerreplymonthview' : 'ngbdatepickerreplymonthviewdisabled disabledView'">
<span [attr.role]="'button'" [attr.aria-label]="' '" [attr.aria.labelledby]="' '" [attr.aria-describedby]="' '">{{ mese.name | translate | slice: 0:3 | uppercase }}</span>
</div>

View File

@ -0,0 +1,20 @@
div[ngbFidDatepickerReplyMonthView] {
border-radius: 0 !important;
box-sizing: border-box;
text-align: center;
min-width: 4.95rem !important;
height: 2.8125rem !important;
line-height: 2.8125rem !important;
vertical-align: middle !important;
border-right-width: 0.0625rem;
border-right-style: solid;
border-top-width: 0.0625rem;
border-top-style: solid;
border-collapse: collapse;
border-spacing: 0;
.ngbdatepickerreplymonthviewdisabled {
cursor: default;
opacity: 0.5;
}
}

View File

@ -0,0 +1,86 @@
import { ChangeDetectionStrategy, Component, Input, OnInit, OnChanges, SimpleChanges, OnDestroy } from '@angular/core';
import { NgbMeseStruct } from './ngb-mese-struct';
import { NgbYearStruct } from './ngb-year-struct';
import { NgbDatepickerServiceNOA11Y } from './datepicker-service';
import { Subscription } from 'rxjs';
import { DatepickerViewModel } from './datepicker-view-model';
@Component({
selector: '[ngbFidDatepickerReplyMonthView]',
changeDetection: ChangeDetectionStrategy.OnPush,
host: {
'class': 'btn-secondary-month',
'[class.bg-primary]': 'selected',
'[class.text-white]': 'selected',
'[class.text-muted]': 'isMuted()',
'[class.outside]': 'isMuted()',
'[class.active]': 'focused',
'[class.is-current]': 'isCurrent'
},
templateUrl: './datepicker-reply-month-view.html',
styleUrls: ['./datepicker-reply-month-view.scss'],
})
export class NgbDatepickerReplyMonthViewNOA11Y implements OnInit, OnDestroy {
@Input() currentMonth: number;
@Input() mese: NgbMeseStruct;
@Input() year: number;
@Input() disabled: boolean;
@Input() focused: boolean;
@Input() selected: boolean;
@Input() startDateEnabled: any;
@Input() endDateEnabled: any;
isCurrent : boolean = false;
private _sub : Subscription;
ngOnDestroy(): void {
// if(this._sub) {
// this._sub.unsubscribe();
// }
}
ngOnInit() {
const now = new Date();
// console.info('onInit month', this.mese.number, (now.getMonth()+1), this.year, now.getFullYear(), this.mese.number === (now.getMonth()+1), this.year === now.getFullYear());
// console.info('onInit month', typeof (this.mese.number), typeof ((now.getMonth()+1)), typeof (this.year), typeof (now.getFullYear()), this.mese.number === (now.getMonth()+1), this.year === now.getFullYear());
// console.info('onInit month selected', this.selected);
this.isCurrent = this.mese.number === (now.getMonth()+1) && this.year === now.getFullYear();
this.setSelected(this.service._model$.getValue());
}
isMuted() { return false };
abilitaMesi(data) {
return (((this.startDateEnabled.year == this.year && this.startDateEnabled.month <= data.number) ||
(data.number < this.startDateEnabled.month && this.startDateEnabled.year < this.year) ||
(this.startDateEnabled.month <= data.number && this.startDateEnabled.year <= this.year))
&& ((data.number <= this.endDateEnabled.month && this.year <= this.endDateEnabled.year) || (data.number > this.endDateEnabled.month && this.year < this.endDateEnabled.year)))
}
setSelected(model : DatepickerViewModel) {
// console.info('selected:month', model, this.mese, this.year);
if(model && model.selectedDate) {
this.selected = (this.mese && this.mese.number === model.selectedDate.month) && this.year === model.selectedDate.year;
return;
}
// console.info('selected:month no current, checking first');
if(model && model.firstDate) {
this.selected = (this.mese && this.mese.number === model.firstDate.month) && this.year === model.firstDate.year;
return;
}
}
constructor(private service : NgbDatepickerServiceNOA11Y) {
// this._sub = this.service.model$.subscribe(this.setSelected);
}
// isMuted() { return !this.selected && (this.mese.number !== this.currentMonth || this.disabled); }
}

View File

@ -0,0 +1,3 @@
<div [ngClass]=" abilitaAnni(year) ? 'ngbDatepickerReplyYearsView' : 'ngbDatepickerReplyYearsViewdisabled disabledView'">
<span [attr.role]="'button'" [attr.aria-label]="' '" [attr.aria.labelledby]="' '" [attr.aria-describedby]="' '">{{ year.name }}</span>
</div>

View File

@ -0,0 +1,19 @@
div[ngbFidDatepickerReplyYearsView] {
border-radius: 0 !important;
box-sizing: border-box;
text-align: center;
min-width: 4.95rem !important;
height: 2.8125rem !important;
line-height: 2.8125rem !important;
vertical-align: middle !important;
border-right-width: 0.0625rem;
border-right-style: solid;
border-top-width: 0.0625rem;
border-top-style: solid;
border-collapse: collapse;
border-spacing:0.0625rem;
.ngbDatepickerReplyYearsViewdisabled {
cursor: default;
opacity: 0.5;
}
}

View File

@ -0,0 +1,79 @@
import { ChangeDetectionStrategy, Component, Input, OnInit, OnDestroy } from '@angular/core';
import { NgbYearStruct } from './ngb-year-struct';
import { NgbDatepickerServiceNOA11Y } from './datepicker-service';
import { Subscription } from 'rxjs';
import { DatepickerViewModel } from './datepicker-view-model';
@Component({
selector: '[ngbFidDatepickerReplyYearsView]',
changeDetection: ChangeDetectionStrategy.OnPush,
host: {
'class': 'btn-secondary-years',
'[class.bg-primary]': 'selected',
'[class.text-white]': 'selected',
'[class.text-muted]': 'isMuted()',
'[class.outside]': 'isMuted()',
'[class.active]': 'focused',
'[class.is-current]':'isCurrent'
},
templateUrl: './datepicker-reply-years-view.html',
styleUrls: ['./datepicker-reply-years-view.scss'],
})
export class NgbDatepickerReplyYearsViewNOA11Y implements OnInit, OnDestroy {
@Input() currentMonth: number;
@Input() year: NgbYearStruct;
@Input() disabled: boolean;
@Input() focused: boolean;
@Input() selected: boolean;
@Input() startDateEnabled: any;
@Input() endDateEnabled: any;
isCurrent : boolean = false;
private _sub : Subscription;
isMuted() { return false };
ngOnInit(): void {
const now = new Date();
this.isCurrent = this.year.number === now.getFullYear();
this.setSelected(this.service._model$.getValue());
}
setSelected(model : DatepickerViewModel) {
// console.info('selected:year', model, this.year);
if(model && model.selectedDate) {
this.selected = this.year && model.selectedDate.year === this.year.number;
return;
}
// console.info('selected:year no current, checking first');
if(model && model.firstDate) {
this.selected = this.year && model.firstDate.year === this.year.number;
}
}
ngOnDestroy(): void {
// if(this._sub) {
// this._sub.unsubscribe();
// }
}
abilitaAnni(data) {
if(this.startDateEnabled.year <= data.number && data.number <= this.endDateEnabled.year){
return true
}
return false
}
constructor(private service : NgbDatepickerServiceNOA11Y) {
// this._sub = this.service.model$.subscribe(this.setSelected);
}
// isMuted() { return !this.selected && (this.mese.number !== this.currentMonth || this.disabled); }
}

View File

@ -0,0 +1,49 @@
import { RplCalendarNOA11Y } from './datepicker';
import { NgbDatepickerConfigNOA11Y } from './datepicker-config';
import { NgbDatepickerDayViewNOA11Y } from './datepicker-day-view';
import { NgbDatepickerI18nDefaultNOA11Y, NgbDatepickerI18nNOA11Y } from './datepicker-i18n';
import { NgbInputDatepickerNOA11Y } from './datepicker-input';
import { NgbDatepickerNavigationNOA11Y } from './datepicker-navigation';
import { NgbDatepickerNavigationSelectNOA11Y } from './datepicker-navigation-select';
import { NgbDatepickerReplyMonthViewNOA11Y } from './datepicker-reply-month-view';
import { NgbDatepickerReplyYearsViewNOA11Y } from './datepicker-reply-years-view';
import { NgbDatepickerRoutingViewNOA11Y } from './datepicker-routing-view';
import { NgbCalendarGregorianNOA11Y, NgbCalendarNOA11Y } from './ngb-calendar';
import { NgbDateISOParserFormatterNOA11Y, NgbDateParserFormatterNOA11Y } from './ngb-date-parser-formatter';
export * from './datepicker';
export * from './datepicker-config';
export * from './datepicker-day-template-context';
export * from './datepicker-day-view';
export * from './datepicker-i18n';
export * from './datepicker-input';
export * from './datepicker-keymap-service';
export * from './datepicker-navigation';
export * from './datepicker-navigation-select';
export * from './datepicker-reply-month-view';
export * from './datepicker-reply-years-view';
export * from './datepicker-routing-view';
export * from './datepicker-service';
export * from './hijri/ngb-calendar-hijri';
export * from './hijri/ngb-calendar-islamic-civil';
export * from './ngb-calendar';
export * from './ngb-date-parser-formatter';
export const RplDeclarations = [
RplCalendarNOA11Y,
NgbDatepickerRoutingViewNOA11Y,
NgbDatepickerNavigationNOA11Y,
NgbDatepickerNavigationSelectNOA11Y,
NgbDatepickerDayViewNOA11Y,
NgbDatepickerReplyMonthViewNOA11Y,
NgbDatepickerReplyYearsViewNOA11Y,
NgbInputDatepickerNOA11Y
];
export const RplExports = [RplCalendarNOA11Y, NgbInputDatepickerNOA11Y];
export const RplEntryComponents = [RplCalendarNOA11Y];
export const RplRootProviders = [
{ provide: NgbCalendarNOA11Y, useClass: NgbCalendarGregorianNOA11Y },
{ provide: NgbDatepickerI18nNOA11Y, useClass: NgbDatepickerI18nDefaultNOA11Y },
{ provide: NgbDateParserFormatterNOA11Y, useClass: NgbDateISOParserFormatterNOA11Y }, NgbDatepickerConfigNOA11Y
];

View File

@ -0,0 +1,102 @@
<div class="isp-datepicker-routing-view" #ispDatepickerRoutingView>
<div [ngSwitch]="currentTemplate">
<!-- giorni -->
<div *ngSwitchCase=0>
<!-- mesi nell'header. -->
<div *ngIf="showWeekdays" class="ngb-dp-week d-flex">
<div *ngIf="showWeekNumbers" class="ngb-dp-weekday"></div>
<div *ngFor="let w of month.weekdays" class="ngb-dp-weekday small text-center text-info font-italic" [attr.role]="'button'" [attr.aria-label]="' '">
<span [attr.role]="'button'" [attr.aria-label]="' '" [attr.aria-labelledby]="' '">
{{ i18n.getWeekdayShortName(w) | translate | slice: 0:3 }}
</span>
</div>
</div>
<ng-template ngFor let-week [ngForOf]="month.weeks">
<div *ngIf="!isCollapsed(week) && !isHiddenWeek(week)" class="ngb-dp-week d-flex">
<div *ngIf="showWeekNumbers" class="ngb-dp-week-number small text-center font-italic text-muted">
<span [attr.role]="'none'" [attr.aria-label]="' '">{{ week.number }}</span>
</div>
<div *ngFor="let day of week.days" (click)="doSelect(day, $event)" class="ngb-dp-day"
[class.disabled]="day.context.disabled" [class.hidden]="isHidden(day)"
[attr.role]="'none'"
[attr.aria-label]="' '">
<ng-template [ngIf]="!isHidden(day)">
<div ngbFidDatepickerDayView
[ngClass] = "{'cursor-pointer' : !disabledWeekend && !day.context.disabled}"
[date]="day.context.date"
[currentMonth]="day.context.currentMonth"
[selected]="day.context.selected"
[disabled]="day.context.disabled"
[focused]="day.context.focused"
[startDateEnabled]="startDateEnabled"
[endDateEnabled]="endDateEnabled"
[isToday]="day.context.isToday"
[isWeekend]="day.context.isWeekend"
[isHoliday]="day.context.isHoliday"
[taxDeadlines]="taxDeadlines"
[isFiscalDay]="day.context.isFiscalDay"
[attr.role]="'none'"
[attr.aria-label]="' '"
[attr.aria-labelledby]="' '"
[attr.aria-describedby]="' '">
</div>
</ng-template>
</div>
</div>
</ng-template>
</div>
<!-- mesi -->
<div *ngSwitchCase=1>
<div *ngFor="let row of mesi" class="d-flex ngb-dp-mese">
<ng-container *ngFor="let mese of row">
<div ngbFidDatepickerReplyMonthView [mese]="mese" [year]="dataTemplate.year" [selected]="mese.selected"
[disabled]="mese.disabled"
[focused]="mese.focused"
[startDateEnabled]="startDateEnabled"
[endDateEnabled]="endDateEnabled"
[attr.role]="'none'"
[attr.aria-label]="' '"
[attr.aria-labelledby]="' '"
[attr.aria-describedby]="' '"
(click)="doSelectMonth(mese, $event)">
</div>
</ng-container>
</div>
</div>
<!-- anni -->
<div *ngSwitchCase=2>
<div *ngFor="let row of years" class="d-flex ngb-dp-mese">
<ng-container *ngFor="let year of row">
<div ngbFidDatepickerReplyYearsView [year]="year" [selected]="year.selected" [disabled]="year.disabled"
[focused]="year.focused"
[startDateEnabled]="startDateEnabled"
[endDateEnabled]="endDateEnabled"
[attr.role]="'none'"
[attr.aria-label]="' '"
[attr.aria-labelledby]="' '"
[attr.aria-describedby]="' '"
(click)="doSelectYear(year, $event)">
</div>
</ng-container>
</div>
</div>
<!-- default -->
<div *ngSwitchDefault>errore template</div>
</div>
<div><button name="today">Oggi</button><button name="clear">Cancella</button><button name="close">Chiudi</button></div>
</div>

View File

@ -0,0 +1,112 @@
.isp-datepicker-routing-view {
pointer-events: auto;
.d-flex {
display: -webkit-box !important;
display: -ms-flexbox !important;
display: flex !important;
border-bottom-width: 0.0625rem;
border-bottom-style: solid;
border-right-width: 0.0625rem;
border-right-style: solid;
border-left-width: 0.0625rem;
border-left-style: solid;
padding: 0 0.0625rem;
&:first-child:not(.ngb-dp-mese) {
border-top-width: 0.0625rem;
border-top-style: solid;
}
&.ngb-dp-week, &.ngb-dp-mese {
.ngb-dp-day {
width: 2.6875rem !important;
height: 2.5625rem !important;
cursor: pointer;
position: relative;
box-sizing: border-box;
&.disabled, &.hidden {
cursor: default;
}
&:not(:first-child) {
border-left-width: 0.0625rem;
border-left-style: solid;
}
.cursor-pointer {
cursor : pointer !important
}
}
.bg-primary {
&::before {
position: absolute;
top: 0;
right: -0.5rem;
content: '';
display: inline-block;
width: 0;
height: 0;
margin: 0;
padding: 0;
}
}
.btn-secondary {
height: inherit;
font-size: .625rem !important;
}
.btn-secondary, .btn-secondary-month, .btn-secondary-years {
font-weight: bold;
font-size: 0.75rem;
}
div[ngbdatepickerreplymonthview], div[ngbdatepickerreplyyearsview]{
&.btn-secondary-month, &.btn-secondary-years {
border-radius: 0 !important;
box-sizing: border-box;
text-align: center;
min-width: 4.95rem !important;
height: 2.8125rem !important;
line-height: 2.8125rem !important;
vertical-align: middle !important;
border-right-width: 0.0625rem;
border-right-style: solid;
border-top-width: 0.0625rem;
border-top-style: solid;
border-collapse: collapse;
border-spacing: 0;
&:last-child {
border-right-style: none;
border-right-width: 0;
}
.ngbdatepickerreplymonthviewdisabled, .ngbDatepickerReplyYearsViewdisabled {
cursor: default;
opacity: 0.5;
}
.d-flex:first-child & {
border-top-width: 0;
border-top-style: none;
}
}
}
.is-weekend, .is-daypast {
cursor: default;
}
.ngb-dp-weekday, .ngb-dp-week-number {
width: 14.28% !important;
height: 2.375rem !important;
line-height: 2.4375rem;
&.small, & small {
font-size: 80%;
font-weight: 400;
}
&.text-center {
text-align: center !important;
}
&.font-italic {
font-family: 'Arial Bold', 'Arial';
font-weight: 700;
font-style: normal !important;
font-size: .875rem;
text-align: center;
text-transform: uppercase;
}
}
}
}
}

View File

@ -0,0 +1,254 @@
import {
Component, EventEmitter, Input, OnInit, Output,
TemplateRef, ChangeDetectionStrategy, ChangeDetectorRef, SimpleChanges, OnChanges, OnDestroy, ViewChild, ElementRef
} from '@angular/core';
import {DayViewModel, MonthViewModel, WeekViewModel} from './datepicker-view-model';
import {NgbDate} from './ngb-date';
import {NgbDatepickerI18nNOA11Y} from './datepicker-i18n';
import {DayTemplateContextNOA11Y} from './datepicker-day-template-context';
import {NgbDataTemplateStruct} from './ngb-dataTemplate-struct';
import { NgbDatepickerServiceNOA11Y } from './datepicker-service';
import { CalendarItemNOA11Y } from './datepicker';
import { Subscription } from 'rxjs';
@Component({
selector: 'ngb-fid-datepicker-routing-view',
host: { 'class': 'd-block' },
templateUrl: './datepicker-routing-view.html',
styleUrls: ['./datepicker-routing-view.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class NgbDatepickerRoutingViewNOA11Y implements OnInit, OnChanges, OnDestroy {
@Input() dayTemplate: TemplateRef<DayTemplateContextNOA11Y>;
@Input() monthTemplate: TemplateRef<DayTemplateContextNOA11Y>;
@Input() yearsTemplate: TemplateRef<DayTemplateContextNOA11Y>;
@Input() currentTemplate: number;
@Input() mesi: any;
@Input() years: any;
@Input() disabledWeekend : boolean;
@Input() date: any;
@Input() dataTemplate: NgbDataTemplateStruct;
@Input() month: MonthViewModel;
@Input() outsideDays: 'visible' | 'hidden' | 'collapsed';
@Input() showWeekdays;
@Input() showWeekNumbers;
@Input() startDateEnabled: any;
@Input() endDateEnabled: any;
@Input() isToday: boolean;
@Input() isWeekend: boolean;
@Input() taxDeadlines: any;
@Output() select = new EventEmitter<NgbDate>();
@Output() changeTemplate = new EventEmitter<NgbDataTemplateStruct>();
@ViewChild("ispDatepickerRoutingView") routingView: ElementRef;
currentYear : number;
currentMonth : number;
currentDay : number;
sub: Subscription;
constructor(public i18n: NgbDatepickerI18nNOA11Y, private cdr: ChangeDetectorRef, private service : NgbDatepickerServiceNOA11Y) {
}
ngOnInit() {
// alert("in select in routing : " + this.startDateEnabled)
// alert("in select in routing : " + this.endDateEnabled)
// this.currentYear = this.date && this.date.year;
// this.currentMonth = this.date && this.date.month;
// console.info('routing init', this.currentYear, this.currentMonth);
this.dataTemplate.day = this.date && this.date.day;
this.dataTemplate.month = this.date && this.date.month;
this.dataTemplate.year = this.date && this.date.year;
const model = this.service._model$.getValue();
if(model && model.selectedDate) {
this.currentDay = model.selectedDate.day;
this.currentMonth = model.selectedDate.month;
this.currentYear = model.selectedDate.year;
}
// this.sub = this.service.model$.subscribe((model) => {
// if(model.selectedDate) {
// this.currentDay = model.selectedDate.day;
// this.currentMonth = model.selectedDate.month;
// this.currentYear = model.selectedDate.year;
// }
// })
// console.info('routing init', this.date, this.dataTemplate);
}
ngOnDestroy(): void {
// if (this.sub) {
// this.sub.unsubscribe();
// }
}
ngOnChanges(changes : SimpleChanges) {
if(changes.years) {
this.years = [...changes.years.currentValue];
}
if(changes.currentTemplate || changes.dataTemplate) {
this.resetMesi();
this.resetAnni();
const model = this.service._model$.getValue();
if(model && model.selectedDate) {
this.currentDay = model.selectedDate.day;
this.currentMonth = model.selectedDate.month;
this.currentYear = model.selectedDate.year;
}
}
this.cdr.detectChanges();
}
doSelect(day: DayViewModel, $event : any) {
if (!this.abilitaGiorni(day.date)) {
return;
}
if (this.dataTemplate.valid) {
// il day si prende quello selezionato e non quello del dataTemplate
// day.date.day = this.dataTemplate.day;
day.date.month = this.dataTemplate.month;
day.date.year = this.dataTemplate.year;
this.currentYear = day.date.year;
this.currentMonth = day.date.month;
this.currentDay = day.date.day;
this.select.emit(NgbDate.from(day.date));
} else {
if (!day.context.disabled && !this.isHidden(day)) {
this.currentYear = day.date.year;
this.currentMonth = day.date.month;
this.currentDay = day.date.day;
this.select.emit(NgbDate.from(day.date));
}
}
$event.stopPropagation();
}
abilitaGiorni(data) {
let buffer = new Date(data.year, data.month - 1, data.day);
let startDate = new Date(this.startDateEnabled.year, this.startDateEnabled.month - 1, this.startDateEnabled.day);
let endDate = new Date(this.endDateEnabled.year, this.endDateEnabled.month - 1, this.endDateEnabled.day);
return (startDate <= buffer && buffer <= endDate);
}
abilitaMesi(data) {
return (((this.startDateEnabled.year == this.dataTemplate.year && this.startDateEnabled.month <= data.number) ||
(data.number < this.startDateEnabled.month && this.startDateEnabled.year < this.dataTemplate.year) ||
(this.startDateEnabled.month <= data.number && this.startDateEnabled.year <= this.dataTemplate.year))
&& ((data.number <= this.endDateEnabled.month && this.dataTemplate.year <= this.endDateEnabled.year) || (data.number > this.endDateEnabled.month && this.dataTemplate.year < this.endDateEnabled.year)))
}
abilitaAnni(data) {
return (this.startDateEnabled.year <= data.number && data.number <= this.endDateEnabled.year);
}
doSelectMonth(mese: any, $event: any) {
if (!this.abilitaMesi(mese)) {
return;
}
this.currentTemplate = 0;
this.dataTemplate.template = this.currentTemplate;
// reset giorni
this.month.weeks.forEach((week) => {
week.days.forEach((day) => {
day.context.selected = day.date.day === this.currentDay && day.date.month === this.currentMonth && day.date.year === this.currentYear;
})
});
this.resetMesi();
this.dataTemplate.month = mese.number;
this.dataTemplate.valid = true;
this.changeTemplate.emit(this.dataTemplate);
$event.stopPropagation();
}
doSelectYear(year: any, $event: any) {
if (!this.abilitaAnni(year)) {
return;
}
this.currentTemplate = 1;
this.dataTemplate.template = this.currentTemplate;
// resetta mesi e anno
this.resetMesi();
this.dataTemplate.year = year.number;
this.dataTemplate.valid = true;
this.changeTemplate.emit(this.dataTemplate);
$event.stopPropagation();
}
isCollapsed(week: WeekViewModel) {
return this.outsideDays === 'collapsed' && week.days[0].date.month !== this.month.number &&
week.days[week.days.length - 1].date.month !== this.month.number;
}
isHiddenWeek(week: WeekViewModel) {
let counter = 0;
for(let i=0; i<week.days.length; i++) {
if (this.isHidden(week.days[i])) {
counter ++;
}
}
return counter === 7;
}
isHidden(day: DayViewModel) {
return (this.outsideDays === 'hidden' || this.outsideDays === 'collapsed') && this.month.number !== day.date.month;
}
getRoutingViewHeight() {
return this.routingView.nativeElement.offsetHeight;
}
getRoutingViewWidth() {
return this.routingView.nativeElement.offsetWidth;
}
private resetMesi(){
let months : CalendarItemNOA11Y[][] = [];
months = this.mesi.map((row) => {
return row.map((m) => {
const res = {...m};
res.selected = res.number === this.currentMonth && this.dataTemplate.year === this.currentYear;
return res;
})
});
this.mesi = months;
}
private resetAnni() {
let yrs : CalendarItemNOA11Y[][] = [];
yrs = this.years.map((row) => {
return row.map((y) => {
const res = {...y};
res.selected = res.number === this.currentYear;
return res;
});
});
this.years = yrs;
}
}

View File

@ -0,0 +1,273 @@
import {NgbCalendarNOA11Y, NgbPeriodNOA11Y} from './ngb-calendar';
import {NgbDate} from './ngb-date';
import {DatepickerViewModel, NgbMarkDisabled} from './datepicker-view-model';
import {Injectable} from '@angular/core';
import {isInteger} from '../util/util';
import {Subject, Observable, BehaviorSubject} from 'rxjs';
import {buildMonths, checkDateInRange, checkMinBeforeMax, isChangedDate, isDateSelectable} from './datepicker-tools';
import {filter} from 'rxjs/operators';
import { NgbDateStruct } from './ngb-date-struct';
@Injectable()
export class NgbDatepickerServiceNOA11Y {
private _state: DatepickerViewModel =
{disabled: false,
displayMonths: 1,
firstDayOfWeek: 1,
focusVisible: false,
months: [],
selectedDate: null
};
public _model$ = new BehaviorSubject<DatepickerViewModel>(this._state);
get model$() : Observable<DatepickerViewModel> { return this._model$.asObservable().pipe(filter(model => model.months.length > 0)); }
set disabled(disabled: boolean) {
if (this._state.disabled !== disabled) {
this._nextState({disabled: disabled});
}
}
set displayMonths(months: number) {
if (isInteger(months) && months > 0 && this._state.displayMonths !== months) {
this._nextState({displayMonths: months});
}
}
set firstDayOfWeek(firstDayOfWeek: number) {
if (isInteger(firstDayOfWeek) && firstDayOfWeek >= 0 && this._state.firstDayOfWeek !== firstDayOfWeek) {
this._nextState({firstDayOfWeek: firstDayOfWeek});
}
}
set focusVisible(focusVisible: boolean) {
if (this._state.focusVisible !== focusVisible && !this._state.disabled) {
this._nextState({focusVisible: focusVisible});
}
}
set maxDate(date: NgbDate) {
if (date === undefined || this._calendar.isValid(date) && isChangedDate(this._state.maxDate, date)) {
this._nextState({maxDate: date});
}
}
set markDisabled(markDisabled: NgbMarkDisabled) {
if (this._state.markDisabled !== markDisabled) {
this._nextState({markDisabled: markDisabled});
}
}
set minDate(date: NgbDate) {
if (date === undefined || this._calendar.isValid(date) && isChangedDate(this._state.minDate, date)) {
this._nextState({minDate: date});
}
}
set disabledWeekend(disabledWeekend: boolean) {
if (this._state.disabledWeekend !== disabledWeekend) {
this._nextState({disabledWeekend: disabledWeekend});
}
}
set holidays(holidays: Array<NgbDateStruct>) {
if (this._state.holidays !== holidays) {
this._nextState({holidays: holidays});
}
}
set taxDeadlines(taxDeadlines: Array<NgbDateStruct>) {
if (this._state.taxDeadlines !== taxDeadlines) {
this._nextState({taxDeadlines: taxDeadlines});
}
}
constructor(private _calendar: NgbCalendarNOA11Y) {}
focus(date: NgbDate) {
if (!this._state.disabled && this._calendar.isValid(date) && isChangedDate(this._state.focusDate, date)) {
this._nextState({focusDate: date});
}
}
focusMove(period?: NgbPeriodNOA11Y, number?: number) {
this.focus(this._calendar.getNext(this._state.focusDate, period, number));
}
focusSelect() {
if (isDateSelectable(this._state.months, this._state.focusDate)) {
this.select(this._state.focusDate);
}
}
open(date: NgbDate) {
if (!this._state.disabled && this._calendar.isValid(date)) {
this._nextState({firstDate: date});
}
}
select(date: NgbDate) {
const validDate = this.toValidDate(date, null);
if (!this._state.disabled && isChangedDate(this._state.selectedDate, validDate)) {
this._nextState({selectedDate: validDate});
}
}
toValidDate(date: {year: number, month: number, day?: number}, defaultValue?: NgbDate): NgbDate {
const ngbDate = NgbDate.from(date);
if (defaultValue === undefined) {
defaultValue = this._calendar.getToday();
}
return this._calendar.isValid(ngbDate) ? ngbDate : defaultValue;
}
private _nextState(patch: Partial<DatepickerViewModel>) {
const newState = this._updateState(patch);
this._patchContexts(newState);
this._state = newState;
this._model$.next(this._state);
}
private _patchContexts(state: DatepickerViewModel) {
state.months.forEach(month => {
month.weeks.forEach(week => {
week.days.forEach(day => {
// patch focus flag
if (state.focusDate) {
day.context.focused = state.focusDate.equals(day.date) && state.focusVisible;
}
// override context disabled
if (state.disabled === true) {
day.context.disabled = true;
}
// patch selection flag
if (state.selectedDate !== undefined) {
day.context.selected = state.selectedDate !== null && state.selectedDate.equals(day.date);
}
// check if day is today
if (day.date.year === new Date().getFullYear()
&& day.date.month === new Date().getMonth() + 1
&& day.date.day === new Date().getDate()) {
day.context.isToday = true;
} else {
/* Se è un giorno del mese corrente ma passato rispetto ad oggi metto la classe default */
if (day.date.year === new Date().getFullYear()
&& day.date.month === new Date().getMonth() + 1
&& day.date.day < new Date().getDate()) {
day.context.isDayPast = true;
}
}
// check if day is a weekend day
const otherday = new Date(day.date.year, day.date.month - 1, day.date.day);
if (otherday.getDay() === 0 || otherday.getDay() === 6) {
day.context.isWeekend = true;
// disable weekend days if flag disableWeekend is set
if(state.disabledWeekend) {
day.context.disabled = true;
}
/* disabilito i giorni di weekend che non sono del mese visualizzato */
if (day.date.month !== new Date().getMonth() + 1
&& (this._state.focusVisible && day.date.month !== this._state.firstDate.month)) {
day.context.disabled = true;
}
}
// Disabilitazione del giorno nel caso in cui è un giorno di festa
if(state.holidays){
state.holidays.forEach((value, index) => {
if (value.year === day.date.year &&
value.month === day.date.month &&
value.day === day.date.day) {
day.context.disabled = true;
day.context.isHoliday = true;
}
});
}
// Controllo se al componente è stato passato un array contenente i giorni di scadenza fiscale
if(state.taxDeadlines){
state.taxDeadlines.forEach((value, index) => {
if (value.year === day.date.year &&
value.month === day.date.month &&
value.day === day.date.day) {
day.context.isFiscalDay = true;
}
});
}
});
});
});
}
private _updateState(patch: Partial<DatepickerViewModel>): DatepickerViewModel {
// patching fields
const state = Object.assign({}, this._state, patch);
let startDate = state.firstDate;
// min/max dates changed
if ('minDate' in patch || 'maxDate' in patch) {
checkMinBeforeMax(state.minDate, state.maxDate);
state.focusDate = checkDateInRange(state.focusDate, state.minDate, state.maxDate);
state.firstDate = checkDateInRange(state.firstDate, state.minDate, state.maxDate);
startDate = state.focusDate;
}
// disabled
if ('disabled' in patch) {
state.focusVisible = false;
}
// focus date changed
if ('focusDate' in patch) {
state.focusDate = checkDateInRange(state.focusDate, state.minDate, state.maxDate);
startDate = state.focusDate;
// nothing to rebuild if only focus changed and it is still visible
if (state.months.length !== 0 && !state.focusDate.before(state.firstDate) &&
!state.focusDate.after(state.lastDate)) {
return state;
}
}
// first date changed
if ('firstDate' in patch) {
state.firstDate = checkDateInRange(state.firstDate, state.minDate, state.maxDate);
startDate = state.firstDate;
}
// rebuilding months
if (startDate) {
const forceRebuild = 'firstDayOfWeek' in patch || 'markDisabled' in patch || 'minDate' in patch ||
'maxDate' in patch || 'disabled' in patch;
const months = buildMonths(
this._calendar, state.months, startDate, state.minDate, state.maxDate, state.displayMonths,
state.firstDayOfWeek, state.markDisabled, forceRebuild);
// updating months and boundary dates
state.months = months;
state.firstDate = months.length > 0 ? months[0].firstDate : undefined;
state.lastDate = months.length > 0 ? months[months.length - 1].lastDate : undefined;
// adjusting focus after months were built
if ('firstDate' in patch) {
if (state.focusDate === undefined || state.focusDate.before(state.firstDate) ||
state.focusDate.after(state.lastDate)) {
state.focusDate = startDate;
}
}
}
return state;
}
}

View File

@ -0,0 +1,144 @@
import {NgbDate} from './ngb-date';
import {DayViewModel, MonthViewModel, NgbMarkDisabled} from './datepicker-view-model';
import {NgbCalendarNOA11Y} from './ngb-calendar';
export function isChangedDate(prev: NgbDate, next: NgbDate) {
return !dateComparator(prev, next);
}
export function dateComparator(prev: NgbDate, next: NgbDate) {
return (!prev && !next) || (!!prev && !!next && prev.equals(next));
}
export function checkMinBeforeMax(minDate: NgbDate, maxDate: NgbDate) {
if (maxDate && minDate && maxDate.before(minDate)) {
throw new Error(`'maxDate' ${maxDate} should be greater than 'minDate' ${minDate}`);
}
}
export function checkDateInRange(date: NgbDate, minDate: NgbDate, maxDate: NgbDate): NgbDate {
if (date && minDate && date.before(minDate)) {
return NgbDate.from(minDate);
}
if (date && maxDate && date.after(maxDate)) {
return NgbDate.from(maxDate);
}
return date;
}
export function isDateSelectable(months: MonthViewModel[], date: NgbDate) {
let selectable = false;
const month = months.find(curMonth => curMonth.year === date.year && curMonth.number === date.month);
if (month) {
month.weeks.find(week => {
const day = week.days.find(day => date.equals(day.date));
if (day && !day.context.disabled) {
selectable = true;
}
return !!day;
});
}
return selectable;
}
export function buildMonths(
calendar: NgbCalendarNOA11Y, months: MonthViewModel[], date: NgbDate, minDate: NgbDate, maxDate: NgbDate,
displayMonths: number, firstDayOfWeek: number, markDisabled: NgbMarkDisabled, force: boolean): MonthViewModel[] {
const newMonths = [];
for (let i = 0; i < displayMonths; i++) {
const newDate = calendar.getNext(date, 'm', i);
const index = months.findIndex(month => month.firstDate.equals(newDate));
if (force || index === -1) {
newMonths.push(buildMonth(calendar, newDate, minDate, maxDate, firstDayOfWeek, markDisabled));
} else {
newMonths.push(months[index]);
}
}
return newMonths;
}
export function buildMonth(
calendar: NgbCalendarNOA11Y, date: NgbDate, minDate: NgbDate, maxDate: NgbDate, firstDayOfWeek: number,
markDisabled: NgbMarkDisabled): MonthViewModel {
const month:
MonthViewModel = {firstDate: null, lastDate: null, number: date.month, year: date.year, weeks: [], weekdays: []};
date = getFirstViewDate(calendar, date, firstDayOfWeek);
// month has weeks
for (let week = 0; week < calendar.getWeeksPerMonth(); week++) {
const days: DayViewModel[] = [];
// week has days
for (let day = 0; day < calendar.getDaysPerWeek(); day++) {
if (week === 0) {
month.weekdays.push(calendar.getWeekday(date));
}
const newDate = new NgbDate(date.year, date.month, date.day);
const nextDate = calendar.getNext(newDate);
// marking date as disabled
let disabled = !!((minDate && newDate.before(minDate)) || (maxDate && newDate.after(maxDate)));
if (!disabled && markDisabled) {
disabled = markDisabled(newDate, {month: month.number, year: month.year});
}
// saving first date of the month
if (month.firstDate === null && newDate.month === month.number) {
month.firstDate = newDate;
}
// saving last date of the month
if (newDate.month === month.number && nextDate.month !== month.number) {
month.lastDate = newDate;
}
days.push({
date: newDate,
context: {
date: {year: newDate.year, month: newDate.month, day: newDate.day},
currentMonth: month.number,
disabled: disabled,
focused: false,
selected: false,
isToday: false,
isWeekend: false,
isDayPast: false,
isFiscalDay: false
}
});
date = nextDate;
}
month.weeks.push(
{number: calendar.getWeekNumber(days.map(day => NgbDate.from(day.date)), firstDayOfWeek), days: days});
}
return month;
}
export function getFirstViewDate(calendar: NgbCalendarNOA11Y, date: NgbDate, firstDayOfWeek: number): NgbDate {
const currentMonth = date.month;
let today = new NgbDate(date.year, date.month, date.day);
let yesterday = calendar.getPrev(today);
const firstDayOfCurrentMonthIsAlsoFirstDayOfWeek =
() => { return today.month !== yesterday.month && firstDayOfWeek === calendar.getWeekday(today); };
const reachedTheFirstDayOfTheLastWeekOfPreviousMonth =
() => { return today.month !== currentMonth && firstDayOfWeek === calendar.getWeekday(today); };
// going back in time
while (!reachedTheFirstDayOfTheLastWeekOfPreviousMonth() && !firstDayOfCurrentMonthIsAlsoFirstDayOfWeek()) {
today = new NgbDate(yesterday.year, yesterday.month, yesterday.day);
yesterday = calendar.getPrev(yesterday);
}
return today;
}

View File

@ -0,0 +1,51 @@
import {NgbDate} from './ngb-date';
import {NgbDateStruct} from './ngb-date-struct';
import {DayTemplateContextNOA11Y} from './datepicker-day-template-context';
export type NgbMarkDisabled = (date: NgbDateStruct, current: {year: number, month: number}) => boolean;
export type DayViewModel = {
date: NgbDate,
context: DayTemplateContextNOA11Y
}
export type WeekViewModel = {
number: number,
days: DayViewModel[]
}
export type MonthViewModel = {
firstDate: NgbDate,
lastDate: NgbDate,
number: number,
year: number,
weeks: WeekViewModel[],
weekdays: number[]
};
// clang-format off
export type DatepickerViewModel = {
disabled: boolean,
displayMonths: number,
firstDate?: NgbDate,
firstDayOfWeek: number,
focusDate?: NgbDate,
focusVisible: boolean,
lastDate?: NgbDate,
markDisabled?: NgbMarkDisabled,
maxDate?: NgbDate,
minDate?: NgbDate,
months: MonthViewModel[],
selectedDate: NgbDate,
disabledWeekend?: boolean,
holidays?: NgbDateStruct[],
taxDeadlines?: NgbDateStruct[]
}
// clang-format on
export enum NavigationEvent {
PREV,
NEXT,
PREVYEAR,
NEXTYEAR,
}

View File

@ -0,0 +1,78 @@
<!-- intestazione -->
<div class="isp-main-datepicker d-none">
<div class="ngb-dp-header bg-faded pt-1 rounded-top" [style.height.rem]="getHeaderHeight()"
[style.marginBottom.rem]="-getHeaderMargin()">
<!-- componente per la navigazione! Seleziona il template -->
<ngb-fid-datepicker-navigation *ngIf="navigation !== 'none'"
[date]="model.firstDate"
[minDate]="model.minDate"
[maxDate]="model.maxDate"
[months]="model.months.length"
[years]="years"
[template]="template"
[disabled]="model.disabled"
[showWeekNumbers]="showWeekNumbers"
[showSelect]="navigation === 'select'"
[disabledWeekend]="model.disabledWeekend"
[holidays]="model.holidays"
[taxDeadlines]="model.taxDeadlines"
(navigate)="onNavigateEvent($event)"
(select)="onNavigateDateSelect($event)"
(newTemplate)="setNewTemplate($event)"
[attr.role]="'none'"
[attr.label]="' '"
[attr.labelledby]="' '"
[attr.describedby]="' '">
</ngb-fid-datepicker-navigation>
</div>
<!-- corpo componente -->
<div class="ngb-dp-months d-flex px-1 pb-1">
<ng-template ngFor let-month [ngForOf]="model.months" let-i="index">
<div class="ngb-dp-month d-block ml-3">
<div *ngIf="navigation !== 'select' || displayMonths > 1" style="min-width:150px"
class="ngb-dp-month-name text-center" (click)="setNewTemplate((template+1)%3);$event.stopPropagation();">
<div [ngSwitch]="template" style="margin-top:1px">
<div *ngSwitchCase=0 >
{{ i18n.getMonthFullName(dataTemplate.month) | translate }} {{ dataTemplate.year }}
</div>
<div *ngSwitchCase=1>
{{ dataTemplate.year }}
</div>
<div *ngSwitchCase=2>
{{ dataTemplate.year }} - {{ dataTemplate.year + 11 }}
</div>
</div>
</div>
<!-- componente routing che usa il template selezionato-->
<ngb-fid-datepicker-routing-view
[mesi]="mesi"
[years]="years"
[disabledWeekend]="disabledWeekend"
[dataTemplate]="dataTemplate"
[date]="model.firstDate"
[currentTemplate]="template"
[month]="month"
[showWeekdays]="showWeekdays"
[showWeekNumbers]="showWeekNumbers"
[startDateEnabled]="startDateEnabled"
[endDateEnabled]="endDateEnabled"
[outsideDays]="(displayMonths === 1 ? outsideDays : 'hidden')"
[taxDeadlines]="taxDeadlines"
(select)="onDateSelect($event)"
(changeTemplate)="onChangeTemplate($event)"
[attr.role]="'none'"
[attr.label]="' '"
[attr.labelledby]="' '"
[attr.describedby]="' '">
</ngb-fid-datepicker-routing-view>
</div>
</ng-template>
</div>
</div>

View File

@ -0,0 +1,201 @@
:host(.isp-corporate-mode-wrapper) {
&.dropdown-menu {
margin-top: 0;
}
.isp-main-datepicker{
.ngb-dp-header {
height: 2.1875rem!important;
margin-bottom: 0 !important;
& ::ng-deep .isp-datepicker-navigation {
height: 2.1875rem !important;
border-top-left-radius: 0.125rem;
border-top-right-radius: 0.125rem;
span {
button.btn-link {
width: 2.1875rem;
height: 2.1875rem;
font-size: 0.9375rem;
&:disabled {
opacity: 0.5;
cursor: default;
}
}
}
}
}
.ngb-dp-months {
.ngb-dp-month {
.ngb-dp-month-name {
height: 2.1875rem !important;
margin-top: -2.1875rem !important;
top: auto;
line-height: 0.875rem !important;
font-size: 0.75rem !important;
}
& ::ng-deep .isp-datepicker-routing-view {
.d-flex {
border-bottom-style: none;
border-bottom-width: initial;
&:last-child{
border-bottom-width: 0.0625rem;
border-bottom-style: solid;
border-bottom-left-radius: 0.125rem;
border-bottom-right-radius: 0.125rem;
}
&.ngb-dp-mese:first-child {
border-top-width: 0.0625rem;
border-top-style: solid;
}
&.ngb-dp-week, &.ngb-dp-mese {
.ngb-dp-week-number {
height: inherit !important;
line-height: inherit;
width: 2.125rem !important;
font-size: 0.75rem;
}
.ngb-dp-weekday {
height: inherit !important;
line-height: 1.3125rem;
width: 2.125rem !important;
font-size: 0.625rem;
}
.ngb-dp-day {
width: 2.125rem !important;
height: 2.125rem !important;
font-size: 0.75rem;
&:not(:first-child) {
border-left: none;
}
.bg-primary, .btn-secondary {
font-size: 0.75rem;
.ngbdatepickerdayview, .ngbdatepickerdayviewdisabled {
line-height: 2.125rem !important;
}
.ngbdatepickerreplymonthview {
cursor: pointer;
}
.ngbdatepickerdayviewdisabled, .ngbdatepickerreplymonthviewdisabled {
cursor: default;
}
.ngbDatepickerReplyYearsView {
cursor: pointer;
}
.ngbDatepickerReplyYearsView[disabled] {
cursor: default;
}
.ngbDatepickerReplyYearsViewdisabled {
cursor: default;
}
}
.is-weekend, .is-daypast, .text-muted {
.ngbdatepickerdayview{
opacity: .5;
}
}
}
div[ngbdatepickerreplymonthview], div[ngbdatepickerreplyyearsview]{
&.btn-secondary-month, &.btn-secondary-years {
min-width: 0rem !important;
width: 3.75rem !important;
height: 2.125rem !important;
line-height: 2.125rem !important;
border-right: none;
border-top: none;
font-size: 0.75rem;
.ngbdatepickerdayview, .ngbdatepickerreplymonthview {
cursor: pointer;
}
.ngbdatepickerdayviewdisabled, .ngbdatepickerreplymonthviewdisabled {
cursor: default;
}
.ngbDatepickerReplyYearsView {
cursor: pointer;
}
.ngbDatepickerReplyYearsView[disabled] {
cursor: default;
}
.ngbDatepickerReplyYearsViewdisabled {
cursor: default;
}
}
}
}
}
}
}
}
}
}
.isp-main-datepicker {
.justify-content-between {
-webkit-box-pack: justify !important;
-ms-flex-pack: justify !important;
justify-content: space-between !important;
}
.d-flex {
display: -webkit-box !important;
display: -ms-flexbox !important;
display: flex !important;
height: 3.125rem !important;
line-height: 1.875rem !important;
}
.collapsed {
margin-bottom: -2rem;
}
.ngb-dp-header {
height: 4.625rem !important;
margin-bottom: -1.5rem !important;
border-bottom: none !important;
&.pt-1 {
padding-top: 0 !important;
height: 4.25rem;
margin-bottom: -2rem;
}
&.rounded-top {
border-radius: 0 !important;
}
}
.ngb-dp-months {
&.pb-1 {
padding: 0 !important;
}
&.px-1 {
padding-left: 0 !important;
padding-right: 0 !important;
}
.ngb-dp-month {
pointer-events: none;
&:first-child {
margin-left: 0 !important;
}
&.ml-3 {
margin-left: 1rem;
}
&.d-block {
display: block !important;
}
.ngb-dp-month-name {
font-family: 'Arial', sans-serif;
font-size: 1rem !important;
font-weight: 700;
text-transform: uppercase;
position: absolute;
text-align: center !important;
top: 0;
height: 3.125rem !important;
line-height: 1.42857143rem !important;
word-wrap: break-word;
word-break: break-word;
left: 0;
right: 0;
margin-left: auto;
margin-right: auto;
display:flex;
justify-content: center;
align-items: center;
cursor: pointer;
}
}
}
}

View File

@ -0,0 +1,599 @@
import { Subscription } from 'rxjs';
import {
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
Input,
OnChanges,
TemplateRef,
forwardRef,
OnInit,
SimpleChanges,
EventEmitter,
Output,
OnDestroy,
ElementRef, ViewChild, ViewChildren
} from '@angular/core';
import { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms';
import { NgbCalendarNOA11Y } from './ngb-calendar';
import { NgbDate } from './ngb-date';
import { NgbDatepickerServiceNOA11Y } from './datepicker-service';
import { NgbDatepickerKeyMapServiceNOA11Y } from './datepicker-keymap-service';
import { DatepickerViewModel, NavigationEvent } from './datepicker-view-model';
import { toInteger } from '../util/util';
import { DayTemplateContextNOA11Y } from './datepicker-day-template-context';
import { NgbDatepickerConfigNOA11Y } from './datepicker-config';
import { NgbDateStruct } from './ngb-date-struct';
import { NgbDatepickerI18nNOA11Y } from './datepicker-i18n';
import { isChangedDate } from './datepicker-tools';
import { NgbDataTemplateStruct } from './ngb-dataTemplate-struct';
import { EnabledRangeService } from '../../nbp-enabled-range.service';
import {NgbDatepickerRoutingViewNOA11Y} from "./datepicker-routing-view";
const NGB_CALENDAR_VALUE_ACCESSOR = {
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => RplCalendarNOA11Y),
multi: true
};
/**
* The payload of the datepicker navigation event
*/
export interface RplCalendarNavigateEventNOA11Y {
/**
* Currently displayed month
*/
current: { year: number, month: number };
/**
* Month we're navigating to
*/
next: { year: number, month: number };
}
export class CalendarItemNOA11Y {
name: string;
number: number;
focused: boolean;
disabled: boolean;
selected: boolean;
}
/**
* A lightweight and highly configurable datepicker directive
*/
@Component({
exportAs: 'rplCalendarNOA11Y',
selector: 'rpl-calendar-noa11y',
changeDetection: ChangeDetectionStrategy.OnPush,
host: {
'class': 'd-inline-block rounded',
'tabindex': '0',
'[attr.tabindex]': 'model.disabled ? undefined : "0"',
'(blur)': 'showFocus(false)',
'(focus)': 'showFocus(true)',
'(keydown)': 'onKeyDown($event)'
},
templateUrl: './datepicker.html',
styleUrls: ['./datepicker.scss'],
providers: [NGB_CALENDAR_VALUE_ACCESSOR, NgbDatepickerServiceNOA11Y, NgbDatepickerKeyMapServiceNOA11Y]
})
export class RplCalendarNOA11Y implements OnDestroy,
OnChanges, OnInit, ControlValueAccessor {
model: DatepickerViewModel;
@ViewChild(forwardRef(() => NgbDatepickerRoutingViewNOA11Y)) datepickerRoutingView: NgbDatepickerRoutingViewNOA11Y;
@ViewChild(forwardRef(() => NgbDatepickerRoutingViewNOA11Y)) datepickerHeader: NgbDatepickerRoutingViewNOA11Y;
private _subscription: Subscription;
/**
* Reference for the custom template for the day display
*/
@Input() dayTemplate: TemplateRef<DayTemplateContextNOA11Y>;
/**
* Number of months to display
*/
@Input() displayMonths: number;
/**
* First day of the week. With default calendar we use ISO 8601: 'weekday' is 1=Mon ... 7=Sun
*/
@Input() firstDayOfWeek: number;
/**
* Callback to mark a given date as disabled.
* 'Current' contains the month that will be displayed in the view
*/
@Input() markDisabled: (date: NgbDateStruct, current: { year: number, month: number }) => boolean;
/**
* Min date for the navigation. If not provided will be 10 years before today or `startDate`
*/
_minDate: NgbDateStruct;
@Input()
get minDate() {
return this._minDate;
}
set minDate(minDate: NgbDateStruct) {
this._minDate = minDate;
this.startDateEnabled = minDate
}
/**
* Max date for the navigation. If not provided will be 10 years from today or `startDate`
*/
_maxDate: NgbDateStruct;
@Input()
get maxDate() {
return this._maxDate;
}
set maxDate(maxDate: NgbDateStruct) {
this._maxDate = maxDate;
this.endDateEnabled = maxDate;
}
/**
* Navigation type: `select` (default with select boxes for month and year), `arrows`
* (without select boxes, only navigation arrows) or `none` (no navigation at all)
*/
@Input() navigation: 'select' | 'arrows' | 'none';
/**
* The way to display days that don't belong to current month: `visible` (default),
* `hidden` (not displayed) or `collapsed` (not displayed with empty space collapsed)
*/
@Input() outsideDays: 'visible' | 'collapsed' | 'hidden';
/**
* Whether to display days of the week
*/
@Input() showWeekdays: boolean;
/**
* Whether to display week numbers
*/
@Input() showWeekNumbers: boolean;
/**
* Date to open calendar with.
* With default calendar we use ISO 8601: 'month' is 1=Jan ... 12=Dec.
* If nothing or invalid date provided, calendar will open with current month.
* Use 'navigateTo(date)' as an alternative
*/
@Input() startDate: { year: number, month: number, day?: number };
@Input() startDateEnabled: any;
@Input() endDateEnabled: any;
@Input() disabledWeekend: boolean;
@Input() holidays: Array<NgbDateStruct>;
@Input() taxDeadlines: Array<NgbDateStruct>;
// /**
// * Start date Enabled
// */
// @Input() startDateEnabled: { year: number, month: number, day: number };
// /**
// * End date Enabled
// */
// @Input() endDateEnabled: { year: number, month: number, day: number };
/**
* In questa variabile sono memorizzati i dati iniziali che scenderanno l'albero dei template
*/
dataTemplate: NgbDataTemplateStruct = { template: 0, day: 0, month: 0, year: 0, valid: false };
/**
* An event fired when navigation happens and currently displayed month changes.
* See NgbDatepickerNavigateEvent for the payload info.
*/
@Output() navigate = new EventEmitter<NgbDatepickerNavigateEventNOA11Y>();
/**
* Template da Adoperare
*/
template: number = 0;
mesi : CalendarItemNOA11Y[][] = [
[
{ name: "JAN", number: 1, disabled: false, selected: false, focused: false },
{ name: "FEB", number: 2, disabled: false, selected: false, focused: false },
{ name: "MAR", number: 3, disabled: false, selected: false, focused: false },
{ name: "APR", number: 4, disabled: false, selected: false, focused: false }
],
[
{ name: "MAY", number: 5, disabled: false, selected: false, focused: false },
{ name: "JUN", number: 6, disabled: false, selected: false, focused: false },
{ name: "JUL", number: 7, disabled: false, selected: false, focused: false },
{ name: "AUG", number: 8, disabled: false, selected: false, focused: false }
],
[
{ name: "SEP", number: 9, disabled: false, selected: false, focused: false },
{ name: "OCT", number: 10, disabled: false, selected: false, focused: false },
{ name: "NOV", number: 11, disabled: false, selected: false, focused: false },
{ name: "DEC", number: 12, disabled: false, selected: false, focused: false }
]
]
years : CalendarItemNOA11Y [][] = [
[
{ name: "2018", number: 2018, disabled: false, selected: false, focused: false },
{ name: "2019", number: 2019, disabled: false, selected: false, focused: false },
{ name: "2020", number: 2020, disabled: false, selected: false, focused: false },
{ name: "2021", number: 2021, disabled: false, selected: false, focused: false }
],
[
{ name: "2022", number: 2022, disabled: false, selected: false, focused: false },
{ name: "2023", number: 2023, disabled: false, selected: false, focused: false },
{ name: "2024", number: 2024, disabled: false, selected: false, focused: false },
{ name: "2025", number: 2025, disabled: false, selected: false, focused: false }
],
[
{ name: "2026", number: 2026, disabled: false, selected: false, focused: false },
{ name: "2027", number: 2027, disabled: false, selected: false, focused: false },
{ name: "2028", number: 2028, disabled: false, selected: false, focused: false },
{ name: "2029", number: 2029, disabled: false, selected: false, focused: false }
]
]
onChange = (_: any) => { };
onTouched = () => { };
// startDateEnabled: string;
// endDateEnabled: string;
constructor(
private enabledRange: EnabledRangeService,
private _keyMapService: NgbDatepickerKeyMapServiceNOA11Y,
public _service: NgbDatepickerServiceNOA11Y,
private _calendar: NgbCalendarNOA11Y,
public i18n: NgbDatepickerI18nNOA11Y, config: NgbDatepickerConfigNOA11Y,
private _cd: ChangeDetectorRef,
private _elementRef: ElementRef) {
this.dayTemplate = config.dayTemplate;
this.displayMonths = config.displayMonths;
this.firstDayOfWeek = config.firstDayOfWeek;
this.markDisabled = config.markDisabled;
this.minDate = config.minDate;
this.maxDate = config.maxDate;
this.navigation = config.navigation;
this.showWeekdays = config.showWeekdays;
this.showWeekNumbers = config.showWeekNumbers;
this.startDate = config.startDate;
this.disabledWeekend = config.disabledWeekend;
this.holidays = config.holidays;
this.taxDeadlines = config.taxDeadlines;
this.startDateEnabled = enabledRange.startDate;
this.endDateEnabled = enabledRange.endDate;
// alert("finale Start : " + this.startDateEnabled)
// alert("finale End : " + this.endDateEnabled)
this._subscription = _service.model$.subscribe(model => {
const newDate = model.firstDate;
const oldDate = this.model ? this.model.firstDate : null;
const newSelectedDate = model.selectedDate;
const oldSelectedDate = this.model ? this.model.selectedDate : null;
this.model = model;
// handling selection change
if (isChangedDate(newSelectedDate, oldSelectedDate)) {
this.onTouched();
this.onChange(
newSelectedDate ? { year: newSelectedDate.year, month: newSelectedDate.month, day: newSelectedDate.day } :
null);
}
// emitting navigation event if the first month changes
if (!newDate.equals(oldDate)) {
this.navigate.emit({
current: oldDate ? { year: oldDate.year, month: oldDate.month } : null,
next: { year: newDate.year, month: newDate.month }
});
}
_cd.markForCheck();
});
}
abilitaMesi(data) {
if(this.startDateEnabled.month <= data && data <= this.endDateEnabled.month && (this.startDateEnabled.year <= this.dataTemplate.year && this.dataTemplate.year <= this.endDateEnabled.year) ){
return true
}
return false
}
abilitaAnni(data) {
if(this.startDateEnabled.year <= data && data <= this.endDateEnabled.year){
return true
}
return false
}
setNewTemplate(selectedTemplate: number) {
this.setMesi(this.dataTemplate.month, true);
this.updateYears(this.dataTemplate.year);
this.setYear(this.dataTemplate.year, true);
const prevTemplate = this.template;
this.template = selectedTemplate;
if(prevTemplate === 2 && this.template === 0) {
const model = this._service._model$.getValue();
if(model && model.selectedDate) {
this.navigateTo({month: model.selectedDate.month, year: model.selectedDate.year});
}
}
}
setMesi(position: number, selected: boolean) {
if (!this.abilitaMesi(position))
return
let nRow = 0, nCol = 0
if (position == 4)
nRow = 0
else if (position == 8)
nRow = 1
else if (position == 12)
nRow = 2
else
nRow = Math.trunc(position / 4)
nCol = position - (nRow * 4) - 1;
console.info('dataTemplate', this.dataTemplate, 'mese', this.mesi[nRow][nCol], 'nRow', nRow, 'nCol', nCol);
this.mesi[nRow][nCol].selected = selected;
}
updateYears(startYearValue: number) {
let yrs : CalendarItemNOA11Y[][] = [];
for (let j = 0; j < 3; j++) {
yrs[j] = [];
for (let i = 0; i < 4; i++) {
const yr = new CalendarItemNOA11Y();
yr.number = startYearValue + i + j * 4;
yr.name = yr.number+"";
yr.disabled = false;
yr.focused = false;
yr.selected = false;
yrs[j][i]= yr;
// this.years[j][i].number = startYearValue + i + j * 4
// this.years[j][i].name = this.years[j][i].number + "";
}
}
yrs.forEach((row) => {
row.forEach((y) => {
y.selected = this.dataTemplate.year === y.number;
})
})
this.years = yrs;
}
setYear(yearValue: number, selected: boolean) {
if (!this.abilitaAnni(yearValue))
return
this.years.forEach((row) => {
row.forEach((year) => {
if (year.number == yearValue) year.selected = selected
})
})
}
/**
* Manually focus the calendar
*/
focus() { this._elementRef.nativeElement.focus(); }
getHeaderHeight() {
const h = this.showWeekdays ? 6.25 : 4.25;
return this.displayMonths === 1 || this.navigation !== 'select' ? h - 2 : h;
}
getHeaderMargin() {
const m = this.showWeekdays ? 2 : 0;
return this.displayMonths !== 1 || this.navigation !== 'select' ? m + 2 : m;
}
/**
* Navigates current view to provided date.
* With default calendar we use ISO 8601: 'month' is 1=Jan ... 12=Dec.
* If nothing or invalid date provided calendar will open current month.
* Use 'startDate' input as an alternative
*/
navigateTo(date?: { year: number, month: number }) {
this._service.open(date ? new NgbDate(date.year, date.month, 1) : this._calendar.getToday());
}
ngOnDestroy() { this._subscription.unsubscribe(); }
ngOnInit() {
if (this.model === undefined) {
this._service.displayMonths = toInteger(this.displayMonths);
this._service.markDisabled = this.markDisabled;
this._service.firstDayOfWeek = this.firstDayOfWeek;
this._service.disabledWeekend = this.disabledWeekend;
this._service.holidays = this.holidays;
this._service.taxDeadlines = this.taxDeadlines;
this._setDates();
// inixializzazione dataTemplate alla data selezionata
if (!this.startDate || !this.startDate.month || !this.startDate.year) {
this.startDate = { year: null, month: null, day: null };
let today = new Date();
let dd = today.getDate();
let mm = today.getMonth() + 1; //January is 0!
let yyyy = today.getFullYear();
this.startDate.day = dd;
this.startDate.month = mm;
this.startDate.year = yyyy
}
this.dataTemplate.day = this.startDate.day;
this.dataTemplate.month = this.startDate.month;
this.dataTemplate.year = this.startDate.year;
this.dataTemplate.valid = false;
let elem: HTMLElement = this._elementRef.nativeElement;
elem.classList.contains('isp-corporate-mode-wrapper') ? this.outsideDays = 'hidden' : this.outsideDays = 'visible';
}
}
ngOnChanges(changes: SimpleChanges) {
if (changes['displayMonths']) {
this._service.displayMonths = toInteger(this.displayMonths);
}
if (changes['markDisabled']) {
this._service.markDisabled = this.markDisabled;
}
if (changes['firstDayOfWeek']) {
this._service.firstDayOfWeek = this.firstDayOfWeek;
}
if (changes['taxDeadlines']) {
this._service.taxDeadlines = this.taxDeadlines;
}
}
onDateSelect(date: NgbDate) {
this._service.focus(date);
this.writeValue(date);
}
onKeyDown(event: KeyboardEvent) { this._keyMapService.processKey(event); }
onNavigateDateSelect(date: NgbDate) {
this._service.open(date);
}
onNavigateEvent(event: NavigationEvent) {
let bufferData: NgbDate;
this.model.firstDate.month = this.dataTemplate.month;
this.model.firstDate.year = this.dataTemplate.year;
if (event == NavigationEvent.PREV && this.template == 0) {
bufferData = this._calendar.getPrev(this.model.firstDate, 'm', 1)
this._service.open(bufferData);
this.updateDataTemplate(bufferData)
}
else if (NavigationEvent.NEXT && this.template == 0) {
bufferData = this._calendar.getNext(this.model.firstDate, 'm', 1);
this._service.open(bufferData);
this.updateDataTemplate(bufferData)
}
else if (event == NavigationEvent.PREV && this.template == 1) {
bufferData = this._calendar.getPrev(this.model.firstDate, 'm', 12);
this._service.open(bufferData);
this.updateDataTemplate(bufferData);
}
else if (event == NavigationEvent.NEXT && this.template == 1) {
bufferData = this._calendar.getNext(this.model.firstDate, 'm', 12);
this._service.open(bufferData);
this.updateDataTemplate(bufferData)
}
else if (event == NavigationEvent.PREV && this.template == 2) {
bufferData = this._calendar.getPrev(this.model.firstDate, 'm', 144);
this._service.open(bufferData);
this.updateDataTemplate(bufferData);
this.updateYears(this.dataTemplate.year);
}
else if (event == NavigationEvent.NEXT && this.template == 2) {
bufferData = this._calendar.getNext(this.model.firstDate, 'm', 144);
this._service.open(bufferData);
this.updateDataTemplate(bufferData);
this.updateYears(this.dataTemplate.year);
}
}
onChangeTemplate(dataTemplate: NgbDataTemplateStruct) {
this.dataTemplate = dataTemplate;
this.template = dataTemplate.template;
this.navigateTo({month: dataTemplate.month, year: dataTemplate.year});
}
updateDataTemplate(date: NgbDate) {
const newTemplate = {...this.dataTemplate};
newTemplate.day = date.day;
newTemplate.month = date.month;
newTemplate.year = date.year;
this.dataTemplate = newTemplate;
this.navigateTo({month: this.dataTemplate.month, year: this.dataTemplate.year});
}
registerOnChange(fn: (value: any) => any): void { this.onChange = fn; }
registerOnTouched(fn: () => any): void { this.onTouched = fn; }
setDisabledState(isDisabled: boolean) { this._service.disabled = isDisabled; }
showFocus(focusVisible: boolean) { this._service.focusVisible = focusVisible; }
writeValue(value: any) { this._service.select(value); }
private _setDates() {
const startDate = this._service.toValidDate(this.startDate, this._calendar.getToday());
const minDate = this._service.toValidDate(this.minDate, this._calendar.getPrev(startDate, 'y', 10));
const maxDate =
this._service.toValidDate(this.maxDate, this._calendar.getPrev(this._calendar.getNext(startDate, 'y', 11)));
this.minDate = { year: minDate.year, month: minDate.month, day: minDate.day };
this.maxDate = { year: maxDate.year, month: maxDate.month, day: maxDate.day };
this._service.minDate = minDate;
this._service.maxDate = maxDate;
this.navigateTo(startDate);
}
public focusOutComponent(event: any){
if(!this._elementRef.nativeElement.contains(event.target)) {
let elem: HTMLElement = this._elementRef.nativeElement;
if(elem.parentElement) {
elem.parentElement.removeChild(elem);
}
this._subscription.unsubscribe();
}
}
}
/**
* The payload of the calendar navigation event
*/
export interface NgbDatepickerNavigateEventNOA11Y {
/**
* Currently displayed month
*/
current: { year: number, month: number };
/**
* Month we're navigating to
*/
next: { year: number, month: number };
}

View File

@ -0,0 +1,95 @@
import {NgbDate} from '../ngb-date';
import {NgbPeriodNOA11Y, NgbCalendarNOA11Y} from '../ngb-calendar';
import {Injectable} from '@angular/core';
import {isNumber} from '../../util/util';
@Injectable()
export abstract class NgbCalendarHijriNOA11Y extends NgbCalendarNOA11Y {
getDaysPerWeek() { return 7; }
getMonths() { return [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; }
getWeeksPerMonth() { return 6; }
isValid(date: NgbDate): boolean {
return date && isNumber(date.year) && isNumber(date.month) && isNumber(date.day) &&
!isNaN(this.toGregorian(date).getTime());
}
setDay(date: NgbDate, day: number): NgbDate {
day = +day;
let mDays = this.getDaysInIslamicMonth(date.month, date.year);
if (day <= 0) {
while (day <= 0) {
date = this.setMonth(date, date.month - 1);
mDays = this.getDaysInIslamicMonth(date.month, date.year);
day += mDays;
}
} else if (day > mDays) {
while (day > mDays) {
day -= mDays;
date = this.setMonth(date, date.month + 1);
mDays = this.getDaysInIslamicMonth(date.month, date.year);
}
}
date.day = day;
return date;
}
setMonth(date: NgbDate, month: number): NgbDate {
month = +month;
date.year = date.year + Math.floor((month - 1) / 12);
date.month = Math.floor(((month - 1) % 12 + 12) % 12) + 1;
return date;
}
setYear(date: NgbDate, yearValue: number): NgbDate {
date.year = +yearValue;
return date;
}
abstract getWeekday(date: NgbDate): number;
abstract getNext(date: NgbDate, period?: NgbPeriodNOA11Y, number?: number): NgbDate;
abstract getPrev(date: NgbDate, period?: NgbPeriodNOA11Y, number?: number): NgbDate;
abstract getWeekNumber(week: NgbDate[], firstDayOfWeek: number): number;
abstract getToday(): NgbDate;
/**
* Returns the equivalent Hijri date value for a give input Gregorian date.
* `gDate` is s JS Date to be converted to Hijri.
*/
abstract fromGregorian(gDate: Date): NgbDate;
/**
* Converts the current Hijri date to Gregorian.
*/
abstract toGregorian(hijriDate: NgbDate): Date;
/**
* Returns the number of days in a specific Hijri month.
* `month` is 1 for Muharram, 2 for Safar, etc.
* `year` is any Hijri year.
*/
abstract getDaysInIslamicMonth(month: number, year: number): number;
protected _isIslamicLeapYear(year: number): boolean { return (14 + 11 * year) % 30 < 11; }
/**
* Returns the start of Hijri Month.
* `month` is 0 for Muharram, 1 for Safar, etc.
* `year` is any Hijri year.
*/
protected _getMonthStart(year: number, month: number): number {
return Math.ceil(29.5 * month) + (year - 1) * 354 + Math.floor((3 + 11 * year) / 30.0);
}
/**
* Returns the start of Hijri year.
* `year` is any Hijri year.
*/
protected _getYearStart(year: number): number { return (year - 1) * 354 + Math.floor((3 + 11 * year) / 30.0); }
}

View File

@ -0,0 +1,429 @@
import {NgbCalendarIslamicCivilNOA11Y} from './ngb-calendar-islamic-civil';
import {NgbDate} from '../ngb-date';
describe('ngb-calendar-islamic-civil', () => {
const DATE_TABLE = [
[1420, 1, 1, 1999, 3, 17], [1420, 1, 12, 1999, 3, 28], [1420, 1, 23, 1999, 4, 9],
[1420, 2, 4, 1999, 4, 20], [1420, 2, 15, 1999, 4, 31], [1420, 2, 26, 1999, 5, 11],
[1420, 3, 8, 1999, 5, 22], [1420, 3, 19, 1999, 6, 3], [1420, 3, 30, 1999, 6, 14],
[1420, 4, 11, 1999, 6, 25], [1420, 4, 22, 1999, 7, 5], [1420, 5, 4, 1999, 7, 16],
[1420, 5, 15, 1999, 7, 27], [1420, 5, 26, 1999, 8, 7], [1420, 6, 7, 1999, 8, 18],
[1420, 6, 18, 1999, 8, 29], [1420, 6, 29, 1999, 9, 10], [1420, 7, 11, 1999, 9, 21],
[1420, 7, 22, 1999, 10, 1], [1420, 8, 3, 1999, 10, 12], [1420, 8, 14, 1999, 10, 23],
[1420, 9, 29, 2000, 0, 6], [1420, 10, 10, 2000, 0, 17], [1420, 10, 21, 2000, 0, 28],
[1420, 11, 3, 2000, 1, 8], [1420, 11, 14, 2000, 1, 19], [1420, 11, 25, 2000, 2, 1],
[1420, 12, 6, 2000, 2, 12], [1420, 12, 17, 2000, 2, 23], [1420, 12, 28, 2000, 3, 3],
[1421, 1, 9, 2000, 3, 14], [1421, 1, 20, 2000, 3, 25], [1421, 2, 1, 2000, 4, 6],
[1421, 2, 12, 2000, 4, 17], [1421, 2, 23, 2000, 4, 28], [1421, 3, 5, 2000, 5, 8],
[1421, 3, 16, 2000, 5, 19], [1421, 3, 27, 2000, 5, 30], [1421, 4, 8, 2000, 6, 11],
[1421, 4, 19, 2000, 6, 22], [1421, 5, 1, 2000, 7, 2], [1421, 5, 12, 2000, 7, 13],
[1421, 5, 23, 2000, 7, 24], [1421, 6, 4, 2000, 8, 4], [1421, 6, 15, 2000, 8, 15],
[1421, 6, 26, 2000, 8, 26], [1421, 7, 8, 2000, 9, 7], [1421, 7, 19, 2000, 9, 18],
[1421, 7, 30, 2000, 9, 29], [1421, 8, 11, 2000, 10, 9], [1421, 8, 22, 2000, 10, 20],
[1421, 10, 7, 2001, 0, 3], [1421, 10, 18, 2001, 0, 14], [1421, 10, 7, 2001, 0, 3],
[1421, 10, 18, 2001, 0, 14], [1421, 10, 29, 2001, 0, 25], [1421, 11, 11, 2001, 1, 5],
[1421, 11, 22, 2001, 1, 16], [1421, 12, 3, 2001, 1, 27], [1421, 12, 14, 2001, 2, 10],
[1421, 12, 25, 2001, 2, 21], [1422, 1, 7, 2001, 3, 1], [1422, 1, 18, 2001, 3, 12],
[1422, 1, 29, 2001, 3, 23], [1422, 2, 10, 2001, 4, 4], [1422, 2, 21, 2001, 4, 15],
[1422, 3, 3, 2001, 4, 26], [1422, 3, 14, 2001, 5, 6], [1422, 3, 25, 2001, 5, 17],
[1422, 4, 6, 2001, 5, 28], [1422, 4, 17, 2001, 6, 9], [1422, 4, 28, 2001, 6, 20],
[1422, 5, 10, 2001, 6, 31], [1422, 5, 21, 2001, 7, 11], [1422, 6, 2, 2001, 7, 22],
[1422, 6, 13, 2001, 8, 2], [1422, 6, 24, 2001, 8, 13], [1422, 7, 6, 2001, 8, 24],
[1422, 7, 17, 2001, 9, 5], [1422, 7, 28, 2001, 9, 16], [1422, 8, 9, 2001, 9, 27],
[1422, 8, 20, 2001, 10, 7], [1422, 9, 2, 2001, 10, 18], [1422, 9, 13, 2001, 10, 29],
[1422, 9, 24, 2001, 11, 10], [1422, 10, 5, 2001, 11, 21], [1422, 10, 16, 2002, 0, 1],
[1422, 10, 27, 2002, 0, 12], [1422, 11, 9, 2002, 0, 23], [1422, 11, 20, 2002, 1, 3],
[1422, 12, 1, 2002, 1, 14], [1422, 12, 12, 2002, 1, 25], [1422, 12, 23, 2002, 2, 8],
[1423, 1, 5, 2002, 2, 19], [1423, 1, 16, 2002, 2, 30], [1423, 1, 27, 2002, 3, 10],
[1423, 2, 8, 2002, 3, 21], [1423, 2, 19, 2002, 4, 2], [1423, 3, 1, 2002, 4, 13],
[1423, 3, 12, 2002, 4, 24], [1423, 3, 23, 2002, 5, 4], [1423, 4, 4, 2002, 5, 15],
[1423, 4, 15, 2002, 5, 26], [1423, 4, 26, 2002, 6, 7], [1423, 5, 8, 2002, 6, 18],
[1423, 5, 19, 2002, 6, 29], [1423, 5, 30, 2002, 7, 9], [1423, 6, 11, 2002, 7, 20],
[1423, 6, 22, 2002, 7, 31], [1423, 7, 4, 2002, 8, 11], [1423, 7, 15, 2002, 8, 22],
[1423, 7, 26, 2002, 9, 3], [1423, 8, 7, 2002, 9, 14], [1423, 8, 18, 2002, 9, 25],
[1423, 8, 29, 2002, 10, 5], [1423, 9, 11, 2002, 10, 16], [1423, 9, 22, 2002, 10, 27],
[1423, 10, 3, 2002, 11, 8], [1423, 10, 14, 2002, 11, 19], [1423, 10, 25, 2002, 11, 30],
[1423, 11, 7, 2003, 0, 10], [1423, 11, 18, 2003, 0, 21], [1423, 11, 29, 2003, 1, 1],
[1423, 12, 10, 2003, 1, 12], [1423, 12, 21, 2003, 1, 23], [1424, 1, 2, 2003, 2, 6],
[1424, 1, 13, 2003, 2, 17], [1424, 1, 24, 2003, 2, 28], [1424, 2, 5, 2003, 3, 8],
[1424, 2, 16, 2003, 3, 19], [1424, 2, 27, 2003, 3, 30], [1424, 3, 9, 2003, 4, 11],
[1424, 3, 20, 2003, 4, 22], [1424, 4, 1, 2003, 5, 2], [1424, 4, 12, 2003, 5, 13],
[1424, 4, 23, 2003, 5, 24], [1424, 5, 5, 2003, 6, 5], [1424, 5, 16, 2003, 6, 16],
[1424, 5, 27, 2003, 6, 27], [1424, 6, 8, 2003, 7, 7], [1424, 6, 19, 2003, 7, 18],
[1424, 7, 1, 2003, 7, 29], [1424, 7, 12, 2003, 8, 9], [1424, 7, 23, 2003, 8, 20],
[1424, 8, 4, 2003, 9, 1], [1424, 8, 15, 2003, 9, 12], [1424, 8, 26, 2003, 9, 23],
[1424, 9, 8, 2003, 10, 3], [1424, 9, 19, 2003, 10, 14], [1424, 9, 30, 2003, 10, 25],
[1424, 11, 15, 2004, 0, 8], [1424, 11, 26, 2004, 0, 19], [1424, 12, 7, 2004, 0, 30],
[1424, 12, 18, 2004, 1, 10], [1424, 12, 29, 2004, 1, 21], [1425, 1, 11, 2004, 2, 3],
[1425, 1, 22, 2004, 2, 14], [1425, 2, 3, 2004, 2, 25], [1425, 2, 14, 2004, 3, 5],
[1425, 2, 25, 2004, 3, 16], [1425, 3, 7, 2004, 3, 27], [1425, 3, 18, 2004, 4, 8],
[1425, 3, 29, 2004, 4, 19], [1425, 4, 10, 2004, 4, 30], [1425, 4, 21, 2004, 5, 10],
[1425, 5, 3, 2004, 5, 21], [1425, 5, 14, 2004, 6, 2], [1425, 5, 25, 2004, 6, 13],
[1425, 6, 6, 2004, 6, 24], [1425, 6, 17, 2004, 7, 4], [1425, 6, 28, 2004, 7, 15],
[1425, 7, 10, 2004, 7, 26], [1425, 7, 21, 2004, 8, 6], [1425, 8, 2, 2004, 8, 17],
[1425, 8, 13, 2004, 8, 28], [1425, 8, 24, 2004, 9, 9], [1425, 9, 6, 2004, 9, 20],
[1425, 9, 17, 2004, 9, 31], [1425, 9, 28, 2004, 10, 11], [1425, 10, 9, 2004, 10, 22],
[1425, 11, 24, 2005, 0, 5], [1425, 12, 5, 2005, 0, 16], [1425, 12, 16, 2005, 0, 27],
[1425, 12, 27, 2005, 1, 7], [1426, 1, 9, 2005, 1, 18], [1426, 1, 20, 2005, 2, 1],
[1426, 2, 1, 2005, 2, 12], [1426, 2, 12, 2005, 2, 23], [1426, 2, 23, 2005, 3, 3],
[1426, 3, 5, 2005, 3, 14], [1426, 3, 16, 2005, 3, 25], [1426, 3, 27, 2005, 4, 6],
[1426, 4, 8, 2005, 4, 17], [1426, 4, 19, 2005, 4, 28], [1426, 5, 1, 2005, 5, 8],
[1426, 5, 12, 2005, 5, 19], [1426, 5, 23, 2005, 5, 30], [1426, 6, 4, 2005, 6, 11],
[1426, 6, 15, 2005, 6, 22], [1426, 6, 26, 2005, 7, 2], [1426, 7, 8, 2005, 7, 13],
[1426, 7, 19, 2005, 7, 24], [1426, 7, 30, 2005, 8, 4], [1426, 8, 11, 2005, 8, 15],
[1426, 8, 22, 2005, 8, 26], [1426, 9, 4, 2005, 9, 7], [1426, 9, 15, 2005, 9, 18],
[1426, 9, 26, 2005, 9, 29], [1426, 10, 7, 2005, 10, 9], [1426, 10, 18, 2005, 10, 20],
[1426, 10, 29, 2005, 11, 1], [1426, 11, 11, 2005, 11, 12], [1426, 11, 22, 2005, 11, 23],
[1426, 12, 3, 2006, 0, 3], [1426, 12, 14, 2006, 0, 14], [1426, 12, 25, 2006, 0, 25],
[1427, 1, 6, 2006, 1, 5], [1427, 1, 17, 2006, 1, 16], [1427, 1, 28, 2006, 1, 27],
[1427, 2, 9, 2006, 2, 10], [1427, 2, 20, 2006, 2, 21], [1427, 3, 2, 2006, 3, 1],
[1427, 3, 13, 2006, 3, 12], [1427, 3, 24, 2006, 3, 23], [1427, 4, 5, 2006, 4, 4],
[1427, 4, 16, 2006, 4, 15], [1427, 4, 27, 2006, 4, 26], [1427, 5, 9, 2006, 5, 6],
[1427, 5, 20, 2006, 5, 17], [1427, 6, 1, 2006, 5, 28], [1427, 6, 12, 2006, 6, 9],
[1427, 6, 23, 2006, 6, 20], [1427, 7, 5, 2006, 6, 31], [1427, 7, 16, 2006, 7, 11],
[1427, 7, 27, 2006, 7, 22], [1427, 8, 8, 2006, 8, 2], [1427, 8, 19, 2006, 8, 13],
[1427, 9, 1, 2006, 8, 24], [1427, 9, 12, 2006, 9, 5], [1427, 9, 23, 2006, 9, 16],
[1427, 10, 4, 2006, 9, 27], [1427, 10, 15, 2006, 10, 7], [1427, 10, 26, 2006, 10, 18],
[1427, 11, 8, 2006, 10, 29], [1427, 11, 19, 2006, 11, 10], [1427, 11, 30, 2006, 11, 21],
[1427, 12, 11, 2007, 0, 1], [1427, 12, 22, 2007, 0, 12], [1428, 1, 4, 2007, 0, 23],
[1428, 1, 15, 2007, 1, 3], [1428, 1, 26, 2007, 1, 14], [1428, 2, 7, 2007, 1, 25],
[1428, 2, 18, 2007, 2, 8], [1428, 2, 29, 2007, 2, 19], [1428, 3, 11, 2007, 2, 30],
[1428, 3, 22, 2007, 3, 10], [1428, 4, 3, 2007, 3, 21], [1428, 4, 14, 2007, 4, 2],
[1428, 4, 25, 2007, 4, 13], [1428, 5, 7, 2007, 4, 24], [1428, 5, 18, 2007, 5, 4],
[1428, 5, 29, 2007, 5, 15], [1428, 6, 10, 2007, 5, 26], [1428, 6, 21, 2007, 6, 7],
[1428, 7, 3, 2007, 6, 18], [1428, 7, 14, 2007, 6, 29], [1428, 7, 25, 2007, 7, 9],
[1428, 8, 6, 2007, 7, 20], [1428, 8, 17, 2007, 7, 31], [1428, 8, 28, 2007, 8, 11],
[1428, 9, 10, 2007, 8, 22], [1428, 9, 21, 2007, 9, 3], [1428, 10, 2, 2007, 9, 14],
[1428, 10, 13, 2007, 9, 25], [1428, 10, 24, 2007, 10, 5], [1428, 11, 6, 2007, 10, 16],
[1428, 11, 17, 2007, 10, 27], [1429, 1, 1, 2008, 0, 10], [1429, 1, 12, 2008, 0, 21],
[1429, 1, 23, 2008, 1, 1], [1429, 2, 4, 2008, 1, 12], [1429, 2, 15, 2008, 1, 23],
[1429, 2, 26, 2008, 2, 5], [1429, 3, 8, 2008, 2, 16], [1429, 3, 19, 2008, 2, 27],
[1429, 3, 30, 2008, 3, 7], [1429, 4, 11, 2008, 3, 18], [1429, 4, 22, 2008, 3, 29],
[1429, 5, 4, 2008, 4, 10], [1429, 5, 15, 2008, 4, 21], [1429, 5, 26, 2008, 5, 1],
[1429, 6, 7, 2008, 5, 12], [1429, 6, 18, 2008, 5, 23], [1429, 6, 29, 2008, 6, 4],
[1429, 7, 11, 2008, 6, 15], [1429, 7, 22, 2008, 6, 26], [1429, 8, 3, 2008, 7, 6],
[1429, 8, 14, 2008, 7, 17], [1429, 8, 25, 2008, 7, 28], [1429, 9, 7, 2008, 8, 8],
[1429, 9, 18, 2008, 8, 19], [1429, 9, 29, 2008, 8, 30], [1429, 10, 10, 2008, 9, 11],
[1429, 10, 21, 2008, 9, 22], [1429, 11, 3, 2008, 10, 2], [1429, 11, 14, 2008, 10, 13],
[1429, 11, 25, 2008, 10, 24], [1430, 1, 10, 2009, 0, 7], [1430, 1, 21, 2009, 0, 18],
[1430, 2, 2, 2009, 0, 29], [1430, 2, 13, 2009, 1, 9], [1430, 2, 24, 2009, 1, 20],
[1430, 3, 6, 2009, 2, 3], [1430, 3, 17, 2009, 2, 14], [1430, 3, 28, 2009, 2, 25],
[1430, 4, 9, 2009, 3, 5], [1430, 4, 20, 2009, 3, 16], [1430, 5, 2, 2009, 3, 27],
[1430, 5, 13, 2009, 4, 8], [1430, 5, 24, 2009, 4, 19], [1430, 6, 5, 2009, 4, 30],
[1430, 6, 16, 2009, 5, 10], [1430, 6, 27, 2009, 5, 21], [1430, 7, 9, 2009, 6, 2],
[1430, 7, 20, 2009, 6, 13], [1430, 8, 1, 2009, 6, 24], [1430, 8, 12, 2009, 7, 4],
[1430, 8, 23, 2009, 7, 15], [1430, 9, 5, 2009, 7, 26], [1430, 9, 16, 2009, 8, 6],
[1430, 9, 27, 2009, 8, 17], [1430, 10, 8, 2009, 8, 28], [1430, 10, 19, 2009, 9, 9],
[1430, 11, 1, 2009, 9, 20], [1430, 11, 12, 2009, 9, 31], [1430, 11, 23, 2009, 10, 11],
[1430, 12, 4, 2009, 10, 22], [1430, 12, 15, 2009, 11, 3], [1430, 12, 26, 2009, 11, 14],
[1431, 1, 8, 2009, 11, 25], [1431, 1, 19, 2010, 0, 5], [1431, 1, 30, 2010, 0, 16],
[1431, 2, 11, 2010, 0, 27], [1431, 2, 22, 2010, 1, 7], [1431, 3, 4, 2010, 1, 18],
[1431, 3, 15, 2010, 2, 1], [1431, 3, 26, 2010, 2, 12], [1431, 4, 7, 2010, 2, 23],
[1431, 4, 18, 2010, 3, 3], [1431, 4, 29, 2010, 3, 14], [1431, 5, 11, 2010, 3, 25],
[1431, 5, 22, 2010, 4, 6], [1431, 6, 3, 2010, 4, 17], [1431, 6, 14, 2010, 4, 28],
[1431, 6, 25, 2010, 5, 8], [1431, 7, 7, 2010, 5, 19], [1431, 7, 18, 2010, 5, 30],
[1431, 7, 29, 2010, 6, 11], [1431, 8, 10, 2010, 6, 22], [1431, 8, 21, 2010, 7, 2],
[1431, 9, 3, 2010, 7, 13], [1431, 9, 14, 2010, 7, 24], [1431, 9, 25, 2010, 8, 4],
[1431, 10, 6, 2010, 8, 15], [1431, 10, 17, 2010, 8, 26], [1431, 10, 28, 2010, 9, 7],
[1431, 11, 10, 2010, 9, 18], [1431, 11, 21, 2010, 9, 29], [1431, 12, 2, 2010, 10, 9],
[1431, 12, 13, 2010, 10, 20], [1431, 12, 24, 2010, 11, 1], [1432, 1, 5, 2010, 11, 12],
[1432, 1, 16, 2010, 11, 23], [1432, 1, 27, 2011, 0, 3], [1432, 2, 8, 2011, 0, 14],
[1432, 2, 19, 2011, 0, 25], [1432, 3, 1, 2011, 1, 5], [1432, 3, 12, 2011, 1, 16],
[1432, 3, 23, 2011, 1, 27], [1432, 4, 4, 2011, 2, 10], [1432, 4, 15, 2011, 2, 21],
[1432, 4, 26, 2011, 3, 1], [1432, 5, 8, 2011, 3, 12], [1432, 5, 19, 2011, 3, 23],
[1432, 5, 30, 2011, 4, 4], [1432, 6, 11, 2011, 4, 15], [1432, 6, 22, 2011, 4, 26],
[1432, 7, 4, 2011, 5, 6], [1432, 7, 15, 2011, 5, 17], [1432, 7, 26, 2011, 5, 28],
[1432, 8, 7, 2011, 6, 9], [1432, 8, 18, 2011, 6, 20], [1432, 8, 29, 2011, 6, 31],
[1432, 9, 11, 2011, 7, 11], [1432, 9, 22, 2011, 7, 22], [1432, 10, 3, 2011, 8, 2],
[1432, 10, 14, 2011, 8, 13], [1432, 10, 25, 2011, 8, 24], [1432, 11, 7, 2011, 9, 5],
[1432, 11, 18, 2011, 9, 16], [1432, 11, 29, 2011, 9, 27], [1432, 12, 10, 2011, 10, 7],
[1432, 12, 21, 2011, 10, 18], [1433, 1, 3, 2011, 10, 29], [1433, 2, 6, 2012, 0, 1],
[1433, 2, 17, 2012, 0, 12], [1433, 2, 28, 2012, 0, 23], [1433, 3, 10, 2012, 1, 3],
[1433, 3, 21, 2012, 1, 14], [1433, 4, 2, 2012, 1, 25], [1433, 4, 13, 2012, 2, 7],
[1433, 4, 24, 2012, 2, 18], [1433, 5, 6, 2012, 2, 29], [1433, 5, 17, 2012, 3, 9],
[1433, 5, 28, 2012, 3, 20], [1433, 6, 9, 2012, 4, 1], [1433, 6, 20, 2012, 4, 12],
[1433, 7, 2, 2012, 4, 23], [1433, 7, 13, 2012, 5, 3], [1433, 7, 24, 2012, 5, 14],
[1433, 8, 5, 2012, 5, 25], [1433, 8, 16, 2012, 6, 6], [1433, 8, 27, 2012, 6, 17],
[1433, 9, 9, 2012, 6, 28], [1433, 9, 20, 2012, 7, 8], [1433, 10, 1, 2012, 7, 19],
[1433, 10, 12, 2012, 7, 30], [1433, 10, 23, 2012, 8, 10], [1433, 11, 5, 2012, 8, 21],
[1433, 11, 16, 2012, 9, 2], [1433, 11, 27, 2012, 9, 13], [1433, 12, 8, 2012, 9, 24],
[1433, 12, 19, 2012, 10, 4], [1434, 1, 1, 2012, 10, 15], [1434, 1, 12, 2012, 10, 26],
[1434, 2, 26, 2013, 0, 9], [1434, 3, 8, 2013, 0, 20], [1434, 3, 19, 2013, 0, 31],
[1434, 3, 30, 2013, 1, 11], [1434, 4, 11, 2013, 1, 22], [1434, 4, 22, 2013, 2, 5],
[1434, 5, 4, 2013, 2, 16], [1434, 5, 15, 2013, 2, 27], [1434, 5, 26, 2013, 3, 7],
[1434, 6, 7, 2013, 3, 18], [1434, 6, 18, 2013, 3, 29], [1434, 6, 29, 2013, 4, 10],
[1434, 7, 11, 2013, 4, 21], [1434, 7, 22, 2013, 5, 1], [1434, 8, 3, 2013, 5, 12],
[1434, 8, 14, 2013, 5, 23], [1434, 8, 25, 2013, 6, 4], [1434, 9, 7, 2013, 6, 15],
[1434, 9, 18, 2013, 6, 26], [1434, 9, 29, 2013, 7, 6], [1434, 10, 10, 2013, 7, 17],
[1434, 10, 21, 2013, 7, 28], [1434, 11, 3, 2013, 8, 8], [1434, 11, 14, 2013, 8, 19],
[1434, 11, 25, 2013, 8, 30], [1434, 12, 6, 2013, 9, 11], [1434, 12, 17, 2013, 9, 22],
[1434, 12, 28, 2013, 10, 2], [1435, 1, 9, 2013, 10, 13], [1435, 1, 20, 2013, 10, 24],
[1435, 2, 1, 2013, 11, 5], [1435, 2, 12, 2013, 11, 16], [1435, 2, 23, 2013, 11, 27],
[1435, 3, 5, 2014, 0, 7], [1435, 3, 16, 2014, 0, 18], [1435, 3, 27, 2014, 0, 29],
[1435, 4, 8, 2014, 1, 9], [1435, 4, 19, 2014, 1, 20], [1435, 5, 1, 2014, 2, 3],
[1435, 5, 12, 2014, 2, 14], [1435, 5, 23, 2014, 2, 25], [1435, 6, 4, 2014, 3, 5],
[1435, 6, 15, 2014, 3, 16], [1435, 6, 26, 2014, 3, 27], [1435, 7, 8, 2014, 4, 8],
[1435, 7, 19, 2014, 4, 19], [1435, 7, 30, 2014, 4, 30], [1435, 8, 11, 2014, 5, 10],
[1435, 8, 22, 2014, 5, 21], [1435, 9, 4, 2014, 6, 2], [1435, 9, 15, 2014, 6, 13],
[1435, 9, 26, 2014, 6, 24], [1435, 10, 7, 2014, 7, 4], [1435, 10, 18, 2014, 7, 15],
[1435, 10, 29, 2014, 7, 26], [1435, 11, 11, 2014, 8, 6], [1435, 11, 22, 2014, 8, 17],
[1435, 12, 3, 2014, 8, 28], [1435, 12, 14, 2014, 9, 9], [1435, 12, 25, 2014, 9, 20],
[1436, 1, 7, 2014, 9, 31], [1436, 1, 18, 2014, 10, 11], [1436, 1, 29, 2014, 10, 22],
[1436, 2, 10, 2014, 11, 3], [1436, 2, 21, 2014, 11, 14], [1436, 3, 3, 2014, 11, 25],
[1436, 3, 14, 2015, 0, 5], [1436, 3, 25, 2015, 0, 16], [1436, 4, 6, 2015, 0, 27],
[1436, 4, 17, 2015, 1, 7], [1436, 4, 28, 2015, 1, 18], [1436, 5, 10, 2015, 2, 1],
[1436, 5, 21, 2015, 2, 12], [1436, 6, 2, 2015, 2, 23], [1436, 6, 13, 2015, 3, 3],
[1436, 6, 24, 2015, 3, 14], [1436, 7, 6, 2015, 3, 25], [1436, 7, 17, 2015, 4, 6],
[1436, 7, 28, 2015, 4, 17], [1436, 8, 9, 2015, 4, 28], [1436, 8, 20, 2015, 5, 8],
[1436, 9, 2, 2015, 5, 19], [1436, 9, 13, 2015, 5, 30], [1436, 9, 24, 2015, 6, 11],
[1436, 10, 5, 2015, 6, 22], [1436, 10, 16, 2015, 7, 2], [1436, 10, 27, 2015, 7, 13],
[1436, 11, 9, 2015, 7, 24], [1436, 11, 20, 2015, 8, 4], [1436, 12, 1, 2015, 8, 15],
[1436, 12, 12, 2015, 8, 26], [1436, 12, 23, 2015, 9, 7], [1437, 1, 4, 2015, 9, 18],
[1437, 1, 15, 2015, 9, 29], [1437, 1, 26, 2015, 10, 9], [1437, 2, 7, 2015, 10, 20],
[1437, 3, 22, 2016, 0, 3], [1437, 4, 3, 2016, 0, 14], [1437, 4, 14, 2016, 0, 25],
[1437, 4, 25, 2016, 1, 5], [1437, 5, 7, 2016, 1, 16], [1437, 5, 18, 2016, 1, 27],
[1437, 5, 29, 2016, 2, 9], [1437, 6, 10, 2016, 2, 20], [1437, 6, 21, 2016, 2, 31],
[1437, 7, 3, 2016, 3, 11], [1437, 7, 14, 2016, 3, 22], [1437, 7, 25, 2016, 4, 3],
[1437, 8, 6, 2016, 4, 14], [1437, 8, 17, 2016, 4, 25], [1437, 8, 28, 2016, 5, 5],
[1437, 9, 10, 2016, 5, 16], [1437, 9, 21, 2016, 5, 27], [1437, 10, 2, 2016, 6, 8],
[1437, 10, 13, 2016, 6, 19], [1437, 10, 24, 2016, 6, 30], [1437, 11, 6, 2016, 7, 10],
[1437, 11, 17, 2016, 7, 21], [1437, 11, 28, 2016, 8, 1], [1437, 12, 9, 2016, 8, 12],
[1437, 12, 20, 2016, 8, 23], [1438, 1, 2, 2016, 9, 4], [1438, 1, 13, 2016, 9, 15],
[1438, 1, 24, 2016, 9, 26], [1438, 2, 5, 2016, 10, 6], [1438, 2, 16, 2016, 10, 17],
[1438, 2, 27, 2016, 10, 28], [1438, 4, 12, 2017, 0, 11], [1438, 4, 23, 2017, 0, 22],
[1438, 5, 5, 2017, 1, 2], [1438, 5, 16, 2017, 1, 13], [1438, 5, 27, 2017, 1, 24],
[1438, 6, 8, 2017, 2, 7], [1438, 6, 19, 2017, 2, 18], [1438, 7, 1, 2017, 2, 29],
[1438, 7, 12, 2017, 3, 9], [1438, 7, 23, 2017, 3, 20], [1438, 8, 4, 2017, 4, 1],
[1438, 8, 15, 2017, 4, 12], [1438, 8, 26, 2017, 4, 23], [1438, 9, 8, 2017, 5, 3],
[1438, 9, 19, 2017, 5, 14], [1438, 9, 30, 2017, 5, 25], [1438, 10, 11, 2017, 6, 6],
[1438, 10, 22, 2017, 6, 17], [1438, 11, 4, 2017, 6, 28], [1438, 11, 15, 2017, 7, 8],
[1438, 11, 26, 2017, 7, 19], [1438, 12, 7, 2017, 7, 30], [1438, 12, 18, 2017, 8, 10],
[1438, 12, 29, 2017, 8, 21], [1439, 1, 11, 2017, 9, 2], [1439, 1, 22, 2017, 9, 13],
[1439, 2, 3, 2017, 9, 24], [1439, 2, 14, 2017, 10, 4], [1439, 2, 25, 2017, 10, 15],
[1439, 3, 7, 2017, 10, 26], [1439, 3, 18, 2017, 11, 7], [1439, 3, 29, 2017, 11, 18],
[1439, 4, 10, 2017, 11, 29], [1439, 4, 21, 2018, 0, 9], [1439, 5, 3, 2018, 0, 20],
[1439, 5, 14, 2018, 0, 31], [1439, 5, 25, 2018, 1, 11], [1439, 6, 6, 2018, 1, 22],
[1439, 6, 17, 2018, 2, 5], [1439, 6, 28, 2018, 2, 16], [1439, 7, 10, 2018, 2, 27],
[1439, 7, 21, 2018, 3, 7], [1439, 8, 2, 2018, 3, 18], [1439, 8, 13, 2018, 3, 29],
[1439, 8, 24, 2018, 4, 10], [1439, 9, 6, 2018, 4, 21], [1439, 9, 17, 2018, 5, 1],
[1439, 9, 28, 2018, 5, 12], [1439, 10, 9, 2018, 5, 23], [1439, 10, 20, 2018, 6, 4],
[1439, 11, 2, 2018, 6, 15], [1439, 11, 13, 2018, 6, 26], [1439, 11, 24, 2018, 7, 6],
[1439, 12, 5, 2018, 7, 17], [1439, 12, 16, 2018, 7, 28], [1439, 12, 27, 2018, 8, 8],
[1440, 1, 8, 2018, 8, 19], [1440, 1, 19, 2018, 8, 30], [1440, 1, 30, 2018, 9, 11],
[1440, 2, 11, 2018, 9, 22], [1440, 2, 22, 2018, 10, 2], [1440, 3, 4, 2018, 10, 13],
[1440, 3, 15, 2018, 10, 24], [1440, 3, 26, 2018, 11, 5], [1440, 4, 7, 2018, 11, 16],
[1440, 4, 18, 2018, 11, 27], [1440, 4, 29, 2019, 0, 7], [1440, 5, 11, 2019, 0, 18],
[1440, 5, 22, 2019, 0, 29], [1440, 6, 3, 2019, 1, 9], [1440, 6, 14, 2019, 1, 20],
[1440, 6, 25, 2019, 2, 3], [1440, 7, 7, 2019, 2, 14], [1440, 7, 18, 2019, 2, 25],
[1440, 7, 29, 2019, 3, 5], [1440, 8, 10, 2019, 3, 16], [1440, 8, 21, 2019, 3, 27],
[1440, 9, 3, 2019, 4, 8], [1440, 9, 14, 2019, 4, 19], [1440, 9, 25, 2019, 4, 30],
[1440, 10, 6, 2019, 5, 10], [1440, 10, 17, 2019, 5, 21], [1440, 10, 28, 2019, 6, 2],
[1440, 11, 10, 2019, 6, 13], [1440, 11, 21, 2019, 6, 24], [1440, 12, 2, 2019, 7, 4],
[1440, 12, 13, 2019, 7, 15], [1440, 12, 24, 2019, 7, 26], [1441, 1, 6, 2019, 8, 6],
[1441, 1, 17, 2019, 8, 17], [1441, 1, 28, 2019, 8, 28], [1441, 2, 9, 2019, 9, 9],
[1441, 2, 20, 2019, 9, 20], [1441, 3, 2, 2019, 9, 31], [1441, 3, 13, 2019, 10, 11],
[1441, 3, 24, 2019, 10, 22], [1441, 5, 9, 2020, 0, 5], [1441, 5, 20, 2020, 0, 16],
[1441, 6, 1, 2020, 0, 27], [1441, 6, 12, 2020, 1, 7], [1441, 6, 23, 2020, 1, 18],
[1441, 7, 5, 2020, 1, 29], [1441, 7, 16, 2020, 2, 11], [1441, 7, 27, 2020, 2, 22],
[1441, 8, 8, 2020, 3, 2], [1441, 8, 19, 2020, 3, 13], [1441, 9, 1, 2020, 3, 24],
[1441, 9, 12, 2020, 4, 5], [1441, 9, 23, 2020, 4, 16], [1441, 10, 4, 2020, 4, 27],
[1441, 10, 15, 2020, 5, 7], [1441, 10, 26, 2020, 5, 18], [1441, 11, 8, 2020, 5, 29],
[1441, 11, 19, 2020, 6, 10], [1441, 11, 30, 2020, 6, 21], [1441, 12, 11, 2020, 7, 1],
[1441, 12, 22, 2020, 7, 12], [1442, 1, 4, 2020, 7, 23], [1442, 1, 15, 2020, 8, 3],
[1442, 1, 26, 2020, 8, 14], [1442, 2, 7, 2020, 8, 25], [1442, 2, 18, 2020, 9, 6],
[1442, 2, 29, 2020, 9, 17], [1442, 3, 11, 2020, 9, 28], [1442, 3, 22, 2020, 10, 8],
[1442, 4, 3, 2020, 10, 19], [1442, 4, 14, 2020, 10, 30], [1442, 5, 18, 2021, 0, 2],
[1442, 5, 29, 2021, 0, 13], [1442, 6, 10, 2021, 0, 24], [1442, 6, 21, 2021, 1, 4],
[1442, 7, 3, 2021, 1, 15], [1442, 7, 14, 2021, 1, 26], [1442, 7, 25, 2021, 2, 9],
[1442, 8, 6, 2021, 2, 20], [1442, 8, 17, 2021, 2, 31], [1442, 8, 28, 2021, 3, 11],
[1442, 9, 10, 2021, 3, 22], [1442, 9, 21, 2021, 4, 3], [1442, 10, 2, 2021, 4, 14],
[1442, 10, 13, 2021, 4, 25], [1442, 10, 24, 2021, 5, 5], [1442, 11, 6, 2021, 5, 16],
[1442, 11, 17, 2021, 5, 27], [1442, 11, 28, 2021, 6, 8], [1442, 12, 9, 2021, 6, 19],
[1442, 12, 20, 2021, 6, 30], [1443, 1, 1, 2021, 7, 10], [1443, 1, 12, 2021, 7, 21],
[1443, 1, 23, 2021, 8, 1], [1443, 2, 4, 2021, 8, 12], [1443, 2, 15, 2021, 8, 23],
[1443, 2, 26, 2021, 9, 4], [1443, 3, 8, 2021, 9, 15], [1443, 3, 19, 2021, 9, 26],
[1443, 3, 30, 2021, 10, 6], [1443, 4, 11, 2021, 10, 17], [1443, 4, 22, 2021, 10, 28],
[1443, 6, 7, 2022, 0, 11], [1443, 6, 18, 2022, 0, 22], [1443, 6, 29, 2022, 1, 2],
[1443, 7, 11, 2022, 1, 13], [1443, 7, 22, 2022, 1, 24], [1443, 8, 3, 2022, 2, 7],
[1443, 8, 14, 2022, 2, 18], [1443, 8, 25, 2022, 2, 29], [1443, 9, 7, 2022, 3, 9],
[1443, 9, 18, 2022, 3, 20], [1443, 9, 29, 2022, 4, 1], [1443, 10, 10, 2022, 4, 12],
[1443, 10, 21, 2022, 4, 23], [1443, 11, 3, 2022, 5, 3], [1443, 11, 14, 2022, 5, 14],
[1443, 11, 25, 2022, 5, 25], [1443, 12, 6, 2022, 6, 6], [1443, 12, 17, 2022, 6, 17],
[1443, 12, 28, 2022, 6, 28], [1444, 1, 10, 2022, 7, 8], [1444, 1, 21, 2022, 7, 19],
[1444, 2, 2, 2022, 7, 30], [1444, 2, 13, 2022, 8, 10], [1444, 2, 24, 2022, 8, 21],
[1444, 3, 6, 2022, 9, 2], [1444, 3, 17, 2022, 9, 13], [1444, 3, 28, 2022, 9, 24],
[1444, 4, 9, 2022, 10, 4], [1444, 4, 20, 2022, 10, 15], [1444, 5, 2, 2022, 10, 26],
[1444, 6, 16, 2023, 0, 9], [1444, 6, 27, 2023, 0, 20], [1444, 7, 9, 2023, 0, 31],
[1444, 7, 20, 2023, 1, 11], [1444, 8, 1, 2023, 1, 22], [1444, 8, 12, 2023, 2, 5],
[1444, 8, 23, 2023, 2, 16], [1444, 9, 5, 2023, 2, 27], [1444, 9, 16, 2023, 3, 7],
[1444, 9, 27, 2023, 3, 18], [1444, 10, 8, 2023, 3, 29], [1444, 10, 19, 2023, 4, 10],
[1444, 11, 1, 2023, 4, 21], [1444, 11, 12, 2023, 5, 1], [1444, 11, 23, 2023, 5, 12],
[1444, 12, 4, 2023, 5, 23], [1444, 12, 15, 2023, 6, 4], [1444, 12, 26, 2023, 6, 15],
[1445, 1, 8, 2023, 6, 26], [1445, 1, 19, 2023, 7, 6], [1445, 1, 30, 2023, 7, 17],
[1445, 2, 11, 2023, 7, 28], [1445, 2, 22, 2023, 8, 8], [1445, 3, 4, 2023, 8, 19],
[1445, 3, 15, 2023, 8, 30], [1445, 3, 26, 2023, 9, 11], [1445, 4, 7, 2023, 9, 22],
[1445, 4, 18, 2023, 10, 2], [1445, 4, 29, 2023, 10, 13], [1445, 5, 11, 2023, 10, 24],
[1445, 6, 25, 2024, 0, 7], [1445, 7, 7, 2024, 0, 18], [1445, 7, 18, 2024, 0, 29],
[1445, 7, 29, 2024, 1, 9], [1445, 8, 10, 2024, 1, 20], [1445, 8, 21, 2024, 2, 2],
[1445, 9, 3, 2024, 2, 13], [1445, 9, 14, 2024, 2, 24], [1445, 9, 25, 2024, 3, 4],
[1445, 10, 6, 2024, 3, 15], [1445, 10, 17, 2024, 3, 26], [1445, 10, 28, 2024, 4, 7],
[1445, 11, 10, 2024, 4, 18], [1445, 11, 21, 2024, 4, 29], [1445, 12, 2, 2024, 5, 9],
[1445, 12, 13, 2024, 5, 20], [1445, 12, 24, 2024, 6, 1], [1446, 1, 5, 2024, 6, 12],
[1446, 1, 16, 2024, 6, 23], [1446, 1, 27, 2024, 7, 3], [1446, 2, 8, 2024, 7, 14],
[1446, 2, 19, 2024, 7, 25], [1446, 3, 1, 2024, 8, 5], [1446, 3, 12, 2024, 8, 16],
[1446, 3, 23, 2024, 8, 27], [1446, 4, 4, 2024, 9, 8], [1446, 4, 15, 2024, 9, 19],
[1446, 4, 26, 2024, 9, 30], [1446, 5, 8, 2024, 10, 10], [1446, 5, 19, 2024, 10, 21],
[1446, 7, 4, 2025, 0, 4], [1446, 7, 15, 2025, 0, 15], [1446, 7, 26, 2025, 0, 26],
[1446, 8, 7, 2025, 1, 6], [1446, 8, 18, 2025, 1, 17], [1446, 8, 29, 2025, 1, 28],
[1446, 9, 11, 2025, 2, 11], [1446, 9, 22, 2025, 2, 22], [1446, 10, 3, 2025, 3, 2],
[1446, 10, 14, 2025, 3, 13], [1446, 10, 25, 2025, 3, 24], [1446, 11, 7, 2025, 4, 5],
[1446, 11, 18, 2025, 4, 16], [1446, 11, 29, 2025, 4, 27], [1446, 12, 10, 2025, 5, 7],
[1446, 12, 21, 2025, 5, 18], [1447, 1, 3, 2025, 5, 29], [1447, 1, 14, 2025, 6, 10],
[1447, 1, 25, 2025, 6, 21], [1447, 2, 6, 2025, 7, 1], [1447, 2, 17, 2025, 7, 12],
[1447, 2, 28, 2025, 7, 23], [1447, 3, 10, 2025, 8, 3], [1447, 3, 21, 2025, 8, 14],
[1447, 4, 2, 2025, 8, 25], [1447, 4, 13, 2025, 9, 6], [1447, 4, 24, 2025, 9, 17],
[1447, 5, 6, 2025, 9, 28], [1447, 5, 17, 2025, 10, 8], [1447, 5, 28, 2025, 10, 19],
[1447, 6, 9, 2025, 10, 30], [1447, 7, 13, 2026, 0, 2], [1447, 7, 24, 2026, 0, 13],
[1447, 8, 5, 2026, 0, 24], [1447, 8, 16, 2026, 1, 4], [1447, 8, 27, 2026, 1, 15],
[1447, 9, 9, 2026, 1, 26], [1447, 9, 20, 2026, 2, 9], [1447, 10, 1, 2026, 2, 20],
[1447, 10, 12, 2026, 2, 31], [1447, 10, 23, 2026, 3, 11], [1447, 11, 5, 2026, 3, 22],
[1447, 11, 16, 2026, 4, 3], [1447, 11, 27, 2026, 4, 14], [1447, 12, 8, 2026, 4, 25],
[1447, 12, 19, 2026, 5, 5], [1447, 12, 30, 2026, 5, 16], [1448, 1, 11, 2026, 5, 27],
[1448, 1, 22, 2026, 6, 8], [1448, 2, 3, 2026, 6, 19], [1448, 2, 14, 2026, 6, 30],
[1448, 2, 25, 2026, 7, 10], [1448, 3, 7, 2026, 7, 21], [1448, 3, 18, 2026, 8, 1],
[1420, 8, 22, 1999, 11, 1], [1424, 10, 6, 2003, 11, 1], [1428, 11, 21, 2007, 11, 1],
[1433, 1, 5, 2011, 11, 1]
];
const calendar = new NgbCalendarIslamicCivilNOA11Y();
describe('toGregorian', () => {
DATE_TABLE.forEach(element => {
let iDate = new NgbDate(element[0], element[1], element[2]);
let gDate = new Date(element[3], element[4], element[5]);
it('should convert correctly from Hijri to Gregorian',
() => { expect(calendar.toGregorian(iDate).getTime()).toEqual(gDate.getTime()); });
});
});
describe('fromGregorian', () => {
DATE_TABLE.forEach(element => {
let iDate = new NgbDate(element[0], element[1], element[2]);
const gDate = new Date(element[3], element[4], element[5]);
let iDate2 = calendar.fromGregorian(gDate);
it('should convert correctly from Gregorian to Hijri', () => { expect(iDate2.equals(iDate)).toBeTruthy(); });
});
});
it('should return number of days per week', () => { expect(calendar.getDaysPerWeek()).toBe(7); });
it('should return number of weeks per month', () => { expect(calendar.getWeeksPerMonth()).toBe(6); });
it('should return months of a year', () => {
expect(calendar.getMonths()).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]);
});
it('should return day of week', () => {
expect(calendar.getWeekday(new NgbDate(1437, 12, 15))).toEqual(7);
expect(calendar.getWeekday(new NgbDate(1437, 12, 16))).toEqual(1);
expect(calendar.getWeekday(new NgbDate(1437, 12, 17))).toEqual(2);
expect(calendar.getWeekday(new NgbDate(1437, 12, 18))).toEqual(3);
expect(calendar.getWeekday(new NgbDate(1437, 12, 19))).toEqual(4);
expect(calendar.getWeekday(new NgbDate(1437, 12, 20))).toEqual(5);
expect(calendar.getWeekday(new NgbDate(1437, 12, 21))).toEqual(6);
expect(calendar.getWeekday(new NgbDate(1431, 1, 11))).toEqual(1);
expect(calendar.getWeekday(new NgbDate(1431, 7, 22))).toEqual(7);
expect(calendar.getWeekday(new NgbDate(1431, 2, 3))).toEqual(2);
expect(calendar.getWeekday(new NgbDate(1431, 3, 10))).toEqual(3);
expect(calendar.getWeekday(new NgbDate(1431, 4, 23))).toEqual(4);
expect(calendar.getWeekday(new NgbDate(1202, 2, 19))).toEqual(5);
expect(calendar.getWeekday(new NgbDate(1431, 7, 21))).toEqual(6);
});
it('should add days to date', () => {
expect(calendar.getNext(new NgbDate(1431, 1, 30))).toEqual(new NgbDate(1431, 2, 1));
expect(calendar.getNext(new NgbDate(1437, 2, 28))).toEqual(new NgbDate(1437, 2, 29));
expect(calendar.getNext(new NgbDate(1437, 2, 29))).toEqual(new NgbDate(1437, 3, 1));
});
it('should subtract days from date', () => {
expect(calendar.getPrev(new NgbDate(1431, 2, 1))).toEqual(new NgbDate(1431, 1, 30));
expect(calendar.getPrev(new NgbDate(1431, 3, 1))).toEqual(new NgbDate(1431, 2, 29));
expect(calendar.getPrev(new NgbDate(1437, 3, 5))).toEqual(new NgbDate(1437, 3, 4));
});
it('should add months to date', () => {
expect(calendar.getNext(new NgbDate(1437, 8, 22), 'm')).toEqual(new NgbDate(1437, 9, 1));
expect(calendar.getNext(new NgbDate(1437, 8, 1), 'm')).toEqual(new NgbDate(1437, 9, 1));
expect(calendar.getNext(new NgbDate(1437, 12, 22), 'm')).toEqual(new NgbDate(1438, 1, 1));
});
it('should subtract months from date', () => {
expect(calendar.getPrev(new NgbDate(1437, 8, 22), 'm')).toEqual(new NgbDate(1437, 7, 1));
expect(calendar.getPrev(new NgbDate(1437, 9, 1), 'm')).toEqual(new NgbDate(1437, 8, 1));
expect(calendar.getPrev(new NgbDate(1437, 1, 22), 'm')).toEqual(new NgbDate(1436, 12, 1));
});
it('should add years to date', () => {
expect(calendar.getNext(new NgbDate(1437, 2, 22), 'y')).toEqual(new NgbDate(1438, 1, 1));
expect(calendar.getNext(new NgbDate(1438, 12, 22), 'y')).toEqual(new NgbDate(1439, 1, 1));
});
it('should subtract years from date', () => {
expect(calendar.getPrev(new NgbDate(1437, 12, 22), 'y')).toEqual(new NgbDate(1436, 1, 1));
expect(calendar.getPrev(new NgbDate(1438, 2, 22), 'y')).toEqual(new NgbDate(1437, 1, 1));
});
it('should return week number', () => {
let week = [
new NgbDate(1437, 1, 4), new NgbDate(1437, 1, 5), new NgbDate(1437, 1, 6), new NgbDate(1437, 1, 7),
new NgbDate(1437, 1, 8), new NgbDate(1437, 1, 9), new NgbDate(1437, 1, 10)
];
expect(calendar.getWeekNumber(week, 7)).toEqual(2);
week = [
new NgbDate(1437, 12, 15), new NgbDate(1437, 12, 16), new NgbDate(1437, 12, 17), new NgbDate(1437, 12, 18),
new NgbDate(1437, 12, 19), new NgbDate(1437, 12, 20), new NgbDate(1437, 12, 21)
];
expect(calendar.getWeekNumber(week, 7)).toEqual(50);
week = [
new NgbDate(1437, 12, 22), new NgbDate(1437, 12, 23), new NgbDate(1437, 12, 24), new NgbDate(1437, 12, 25),
new NgbDate(1437, 12, 26), new NgbDate(1437, 12, 27), new NgbDate(1437, 12, 28)
];
expect(calendar.getWeekNumber(week, 7)).toEqual(51);
});
describe('setDay', () => {
it('should return correct value of day', () => {
expect(calendar.setDay(new NgbDate(1202, 9, 1), 19).day).toEqual(19);
expect(calendar.setDay(new NgbDate(1431, 1, 1), 1).day).toEqual(1);
expect(calendar.setDay(new NgbDate(1431, 1, 1), 31).day).toEqual(1);
expect(calendar.setDay(new NgbDate(1437, 1, 1), 61).day).toEqual(2);
expect(calendar.setDay(new NgbDate(1431, 2, 1), 0).day).toEqual(30);
expect(calendar.setDay(new NgbDate(1431, 2, 1), -1).day).toEqual(29);
expect(calendar.setDay(new NgbDate(1431, 2, 1), -2).day).toEqual(28);
});
});
describe('setMonth', () => {
it('should return correct value of month', () => {
expect(calendar.setMonth(new NgbDate(1202, 9, 1), 9).month).toEqual(9);
expect(calendar.setMonth(new NgbDate(1431, 1, 30), 1).month).toEqual(1);
expect(calendar.setDay(new NgbDate(1431, 1, 1), 31).month).toEqual(2);
expect(calendar.setDay(new NgbDate(1437, 1, 1), 61).month).toEqual(3);
expect(calendar.setDay(new NgbDate(1431, 2, 1), -1).month).toEqual(1);
expect(calendar.setDay(new NgbDate(1431, 2, 1), -30).month).toEqual(12);
expect(calendar.setMonth(new NgbDate(1431, 1, 1), 0).month).toEqual(12);
});
});
describe('setYear', () => {
it('should return correct value of yar', () => {
expect(calendar.setYear(new NgbDate(1200, 1, 1), 1202).year).toEqual(1202);
expect(calendar.setYear(new NgbDate(1430, 11, 30), 1431).year).toEqual(1431);
expect(calendar.setDay(new NgbDate(1431, 12, 1), 31).year).toEqual(1432);
expect(calendar.setMonth(new NgbDate(1431, 1, 1), 13).year).toEqual(1432);
expect(calendar.setMonth(new NgbDate(1431, 1, 1), 25).year).toEqual(1433);
expect(calendar.setDay(new NgbDate(1431, 1, 1), -1).year).toEqual(1430);
expect(calendar.setMonth(new NgbDate(1431, 1, 1), 0).year).toEqual(1430);
expect(calendar.setMonth(new NgbDate(1431, 1, 1), -13).year).toEqual(1429);
});
});
});

View File

@ -0,0 +1,153 @@
import {NgbCalendarHijriNOA11Y} from './ngb-calendar-hijri';
import {NgbDate} from '../ngb-date';
import {NgbPeriodNOA11Y} from '../ngb-calendar';
import {Injectable} from '@angular/core';
function isGregorianLeapYear(date: Date): boolean {
const year = date.getFullYear();
return year % 4 === 0 && year % 100 !== 0 || year % 400 === 0;
}
function mod(a: number, b: number): number {
return a - b * Math.floor(a / b);
}
/**
* The civil calendar is one type of Hijri calendars used in islamic countries.
* Uses a fixed cycle of alternating 29- and 30-day months,
* with a leap day added to the last month of 11 out of every 30 years.
* http://cldr.unicode.org/development/development-process/design-proposals/islamic-calendar-types
* All the calculations here are based on the equations from "Calendrical Calculations" By Edward M. Reingold, Nachum
* Dershowitz.
*/
const GREGORIAN_EPOCH = 1721425.5;
const ISLAMIC_EPOCH = 1948439.5;
@Injectable()
export class NgbCalendarIslamicCivilNOA11Y extends NgbCalendarHijriNOA11Y {
/**
* Returns the equivalent islamic(civil) date value for a give input Gregorian date.
* `gdate` is a JS Date to be converted to Hijri.
*/
fromGregorian(gdate: Date): NgbDate {
const date = new Date(gdate);
const gYear = date.getFullYear(), gMonth = date.getMonth(), gDay = date.getDate();
let julianDay = GREGORIAN_EPOCH - 1 + 365 * (gYear - 1) + Math.floor((gYear - 1) / 4) +
-Math.floor((gYear - 1) / 100) + Math.floor((gYear - 1) / 400) +
Math.floor(
(367 * (gMonth + 1) - 362) / 12 + (gMonth + 1 <= 2 ? 0 : isGregorianLeapYear(date) ? -1 : -2) + gDay);
julianDay = Math.floor(julianDay) + 0.5;
const days = julianDay - ISLAMIC_EPOCH;
const hYear = Math.floor((30 * days + 10646) / 10631.0);
let hMonth = Math.ceil((days - 29 - this._getYearStart(hYear)) / 29.5);
hMonth = Math.min(hMonth, 11);
const hDay = Math.ceil(days - this._getMonthStart(hYear, hMonth)) + 1;
return new NgbDate(hYear, hMonth + 1, hDay);
}
/**
* Returns the equivalent JS date value for a give input islamic(civil) date.
* `hijriDate` is an islamic(civil) date to be converted to Gregorian.
*/
toGregorian(hijriDate: NgbDate): Date {
const hYear = hijriDate.year;
const hMonth = hijriDate.month - 1;
const hDate = hijriDate.day;
const julianDay =
hDate + Math.ceil(29.5 * hMonth) + (hYear - 1) * 354 + Math.floor((3 + 11 * hYear) / 30) + ISLAMIC_EPOCH - 1;
const wjd = Math.floor(julianDay - 0.5) + 0.5, depoch = wjd - GREGORIAN_EPOCH,
quadricent = Math.floor(depoch / 146097), dqc = mod(depoch, 146097), cent = Math.floor(dqc / 36524),
dcent = mod(dqc, 36524), quad = Math.floor(dcent / 1461), dquad = mod(dcent, 1461),
yindex = Math.floor(dquad / 365);
let year = quadricent * 400 + cent * 100 + quad * 4 + yindex;
if (!(cent === 4 || yindex === 4)) {
year++;
}
const gYearStart = GREGORIAN_EPOCH + 365 * (year - 1) + Math.floor((year - 1) / 4) - Math.floor((year - 1) / 100) +
Math.floor((year - 1) / 400);
const yearday = wjd - gYearStart;
const tjd = GREGORIAN_EPOCH - 1 + 365 * (year - 1) + Math.floor((year - 1) / 4) - Math.floor((year - 1) / 100) +
Math.floor((year - 1) / 400) + Math.floor(739 / 12 + (isGregorianLeapYear(new Date(year, 3, 1)) ? -1 : -2) + 1);
const leapadj = wjd < tjd ? 0 : isGregorianLeapYear(new Date(year, 3, 1)) ? 1 : 2;
const month = Math.floor(((yearday + leapadj) * 12 + 373) / 367);
const tjd2 = GREGORIAN_EPOCH - 1 + 365 * (year - 1) + Math.floor((year - 1) / 4) - Math.floor((year - 1) / 100) +
Math.floor((year - 1) / 400) +
Math.floor(
(367 * month - 362) / 12 + (month <= 2 ? 0 : isGregorianLeapYear(new Date(year, month - 1, 1)) ? -1 : -2) +
1);
const day = wjd - tjd2 + 1;
return new Date(year, month - 1, day);
}
/**
* Returns the number of days in a specific Hijri month.
* `month` is 1 for Muharram, 2 for Safar, etc.
* `year` is any Hijri year.
*/
getDaysInIslamicMonth(month: number, year: number): number {
year = year + Math.floor(month / 13);
month = ((month - 1) % 12) + 1;
let length = 29 + month % 2;
if (month === 12 && this._isIslamicLeapYear(year)) {
length++;
}
return length;
}
getNext(date: NgbDate, period: NgbPeriodNOA11Y = 'd', number = 1) {
date = NgbDate.from(date);
switch (period) {
case 'y':
date = this.setYear(date, date.year + number);
date.month = 1;
date.day = 1;
return date;
case 'm':
date = this.setMonth(date, date.month + number);
date.day = 1;
return date;
case 'd':
return this.setDay(date, date.day + number);
default:
return date;
}
}
getPrev(date: NgbDate, period: NgbPeriodNOA11Y = 'd', number = 1) { return this.getNext(date, period, -number); }
getWeekday(date: NgbDate) {
const day = this.toGregorian(date).getDay();
// in JS Date Sun=0, in ISO 8601 Sun=7
return day === 0 ? 7 : day;
}
getWeekNumber(week: NgbDate[], firstDayOfWeek: number) {
// in JS Date Sun=0, in ISO 8601 Sun=7
if (firstDayOfWeek === 7) {
firstDayOfWeek = 0;
}
const thursdayIndex = (4 + 7 - firstDayOfWeek) % 7;
const date = week[thursdayIndex];
const jsDate = this.toGregorian(date);
jsDate.setDate(jsDate.getDate() + 4 - (jsDate.getDay() || 7)); // Thursday
const time = jsDate.getTime();
const MuhDate = this.toGregorian(new NgbDate(date.year, 1, 1)); // Compare with Muharram 1
return Math.floor(Math.round((time - MuhDate.getTime()) / 86400000) / 7) + 1;
}
getToday(): NgbDate { return this.fromGregorian(new Date()); }
}

View File

@ -0,0 +1,100 @@
import {NgbDate} from './ngb-date';
import {Injectable} from '@angular/core';
import {isInteger} from '../util/util';
function fromJSDate(jsDate: Date) {
return new NgbDate(jsDate.getFullYear(), jsDate.getMonth() + 1, jsDate.getDate());
}
function toJSDate(date: NgbDate) {
const jsDate = new Date(date.year, date.month - 1, date.day, 12);
// this is done avoid 30 -> 1930 conversion
if (!isNaN(jsDate.getTime())) {
jsDate.setFullYear(date.year);
}
return jsDate;
}
export type NgbPeriodNOA11Y = 'y' | 'm' | 'd';
@Injectable()
export abstract class NgbCalendarNOA11Y {
abstract getDaysPerWeek(): number;
abstract getMonths(): number[];
abstract getWeeksPerMonth(): number;
abstract getWeekday(date: NgbDate): number;
abstract getNext(date: NgbDate, period?: NgbPeriodNOA11Y, number?: number): NgbDate;
abstract getPrev(date: NgbDate, period?: NgbPeriodNOA11Y, number?: number): NgbDate;
abstract getWeekNumber(week: NgbDate[], firstDayOfWeek: number): number;
abstract getToday(): NgbDate;
abstract isValid(date: NgbDate): boolean;
}
@Injectable()
export class NgbCalendarGregorianNOA11Y extends NgbCalendarNOA11Y {
getDaysPerWeek() { return 7; }
getMonths() { return [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; }
getWeeksPerMonth() { return 6; }
getNext(date: NgbDate, period: NgbPeriodNOA11Y = 'd', number = 1) {
let jsDate = toJSDate(date);
switch (period) {
case 'y':
return new NgbDate(date.year + number, 1, 1);
case 'm':
jsDate = new Date(date.year, date.month + number - 1, 1, 12);
break;
case 'd':
jsDate.setDate(jsDate.getDate() + number);
break;
default:
return date;
}
return fromJSDate(jsDate);
}
getPrev(date: NgbDate, period: NgbPeriodNOA11Y = 'd', number = 1) { return this.getNext(date, period, -number); }
getWeekday(date: NgbDate) {
let jsDate = toJSDate(date);
let day = jsDate.getDay();
// in JS Date Sun=0, in ISO 8601 Sun=7
return day === 0 ? 7 : day;
}
getWeekNumber(week: NgbDate[], firstDayOfWeek: number) {
// in JS Date Sun=0, in ISO 8601 Sun=7
if (firstDayOfWeek === 7) {
firstDayOfWeek = 0;
}
const thursdayIndex = (4 + 7 - firstDayOfWeek) % 7;
let date = week[thursdayIndex];
const jsDate = toJSDate(date);
jsDate.setDate(jsDate.getDate() + 4 - (jsDate.getDay() || 7)); // Thursday
const time = jsDate.getTime();
jsDate.setMonth(0); // Compare with Jan 1
jsDate.setDate(1);
return Math.floor(Math.round((time - jsDate.getTime()) / 86400000) / 7) + 1;
}
getToday(): NgbDate { return fromJSDate(new Date()); }
isValid(date: NgbDate): boolean {
if (!date || !isInteger(date.year) || !isInteger(date.month) || !isInteger(date.day)) {
return false;
}
const jsDate = toJSDate(date);
return !isNaN(jsDate.getTime()) && jsDate.getFullYear() === date.year && jsDate.getMonth() + 1 === date.month &&
jsDate.getDate() === date.day;
}
}

View File

@ -0,0 +1,26 @@
export interface NgbDataTemplateStruct {
/**
* Il template selezionato
*/
template: number;
/**
* Il numero del giorno
*/
day: number;
/**
* Il numero del mese
*/
month: number;
/**
* Il numero dell'anno
*/
year: number;
/**
* Se i dati sono validi o meno
*/
valid: boolean;
}

View File

@ -0,0 +1,46 @@
import { NbpCalendarPattern, NbpDateSeparator } from '../../nbp-calendar-generic.enum';
import {padNumber, toInteger, isNumber} from '../util/util';
import {NgbDateStruct} from './ngb-date-struct';
/**
* Abstract type serving as a DI token for the service parsing and formatting dates for the NgbInputDatepicker
* directive. A default implementation using the ISO 8601 format is provided, but you can provide another implementation
* to use an alternative format.
*/
export abstract class NgbDateParserFormatterNOA11Y {
/**
* Parses the given value to an NgbDateStruct. Implementations should try their best to provide a result, even
* partial. They must return null if the value can't be parsed.
* @param value the value to parse
*/
abstract parse(value: string, pattern?: NbpCalendarPattern): NgbDateStruct;
/**
* Formats the given date to a string. Implementations should return an empty string if the given date is null,
* and try their best to provide a partial result if the given date is incomplete or invalid.
* @param date the date to format as a string
*/
abstract format(date: NgbDateStruct, pattern?: NbpCalendarPattern, separator?: NbpDateSeparator): string;
}
export class NgbDateISOParserFormatterNOA11Y extends NgbDateParserFormatterNOA11Y {
parse(value: string): NgbDateStruct {
if (value) {
const dateParts = value.trim().split('-');
if (dateParts.length === 1 && isNumber(dateParts[0])) {
return {year: toInteger(dateParts[0]), month: null, day: null};
} else if (dateParts.length === 2 && isNumber(dateParts[0]) && isNumber(dateParts[1])) {
return {year: toInteger(dateParts[0]), month: toInteger(dateParts[1]), day: null};
} else if (dateParts.length === 3 && isNumber(dateParts[0]) && isNumber(dateParts[1]) && isNumber(dateParts[2])) {
return {year: toInteger(dateParts[0]), month: toInteger(dateParts[1]), day: toInteger(dateParts[2])};
}
}
return null;
}
format(date: NgbDateStruct): string {
return date ?
`${date.year}-${isNumber(date.month) ? padNumber(date.month) : ''}-${isNumber(date.day) ? padNumber(date.day) : ''}` :
'';
}
}

View File

@ -0,0 +1,19 @@
/**
* Interface of the model of the NgbDatepicker and NgbInputDatepicker directives
*/
export interface NgbDateStruct {
/**
* The year, for example 2016
*/
year: number;
/**
* The month, with default calendar we use ISO 8601: 1=Jan ... 12=Dec
*/
month: number;
/**
* The day of month, starting at 1
*/
day: number;
}

View File

@ -0,0 +1,46 @@
export class NgbDate {
static from(date: {year: number, month: number, day?: number}) {
return date ? new NgbDate(date.year, date.month, date.day ? date.day : 1) : null;
}
constructor(public year: number, public month: number, public day: number) {}
equals(other: NgbDate) {
return other && this.year === other.year && this.month === other.month && this.day === other.day;
}
before(other: NgbDate) {
if (!other) {
return false;
}
if (this.year === other.year) {
if (this.month === other.month) {
return this.day === other.day ? false : this.day < other.day;
} else {
return this.month < other.month;
}
} else {
return this.year < other.year;
}
}
after(other: NgbDate) {
if (!other) {
return false;
}
if (this.year === other.year) {
if (this.month === other.month) {
return this.day === other.day ? false : this.day > other.day;
} else {
return this.month > other.month;
}
} else {
return this.year > other.year;
}
}
toStruct() { return {year: this.year, month: this.month, day: this.day}; }
toString() { return `${this.year}-${this.month}-${this.day}`; }
}

View File

@ -0,0 +1,14 @@
/**
* Interface of the model of the NgbDatepicker and NgbInputDatepicker directives
*/
export interface NgbMeseStruct {
/**
* Il nome del mese
*/
name: string;
/**
* Il numero del mese
*/
number: number;
}

View File

@ -0,0 +1,14 @@
/**
* Interface of the model of the NgbDatepicker and NgbInputDatepicker directives
*/
export interface NgbYearStruct {
/**
* Il nome del mese
*/
name: string;
/**
* Il numero del mese
*/
number: number;
}

View File

@ -0,0 +1,59 @@
import {
Injector,
TemplateRef,
ViewRef,
ViewContainerRef,
Renderer2,
ComponentRef,
ComponentFactory,
ComponentFactoryResolver
} from '@angular/core';
export class ContentRef {
constructor(public nodes: any[], public viewRef?: ViewRef, public componentRef?: ComponentRef<any>) {}
}
export class PopupService<T> {
private _windowFactory: ComponentFactory<T>;
private _windowRef: ComponentRef<T>;
private _contentRef: ContentRef;
constructor(
type: any, private _injector: Injector, private _viewContainerRef: ViewContainerRef, private _renderer: Renderer2,
componentFactoryResolver: ComponentFactoryResolver) {
this._windowFactory = componentFactoryResolver.resolveComponentFactory<T>(type);
}
open(content?: string | TemplateRef<any>, context?: any): ComponentRef<T> {
if (!this._windowRef) {
this._contentRef = this._getContentRef(content, context);
this._windowRef =
this._viewContainerRef.createComponent(this._windowFactory, 0, this._injector, this._contentRef.nodes);
}
return this._windowRef;
}
close() {
if (this._windowRef) {
this._viewContainerRef.remove(this._viewContainerRef.indexOf(this._windowRef.hostView));
this._windowRef = null;
if (this._contentRef.viewRef) {
this._viewContainerRef.remove(this._viewContainerRef.indexOf(this._contentRef.viewRef));
this._contentRef = null;
}
}
}
private _getContentRef(content: string | TemplateRef<any>, context?: any): ContentRef {
if (!content) {
return new ContentRef([]);
} else if (content instanceof TemplateRef) {
const viewRef = this._viewContainerRef.createEmbeddedView(<TemplateRef<T>>content, context);
return new ContentRef([viewRef.rootNodes], viewRef);
} else {
return new ContentRef([[this._renderer.createText(`${content}`)]]);
}
}
}

View File

@ -0,0 +1,192 @@
import {Positioning} from './positioning';
describe('Positioning', () => {
const positioning = new Positioning();
const documentMargin = document.documentElement.style.margin;
const bodyMargin = document.body.style.margin;
const bodyHeight = document.body.style.height;
const bodyWidth = document.body.style.width;
function createElement(height: number, width: number, marginTop: number, marginLeft: number): HTMLElement {
let element = document.createElement('div');
element.style.display = 'inline-block';
element.style.height = height + 'px';
element.style.width = width + 'px';
element.style.marginTop = marginTop + 'px';
element.style.marginLeft = marginLeft + 'px';
return element;
}
let element = createElement(200, 300, 100, 150);
document.body.appendChild(element);
let targetElement = createElement(50, 100, 10, 20);
document.body.appendChild(targetElement);
document.documentElement.style.margin = '0';
document.body.style.margin = '0';
document.body.style.height = '2000px';
document.body.style.width = '2000px';
it('should calculate the element offset', () => {
let position = positioning.offset(element);
expect(position.height).toBe(200);
expect(position.width).toBe(300);
expect(position.top).toBe(100);
expect(position.bottom).toBe(300);
expect(position.left).toBe(150);
expect(position.right).toBe(450);
});
it('should calculate the element offset when scrolled', () => {
document.documentElement.scrollTop = 1000;
document.documentElement.scrollLeft = 1000;
let position = positioning.offset(element);
expect(position.top).toBe(100);
expect(position.bottom).toBe(300);
expect(position.left).toBe(150);
expect(position.right).toBe(450);
document.documentElement.scrollTop = 0;
document.documentElement.scrollLeft = 0;
});
it('should calculate the element position', () => {
let position = positioning.position(element);
expect(position.height).toBe(200);
expect(position.width).toBe(300);
expect(position.top).toBe(100);
expect(position.bottom).toBe(300);
expect(position.left).toBe(150);
expect(position.right).toBe(450);
});
it('should calculate the element position when scrolled', () => {
document.documentElement.scrollTop = 1000;
document.documentElement.scrollLeft = 1000;
let position = positioning.position(element);
expect(position.top).toBe(100);
expect(position.bottom).toBe(300);
expect(position.left).toBe(150);
expect(position.right).toBe(450);
document.documentElement.scrollTop = 0;
document.documentElement.scrollLeft = 0;
});
it('should calculate the element position on positioned ancestor', () => {
let childElement = createElement(100, 150, 50, 75);
element.style.position = 'relative';
element.appendChild(childElement);
let position = positioning.position(childElement);
expect(position.top).toBe(50);
expect(position.bottom).toBe(150);
expect(position.left).toBe(75);
expect(position.right).toBe(225);
element.style.position = '';
element.removeChild(childElement);
});
it('should position the element top-left', () => {
let position = positioning.positionElements(element, targetElement, 'top-left');
expect(position.top).toBe(50);
expect(position.left).toBe(150);
});
it('should position the element top-center', () => {
let position = positioning.positionElements(element, targetElement, 'top');
expect(position.top).toBe(50);
expect(position.left).toBe(250);
});
it('should position the element top-right', () => {
let position = positioning.positionElements(element, targetElement, 'top-right');
expect(position.top).toBe(50);
expect(position.left).toBe(350);
});
it('should position the element bottom-left', () => {
let position = positioning.positionElements(element, targetElement, 'bottom-left');
expect(position.top).toBe(300);
expect(position.left).toBe(150);
});
it('should position the element bottom-center', () => {
let position = positioning.positionElements(element, targetElement, 'bottom');
expect(position.top).toBe(300);
expect(position.left).toBe(250);
});
it('should position the element bottom-right', () => {
let position = positioning.positionElements(element, targetElement, 'bottom-right');
expect(position.top).toBe(300);
expect(position.left).toBe(350);
});
it('should position the element left-top', () => {
let position = positioning.positionElements(element, targetElement, 'left-top');
expect(position.top).toBe(100);
expect(position.left).toBe(50);
});
it('should position the element left-center', () => {
let position = positioning.positionElements(element, targetElement, 'left');
expect(position.top).toBe(175);
expect(position.left).toBe(50);
});
it('should position the element left-bottom', () => {
let position = positioning.positionElements(element, targetElement, 'left-bottom');
expect(position.top).toBe(250);
expect(position.left).toBe(50);
});
it('should position the element right-top', () => {
let position = positioning.positionElements(element, targetElement, 'right-top');
expect(position.top).toBe(100);
expect(position.left).toBe(450);
});
it('should position the element right-center', () => {
let position = positioning.positionElements(element, targetElement, 'right');
expect(position.top).toBe(175);
expect(position.left).toBe(450);
});
it('should position the element right-bottom', () => {
let position = positioning.positionElements(element, targetElement, 'right-bottom');
expect(position.top).toBe(250);
expect(position.left).toBe(450);
});
it('cleanUp', () => {
document.body.removeChild(element);
document.body.removeChild(targetElement);
document.documentElement.style.margin = documentMargin;
document.body.style.margin = bodyMargin;
document.body.style.height = bodyHeight;
document.body.style.width = bodyWidth;
});
});

View File

@ -0,0 +1,151 @@
// previous version:
// https://github.com/angular-ui/bootstrap/blob/07c31d0731f7cb068a1932b8e01d2312b796b4ec/src/position/position.js
export class Positioning {
private getStyle(element: HTMLElement, prop: string): string { return window.getComputedStyle(element)[prop]; }
private isStaticPositioned(element: HTMLElement): boolean {
return (this.getStyle(element, 'position') || 'static') === 'static';
}
private offsetParent(element: HTMLElement): HTMLElement {
let offsetParentEl = <HTMLElement>element.offsetParent || document.documentElement;
while (offsetParentEl && offsetParentEl !== document.documentElement && this.isStaticPositioned(offsetParentEl)) {
offsetParentEl = <HTMLElement>offsetParentEl.offsetParent;
}
return offsetParentEl || document.documentElement;
}
position(element: HTMLElement, round = true): ClientRect {
let elPosition: ClientRect;
let parentOffset: ClientRect = {width: 0, height: 0, top: 0, bottom: 0, left: 0, right: 0};
if (this.getStyle(element, 'position') === 'fixed') {
elPosition = element.getBoundingClientRect();
} else {
const offsetParentEl = this.offsetParent(element);
elPosition = this.offset(element, false);
if (offsetParentEl !== document.documentElement) {
parentOffset = this.offset(offsetParentEl, false);
}
parentOffset.top += offsetParentEl.clientTop;
parentOffset.left += offsetParentEl.clientLeft;
}
elPosition.top -= parentOffset.top;
elPosition.bottom -= parentOffset.top;
elPosition.left -= parentOffset.left;
elPosition.right -= parentOffset.left;
if (round) {
elPosition.top = Math.round(elPosition.top);
elPosition.bottom = Math.round(elPosition.bottom);
elPosition.left = Math.round(elPosition.left);
elPosition.right = Math.round(elPosition.right);
}
return elPosition;
}
offset(element: HTMLElement, round = true): ClientRect {
const elBcr = element.getBoundingClientRect();
const viewportOffset = {
top: window.pageYOffset - document.documentElement.clientTop,
left: window.pageXOffset - document.documentElement.clientLeft
};
let elOffset = {
height: elBcr.height || element.offsetHeight,
width: elBcr.width || element.offsetWidth,
top: elBcr.top + viewportOffset.top,
bottom: elBcr.bottom + viewportOffset.top,
left: elBcr.left + viewportOffset.left,
right: elBcr.right + viewportOffset.left
};
if (round) {
elOffset.height = Math.round(elOffset.height);
elOffset.width = Math.round(elOffset.width);
elOffset.top = Math.round(elOffset.top);
elOffset.bottom = Math.round(elOffset.bottom);
elOffset.left = Math.round(elOffset.left);
elOffset.right = Math.round(elOffset.right);
}
return elOffset;
}
positionElements(hostElement: HTMLElement, targetElement: HTMLElement, placement: string, appendToBody?: boolean):
ClientRect {
const hostElPosition = appendToBody ? this.offset(hostElement, false) : this.position(hostElement, false);
const targetElBCR = targetElement.getBoundingClientRect();
const placementPrimary = placement.split('-')[0] || 'top';
const placementSecondary = placement.split('-')[1] || 'center';
let targetElPosition: ClientRect = {
'height': targetElBCR.height || targetElement.offsetHeight,
'width': targetElBCR.width || targetElement.offsetWidth,
'top': 0,
'bottom': targetElBCR.height || targetElement.offsetHeight,
'left': 0,
'right': targetElBCR.width || targetElement.offsetWidth
};
switch (placementPrimary) {
case 'top':
targetElPosition.top = hostElPosition.top - targetElement.offsetHeight;
break;
case 'bottom':
targetElPosition.top = hostElPosition.top + hostElPosition.height;
break;
case 'left':
targetElPosition.left = hostElPosition.left - targetElement.offsetWidth;
break;
case 'right':
targetElPosition.left = hostElPosition.left + hostElPosition.width;
break;
}
switch (placementSecondary) {
case 'top':
targetElPosition.top = hostElPosition.top;
break;
case 'bottom':
targetElPosition.top = hostElPosition.top + hostElPosition.height - targetElement.offsetHeight;
break;
case 'left':
targetElPosition.left = hostElPosition.left;
break;
case 'right':
targetElPosition.left = hostElPosition.left + hostElPosition.width - targetElement.offsetWidth;
break;
case 'center':
if (placementPrimary === 'top' || placementPrimary === 'bottom') {
targetElPosition.left = hostElPosition.left + hostElPosition.width / 2 - targetElement.offsetWidth / 2;
} else {
targetElPosition.top = hostElPosition.top + hostElPosition.height / 2 - targetElement.offsetHeight / 2;
}
break;
}
targetElPosition.top = Math.round(targetElPosition.top);
targetElPosition.bottom = Math.round(targetElPosition.bottom);
targetElPosition.left = Math.round(targetElPosition.left);
targetElPosition.right = Math.round(targetElPosition.right);
return targetElPosition;
}
}
const positionService = new Positioning();
export function positionElements(
hostElement: HTMLElement, targetElement: HTMLElement, placement: string, appendToBody?: boolean): void {
const pos = positionService.positionElements(hostElement, targetElement, placement, appendToBody);
targetElement.style.top = `${pos.top}px`;
targetElement.style.left = `${pos.left}px`;
}

View File

@ -0,0 +1,88 @@
import {parseTriggers} from './triggers';
describe('triggers', () => {
describe('parseTriggers', () => {
it('should parse single trigger', () => {
const t = parseTriggers('foo');
expect(t.length).toBe(1);
expect(t[0].open).toBe('foo');
expect(t[0].close).toBe('foo');
});
it('should parse open:close form', () => {
const t = parseTriggers('foo:bar');
expect(t.length).toBe(1);
expect(t[0].open).toBe('foo');
expect(t[0].close).toBe('bar');
});
it('should parse multiple triggers', () => {
const t = parseTriggers('foo:bar bar:baz');
expect(t.length).toBe(2);
expect(t[0].open).toBe('foo');
expect(t[0].close).toBe('bar');
expect(t[1].open).toBe('bar');
expect(t[1].close).toBe('baz');
});
it('should parse multiple triggers with mixed forms', () => {
const t = parseTriggers('foo bar:baz');
expect(t.length).toBe(2);
expect(t[0].open).toBe('foo');
expect(t[0].close).toBe('foo');
expect(t[1].open).toBe('bar');
expect(t[1].close).toBe('baz');
});
it('should properly trim excessive white-spaces', () => {
const t = parseTriggers('foo bar \n baz ');
expect(t.length).toBe(3);
expect(t[0].open).toBe('foo');
expect(t[0].close).toBe('foo');
expect(t[1].open).toBe('bar');
expect(t[1].close).toBe('bar');
expect(t[2].open).toBe('baz');
expect(t[2].close).toBe('baz');
});
it('should lookup and translate special aliases', () => {
const t = parseTriggers('hover');
expect(t.length).toBe(1);
expect(t[0].open).toBe('mouseenter');
expect(t[0].close).toBe('mouseleave');
});
it('should detect manual triggers', () => {
const t = parseTriggers('manual');
expect(t[0].isManual).toBeTruthy();
});
it('should ignore empty inputs', () => {
expect(parseTriggers(null).length).toBe(0);
expect(parseTriggers(undefined).length).toBe(0);
expect(parseTriggers('').length).toBe(0);
});
it('should throw when more than one manual trigger detected', () => {
expect(() => {
parseTriggers('manual click manual');
}).toThrow('Triggers parse error: only one manual trigger is allowed');
});
it('should throw when manual trigger is mixed with other triggers', () => {
expect(() => {
parseTriggers('click manual');
}).toThrow(`Triggers parse error: manual trigger can\'t be mixed with other triggers`);
});
});
});

View File

@ -0,0 +1,60 @@
export class Trigger {
constructor(public open: string, public close?: string) {
if (!close) {
this.close = open;
}
}
isManual() { return this.open === 'manual' || this.close === 'manual'; }
}
const DEFAULT_ALIASES = {
'hover': ['mouseenter', 'mouseleave']
};
export function parseTriggers(triggers: string, aliases = DEFAULT_ALIASES): Trigger[] {
const trimmedTriggers = (triggers || '').trim();
if (trimmedTriggers.length === 0) {
return [];
}
const parsedTriggers = trimmedTriggers.split(/\s+/).map(trigger => trigger.split(':')).map((triggerPair) => {
let alias = aliases[triggerPair[0]] || triggerPair;
return new Trigger(alias[0], alias[1]);
});
const manualTriggers = parsedTriggers.filter(triggerPair => triggerPair.isManual());
if (manualTriggers.length > 1) {
throw 'Triggers parse error: only one manual trigger is allowed';
}
if (manualTriggers.length === 1 && parsedTriggers.length > 1) {
throw 'Triggers parse error: manual trigger can\'t be mixed with other triggers';
}
return parsedTriggers;
}
const noopFn = () => {};
export function listenToTriggers(renderer: any, nativeElement: any, triggers: string, openFn, closeFn, toggleFn) {
const parsedTriggers = parseTriggers(triggers);
const listeners = [];
if (parsedTriggers.length === 1 && parsedTriggers[0].isManual()) {
return noopFn;
}
parsedTriggers.forEach((trigger: Trigger) => {
if (trigger.open === trigger.close) {
listeners.push(renderer.listen(nativeElement, trigger.open, toggleFn));
} else {
listeners.push(
renderer.listen(nativeElement, trigger.open, openFn), renderer.listen(nativeElement, trigger.close, closeFn));
}
});
return () => { listeners.forEach(unsubscribeFn => unsubscribeFn()); };
}

View File

@ -0,0 +1,93 @@
import {toInteger, toString, getValueInRange, isInteger, isString} from './util';
describe('util', () => {
describe('toInteger', () => {
it('should be noop for integers', () => {
expect(toInteger(0)).toBe(0);
expect(toInteger(10)).toBe(10);
});
it('should act as Math.floor for numbers', () => {
expect(toInteger(0.1)).toBe(0);
expect(toInteger(0.9)).toBe(0);
});
it('should parse strings', () => {
expect(toInteger('0')).toBe(0);
expect(toInteger('10')).toBe(10);
expect(toInteger('10.1')).toBe(10);
expect(toInteger('10.9')).toBe(10);
});
});
describe('toString', () => {
it('should be noop for strings', () => { expect(toString('foo')).toBe('foo'); });
it('should return empty string for undefined values', () => {
expect(toString(null)).toBe('');
expect(toString(undefined)).toBe('');
});
it('should stringify non-string values', () => {
expect(toString(10)).toBe('10');
expect(toString(false)).toBe('false');
});
});
describe('getValueInRange', () => {
it('should be noop for numbers in range', () => { expect(getValueInRange(5, 10, 0)).toBe(5); });
it('should do corrections in range', () => {
expect(getValueInRange(11, 10, 0)).toBe(10);
expect(getValueInRange(-1, 10, 0)).toBe(0);
});
it('should take 0 as a default min bound', () => {
expect(getValueInRange(11, 10)).toBe(10);
expect(getValueInRange(-1, 10)).toBe(0);
});
});
describe('isInteger', () => {
it('should recognize integers', () => {
expect(isInteger(0)).toBeTruthy();
expect(isInteger(10)).toBeTruthy();
expect(isInteger(-110)).toBeTruthy();
});
it('should recognize non-integers', () => {
expect(isInteger(null)).toBeFalsy();
expect(isString([])).toBeFalsy();
expect(isString(undefined)).toBeFalsy();
expect(isInteger('2048')).toBeFalsy();
expect(isInteger(14.1)).toBeFalsy();
expect(isInteger(-14.1)).toBeFalsy();
});
});
describe('isString', () => {
it('should recognize strings', () => {
expect(isString('string')).toBeTruthy();
expect(isString('')).toBeTruthy();
});
it('should recognize non-strings', () => {
expect(isString(null)).toBeFalsy();
expect(isString(2048)).toBeFalsy();
expect(isString([])).toBeFalsy();
expect(isString(undefined)).toBeFalsy();
});
});
});

View File

@ -0,0 +1,39 @@
export function toInteger(value: any): number {
return parseInt(`${value}`, 10);
}
export function toString(value: any): string {
return (value !== undefined && value !== null) ? `${value}` : '';
}
export function getValueInRange(value: number, max: number, min = 0): number {
return Math.max(Math.min(value, max), min);
}
export function isString(value: any): value is string {
return typeof value === 'string';
}
export function isNumber(value: any): value is number {
return !isNaN(toInteger(value));
}
export function isInteger(value: any): value is number {
return typeof value === 'number' && isFinite(value) && Math.floor(value) === value;
}
export function isDefined(value: any): boolean {
return value !== undefined && value !== null;
}
export function padNumber(value: number) {
if (isNumber(value)) {
return `0${value}`.slice(-2);
} else {
return '';
}
}
export function regExpEscape(text) {
return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
}

View File

@ -0,0 +1,23 @@
export enum NbpCalendarPattern {
GGMMAAAA = 'gg/mm/aaaa',
MMAAAA = 'mm/aaaa',
MMGGAAAA = 'mm/gg/aaaa',
AAAAMMGG = 'aaaa/mm/gg'
}
export enum NbpCalendarPosition {
LEFT = 'left',
RIGHT = 'right',
TOP = 'top',
TOP_LEFT = 'top-left',
TOP_RIGHT = 'top-right',
BOTTOM = 'bottom',
BOTTOM_LEFT = 'bottom-left',
BOTTOM_RIGHT = 'bottom-right'
}
export enum NbpDateSeparator {
DOT = '.',
SLASH = '/',
HYPHEN = '-'
}

View File

@ -0,0 +1,8 @@
import {Injectable} from '@angular/core';
@Injectable()
export class EnabledRangeService {
startDate: any = {};
endDate: any = {};
}

View File

@ -1,123 +1,32 @@
<div class="datepicker-wrapper">
<input
#dateInput
[disabled]="disabled"
[id]="id"
[name]="name"
class="datepicker-input"
type="text"
placeholder="DD/MM/YYYY"
[value]="formattedSelectedDate"
(input)="onDateInputChange($event)"
/>
<i class="datepicker-icon fa fa-calendar" (click)="toggleCalendar()"></i>
<div
#calendarPopup
class="calendar calendar-popup"
[class.view-days]="view === 'days'"
[class.view-months]="view === 'months'"
[class.view-years]="view === 'years'"
[style.display]="calendarVisible ? 'block' : 'none'"
>
<!-- Calendar Header -->
<div class="calendar-header">
<button
class="calendar-cell fa fa-chevron-left"
(click)="prev()"
></button>
<div class="calendar-cell" id="monthYear" (click)="changeView()">
{{ monthYearHeader }}
</div>
<button
class="calendar-cell fa fa-chevron-right"
(click)="next()"
></button>
</div>
<!-- Calendar Grid -->
<div
class="calendar-grid"
[class.calendar-grid-7]="view === 'days'"
[class.calendar-grid-5]="view === 'years'"
>
<!-- Days View -->
<ng-container *ngIf="view === 'days'">
<!-- Days of Week -->
<div *ngFor="let day of daysOfWeek" class="day">{{ day }}</div>
<!-- Previous Month Days -->
<div
*ngFor="let day of getPreviousMonthDays()"
class="calendar-cell other-month"
[class.disabled]="day.disabled"
(click)="onPrevMonthDayClick(day)"
>
{{ pad(day.day) }}
</div>
<!-- Current Month Days -->
<div
*ngFor="let day of getCurrentMonthDays()"
class="calendar-cell"
[class.today]="day.isToday"
[class.selected]="day.isSelected"
[class.disabled]="day.disabled"
(click)="onCurrentMonthDayClick(day)"
>
{{ pad(day.day) }}
</div>
<!-- Next Month Days -->
<div
*ngFor="let day of getNextMonthDays()"
class="calendar-cell other-month"
[class.disabled]="day.disabled"
(click)="onNextMonthDayClick(day)"
>
{{ pad(day.day) }}
</div>
</ng-container>
<!-- Months View -->
<ng-container *ngIf="view === 'months'">
<div
*ngFor="let month of getVisibleMonths()"
class="calendar-cell"
[class.today]="month.isCurrentMonth"
[class.selected]="month.isSelected"
[class.disabled]="month.disabled"
(click)="onMonthClick(month)"
>
{{ month.name }}
</div>
</ng-container>
<!-- Years View -->
<ng-container *ngIf="view === 'years'">
<div
*ngFor="let yearObj of getVisibleYears()"
class="calendar-cell"
[class.today]="yearObj.isCurrentYear"
[class.selected]="yearObj.isSelected"
[class.disabled]="yearObj.disabled"
(click)="onYearClick(yearObj)"
>
{{ yearObj.year }}
</div>
</ng-container>
</div>
<!-- Calendar Actions -->
<div class="calendar-actions">
<button id="todayBtn" [disabled]="isTodayDisabled()" (click)="goToday()">
{{ "CALENDARIO.OGGI" | translate }}
</button>
<button id="clearBtn" (click)="clearSelection()">
{{ "CALENDARIO.CANCELLA" | translate }}
</button>
<button id="confirmBtn" (click)="confirmDate()">
{{ "CALENDARIO.CONFERMA" | translate }}
<div class="nbp-fid-calendar-container">
<div class="input-group">
<input #inputElement
type="text"
class="form-control"
[placeholder]="placeholder"
[disabled]="disabled"
[required]="required"
#datepickerInput="rplFidCalendarNOA11Y"
rplFidCalendarNOA11Y
[nbpLabelPattern]="datePattern"
[nbpDateSeparator]="dateSeparator"
[minDate]="minDate"
[maxDate]="maxDate"
[startDate]="startDate"
[placement]="placementPosition"
[showWeekNumbers]="showWeekNumbers"
[showWeekdays]="showWeekdays"
[showNavigation]="showNavigation"
[outsideDays]="outsideDays"
[displayMonths]="displayMonths"
(dateSelect)="onDateSelect($event)"
(navigate)="onDateChange($event)">
<div class="input-group-append">
<button class="btn btn-outline-secondary calendar-button"
type="button"
[disabled]="disabled"
(click)="toggle()">
<i class="fa fa-calendar"></i>
</button>
</div>
</div>

View File

@ -1,201 +1,91 @@
// Stili del calendario
.calendar {
font-size: 12px;
padding: 15px;
border: 1px solid #e6e6e6;
color: #333333;
background-color: #ffffff;
}
.calendar-popup {
position: absolute;
z-index: 100;
display: none;
min-width: 160px;
padding: 5px 0;
margin: 2px 0 0;
-webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);
background-clip: padding-box;
}
.calendar-header {
display: grid;
grid-template-columns: repeat(3, 1fr);
align-items: center;
}
.view-days .calendar-header {
grid-template-columns: 1fr 5fr 1fr;
}
.view-years .calendar-header {
grid-template-columns: 1fr 3fr 1fr;
}
.view-months .calendar-cell,
.view-years .calendar-cell {
padding: 6px 20px;
}
.calendar-cell {
padding: 5px 10px;
line-height: 1.5;
font-size: 12px;
background-color: #ffffff;
border: 1px solid #e6e6e6;
border-radius: 3px;
cursor: pointer;
-webkit-transition: all 0.1s;
-o-transition: all 0.1s;
transition: all 0.1s;
}
.calendar-cell:not(.disabled):not(.selected):hover {
background-color: #e6e6e6;
}
#monthYear {
font-weight: bold;
flex-grow: 1;
text-align: center;
}
.calendar-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
text-align: center;
}
.calendar-grid-7 {
grid-template-columns: repeat(7, 1fr);
}
.calendar-grid-5 {
grid-template-columns: repeat(5, 1fr);
}
.calendar-grid .day {
font-size: 11px;
line-height: 1.5;
font-weight: bold;
}
.calendar-grid .selected {
background-color: #1797be;
color: white;
}
.calendar-grid .selected:hover {
background-color: #137d9f;
border-color: #0e5d76;
}
.calendar-grid .other-month {
color: #909fa7;
}
.calendar-grid .today {
color: #23b7e5;
}
.calendar-grid:not(:has(.selected)) .today {
background-color: #e6e6e6;
}
.calendar-grid .disabled {
color: #989898;
background-color: #edf1f2;
border-color: #dde6e9;
cursor: not-allowed;
}
.calendar-actions {
padding: 10px 9px 2px;
display: flex;
}
.calendar-actions button {
font-size: 12px;
padding: 5px 10px;
line-height: 1.5;
background-color: #eb690b;
color: #fff;
border: 1px solid #e6e6e6;
border-radius: 3px;
cursor: pointer;
}
.calendar-actions button#todayBtn {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
.calendar-actions button#clearBtn {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
border-left-width: 0;
background-color: #fff;
color: #eb690b;
}
.calendar-actions button#confirmBtn {
margin-left: auto;
}
// Stili del datepicker
.datepicker-wrapper {
position: relative;
display: inline-flex;
}
.datepicker-input {
padding: 5px;
height: 22px;
box-sizing: border-box;
border: 1px solid #ccc;
border-right-width: 0;
background: #fff;
font-size: 12px;
.nbp-fid-calendar-container {
width: 100%;
position: relative;
.input-group {
width: 100%;
.form-control {
height: 38px;
border-radius: 4px 0 0 4px;
&:focus {
box-shadow: none;
border-color: #80bdff;
}
&:disabled {
background-color: #e9ecef;
cursor: not-allowed;
}
}
.input-group-append {
.calendar-button {
height: 38px;
border-radius: 0 4px 4px 0;
background-color: #f8f9fa;
border-color: #ced4da;
color: #495057;
cursor: pointer;
&:hover:not(:disabled) {
background-color: #e9ecef;
}
&:disabled {
cursor: not-allowed;
opacity: 0.65;
}
i {
font-size: 16px;
}
}
}
}
}
.datepicker-input::placeholder {
color: #909fa7;
}
// Personalizzazione del dropdown del datepicker
::ng-deep {
.dropdown-menu {
padding: 10px !important;
border-radius: 4px;
box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
.datepicker-input:focus {
border-color: #66afe9;
outline: 0;
}
.btn-light {
background-color: #f8f9fa;
border-color: #f8f9fa;
.datepicker-input.input-error {
border-color: #f05050;
background-color: #fff0f0;
}
&:hover:not(:disabled) {
background-color: #e9ecef;
border-color: #e9ecef;
}
.datepicker-icon {
display: inline-flex;
align-items: center;
font-size: 13.5px;
padding: 0 10px;
box-sizing: border-box;
height: 22px;
background: #fff;
border: 1px solid #ccc;
border-bottom-right-radius: 5px;
border-top-right-radius: 5px;
cursor: pointer;
}
&.active {
background-color: #007bff;
border-color: #007bff;
color: white;
}
}
.datepicker-icon:active,
.datepicker-icon:hover,
.datepicker-icon:focus {
background-color: #e6e6e6;
border-color: #cbcbcb;
}
.ngb-dp-header {
background-color: #f8f9fa;
border-radius: 4px;
.datepicker-icon:hover:active {
background-color: #d4d4d4;
border-color: #aaaaaa;
.ngb-dp-navigation-select {
select {
padding: 0.25rem 0.5rem;
font-size: 0.875rem;
border-radius: 3px;
}
}
}
.ngb-dp-day {
&.disabled {
opacity: 0.5;
}
}
}
}

View File

@ -1,665 +1,95 @@
import {
Component,
OnInit,
Input,
Output,
EventEmitter,
ElementRef,
ViewChild,
HostListener,
Renderer2,
forwardRef,
} from "@angular/core";
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from "@angular/forms";
import { NbpCalendarPattern, NbpCalendarPosition, NbpStyle } from "@isp/xdce-widget";
import { TranslateService } from "@ngx-translate/core";
import { Component, Input, Output, EventEmitter, ViewChild, ElementRef, OnInit } from '@angular/core';
import { NgbInputDatepickerNOA11Y } from './@ng-bootstrap-noa11y/datepicker/datepicker-input';
import { NbpCalendarPattern, NbpCalendarPosition, NbpDateSeparator } from './nbp-calendar-generic.enum';
import { NgbDateStruct } from './@ng-bootstrap-noa11y/datepicker/ngb-date-struct';
import { EventManager } from '@isp/xdce-arch-core-base';
@Component({
selector: 'nbp-fid-calendar-generic',
templateUrl: './nbp-fid-calendar-generic.component.html',
styleUrls: ["./nbp-fid-calendar-generic.component.scss"],
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => NbpFidCalendarGenericComponent),
multi: true,
},
],
styleUrls: ['./nbp-fid-calendar-generic.component.scss']
})
export class NbpFidCalendarGenericComponent
implements OnInit, ControlValueAccessor
{
@Input() id: string= "";
@Input() name: string = "";
export class NbpFidCalendarGenericComponent implements OnInit {
@ViewChild('datepickerInput') datepickerInput: NgbInputDatepickerNOA11Y;
@ViewChild('inputElement') inputElement: ElementRef;
@Input() placeholder: string = '';
@Input() disabled: boolean = false;
@Input() dateFormat: string = "dd/MM/yyyy";
@Input() disabledWeekdays: number[] = []; // 0=domenica, 6=sabato
@Input() disabledDateRanges: { start: Date; end: Date }[] = [];
@Input() minDate: Date;
@Input() maxDate: Date;
@Input() nbpErrorMessage: string = "";
@Input() set disabledWeekends(value: boolean) {
if (value) {
this.disabledWeekdays = [...this.disabledWeekdays, 0, 6]; // Domenica e Sabato
}
}
@Input() nbpStyle: NbpStyle = NbpStyle.DEFAULT;
@Input() nbpLabelPattern : NbpCalendarPattern = NbpCalendarPattern.GGMMAAAA;
@Input() nbpPlacement : NbpCalendarPosition = NbpCalendarPosition.BOTTOM_LEFT;
@Input() startDateEnabled : Date = null;
@Input() endDateEnabled : Date = null;
@Input() required: boolean = false;
@Input() datePattern: NbpCalendarPattern = NbpCalendarPattern.GGMMAAAA;
@Input() dateSeparator: NbpDateSeparator = NbpDateSeparator.SLASH;
@Input() placementPosition: NbpCalendarPosition = NbpCalendarPosition.BOTTOM;
@Input() minDate: NgbDateStruct;
@Input() maxDate: NgbDateStruct;
@Input() startDate: NgbDateStruct;
@Input() showWeekNumbers: boolean = false;
@Input() showWeekdays: boolean = true;
@Input() showNavigation: boolean = true;
@Input() outsideDays: 'visible' | 'collapsed' | 'hidden' = 'visible';
@Input() displayMonths: number = 1;
@Output() ngModelChange = new EventEmitter<Date>();
@Output() dateSelected = new EventEmitter<NgbDateStruct>();
@Output() dateChanged = new EventEmitter<NgbDateStruct>();
@Output() datepickerClosed = new EventEmitter<void>();
@ViewChild("dateInput") dateInput: ElementRef;
constructor(private eventManager: EventManager) { }
// Cache per evitare ricalcoli continui e problemi di rendering
private _previousMonthDaysCache: { day: number; disabled: boolean }[] = [];
private _currentMonthDaysCache: {
day: number;
isToday: boolean;
isSelected: boolean;
disabled: boolean;
}[] = [];
private _nextMonthDaysCache: { day: number; disabled: boolean }[] = [];
private _visibleMonthsCache: {
monthIndex: number;
name: string;
isCurrentMonth: boolean;
isSelected: boolean;
disabled: boolean;
}[] = [];
private _visibleYearsCache: {
year: number;
isCurrentYear: boolean;
isSelected: boolean;
disabled: boolean;
}[] = [];
@ViewChild("calendarPopup") calendarPopup: ElementRef;
currentDate: Date = new Date();
selectedDate: Date = null;
view: "days" | "months" | "years" = "days";
months: string[] = [
"gennaio",
"febbraio",
"marzo",
"aprile",
"maggio",
"giugno",
"luglio",
"agosto",
"settembre",
"ottobre",
"novembre",
"dicembre",
];
daysOfWeek: string[] = ["lun", "mar", "mer", "gio", "ven", "sab", "dom"];
formattedSelectedDate: string = "";
calendarVisible: boolean = false;
constructor(private renderer: Renderer2, private elementRef: ElementRef, public translate : TranslateService) {}
private onChange = (value: Date | null) => {};
private onTouched = () => {};
writeValue(value: Date | null): void {
this.selectedDate = value;
}
registerOnChange(fn: any): void {
this.onChange = fn;
}
registerOnTouched(fn: any): void {
this.onTouched = fn;
}
setDisabledState?(isDisabled: boolean): void {
this.disabled = isDisabled;
}
ngOnInit(): void {
// Inizializza la data selezionata se presente
if (this.selectedDate) {
this.formattedSelectedDate = this.formatDate(
this.selectedDate,
this.dateFormat
);
}
// Inizializza le cache
this.updateAllCaches();
}
// --- UTILITY ---
private pad(n: number): string {
return n < 10 ? "0" + n : n.toString();
}
formatDate(date: Date, format: string): string {
if (!date) return "";
return format
.replace("dd", this.pad(date.getDate()))
.replace("MM", this.pad(date.getMonth() + 1))
.replace("yyyy", date.getFullYear().toString())
.replace("yy", String(date.getFullYear()).slice(-2));
}
sameDate(d1: Date, d2: Date): boolean {
return (
d1.getFullYear() === d2.getFullYear() &&
d1.getMonth() === d2.getMonth() &&
d1.getDate() === d2.getDate()
);
}
// --- GESTIONE POPUP ---
positionCalendarPopup(): void {
if (!this.calendarPopup || !this.dateInput) return;
const input = this.dateInput.nativeElement;
const popup = this.calendarPopup.nativeElement;
// Sposta il popup in fondo al body (portal)
if (popup.parentNode !== document.body) {
document.body.appendChild(popup);
}
popup.style.display = "block";
popup.style.position = "absolute";
popup.style.zIndex = "9999";
const rect = input.getBoundingClientRect();
const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
const scrollLeft =
window.pageXOffset || document.documentElement.scrollLeft;
popup.style.top = rect.bottom + scrollTop + "px";
popup.style.left = rect.left + scrollLeft + "px";
}
toggleCalendar(): void {
if (!this.disabled) {
this.calendarVisible = !this.calendarVisible;
if (this.calendarVisible) {
this.showCalendar();
this.updateAllCaches();
} else {
this.hideCalendar();
}
}
}
showCalendar(): void {
this.calendarVisible = true;
setTimeout(() => {
this.positionCalendarPopup();
ngOnInit() {
// Sottoscrizione all'evento di chiusura del datepicker
this.eventManager.subscribeToEvent('DATEPICKER_CLOSE', () => {
this.datepickerClosed.emit();
});
}
hideCalendar(): void {
this.calendarVisible = false;
if (this.calendarPopup) {
this.calendarPopup.nativeElement.style.display = "none";
}
if (this.selectedDate) {
this.currentDate = new Date(this.selectedDate);
} else {
this.currentDate = new Date();
/**
* Apre il datepicker
*/
open() {
if (this.datepickerInput && !this.disabled) {
this.datepickerInput.open(true);
}
}
@HostListener("document:mousedown", ["$event"])
onClickOutside(event: MouseEvent): void {
if (
this.calendarVisible &&
!this.elementRef.nativeElement.contains(event.target) &&
this.calendarPopup &&
!this.calendarPopup.nativeElement.contains(event.target)
) {
this.hideCalendar();
/**
* Chiude il datepicker
*/
close() {
if (this.datepickerInput) {
this.datepickerInput.close();
}
}
// --- LOGICA DATE ---
isDateDisabled(date: Date): boolean {
// Disabilita date precedenti alla minDate
if (this.minDate && date < this.minDate) return true;
// Disabilita date precedenti alla maxDate
if (this.maxDate && date > this.maxDate) return true;
// Disabilita per giorno della settimana
if (this.disabledWeekdays.indexOf(date.getDay()) !== -1) return true;
// Disabilita per range
for (const range of this.disabledDateRanges) {
if (date >= range.start && date <= range.end) return true;
}
return false;
}
isTodayDisabled(): boolean {
const today = new Date();
return this.isDateDisabled(today);
}
// --- NAVIGATION ---
prev(): void {
if (this.view === "days") {
this.currentDate.setMonth(this.currentDate.getMonth() - 1);
} else if (this.view === "months") {
this.currentDate.setFullYear(this.currentDate.getFullYear() - 1);
} else {
this.currentDate.setFullYear(this.currentDate.getFullYear() - 20);
}
this.currentDate = new Date(this.currentDate); // Forza refresh
this.updateAllCaches();
}
next(): void {
if (this.view === "days") {
this.currentDate.setMonth(this.currentDate.getMonth() + 1);
} else if (this.view === "months") {
this.currentDate.setFullYear(this.currentDate.getFullYear() + 1);
} else {
this.currentDate.setFullYear(this.currentDate.getFullYear() + 20);
}
this.currentDate = new Date(this.currentDate); // Forza refresh
this.updateAllCaches();
}
goToday(): void {
this.currentDate = new Date();
this.selectedDate = new Date();
this.formattedSelectedDate = this.formatDate(
this.selectedDate,
this.dateFormat
);
this.view = "days";
this.selectedDateChange.emit(this.selectedDate);
this.updateAllCaches();
}
clearSelection(): void {
this.selectedDate = null;
this.formattedSelectedDate = "";
this.selectedDateChange.emit(null);
}
confirmDate(): void {
// Metodo usato per confermare esplicitamente la data corrente
this.selectedDateChange.emit(this.selectedDate);
this.hideCalendar();
}
changeView(): void {
if (this.view === "days") {
this.view = "months";
} else if (this.view === "months") {
this.view = "years";
}
this.updateAllCaches();
}
// --- SELEZIONE DATE ---
selectDate(date: Date): void {
if (this.isDateDisabled(date)) return;
this.selectedDate = date;
this.formattedSelectedDate = this.formatDate(
this.selectedDate,
this.dateFormat
);
// Non emettiamo qui l'evento dateChange per evitare doppie emissioni
this.updateAllCaches();
}
selectMonth(monthIndex: number): void {
if (this.isMonthDisabled(monthIndex)) return;
this.currentDate.setMonth(monthIndex);
this.currentDate = new Date(this.currentDate); // Forza refresh
this.view = "days";
this.updateAllCaches();
}
selectYear(year: number): void {
if (this.isYearDisabled(year)) return;
this.currentDate.setFullYear(year);
this.currentDate = new Date(this.currentDate); // Forza refresh
this.view = "months";
this.updateAllCaches();
}
selectDayFromPrevMonth(day: number): void {
const year = this.currentDate.getFullYear();
const month = this.currentDate.getMonth();
const prevMonthDate = new Date(year, month - 1, day);
if (this.isDateDisabled(prevMonthDate)) return;
this.currentDate.setMonth(month - 1);
this.currentDate = new Date(this.currentDate); // Forza refresh
this.selectedDate = prevMonthDate;
this.formattedSelectedDate = this.formatDate(
this.selectedDate,
this.dateFormat
);
this.selectedDateChange.emit(this.selectedDate);
this.updateAllCaches();
this.hideCalendar(); // Chiudi il calendario dopo la selezione
}
selectDayFromNextMonth(day: number): void {
const year = this.currentDate.getFullYear();
const month = this.currentDate.getMonth();
const nextMonthDate = new Date(year, month + 1, day);
if (this.isDateDisabled(nextMonthDate)) return;
this.currentDate.setMonth(month + 1);
this.currentDate = new Date(this.currentDate); // Forza refresh
this.selectedDate = nextMonthDate;
this.formattedSelectedDate = this.formatDate(
this.selectedDate,
this.dateFormat
);
this.selectedDateChange.emit(this.selectedDate);
this.updateAllCaches();
this.hideCalendar(); // Chiudi il calendario dopo la selezione
}
// --- UTILITY PER MESI E ANNI ---
isMonthDisabled(monthIndex: number): boolean {
// Se non ci sono restrizioni, il mese è abilitato
if (
!this.minDate &&
!this.maxDate &&
(!this.disabledDateRanges || this.disabledDateRanges.length === 0)
) {
return false;
}
const year = this.currentDate.getFullYear();
const firstDayOfMonth = new Date(year, monthIndex, 1, 0, 0, 0, 0);
const lastDayOfMonth = new Date(year, monthIndex + 1, 0, 23, 59, 59, 999);
// Disabilita mese se completamente fuori dai limiti
if (this.minDate && lastDayOfMonth < this.minDate) return true;
if (this.maxDate && firstDayOfMonth > this.maxDate) return true;
return false;
}
isYearDisabled(year: number): boolean {
// Se non ci sono restrizioni, l'anno è abilitato
if (!this.minDate && !this.maxDate) {
return false;
}
const firstDayOfYear = new Date(year, 0, 1, 0, 0, 0, 0);
const lastDayOfYear = new Date(year, 11, 31, 23, 59, 59, 999);
// Disabilita anno se completamente fuori dai limiti
if (this.minDate && lastDayOfYear < this.minDate) return true;
if (this.maxDate && firstDayOfYear > this.maxDate) return true;
return false;
}
// --- INPUT HANDLING ---
onDateInputChange(event: Event): void {
const value = (event.target as HTMLInputElement).value;
const datePattern = /^(\d{2})\/(\d{2})\/(\d{4})$/;
if (datePattern.test(value)) {
const [, dd, mm, yyyy] = value.match(datePattern);
const date = new Date(parseInt(yyyy), parseInt(mm) - 1, parseInt(dd));
// Controlla che sia una data valida
if (
date &&
date.getDate() === parseInt(dd) &&
date.getMonth() + 1 === parseInt(mm) &&
date.getFullYear() === parseInt(yyyy)
) {
if (!this.isDateDisabled(date)) {
this.selectedDate = date;
this.currentDate = new Date(date);
this.formattedSelectedDate = this.formatDate(
this.selectedDate,
this.dateFormat
);
this.selectedDateChange.emit(this.selectedDate);
this.updateAllCaches();
return;
}
}
/**
* Alterna l'apertura e la chiusura del datepicker
*/
toggle() {
if (this.datepickerInput && !this.disabled) {
this.datepickerInput.toggle(true);
}
}
// --- CALENDAR DATA ---
getDaysInMonth(year: number, month: number): number {
return new Date(year, month + 1, 0).getDate();
/**
* Gestisce l'evento di selezione della data
* @param date La data selezionata
*/
onDateSelect(date: NgbDateStruct) {
this.dateSelected.emit(date);
}
// Metodo per aggiornare tutte le cache quando cambiano i dati
private updateAllCaches(): void {
this.updatePreviousMonthDaysCache();
this.updateCurrentMonthDaysCache();
this.updateNextMonthDaysCache();
this.updateVisibleMonthsCache();
this.updateVisibleYearsCache();
/**
* Gestisce l'evento di modifica della data
* @param date La nuova data
*/
onDateChange(date: NgbDateStruct) {
this.dateChanged.emit(date);
}
// Metodi per aggiornare le singole cache
private updatePreviousMonthDaysCache(): void {
const year = this.currentDate.getFullYear();
const month = this.currentDate.getMonth();
const startDay = this.getFirstDayOfMonth(year, month);
const daysInPrevMonth = this.getDaysInMonth(year, month - 1);
const days = [];
for (let i = startDay; i > 0; i--) {
const day = daysInPrevMonth - i + 1;
const prevMonthDate = new Date(year, month - 1, day);
days.push({
day,
disabled: this.isDateDisabled(prevMonthDate),
});
/**
* Imposta il focus sull'input
*/
focus() {
if (this.inputElement) {
this.inputElement.nativeElement.focus();
}
this._previousMonthDaysCache = days;
}
private updateCurrentMonthDaysCache(): void {
const year = this.currentDate.getFullYear();
const month = this.currentDate.getMonth();
const daysInMonth = this.getDaysInMonth(year, month);
const today = new Date();
const days = [];
for (let i = 1; i <= daysInMonth; i++) {
const date = new Date(year, month, i);
days.push({
day: i,
isToday: this.sameDate(today, date),
isSelected: this.selectedDate
? this.sameDate(this.selectedDate, date)
: false,
disabled: this.isDateDisabled(date),
});
}
this._currentMonthDaysCache = days;
}
private updateNextMonthDaysCache(): void {
const year = this.currentDate.getFullYear();
const month = this.currentDate.getMonth();
const startDay = this.getFirstDayOfMonth(year, month);
const daysInMonth = this.getDaysInMonth(year, month);
const totalCells = 42; // 7 giorni x 6 settimane
const nextMonthDays = totalCells - (startDay + daysInMonth);
const days = [];
for (let i = 1; i <= nextMonthDays; i++) {
const nextMonthDate = new Date(year, month + 1, i);
days.push({
day: i,
disabled: this.isDateDisabled(nextMonthDate),
});
}
this._nextMonthDaysCache = days;
}
private updateVisibleMonthsCache(): void {
const currentYear = this.currentDate.getFullYear();
const today = new Date();
const months = this.months.map((name, idx) => ({
monthIndex: idx,
name,
isCurrentMonth:
currentYear === today.getFullYear() && idx === today.getMonth(),
isSelected: this.selectedDate
? currentYear === this.selectedDate.getFullYear() &&
idx === this.selectedDate.getMonth()
: false,
disabled: this.isMonthDisabled(idx),
}));
this._visibleMonthsCache = months;
}
private updateVisibleYearsCache(): void {
const base = Math.floor(this.currentDate.getFullYear() / 20) * 20;
const currentYear = new Date().getFullYear();
const years = [];
for (let y = base; y < base + 20; y++) {
years.push({
year: y,
isCurrentYear: y === currentYear,
isSelected: this.selectedDate
? y === this.selectedDate.getFullYear()
: false,
disabled: this.isYearDisabled(y),
});
}
this._visibleYearsCache = years;
}
getFirstDayOfMonth(year: number, month: number): number {
return (new Date(year, month, 1).getDay() + 6) % 7; // Lunedì=0, Domenica=6
}
getPreviousMonthDays(): { day: number; disabled: boolean }[] {
return this._previousMonthDaysCache;
}
getCurrentMonthDays(): {
day: number;
isToday: boolean;
isSelected: boolean;
disabled: boolean;
}[] {
return this._currentMonthDaysCache;
}
getNextMonthDays(): { day: number; disabled: boolean }[] {
return this._nextMonthDaysCache;
}
getVisibleYears(): {
year: number;
isCurrentYear: boolean;
isSelected: boolean;
disabled: boolean;
}[] {
return this._visibleYearsCache;
}
getVisibleMonths(): {
monthIndex: number;
name: string;
isCurrentMonth: boolean;
isSelected: boolean;
disabled: boolean;
}[] {
return this._visibleMonthsCache;
}
get yearRange(): string {
if (this.view === "years") {
const base = Math.floor(this.currentDate.getFullYear() / 20) * 20;
return `${base} - ${base + 19}`;
}
return this.currentDate.getFullYear().toString();
}
get monthYearHeader(): string {
if (this.view === "days") {
return `${
this.months[this.currentDate.getMonth()]
} ${this.currentDate.getFullYear()}`;
}
return this.yearRange;
}
// --- AZIONI SUI GIORNI, MESI E ANNI ---
onPrevMonthDayClick(day: { day: number; disabled: boolean }): void {
if (day.disabled) return;
this.selectDayFromPrevMonth(day.day);
// Non serve chiamare hideCalendar() qui perché lo fa già selectDayFromPrevMonth
}
onCurrentMonthDayClick(day: {
day: number;
isToday: boolean;
isSelected: boolean;
disabled: boolean;
}): void {
if (day.disabled) return;
const date = new Date(
this.currentDate.getFullYear(),
this.currentDate.getMonth(),
day.day
);
this.selectDate(date);
this.selectedDateChange.emit(this.selectedDate);
this.hideCalendar();
}
onNextMonthDayClick(day: { day: number; disabled: boolean }): void {
if (day.disabled) return;
this.selectDayFromNextMonth(day.day);
// Non serve chiamare hideCalendar() qui perché lo fa già selectDayFromNextMonth
}
onMonthClick(month: {
monthIndex: number;
name: string;
isCurrentMonth: boolean;
isSelected: boolean;
disabled: boolean;
}): void {
if (month.disabled) return;
this.selectMonth(month.monthIndex);
}
onYearClick(yearObj: {
year: number;
isCurrentYear: boolean;
isSelected: boolean;
disabled: boolean;
}): void {
if (yearObj.disabled) return;
this.selectYear(yearObj.year);
}
}

View File

@ -1,18 +1,9 @@
<select
class="nbp-fid-combo"
[name]="name"
ngDefaultControl
(change)="onValueChange($event)"
[disabled]="disabled">
<option
*ngIf="nbpShowEmptyValue"
[selected]="value === _emptyValue"
[ngValue]="_emptyValue"
[value]="_emptyValue"
>{{_emptyLabel}}</option>
<select class="nbp-fid-combo" (change)="onChange($event)" [disabled]="disabled">
<option *ngIf="nbpShowEmptyValue"
[selected]="ngModel === _emptyValue"
[value]="_emptyValue">{{_emptyLabel}}</option>
<option *ngFor="let op of _options"
[value]="op.strValue"
[ngValue]="op.value"
[selected]="op.selected"
>{{op.label}}</option>
[value]="optStrValue(op)"
[selected]="selected(op)"
>{{optLabel(op)}}</option>
</select>

View File

@ -1,35 +1,24 @@
.nbp-fid-combo {
// border: 1px solid;
// border-color: #DDE6E9; // map-get($gray-palette, 100);
// background: #fff;
// min-width: 2em;
// padding-top: 1px;
// padding-bottom: 1px;
// padding-left: 1px;
// padding-right: 1em !important;
// width: 100%;
display: block;
border: 1px solid;
border-color: #DDE6E9; // map-get($gray-palette, 100);
// background: url("data:image/svg+xml,<svg height='10px' width='10px' viewBox='0 0 16 16' fill='%23000000' xmlns='http://www.w3.org/2000/svg'><path d='M7.247 11.14 2.451 5.658C1.885 5.013 2.345 4 3.204 4h9.592a1 1 0 0 1 .753 1.659l-4.796 5.48a1 1 0 0 1-1.506 0z'/></svg>") no-repeat;
// background: #fff url("data:image/svg+xml;utf8,<svg viewBox='0 0 16 16' width='10px' height='10px' xmlns='http://www.w3.org/2000/svg'><g><path d='m121.3,34.6c-1.6-1.6-4.2-1.6-5.8,0l-51,51.1-51.1-51.1c-1.6-1.6-4.2-1.6-5.8,0-1.6,1.6-1.6,4.2 0,5.8l53.9,53.9c0.8,0.8 1.8,1.2 2.9,1.2 1,0 2.1-0.4 2.9-1.2l53.9-53.9c1.7-1.6 1.7-4.2 0.1-5.8z' fill='white'/></g></svg>") no-repeat;
// background: #fff url("data:image/svg+xml;utf8,<svg viewBox='0 0 16 16' width='10px' height='10px' fill='%23000000' xmlns='http://www.w3.org/2000/svg'><g><path d='m121.3,34.6c-1.6-1.6-4.2-1.6-5.8,0l-51,51.1-51.1-51.1c-1.6-1.6-4.2-1.6-5.8,0-1.6,1.6-1.6,4.2 0,5.8l53.9,53.9c0.8,0.8 1.8,1.2 2.9,1.2 1,0 2.1-0.4 2.9-1.2l53.9-53.9c1.7-1.6 1.7-4.2 0.1-5.8z'/></g></svg>") no-repeat;
// background-position: calc(100% - 0.75em) center !important;
background: #fff;
// -moz-appearance:none !important;
// -webkit-appearance: none !important;
// appearance: none !important;
min-width: 2em;
padding-top: 1px;
padding-bottom: 1px;
padding-left: 1px;
padding-right: 1em !important;
width: 100%;
padding: 1px;
height: 22px;
font-size: 12px;
line-height: 1.52857143;
color: #3a3f51;
background-color: #ffffff;
background-image: none;
border: 1px solid #dde6e9;
border-radius: 0;
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
box-shadow: 0 0 0 #000 !important;
-webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
-o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
&:focus,
&:active {
outline: 0 !important;
box-shadow: 0 0 0 #000 !important;
border-color: #66AFE9; // map-get($blue-palette, 100);
}
}

View File

@ -1,57 +1,20 @@
import { Component, EventEmitter, Input, Output, OnInit, forwardRef, ChangeDetectionStrategy } from '@angular/core';
import { Component, EventEmitter, Input, Output } from '@angular/core';
import {
NbpBaseComponent,
NbpStyle,
NbpDataSource
} from '@isp/xdce-widget';
import {ControlValueAccessor, FormControl, NG_VALUE_ACCESSOR, } from '@angular/forms';
//
// auto incremental index for noname combo instance
let comboIndex = 111;
@Component({
selector: 'nbp-fid-combo',
templateUrl: './nbp-fid-combo.component.html',
styleUrls: ['./nbp-fid-combo.component.scss'],
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => NbpFidComboComponent),
multi: true
}
]
styleUrls: ['./nbp-fid-combo.component.scss']
})
export class NbpFidComboComponent
extends NbpBaseComponent
implements ControlValueAccessor {
constructor() {
export class NbpFidComboComponent extends NbpBaseComponent {
constructor(){
super()
}
@Input() name: string;
onChange: any = () => { };
onTouch: any = () => {};
compareFn(c1: any, c2: any): boolean {
return c1 && c2 ? c1.value === c2.value : c1 === c2;
}
registerOnChange(fn: any): void {
this.onChange = fn;
}
registerOnTouched(fn: any): void {
this.onTouch = fn;
}
writeValue(input: string) {
this.value = input;
}
@Input() nbpViewField : string = null;
@Input() nbpKeyField : string = null;
@ -61,23 +24,16 @@ export class NbpFidComboComponent
private _model: any;
@Input()
set value(value: any) {
set ngModel(value: any) {
this._model = value;
if (this._model === undefined)
this._model = null;
// FUTURE handle a model value that is not present in options
// as "empty" value
// if (this._nbpShowEmptyValue && this._model !== null && !this.nbpViewField) {
// this._emptyValue = this._model;
// this._emptyLabel = this._model;
// }
this._selectOnModel();
if (this._nbpShowEmptyValue && this._model !== null && !this.nbpViewField) {
this._emptyValue = this._model;
this._emptyLabel = this._model;
}
}
@Output() ngModelChange = new EventEmitter<any>();
get value(): any {
get ngModel(): any {
return this._model;
}
@ -120,9 +76,6 @@ export class NbpFidComboComponent
}
ngOnInit(): void {
if (!this.name) {
this.name = "combo_" + (comboIndex++);
}
this._readOptions();
}
@ -168,26 +121,11 @@ export class NbpFidComboComponent
}
_selectOnModel() {
const arr = this._options;
for (let a of arr) {
a.selected = false;
}
const val = this.value;
if (val === null || val === undefined)
return;
for (let a of arr) {
const v = a.value;
const sv = a.strValue;
if (sv === val) {
a.selected = true;
break;
}
}
selected(op : any) {
return this.optValue(op) === this.ngModel;
}
onValueChange(event: Event) {
onChange(event: Event) {
if (this._disabled)
return;
@ -204,9 +142,7 @@ export class NbpFidComboComponent
}
}
this.value = sel;
this.ngModelChange.emit(this.value);
if (this.onChange)
this.onChange(this.value);
this.ngModel = sel;
this.ngModelChange.emit(this.ngModel);
}
}

View File

@ -1,325 +1,189 @@
<div>
<p class="new-part">Tabbar (nbp-tab-bar):</p>
<nbp-tab-bar
[nbpStyle]="_nbpStyle.DEFAULT"
[nbpItems]="items"
[(nbpSelectedIndex)]="currentSelectedIndex"
[nbpTabContent]="true"
>
</nbp-tab-bar>
<p class="new-part">Tabbar (nbp-tab-bar):</p>
<p class="new-part">Tabbar with title:</p>
<div class="nbp-tab-bar-title">
<div class="tab-bar-title">Title:</div>
<nbp-tab-bar
[nbpStyle]="_nbpStyle.DEFAULT"
[nbpItems]="items"
[(nbpSelectedIndex)]="currentSelectedIndex"
[nbpTabContent]="true"
>
<nbp-tab-bar [nbpStyle]="_nbpStyle.DEFAULT" [nbpItems]="items" [(nbpSelectedIndex)]="currentSelectedIndex"
[nbpTabContent]="true">
</nbp-tab-bar>
</div>
<p class="new-part">
Toggle Tabset (.nbp-tab-bar-title + .tab-bar-title + nbp-toggle-tabset)
check devtools inspector elements:
</p>
<div class="nbp-tab-bar-title">
<div class="tab-bar-title">Title:</div>
<nbp-toggle-tabset>
<nbp-toggle-tab disabled="true" title="Scheda 0">
<h3>Scheda 0 - Selezionata</h3>
<span>{{ longText }}</span>
</nbp-toggle-tab>
<nbp-toggle-tab active="true" title="Scheda 1">
<h3>Scheda 1 - Selezionata</h3>
<span>{{ longText }}</span>
</nbp-toggle-tab>
<nbp-toggle-tab title="Scheda 2">
<h3>Scheda 2 - Selezionata</h3>
<span>{{ longText }}</span>
</nbp-toggle-tab>
<nbp-toggle-tab title="Scheda 3">
<h3>Scheda 3 - Selezionata</h3>
<span>{{ longText }}</span>
</nbp-toggle-tab>
</nbp-toggle-tabset>
</div>
<p class="new-part">Tabbar with title:</p>
<p class="new-part">Input text (nbp-input-container + nbp-input-text):</p>
<div>
<nbp-input-container
[nbpLabel]="labelInput4"
[nbpStyle]="_nbpStyle.PRIMARY"
[infoText]="'Inserire un importo'"
>
<nbp-input-text
id="input-text-primary-3"
[name]="'importoPrimary'"
[(ngModel)]="importoprovaR"
nbpInputType="nbpImporto"
[nbpFormat]="currency"
[nbpShowValidation]="true"
[placeholder]="'placeholder'"
[nbpErrorMessage]="errorMessageInput"
[nbpRoundBorder]="false"
[nbpStyle]="_nbpStyle.PRIMARY"
[nbpIcon]="'ispv2-font-euro-sign'"
[accessibleTextForIcon]="'euro'"
[label]="labelInput4"
>
</nbp-input-text>
</nbp-input-container>
</div>
<div class="nbp-tab-bar-title">
<div class="tab-bar-title">Title:</div>
<nbp-tab-bar [nbpStyle]="_nbpStyle.DEFAULT" [nbpItems]="items" [(nbpSelectedIndex)]="currentSelectedIndex"
[nbpTabContent]="true">
</nbp-tab-bar>
</div>
<p class="new-part">
Calendar generic (nbp-input-container + nbp-calendar-generic)
</p>
<div>
<nbp-input-container [nbpStyle]="_nbpStyle.DEFAULT" [nbpLabel]="'Default'">
<nbp-calendar-generic
[id]="'calendarDefault'"
[name]="'calendarDefault'"
[nbpStyle]="_nbpStyle.DEFAULT"
[nbpPlacement]="_nbpCalendarPosition.BOTTOM_LEFT"
[nbpLabelPattern]="_nbpCalendarPattern.GGMMAAAA"
[(ngModel)]="calendarModel"
>
</nbp-calendar-generic>
</nbp-input-container>
</div>
<div>
<nbp-input-container [nbpStyle]="_nbpStyle.DEFAULT" [nbpLabel]="'Default'">
<nbp-calendar-generic
[id]="'calendarConstrainedDateInterval'"
[name]="'calendarConstrainedDateInterval'"
[nbpStyle]="_nbpStyle.DEFAULT"
[nbpPlacement]="_nbpCalendarPosition.BOTTOM_RIGHT"
[nbpLabelPattern]="_nbpCalendarPattern.GGMMAAAA"
[(ngModel)]="calendarModel"
[startDateEnabled]="startDate"
[endDateEnabled]="endDate"
>
</nbp-calendar-generic>
</nbp-input-container>
</div>
<div>
<nbp-input-container [nbpStyle]="_nbpStyle.DEFAULT" [nbpLabel]="'Default'">
<nbp-calendar-generic
[id]="'calendarConstrainedDateInterval'"
[name]="'calendarConstrainedDateInterval'"
[nbpStyle]="_nbpStyle.DEFAULT"
[nbpPlacement]="_nbpCalendarPosition.BOTTOM_RIGHT"
[disabled]="true"
[nbpLabelPattern]="_nbpCalendarPattern.GGMMAAAA"
[(ngModel)]="calendarModel"
[startDateEnabled]="startDate"
[endDateEnabled]="endDate"
>
</nbp-calendar-generic>
</nbp-input-container>
</div>
<p class="new-part">Toggle Tabset (.nbp-tab-bar-title + .tab-bar-title + nbp-toggle-tabset) check devtools inspector
elements:</p>
<div class="nbp-tab-bar-title">
<div class="tab-bar-title">Title:</div>
<nbp-toggle-tabset>
<nbp-toggle-tab disabled="true" title="Scheda 0">
<h3>Scheda 0 - Selezionata</h3>
<span>{{ longText }}</span>
</nbp-toggle-tab>
<nbp-toggle-tab active="true" title="Scheda 1">
<h3>Scheda 1 - Selezionata</h3>
<span>{{ longText }}</span>
</nbp-toggle-tab>
<nbp-toggle-tab title="Scheda 2">
<h3>Scheda 2 - Selezionata</h3>
<span>{{ longText }}</span>
</nbp-toggle-tab>
<nbp-toggle-tab title="Scheda 3">
<h3>Scheda 3 - Selezionata</h3>
<span>{{ longText }}</span>
</nbp-toggle-tab>
</nbp-toggle-tabset>
</div>
<p class="new-part">
Fideuram Calendar generic (nbp-input-container + bp-fid-calendar-generic)
</p>
<div>
<nbp-input-container [nbpStyle]="_nbpStyle.DEFAULT" [nbpLabel]="'Default'">
<nbp-fid-calendar-generic
[id]="'calendarId'"
[name]="'calendarName'"
[dateFormat]="'dd/MM/yyyy'"
[minDate]="fidMinDate"
[maxDate]="fidMaxDate"
[disabled]="false"
[(ngModel)]="fidCalendarModel"
(ngModelChange)="onDateChange($event)"
>
</nbp-fid-calendar-generic>
</nbp-input-container>
</div>
<p class="new-part">Input text (nbp-input-container + nbp-input-text):</p>
<div>
<nbp-input-container [nbpLabel]="labelInput4" [nbpStyle]="_nbpStyle.PRIMARY" [infoText]="'Inserire un importo'">
<nbp-input-text id="input-text-primary-3" [name]="'importoPrimary'" [(ngModel)]="importoprovaR"
nbpInputType=nbpImporto [nbpFormat]="currency" [nbpShowValidation]="true" [placeholder]="'placeholder'"
[nbpErrorMessage]="errorMessageInput" [nbpRoundBorder]="false" [nbpStyle]="_nbpStyle.PRIMARY"
[nbpIcon]="'ispv2-font-euro-sign'" [accessibleTextForIcon]="'euro'" [label]="labelInput4">
</nbp-input-text>
</nbp-input-container>
</div>
<p class="new-part">Combo (nbp-input-container + nbp-combo)</p>
<div>
<nbp-input-container [nbpStyle]="_nbpStyle.DEFAULT" [nbpLabel]="'Default'">
<nbp-combo
[id]="'comboDefault'"
[name]="'comboDefault'"
[nbpStyle]="_nbpStyle.DEFAULT"
[nbpDataSource]="comboDatasource"
[(ngModel)]="comboSelectedValue"
[nbpShowEmptyValue]="true"
>
</nbp-combo>
</nbp-input-container>
<nbp-input-container [nbpStyle]="_nbpStyle.DEFAULT" [nbpLabel]="'Default'">
<nbp-combo
[id]="'comboDefault'"
[name]="'comboDefault'"
[nbpStyle]="_nbpStyle.DEFAULT"
[nbpDataSource]="comboDatasource"
[(ngModel)]="comboSelectedValue"
[nbpShowEmptyValue]="true"
[disabled]="true"
>
</nbp-combo>
</nbp-input-container>
</div>
<p class="new-part">Calendar generic (nbp-input-container + nbp-calendar-generic)</p>
<div>
<nbp-input-container [nbpStyle]="_nbpStyle.DEFAULT" [nbpLabel]="'Default'">
<nbp-calendar-generic [id]="'calendarDefault'" [name]="'calendarDefault'" [nbpStyle]="_nbpStyle.DEFAULT"
[nbpPlacement]="_nbpCalendarPosition.BOTTOM_LEFT" [nbpLabelPattern]="_nbpCalendarPattern.GGMMAAAA"
[(ngModel)]="calendarModel">
</nbp-calendar-generic>
</nbp-input-container>
</div>
<div>
<nbp-input-container [nbpStyle]="_nbpStyle.DEFAULT" [nbpLabel]="'Default'">
<nbp-calendar-generic [id]="'calendarConstrainedDateInterval'" [name]="'calendarConstrainedDateInterval'"
[nbpStyle]="_nbpStyle.DEFAULT" [nbpPlacement]="_nbpCalendarPosition.BOTTOM_RIGHT"
[nbpLabelPattern]="_nbpCalendarPattern.GGMMAAAA" [(ngModel)]="calendarModel"
[startDateEnabled]="startDate" [endDateEnabled]="endDate">
</nbp-calendar-generic>
</nbp-input-container>
</div>
<div>
<nbp-input-container [nbpStyle]="_nbpStyle.DEFAULT" [nbpLabel]="'Default'">
<nbp-calendar-generic [id]="'calendarConstrainedDateInterval'" [name]="'calendarConstrainedDateInterval'"
[nbpStyle]="_nbpStyle.DEFAULT" [nbpPlacement]="_nbpCalendarPosition.BOTTOM_RIGHT" [disabled]="true"
[nbpLabelPattern]="_nbpCalendarPattern.GGMMAAAA" [(ngModel)]="calendarModel"
[startDateEnabled]="startDate" [endDateEnabled]="endDate">
</nbp-calendar-generic>
</nbp-input-container>
</div>
<div>
<nbp-fid-calendar-generic [placeholder]="'Seleziona data'" [datePattern]="_nbpCalendarPattern.GGMMAAAA"
[dateSeparator]="_nbpDateSeparator.SLASH" [placementPosition]="_nbpCalendarPosition.BOTTOM"
(dateSelected)="onDateSelect($event)">
</nbp-fid-calendar-generic>
</div>
<p class="new-part">Combo Filter (nbp-input-container + nbp-combo-filter)</p>
<div>
<nbp-input-container [nbpStyle]="_nbpStyle.DEFAULT" [nbpLabel]="'Default'">
<nbp-combo-filter
[id]="'comboDefault'"
[name]="'comboDefault'"
[nbpStyle]="_nbpStyle.DEFAULT"
[nbpDataSource]="comboDatasource"
[(ngModel)]="comboSelectedValue"
[nbpShowEmptyValue]="true"
>
</nbp-combo-filter>
</nbp-input-container>
</div>
<p class="new-part">Combo (nbp-input-container + nbp-combo)</p>
<div>
<nbp-input-container [nbpStyle]="_nbpStyle.DEFAULT" [nbpLabel]="'Default'">
<nbp-combo [id]="'comboDefault'" [name]="'comboDefault'" [nbpStyle]="_nbpStyle.DEFAULT"
[nbpDataSource]="comboDatasource" [(ngModel)]="comboSelectedValue" [nbpShowEmptyValue]="true">
</nbp-combo>
</nbp-input-container>
<nbp-input-container [nbpStyle]="_nbpStyle.DEFAULT" [nbpLabel]="'Default'">
<nbp-combo [id]="'comboDefault'" [name]="'comboDefault'" [nbpStyle]="_nbpStyle.DEFAULT"
[nbpDataSource]="comboDatasource" [(ngModel)]="comboSelectedValue" [nbpShowEmptyValue]="true"
[disabled]="true">
</nbp-combo>
</nbp-input-container>
</div>
<p class="new-part">Combo Multi (nbp-input-container + nbp-combo-multi)</p>
<div>
<nbp-input-container [nbpStyle]="_nbpStyle.DEFAULT" [nbpLabel]="'Default'">
<nbp-combo-multi
[id]="'comboMultiIndent'"
[name]="'comboMultiIndent'"
[nbpStyle]="_nbpStyle.DEFAULT"
[nbpDataSource]="datasource"
[(ngModel)]="selectedValues"
[dropdownVisible]="comboMultiVisible"
>
</nbp-combo-multi>
</nbp-input-container>
<p class="new-part">Combo Filter (nbp-input-container + nbp-combo-filter)</p>
<div>
<nbp-input-container [nbpStyle]="_nbpStyle.DEFAULT" [nbpLabel]="'Default'">
<nbp-combo-filter [id]="'comboDefault'" [name]="'comboDefault'" [nbpStyle]="_nbpStyle.DEFAULT"
[nbpDataSource]="comboDatasource" [(ngModel)]="comboSelectedValue" [nbpShowEmptyValue]="true">
</nbp-combo-filter>
</nbp-input-container>
</div>
<nbp-input-container [nbpStyle]="_nbpStyle.PRIMARY" [nbpLabel]="'Default'">
<nbp-combo-multi
[id]="'combomultiDefault'"
[name]="'combomultiDefault'"
[nbpStyle]="_nbpStyle.PRIMARY"
[nbpDataSource]="datasource"
[(ngModel)]="selectedValues"
>
</nbp-combo-multi>
</nbp-input-container>
</div>
<p class="new-part">Combo Multi (nbp-input-container + nbp-combo-multi)</p>
<div>
<nbp-input-container [nbpStyle]="_nbpStyle.DEFAULT" [nbpLabel]="'Default'">
<nbp-combo-multi [id]="'comboMultiIndent'" [name]="'comboMultiIndent'" [nbpStyle]="_nbpStyle.DEFAULT"
[nbpDataSource]="datasource" [(ngModel)]="selectedValues" [dropdownVisible]="comboMultiVisible">
</nbp-combo-multi>
</nbp-input-container>
<p class="new-part">Textarea (nbp-input-container + nbp-textarea)</p>
<div>
<nbp-input-container
[nbpLabel]="'Textarea stile default'"
[nbpStyle]="_nbpStyle.DEFAULT"
>
<nbp-textarea
[name]="'default-a'"
[(ngModel)]="contenutoEmpty"
[required]="required"
[placeholder]="'placeholder'"
[maxlength]="lunghezzamax"
[minlength]="lunghezzamin"
[nbpStyle]="_nbpStyle.DEFAULT"
></nbp-textarea>
</nbp-input-container>
</div>
<nbp-input-container [nbpStyle]="_nbpStyle.PRIMARY" [nbpLabel]="'Default'">
<nbp-combo-multi [id]="'combomultiDefault'" [name]="'combomultiDefault'" [nbpStyle]="_nbpStyle.PRIMARY"
[nbpDataSource]="datasource" [(ngModel)]="selectedValues">
</nbp-combo-multi>
</nbp-input-container>
</div>
<p class="new-part">Card (nbp-card)</p>
<div style="width: 250px">
<nbp-card
[id]="'crd5'"
[nbpStyle]="_nbpStyle.DEFAULT"
[title]="cardTitle"
[description]="cardDescr"
[templateRef]="template4"
>
</nbp-card>
<ng-template #template4>
<div class="row">
<div class="col gap-1">
<nbp-button [nbpLabel]="'button'" [nbpStyle]="_nbpStyle.FOURTH">
</nbp-button>
<p class="new-part">Textarea (nbp-input-container + nbp-textarea)</p>
<div>
<nbp-input-container [nbpLabel]="'Textarea stile default'" [nbpStyle]="_nbpStyle.DEFAULT">
<nbp-textarea [name]="'default-a'" [(ngModel)]="contenutoEmpty" [required]="required"
[placeholder]="'placeholder'" [maxlength]="lunghezzamax" [minlength]="lunghezzamin"
[nbpStyle]="_nbpStyle.DEFAULT"></nbp-textarea>
</nbp-input-container>
</div>
<nbp-button [nbpLabel]="'button'" [nbpStyle]="_nbpStyle.PRIMARY">
</nbp-button>
</div>
</div>
</ng-template>
</div>
<p class="new-part">Card (nbp-card)</p>
<div style="width: 250px">
<nbp-card [id]="'crd5'" [nbpStyle]="_nbpStyle.DEFAULT" [title]="cardTitle" [description]="cardDescr"
[templateRef]="template4">
</nbp-card>
<ng-template #template4>
<div class="row">
<div class="col gap-1">
<nbp-button [nbpLabel]="'button'" [nbpStyle]="_nbpStyle.FOURTH">
</nbp-button>
<p class="new-part">Table (nbp-table)</p>
<div>
<nbp-table
[scrollBar]="'auto'"
ariaLabel="table"
[nbpId]="'defTable1'"
[nbpOptions]="tableOptions"
[nbpDataSource]="tableDs"
[nbpAutoBind]="true"
[nbpSelectionType]="tableSelectionType"
[nbpLayoutAuto]="true"
>
<nbp-table-column
nbpId="headerField"
nbpTitle="Header field"
nbpField="headerField"
[nbpVisible]="true"
>
</nbp-table-column>
<nbp-button [nbpLabel]="'button'" [nbpStyle]="_nbpStyle.PRIMARY">
</nbp-button>
</div>
</div>
</ng-template>
</div>
<p class="new-part">Table (nbp-table)</p>
<div>
<nbp-table [scrollBar]="'auto'" ariaLabel="table" [nbpId]="'defTable1'" [nbpOptions]="tableOptions"
[nbpDataSource]="tableDs" [nbpAutoBind]="true" [nbpSelectionType]="tableSelectionType"
[nbpLayoutAuto]="true">
<nbp-table-column nbpId='headerField' nbpTitle='Header field' nbpField='headerField' [nbpVisible]='true'>
</nbp-table-column>
<nbp-table-column nbpId='headerField2' nbpTitle='Header field 2' nbpField='headerField2'
[nbpSortable]="true" [nbpVisible]='true'>
</nbp-table-column>
</nbp-table>
</div>
<p class="new-part">Tree-table</p>
<div>
<!-- [paginationOptions]="table2PageConfig" -->
<isp-turbo-table [columns]="table2Columns" [datasource]="table2Data" [hasAccordionRows]="true"
[rowExpander]="table2RowExpander" tableMinWidth='35rem' ariaLabel="table with children"></isp-turbo-table>
</div>
<p class="new-part">Checkbox-table</p>
<nbp-table [scrollBar]="'auto'" [nbpId]="'defTable'" [nbpOptions]="simpleOptions"
[nbpDataSource]="campiStandardData" ariaLabel="multi selection table" [nbpAutoBind]="true"
[nbpSelectionType]="multi">
<nbp-table-column nbpId='headerField' nbpTitle='Header field' nbpField='headerField' [nbpSortable]='true'
[nbpVisible]='true'>
</nbp-table-column>
<nbp-table-column nbpId='headerField2' nbpTitle='Header field 2' nbpField='headerField2' [nbpSortable]='true'
[nbpVisible]='true'>
</nbp-table-column>
<nbp-table-column
nbpId="headerField2"
nbpTitle="Header field 2"
nbpField="headerField2"
[nbpSortable]="true"
[nbpVisible]="true"
>
</nbp-table-column>
</nbp-table>
</div>
<p class="new-part">Tree-table</p>
<div>
<!-- [paginationOptions]="table2PageConfig" -->
<isp-turbo-table
[columns]="table2Columns"
[datasource]="table2Data"
[hasAccordionRows]="true"
[rowExpander]="table2RowExpander"
tableMinWidth="35rem"
ariaLabel="table with children"
></isp-turbo-table>
</div>
<p class="new-part">Checkbox-table</p>
<nbp-table
[scrollBar]="'auto'"
[nbpId]="'defTable'"
[nbpOptions]="simpleOptions"
[nbpDataSource]="campiStandardData"
ariaLabel="multi selection table"
[nbpAutoBind]="true"
[nbpSelectionType]="multi"
>
<nbp-table-column
nbpId="headerField"
nbpTitle="Header field"
nbpField="headerField"
[nbpSortable]="true"
[nbpVisible]="true"
>
</nbp-table-column>
<nbp-table-column
nbpId="headerField2"
nbpTitle="Header field 2"
nbpField="headerField2"
[nbpSortable]="true"
[nbpVisible]="true"
>
</nbp-table-column>
</nbp-table>
</div>

View File

@ -5,7 +5,10 @@ import {
NbpCalendarPattern, NbpCalendarPosition, NbpComboMultiComponent,
NbpDataSource, NbpStyle, NbpTableSelectionType, NgbDateStruct,
RowAction, RowDataExpander, RowModel,
NbpComboComponent
NbpComboComponent,
NgbDatepickerConfig,
NbpDatepickerConfiguration,
NbpCalendarGenericComponentNOA11Y
} from '@isp/xdce-widget';
@Component({
@ -17,6 +20,8 @@ export class Showcase1Component extends NbpBaseComponent {
public _nbpStyle = NbpStyle;
x : NbpCalendarGenericComponentNOA11Y
//
// TABBAR
items: Array<ITabItem<void>> = [
@ -43,19 +48,6 @@ export class Showcase1Component extends NbpBaseComponent {
startDate: NgbDateStruct = { year: 2023, month: 3, day: 15 };
endDate: NgbDateStruct = { year: 2023, month: 8, day: 15 };
// FIDEURAM CALENDAR GENERIC
fidCalendarModel: Date = null;
// Date di limite per l'esempio min/max
fidMinDate: Date = new Date(2025, 4, 1); // 1 maggio 2025
fidMaxDate: Date = new Date(2025, 5, 30); // 30 giugno 2025
// Range di date disabilitate per l'esempio
fidDisabledDateRanges: { start: Date, end: Date }[] = [
{ start: new Date(2025, 4, 10), end: new Date(2025, 5, 15) }, // 10-15 maggio 2025
{ start: new Date(2025, 4, 25), end: new Date(2025, 4, 28) } // 25-28 maggio 2025
];
//
//
@ -194,8 +186,9 @@ export class Showcase1Component extends NbpBaseComponent {
campiStandardData: NbpDataSource<any>;
//
constructor(injector: Injector) {
constructor(injector: Injector, private calendarConfig: NgbDatepickerConfig) {
super(injector);
calendarConfig.outsideDays = "visible";
// table2
this.setDataRowExpander(this.table2Rows[0], 0);
this.campiStandardData = new NbpDataSource<any>(this.oggetti);
@ -205,12 +198,6 @@ export class Showcase1Component extends NbpBaseComponent {
array = array.map(convertPageToRowModel);
this.table2Data.setData(array, pageNumber, sortField, pageSize);
}
// Metodo per gestire il cambio di data nel calendario Fideuram
onDateChange(date: Date): void {
console.log('Data selezionata:', date);
// Puoi aggiungere qui la logica per gestire il cambio di data
}
}
export class RowExpanderTreeExpandedTest implements RowDataExpander {

View File

@ -1,99 +0,0 @@
@echo off
setlocal enabledelayedexpansion
REM Script to switch between Fideuram (fid) and Armundia (arm) Git environments
REM This script compresses the current .git folder and extracts the other one
echo Switching Git environment...
REM Check if .git folder exists
if exist ".git" (
REM Determine which environment to switch to
if exist "fid-git.zip" (
REM Current environment is Armundia, switch to Fideuram
echo Current environment: Armundia
echo Switching to Fideuram environment...
REM Compress Armundia .git folder
echo Compressing Armundia .git folder...
powershell -command "Compress-Archive -Path '.git' -DestinationPath 'arm-git.zip' -Force"
REM Remove current .git folder
echo Removing current .git folder...
rmdir /s /q .git
REM Extract Fideuram .git folder
echo Extracting Fideuram .git folder...
powershell -command "Expand-Archive -Path 'fid-git.zip' -DestinationPath '.' -Force"
REM Delete the zip file after extraction
echo Removing the Fideuram zip file...
del /f /q fid-git.zip
echo Successfully switched to Fideuram environment.
) else if exist "arm-git.zip" (
REM Current environment is Fideuram, switch to Armundia
echo Current environment: Fideuram
echo Switching to Armundia environment...
REM Compress Fideuram .git folder
echo Compressing Fideuram .git folder...
powershell -command "Compress-Archive -Path '.git' -DestinationPath 'fid-git.zip' -Force"
REM Remove current .git folder
echo Removing current .git folder...
rmdir /s /q .git
REM Extract Armundia .git folder
echo Extracting Armundia .git folder...
powershell -command "Expand-Archive -Path 'arm-git.zip' -DestinationPath '.' -Force"
REM Delete the zip file after extraction
echo Removing the Armundia zip file...
del /f /q arm-git.zip
echo Successfully switched to Armundia environment.
) else (
REM First run - no compressed Git folders exist yet
echo This appears to be the first run.
echo Current .git folder will be considered as Fideuram environment.
REM Compress current .git as Fideuram
echo Compressing current .git folder as Fideuram...
powershell -command "Compress-Archive -Path '.git' -DestinationPath 'fid-git.zip' -Force"
echo Please initialize the Armundia Git repository and run this script again.
echo You can initialize a new Git repository with: git init
)
) else (
REM No .git folder exists
if exist "fid-git.zip" (
REM Extract Fideuram .git folder
echo No .git folder found. Extracting Fideuram environment...
powershell -command "Expand-Archive -Path 'fid-git.zip' -DestinationPath '.' -Force"
REM Delete the zip file after extraction
echo Removing the Fideuram zip file...
del /f /q fid-git.zip
echo Successfully switched to Fideuram environment.
) else if exist "arm-git.zip" (
REM Extract Armundia .git folder
echo No .git folder found. Extracting Armundia environment...
powershell -command "Expand-Archive -Path 'arm-git.zip' -DestinationPath '.' -Force"
REM Delete the zip file after extraction
echo Removing the Armundia zip file...
del /f /q arm-git.zip
echo Successfully switched to Armundia environment.
) else (
REM No Git environments found
echo No Git environments found.
echo Please initialize a Git repository with: git init
)
)
echo.
echo Done!
pause