From 9b65ba5793da59a50e6176860424974f9bb0f4fa Mon Sep 17 00:00:00 2001 From: Vlad Ioffe Date: Mon, 5 Mar 2018 23:08:14 +0200 Subject: [PATCH] Next (#360) * fixing #340 (#341) * updating change log * fixing changelog * testing new build (#351) * version bump * fixing issue #355 (#356) * resolving conflict * fixing 359 * Adding documentation for * fixing changelog * fixing build --- CHANGELOG.md | 13 +- README.md | 4 +- build-helpers/inliner.js | 118 ------------------ .../services/utils/utils.service.spec.ts | 13 ++ .../common/services/utils/utils.service.ts | 33 +++++ .../date-picker/date-picker-config.model.ts | 2 +- .../date-picker-directive.service.ts | 14 ++- src/app/date-picker/date-picker.component.ts | 2 +- .../date-picker/date-picker.directive.spec.ts | 2 +- src/app/date-picker/date-picker.directive.ts | 8 +- .../day-time-calendar.service.spec.ts | 1 + tsconfig.json | 3 - 12 files changed, 78 insertions(+), 135 deletions(-) delete mode 100644 build-helpers/inliner.js diff --git a/CHANGELOG.md b/CHANGELOG.md index df4f070d..90658d38 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,13 +1,16 @@ # Changelog All notable changes to this project will be documented in this file. - -# [2.7.4] (???) + +# [2.7.5] (???) ### Bug Fixes -- Fixing disabled dates when selecting past/future time from current day ([18db1ca](https://github.com/vlio20/angular-datepicker/commit/18db1ca)) closes [#340](https://github.com/vlio20/angular-datepicker/issues/340) +- Adding documentation for `showGoToCurrent` ([b3e3728](https://github.com/vlio20/angular-datepicker/commit/b3e3728)) closes [#357](https://github.com/vlio20/angular-datepicker/issues/357) +- Fixing `inputElementContainer` which did not work on directive + added to docs ([6344b38](https://github.com/vlio20/angular-datepicker/commit/6344b38)) closes [#359](https://github.com/vlio20/angular-datepicker/issues/359) +- Fixing Not able to bind to moment, getting TypeError: `(value || "").split is not a function` ([19cee2d](https://github.com/vlio20/angular-datepicker/commit/19cee2d)) closes [#355](https://github.com/vlio20/angular-datepicker/issues/355) - -# [2.7.3] (2018-01-13) + +# [2.7.4] (2018-01-13) +- Fixing disabled dates when selecting past/future time from current day ([18db1ca](https://github.com/vlio20/angular-datepicker/commit/18db1ca)) closes [#340](https://github.com/vlio20/angular-datepicker/issues/340) ### Features - Navigation events are now dispatched from all relevant components ([2552889](https://github.com/vlio20/angular-datepicker/commit/2552889)) closes [#329](https://github.com/vlio20/angular-datepicker/issues/329) diff --git a/README.md b/README.md index c70a3a72..94362245 100644 --- a/README.md +++ b/README.md @@ -121,7 +121,9 @@ Here are the available configurations: | showMultipleYearsNavigation | `boolean` | `false` | `day\|month\|daytime` | If set to `true` will show buttons to navigate by multiple years (10 by default) | | multipleYearsNavigateBy | `number` | `10` | `day\|month\|daytime` | Number of years to navigate when showMultipleYearsNavigation is `true` | | returnedValueType | `ECalendarValue` | `Moment` | All | The returned value type (`Moment`, `Moment[]`, `string`, `string[]` | -| unSelectOnClick | `boolean` | true | `day\|month` | Will allow disallow/unselect to selected date by clicking on the selected date | +| unSelectOnClick | `boolean` | `true` | `day\|month` | Will allow disallow/unselect to selected date by clicking on the selected date | +| inputElementContainer | `string\|HTMLElement` | `undefined` | ALL | Will place picker popup relative to the provided elemenr (if string provided will used as a selector) | +| showGoToCurrent | `boolean` | `true` | ALL | Show/Hides the go to current button on the calendars navigation | ### API: In order to use the date-picker api user the `@ViewChild` annotation in the date-picker containing component class, take at the example below: diff --git a/build-helpers/inliner.js b/build-helpers/inliner.js deleted file mode 100644 index 580ec59d..00000000 --- a/build-helpers/inliner.js +++ /dev/null @@ -1,118 +0,0 @@ -'use strict'; - -const fs = require('fs'); -const path = require('path'); -const less = require('less'); - -module.exports = function (content, options, targetDir) { - options = options || {}; - options.base = options.base || './'; - - return processStyleUrls(content, options, targetDir).then( - (r) => processTemplateUrl(r, options, targetDir)); -}; - -function processStyleUrls(content, options, targetDir) { - let closure = content; - let re = /styleUrls\s*:\s*(\[[^](.[^]*?)\])/g; - let matches = closure.match(re); - - if (matches === null || matches.length <= 0) { - return Promise.resolve(closure); - } - - return Promise.all(matches.map(function () { - let exec = re.exec(closure); - let style = exec[0]; - let urls = exec[1]; - urls = urls.replace(/'/g, '"'); - urls = JSON.parse(urls); - - return Promise.all(urls.map(function (url) { - let file = fs.readFileSync(getAbsoluteUrl(url, options, targetDir), - 'utf-8'); - - let fileNamePartsRe = /^[\./]*([^]*)\.(css|less)$/g; - let fileNamePartsMatches = url.match(fileNamePartsRe); - if (fileNamePartsMatches === null || fileNamePartsMatches.length <= 0) { - // Unsupported file mode / malformed url - return file; - } - - let fileNamePartsExec = fileNamePartsRe.exec(url); - let fileName = fileNamePartsExec[1]; - let extension = fileNamePartsExec[2]; - let promise; - if (extension === 'less') { - promise = less.render( - file, - { - paths: [options.base ? options.base : '.'], - filename: targetDir ? path.join(targetDir, fileName) : fileName, - compress: options.compress - } - ).then((output) => { - return output.css; - }, (e) => { - throw e; - }); - } else { - promise = Promise.resolve(file); - } - - return promise.then((processed) => { - processed = processed.replace(/[\r\n]/g, ''); - - // escape quote chars - processed = processed.replace(new RegExp('\'', 'g'), '\\\''); - return processed; - }); - })).then((files) => { - closure = closure.replace(style, 'styles: [\'' + files.join('') + '\']'); - }); - })).then(() => { - return closure; - }); -} - -function processTemplateUrl(content, options, targetDir) { - let closure = content; - let re = /templateUrl\s*:\s*(?:"([^"]+)"|'([^']+)')/g; - let matches = closure.match(re); - - if (matches === null || matches.length <= 0) { - return Promise.resolve(closure); - } - - matches.forEach(function () { - let exec = re.exec(closure); - let template = exec[0]; - let quote; - let url; - - if (exec[1]) { - url = exec[1]; - quote = '"'; - } else { - url = exec[2]; - quote = '\''; - } - - let file = fs.readFileSync(getAbsoluteUrl(url, options, targetDir), - 'utf-8'); - - file = file.replace(/\n|\t/g, ' '); - - // escape quote chars - file = file.replace(new RegExp(quote, 'g'), '\\' + quote); - - closure = closure.replace(template, 'template: ' + quote + file + quote); - }); - - return Promise.resolve(closure); -} - -function getAbsoluteUrl(url, options, targetDir) { - return options.relative ? path.join(targetDir, url) : - path.join(options.base, url); -} diff --git a/src/app/common/services/utils/utils.service.spec.ts b/src/app/common/services/utils/utils.service.spec.ts index b9097f2a..aca2b18b 100644 --- a/src/app/common/services/utils/utils.service.spec.ts +++ b/src/app/common/services/utils/utils.service.spec.ts @@ -2,6 +2,7 @@ import {inject, TestBed} from '@angular/core/testing'; import {UtilsService} from './utils.service'; import * as momentNs from 'moment'; import {IDate} from '../../models/date.model'; + const moment = momentNs; describe('Service: ObUtilsService', () => { @@ -116,4 +117,16 @@ describe('Service: ObUtilsService', () => { expect(service.datesStringToStringArray('14,01-1984| asdasd')) .toEqual(['14,01-1984', 'asdasd']); })); + + it('check convertToString', inject([UtilsService], (service: UtilsService) => { + const format = 'MM/DD/YYYY'; + expect(service.convertToString(null, format)).toEqual(''); + expect(service.convertToString('', format)).toEqual(''); + expect(service.convertToString(moment(), format)).toEqual(moment().format(format)); + expect(service.convertToString([moment()], format)).toEqual(moment().format(format)); + expect(service.convertToString([moment(), moment().add(1, 'd')], format)) + .toEqual(moment().format(format) + ' | ' + moment().add(1, 'd').format(format)); + expect(service.convertToString([moment().format(format), moment().add(1, 'd').format(format)], format)) + .toEqual(moment().format(format) + ' | ' + moment().add(1, 'd').format(format)); + })); }); diff --git a/src/app/common/services/utils/utils.service.ts b/src/app/common/services/utils/utils.service.ts index 49cbe3b5..8b1b8aed 100644 --- a/src/app/common/services/utils/utils.service.ts +++ b/src/app/common/services/utils/utils.service.ts @@ -8,6 +8,7 @@ import {IDate} from '../../models/date.model'; import {CalendarMode} from '../../types/calendar-mode'; import {DateValidator} from '../../types/validator.type'; import {ICalendarInternal} from '../../models/calendar.model'; + const moment = momentNs; export interface DateLimits { @@ -127,6 +128,28 @@ export class UtilsService { } } + convertToString(value: CalendarValue, format: string): string { + let tmpVal: string[]; + + if (typeof value === 'string') { + tmpVal = [value]; + } else if (Array.isArray(value)) { + if (value.length) { + tmpVal = (value).map((v) => { + return this.convertToMoment(v, format).format(format); + }); + } else { + tmpVal = value; + } + } else if (moment.isMoment(value)) { + tmpVal = [value.format(format)]; + } else { + return ''; + } + + return tmpVal.filter(Boolean).join(' | '); + } + // todo:: add unit test clearUndefined(obj: T): T { if (!obj) { @@ -305,4 +328,14 @@ export class UtilsService { return false; } + + getNativeElement(elem: HTMLElement | string): HTMLElement { + if (!elem) { + return null; + } else if (typeof elem === 'string') { + return document.querySelector(elem); + } else { + return elem; + } + } } diff --git a/src/app/date-picker/date-picker-config.model.ts b/src/app/date-picker/date-picker-config.model.ts index 7eeab6d5..542ae0de 100644 --- a/src/app/date-picker/date-picker-config.model.ts +++ b/src/app/date-picker/date-picker-config.model.ts @@ -11,7 +11,7 @@ export interface IConfig { onOpenDelay?: number; disableKeypress?: boolean; appendTo?: string | HTMLElement; - inputElementContainer?: HTMLElement; + inputElementContainer?: HTMLElement | string; drops?: TDrops; opens?: TOpens; hideInputContainer?: boolean; diff --git a/src/app/date-picker/date-picker-directive.service.ts b/src/app/date-picker/date-picker-directive.service.ts index ba922b50..26c23c2a 100644 --- a/src/app/date-picker/date-picker-directive.service.ts +++ b/src/app/date-picker/date-picker-directive.service.ts @@ -23,10 +23,18 @@ export class DatePickerDirectiveService { const _config: IDatePickerDirectiveConfig = {...config}; _config.hideInputContainer = true; - if (baseElement) { + let native; + + if (config.inputElementContainer) { + native = this.utilsService.getNativeElement(config.inputElementContainer); + } else { + native = baseElement ? baseElement.nativeElement : null; + } + + if (native) { _config.inputElementContainer = attachTo - ? this.convertToHTMLElement(attachTo, baseElement.nativeElement) - : baseElement.nativeElement; + ? this.convertToHTMLElement(attachTo, native) + : native; } return _config; diff --git a/src/app/date-picker/date-picker.component.ts b/src/app/date-picker/date-picker.component.ts index d6b7537c..6ee852d8 100644 --- a/src/app/date-picker/date-picker.component.ts +++ b/src/app/date-picker/date-picker.component.ts @@ -335,7 +335,7 @@ export class DatePickerComponent implements OnChanges, } setInputElementContainer() { - this.inputElementContainer = this.componentConfig.inputElementContainer + this.inputElementContainer = this.utilsService.getNativeElement(this.componentConfig.inputElementContainer) || this.elemRef.nativeElement.querySelector('.dp-input-container') || document.body; } diff --git a/src/app/date-picker/date-picker.directive.spec.ts b/src/app/date-picker/date-picker.directive.spec.ts index 75422a70..cc85ea34 100644 --- a/src/app/date-picker/date-picker.directive.spec.ts +++ b/src/app/date-picker/date-picker.directive.spec.ts @@ -17,7 +17,7 @@ describe('Directive: DpDayPicker', () => { }); }); - const directive = new DatePickerDirective(null, null, null, null, null); + const directive = new DatePickerDirective(null, null, null, null, null, null); it('should create an instance', () => { expect(directive).toBeTruthy(); diff --git a/src/app/date-picker/date-picker.directive.ts b/src/app/date-picker/date-picker.directive.ts index cbae7c30..e7a6af68 100644 --- a/src/app/date-picker/date-picker.directive.ts +++ b/src/app/date-picker/date-picker.directive.ts @@ -19,6 +19,8 @@ import {NgControl} from '@angular/forms'; import {CalendarValue} from '../common/types/calendar-value'; import {SingleCalendarValue} from '../common/types/single-calendar-value'; import {INavEvent} from '../common/models/navigation-event.model'; +import {UtilsService} from '../common/services/utils/utils.service'; +import {ECalendarValue} from '../common/types/calendar-value-enum'; @Directive({ exportAs: 'dpDayPicker', @@ -164,7 +166,8 @@ export class DatePickerDirective implements OnInit { public elemRef: ElementRef, public componentFactoryResolver: ComponentFactoryResolver, public service: DatePickerDirectiveService, - @Optional() public formControl: NgControl) { + @Optional() public formControl: NgControl, + public utilsService: UtilsService) { } ngOnInit(): void { @@ -189,7 +192,8 @@ export class DatePickerDirective implements OnInit { this.formControl.valueChanges.subscribe((value) => { if (value !== this.datePicker.inputElementValue) { - this.datePicker.onViewDateChange(value); + const strVal = this.utilsService.convertToString(value, this.datePicker.componentConfig.format); + this.datePicker.onViewDateChange(strVal); } }); diff --git a/src/app/day-time-calendar/day-time-calendar.service.spec.ts b/src/app/day-time-calendar/day-time-calendar.service.spec.ts index 2ce4f360..502b9e6f 100644 --- a/src/app/day-time-calendar/day-time-calendar.service.spec.ts +++ b/src/app/day-time-calendar/day-time-calendar.service.spec.ts @@ -5,6 +5,7 @@ import {UtilsService} from '../common/services/utils/utils.service'; import {DayCalendarService} from '../day-calendar/day-calendar.service'; import {TimeSelectService} from '../time-select/time-select.service'; import {IDayCalendarConfigInternal} from '../day-calendar/day-calendar-config.model'; + const moment = momentNs; const DAY_FORMAT = 'YYYYMMDD'; diff --git a/tsconfig.json b/tsconfig.json index 0b54e05c..5fc7026d 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -17,9 +17,6 @@ "dom" ] }, - "include": [ - "prebuild/app/index.ts" - ], "exclude": [ "node_modules", "**/*.spec.ts"