diff --git a/src/pipes/bytes-to-size.ts b/src/pipes/bytes-to-size.ts new file mode 100644 index 000000000..a05ef7e4b --- /dev/null +++ b/src/pipes/bytes-to-size.ts @@ -0,0 +1,51 @@ +// (C) Copyright 2015 Martin Dougiamas +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { Pipe, PipeTransform } from '@angular/core'; +import { CoreLoggerProvider } from '../providers/logger'; +import { CoreTextUtilsProvider } from '../providers/utils/text'; + +/** + * Pipe to turn a number in bytes to a human readable size (e.g. 5,25 MB). + */ +@Pipe({ + name: 'coreBytesToSize', +}) +export class CoreBytesToSizePipe implements PipeTransform { + protected logger; + + constructor(logger: CoreLoggerProvider, private textUtils: CoreTextUtilsProvider) { + this.logger = logger.getInstance('CoreBytesToSizePipe'); + } + + /** + * Takes a number and turns it to a human readable size. + * + * @param {number|string} value The bytes to convert. + * @return {string} Readable bytes. + */ + transform(value: number|string) : string { + if (typeof value == 'string') { + // Convert the value to a number. + const numberValue = parseInt(value, 10); + if (isNaN(numberValue)) { + this.logger.error('Invalid value received', value); + return value; + } + value = numberValue; + } + + return this.textUtils.bytesToSize(value); + } +} diff --git a/src/pipes/create-links.ts b/src/pipes/create-links.ts new file mode 100644 index 000000000..0cc66c27a --- /dev/null +++ b/src/pipes/create-links.ts @@ -0,0 +1,35 @@ +// (C) Copyright 2015 Martin Dougiamas +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { Pipe, PipeTransform } from '@angular/core'; + +/** + * Pipe to search URLs that are not inside tags and add the corresponding tags. + */ +@Pipe({ + name: 'coreCreateLinks', +}) +export class CoreCreateLinksPipe implements PipeTransform { + private replacePattern = /(\b(https?|ftp):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])(?![^<]*>|[^<>]*<\/)/gim; + + /** + * Takes some text and adds anchor tags to all links that aren't inside anchors. + * + * @param {string} text Text to treat. + * @return {string} Treated text. + */ + transform(text: string) { + return text.replace(this.replacePattern, '$1'); + } +} diff --git a/src/pipes/date-day-or-time.ts b/src/pipes/date-day-or-time.ts new file mode 100644 index 000000000..d216c150a --- /dev/null +++ b/src/pipes/date-day-or-time.ts @@ -0,0 +1,66 @@ +// (C) Copyright 2015 Martin Dougiamas +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { Pipe, PipeTransform } from '@angular/core'; +import { TranslateService } from '@ngx-translate/core'; +import { CoreLoggerProvider } from '../providers/logger'; +import * as moment from 'moment'; + +/** + * Filter to display a date using the day, or the time. + * + * This shows a short version of a date. Use this filter when you want + * the user to visualise when the action was done relatively to today's date. + * + * For instance, if the action happened during this day it will display the time, + * but when the action happened few days ago, it will display the day of the week. + * + * The older the date is, the more information about it will be displayed. + * + * This filter expects a timestamp NOT including milliseconds. + */ +@Pipe({ + name: 'coreDateDayOrTime', +}) +export class CoreDateDayOrTimePipe implements PipeTransform { + protected logger; + + constructor(logger: CoreLoggerProvider, private translate: TranslateService) { + this.logger = logger.getInstance('CoreDateDayOrTimePipe'); + } + + /** + * Format a timestamp. + * + * @param {number|string} timestamp The UNIX timestamp (without milliseconds). + * @return {string} Formatted time. + */ + transform(timestamp: string|number) : string { + if (typeof timestamp == 'string') { + // Convert the value to a number. + const numberTimestamp = parseInt(timestamp, 10); + if (isNaN(numberTimestamp)) { + this.logger.error('Invalid value received', timestamp); + return timestamp; + } + timestamp = numberTimestamp; + } + + return moment(timestamp * 1000).calendar(null, { + sameDay: this.translate.instant('mm.core.dftimedate'), + lastDay: this.translate.instant('mm.core.dflastweekdate'), + lastWeek: this.translate.instant('mm.core.dflastweekdate') + }); + } +} diff --git a/src/pipes/duration.ts b/src/pipes/duration.ts new file mode 100644 index 000000000..c5bde0e2a --- /dev/null +++ b/src/pipes/duration.ts @@ -0,0 +1,51 @@ +// (C) Copyright 2015 Martin Dougiamas +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { Pipe, PipeTransform } from '@angular/core'; +import { CoreLoggerProvider } from '../providers/logger'; +import * as moment from 'moment'; + +/** + * Filter to turn a number of seconds to a duration. E.g. 60 -> 1 minute. + */ +@Pipe({ + name: 'coreDuration', +}) +export class CoreDurationPipe implements PipeTransform { + protected logger; + + constructor(logger: CoreLoggerProvider) { + this.logger = logger.getInstance('CoreBytesToSizePipe'); + } + + /** + * Turn a number of seconds to a duration. E.g. 60 -> 1 minute. + * + * @param {number|string} seconds The number of seconds. + * @return {string} Formatted duration. + */ + transform(seconds: string|number) { + if (typeof seconds == 'string') { + // Convert the value to a number. + const numberSeconds = parseInt(seconds, 10); + if (isNaN(numberSeconds)) { + this.logger.error('Invalid value received', seconds); + return seconds; + } + seconds = numberSeconds; + } + + return moment.duration(seconds * 1000).humanize(); + } +} diff --git a/src/pipes/format-date.ts b/src/pipes/format-date.ts new file mode 100644 index 000000000..d4c4b491a --- /dev/null +++ b/src/pipes/format-date.ts @@ -0,0 +1,59 @@ +// (C) Copyright 2015 Martin Dougiamas +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { Pipe, PipeTransform } from '@angular/core'; +import { TranslateService } from '@ngx-translate/core'; +import { CoreLoggerProvider } from '../providers/logger'; +import * as moment from 'moment'; + +/** + * Filter to format a date. + */ +@Pipe({ + name: 'coreFormatDate', +}) +export class CoreFormatDatePipe implements PipeTransform { + protected logger; + + constructor(logger: CoreLoggerProvider, private translate: TranslateService) { + this.logger = logger.getInstance('CoreDateDayOrTimePipe'); + } + + /** + * Format a date. + * + * @param {string|number} timestamp Timestamp to format (in milliseconds). If not defined, use current time. + * @param {string} format Format to use. It should be a string code to handle i18n (e.g. mm.core.dftimedate). If the code + * doesn't have a prefix, 'mm.core' will be used by default. E.g. 'dftimedate' -> 'mm.core.dftimedate'. + * @return {String} Formatted date. + */ + transform(timestamp: string|number, format: string) { + timestamp = timestamp || Date.now(); + + if (typeof timestamp == 'string') { + // Convert the value to a number. + const numberTimestamp = parseInt(timestamp, 10); + if (isNaN(numberTimestamp)) { + this.logger.error('Invalid value received', timestamp); + return timestamp; + } + timestamp = numberTimestamp; + } + + if (format.indexOf('.') == -1) { + format = 'mm.core.' + format; + } + return moment(timestamp).format(this.translate.instant(format)); + } +} diff --git a/src/pipes/no-tags.ts b/src/pipes/no-tags.ts new file mode 100644 index 000000000..d43e40794 --- /dev/null +++ b/src/pipes/no-tags.ts @@ -0,0 +1,34 @@ +// (C) Copyright 2015 Martin Dougiamas +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { Pipe, PipeTransform } from '@angular/core'; + +/** + * Pipe to remove HTML tags. + */ +@Pipe({ + name: 'coreNoTags', +}) +export class CoreNoTagsPipe implements PipeTransform { + + /** + * Takes a text and removes HTML tags. + * + * @param {string} text The text to treat. + * @return {string} Treated text. + */ + transform(text: string) : string { + return text.replace(/(<([^>]+)>)/ig, ''); + } +} diff --git a/src/pipes/pipes.module.ts b/src/pipes/pipes.module.ts new file mode 100644 index 000000000..b91eccfc6 --- /dev/null +++ b/src/pipes/pipes.module.ts @@ -0,0 +1,51 @@ +// (C) Copyright 2015 Martin Dougiamas +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { NgModule } from '@angular/core'; +import { CoreBytesToSizePipe } from './bytes-to-size'; +import { CoreCreateLinksPipe } from './create-links'; +import { CoreDateDayOrTimePipe } from './date-day-or-time'; +import { CoreDurationPipe } from './duration'; +import { CoreFormatDatePipe } from './format-date'; +import { CoreNoTagsPipe } from './no-tags'; +import { CoreSecondsToHMSPipe } from './seconds-to-hms'; +import { CoreTimeAgoPipe } from './time-ago'; +import { CoreToLocaleStringPipe } from './to-locale-string'; + +@NgModule({ + declarations: [ + CoreBytesToSizePipe, + CoreCreateLinksPipe, + CoreDateDayOrTimePipe, + CoreDurationPipe, + CoreFormatDatePipe, + CoreNoTagsPipe, + CoreSecondsToHMSPipe, + CoreTimeAgoPipe, + CoreToLocaleStringPipe + ], + imports: [], + exports: [ + CoreBytesToSizePipe, + CoreCreateLinksPipe, + CoreDateDayOrTimePipe, + CoreDurationPipe, + CoreFormatDatePipe, + CoreNoTagsPipe, + CoreSecondsToHMSPipe, + CoreTimeAgoPipe, + CoreToLocaleStringPipe + ] +}) +export class CorePipesModule {} diff --git a/src/pipes/seconds-to-hms.ts b/src/pipes/seconds-to-hms.ts new file mode 100644 index 000000000..c88164cbc --- /dev/null +++ b/src/pipes/seconds-to-hms.ts @@ -0,0 +1,64 @@ +// (C) Copyright 2015 Martin Dougiamas +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { Pipe, PipeTransform } from '@angular/core'; +import { CoreLoggerProvider } from '../providers/logger'; +import { CoreTextUtilsProvider } from '../providers/utils/text'; +import { CoreConstants } from '../core/constants'; + +/** + * Pipe to convert a number of seconds to Hours:Minutes:Seconds. + * + * This converts a number of seconds to Hours:Minutes:Seconds. If the number of seconds is negative, returns 00:00:00. + */ +@Pipe({ + name: 'coreSecondsToHMS', +}) +export class CoreSecondsToHMSPipe implements PipeTransform { + protected logger; + + constructor(logger: CoreLoggerProvider, private textUtils: CoreTextUtilsProvider) { + this.logger = logger.getInstance('CoreSecondsToHMSPipe'); + } + + /** + * Convert a number of seconds to Hours:Minutes:Seconds. + * + * @param {number|string} seconds Number of seconds. + * @return {string} Formatted seconds. + */ + transform(seconds: string|number) : string { + let hours, + minutes; + + if (!seconds || seconds < 0) { + seconds = 0; + } else if (typeof seconds == 'string') { + // Convert the value to a number. + const numberSeconds = parseInt(seconds, 10); + if (isNaN(numberSeconds)) { + this.logger.error('Invalid value received', seconds); + return seconds; + } + seconds = numberSeconds; + } + + hours = Math.floor(seconds / CoreConstants.secondsHour); + seconds -= hours * CoreConstants.secondsHour; + minutes = Math.floor(seconds / CoreConstants.secondsMinute); + seconds -= minutes * CoreConstants.secondsMinute; + + return this.textUtils.twoDigits(hours) + ':' + this.textUtils.twoDigits(minutes) + ':' + this.textUtils.twoDigits(seconds); + } +} diff --git a/src/pipes/time-ago.ts b/src/pipes/time-ago.ts new file mode 100644 index 000000000..b1c7ad1c0 --- /dev/null +++ b/src/pipes/time-ago.ts @@ -0,0 +1,51 @@ +// (C) Copyright 2015 Martin Dougiamas +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { Pipe, PipeTransform } from '@angular/core'; +import { CoreLoggerProvider } from '../providers/logger'; +import * as moment from 'moment'; + +/** + * Pipe to turn a UNIX timestamp to "time ago". + */ +@Pipe({ + name: 'coreTimeAgo', +}) +export class CoreTimeAgoPipe implements PipeTransform { + protected logger; + + constructor(logger: CoreLoggerProvider) { + this.logger = logger.getInstance('CoreTimeAgoPipe'); + } + + /** + * Turn a UNIX timestamp to "time ago". + * + * @param {number|string} timestamp The UNIX timestamp (without milliseconds). + * @return {string} Formatted time. + */ + transform(timestamp: string|number) : string { + if (typeof timestamp == 'string') { + // Convert the value to a number. + const numberTimestamp = parseInt(timestamp, 10); + if (isNaN(numberTimestamp)) { + this.logger.error('Invalid value received', timestamp); + return timestamp; + } + timestamp = numberTimestamp; + } + + return moment(timestamp * 1000).fromNow(true); + } +} diff --git a/src/pipes/to-locale-string.ts b/src/pipes/to-locale-string.ts new file mode 100644 index 000000000..eb7aec685 --- /dev/null +++ b/src/pipes/to-locale-string.ts @@ -0,0 +1,58 @@ +// (C) Copyright 2015 Martin Dougiamas +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { Pipe, PipeTransform } from '@angular/core'; +import { CoreLoggerProvider } from '../providers/logger'; + +/** + * Filter to format a timestamp to a locale string. Timestamp can be in seconds or milliseconds. + */ +@Pipe({ + name: 'coreToLocaleString', +}) +export class CoreToLocaleStringPipe implements PipeTransform { + protected logger; + + constructor(logger: CoreLoggerProvider) { + this.logger = logger.getInstance('CoreToLocaleStringPipe'); + } + + /** + * Format a timestamp to a locale string. + * + * @param {number|string} timestamp The timestamp (can be in seconds or milliseconds). + * @return {string} Formatted time. + */ + transform(timestamp: number|string) : string { + if (typeof timestamp == 'string') { + // Convert the value to a number. + const numberTimestamp = parseInt(timestamp, 10); + if (isNaN(numberTimestamp)) { + this.logger.error('Invalid value received', timestamp); + return timestamp; + } + timestamp = numberTimestamp; + } + + if (timestamp < 0) { + // Date not valid. + return ''; + } + if (timestamp < 100000000000) { + // Timestamp is in seconds, convert it to milliseconds. + timestamp = timestamp * 1000; + } + return new Date(timestamp).toLocaleString(); + } +}