diff options
Diffstat (limited to 'app/assets/javascripts/lib')
-rw-r--r-- | app/assets/javascripts/lib/graphql.js | 6 | ||||
-rw-r--r-- | app/assets/javascripts/lib/utils/chart_utils.js | 17 | ||||
-rw-r--r-- | app/assets/javascripts/lib/utils/datetime_utility.js | 58 | ||||
-rw-r--r-- | app/assets/javascripts/lib/utils/notify.js | 8 | ||||
-rw-r--r-- | app/assets/javascripts/lib/utils/number_utils.js | 33 | ||||
-rw-r--r-- | app/assets/javascripts/lib/utils/text_utility.js | 23 | ||||
-rw-r--r-- | app/assets/javascripts/lib/utils/tick_formats.js | 39 |
7 files changed, 122 insertions, 62 deletions
diff --git a/app/assets/javascripts/lib/graphql.js b/app/assets/javascripts/lib/graphql.js index c05db4a5c71..2c5278d16ae 100644 --- a/app/assets/javascripts/lib/graphql.js +++ b/app/assets/javascripts/lib/graphql.js @@ -26,7 +26,11 @@ export default (resolvers = {}, config = {}) => { createUploadLink(httpOptions), new BatchHttpLink(httpOptions), ), - cache: new InMemoryCache(config.cacheConfig), + cache: new InMemoryCache({ + ...config.cacheConfig, + freezeResults: config.assumeImmutableResults, + }), resolvers, + assumeImmutableResults: config.assumeImmutableResults, }); }; diff --git a/app/assets/javascripts/lib/utils/chart_utils.js b/app/assets/javascripts/lib/utils/chart_utils.js index 0f78756aac8..4a1e6c5d68c 100644 --- a/app/assets/javascripts/lib/utils/chart_utils.js +++ b/app/assets/javascripts/lib/utils/chart_utils.js @@ -81,3 +81,20 @@ export const lineChartOptions = ({ width, numberOfPoints, shouldAdjustFontSize } }, }, }); + +/** + * Takes a dataset and returns an array containing the y-values of it's first and last entry. + * (e.g., [['xValue1', 'yValue1'], ['xValue2', 'yValue2'], ['xValue3', 'yValue3']] will yield ['yValue1', 'yValue3']) + * + * @param {Array} data + * @returns {[*, *]} + */ +export const firstAndLastY = data => { + const [firstEntry] = data; + const [lastEntry] = data.slice(-1); + + const firstY = firstEntry[1]; + const lastY = lastEntry[1]; + + return [firstY, lastY]; +}; diff --git a/app/assets/javascripts/lib/utils/datetime_utility.js b/app/assets/javascripts/lib/utils/datetime_utility.js index 37b0215f6f9..28143859e4c 100644 --- a/app/assets/javascripts/lib/utils/datetime_utility.js +++ b/app/assets/javascripts/lib/utils/datetime_utility.js @@ -78,11 +78,11 @@ export const getDayName = date => * @param {date} datetime * @returns {String} */ -export const formatDate = datetime => { +export const formatDate = (datetime, format = 'mmm d, yyyy h:MMtt Z') => { if (_.isString(datetime) && datetime.match(/\d+-\d+\d+ /)) { throw new Error(__('Invalid date')); } - return dateFormat(datetime, 'mmm d, yyyy h:MMtt Z'); + return dateFormat(datetime, format); }; /** @@ -541,7 +541,7 @@ export const stringifyTime = (timeObject, fullNameFormat = false) => { * The result cannot become negative. * * @param endDate date string that the time difference is calculated for - * @return {number} number of milliseconds remaining until the given date + * @return {Number} number of milliseconds remaining until the given date */ export const calculateRemainingMilliseconds = endDate => { const remainingMilliseconds = new Date(endDate).getTime() - Date.now(); @@ -552,15 +552,53 @@ export const calculateRemainingMilliseconds = endDate => { * Subtracts a given number of days from a given date and returns the new date. * * @param {Date} date the date that we will substract days from - * @param {number} daysInPast number of days that are subtracted from a given date - * @returns {String} Date string in ISO format + * @param {Number} daysInPast number of days that are subtracted from a given date + * @returns {Date} Date in past as Date object */ -export const getDateInPast = (date, daysInPast) => { - const dateClone = newDate(date); - return new Date( - dateClone.setTime(dateClone.getTime() - daysInPast * 24 * 60 * 60 * 1000), - ).toISOString(); +export const getDateInPast = (date, daysInPast) => + new Date(newDate(date).setDate(date.getDate() - daysInPast)); + +/* + * Appending T00:00:00 makes JS assume local time and prevents it from shifting the date + * to match the user's time zone. We want to display the date in server time for now, to + * be consistent with the "edit issue -> due date" UI. + */ + +export const newDateAsLocaleTime = date => { + const suffix = 'T00:00:00'; + return new Date(`${date}${suffix}`); }; export const beginOfDayTime = 'T00:00:00Z'; export const endOfDayTime = 'T23:59:59Z'; + +/** + * @param {Date} d1 + * @param {Date} d2 + * @param {Function} formatter + * @return {Any[]} an array of formatted dates between 2 given dates (including start&end date) + */ +export const getDatesInRange = (d1, d2, formatter = x => x) => { + if (!(d1 instanceof Date) || !(d2 instanceof Date)) { + return []; + } + let startDate = d1.getTime(); + const endDate = d2.getTime(); + const oneDay = 24 * 3600 * 1000; + const range = [d1]; + + while (startDate < endDate) { + startDate += oneDay; + range.push(new Date(startDate)); + } + + return range.map(formatter); +}; + +/** + * Converts the supplied number of seconds to milliseconds. + * + * @param {Number} seconds + * @return {Number} number of milliseconds + */ +export const secondsToMilliseconds = seconds => seconds * 1000; diff --git a/app/assets/javascripts/lib/utils/notify.js b/app/assets/javascripts/lib/utils/notify.js index cd509a13193..8db08099b3f 100644 --- a/app/assets/javascripts/lib/utils/notify.js +++ b/app/assets/javascripts/lib/utils/notify.js @@ -1,8 +1,7 @@ -/* eslint-disable no-var, consistent-return, no-return-assign */ +/* eslint-disable consistent-return, no-return-assign */ function notificationGranted(message, opts, onclick) { - var notification; - notification = new Notification(message, opts); + const notification = new Notification(message, opts); setTimeout( () => // Hide the notification after X amount of seconds @@ -21,8 +20,7 @@ function notifyPermissions() { } function notifyMe(message, body, icon, onclick) { - var opts; - opts = { + const opts = { body, icon, }; diff --git a/app/assets/javascripts/lib/utils/number_utils.js b/app/assets/javascripts/lib/utils/number_utils.js index 0f2cc57b1f9..bc87232f40b 100644 --- a/app/assets/javascripts/lib/utils/number_utils.js +++ b/app/assets/javascripts/lib/utils/number_utils.js @@ -117,3 +117,36 @@ export const median = arr => { const sorted = arr.sort((a, b) => a - b); return arr.length % 2 !== 0 ? sorted[middle] : (sorted[middle - 1] + sorted[middle]) / 2; }; + +/** + * Computes the change from one value to the other as a percentage. + * @param {Number} firstY + * @param {Number} lastY + * @returns {Number} + */ +export const changeInPercent = (firstY, lastY) => { + if (firstY === lastY) { + return 0; + } + + return Math.round(((lastY - firstY) / Math.abs(firstY)) * 100); +}; + +/** + * Computes and formats the change from one value to the other as a percentage. + * Prepends the computed percentage with either "+" or "-" to indicate an in- or decrease and + * returns a given string if the result is not finite (for example, if the first value is "0"). + * @param firstY + * @param lastY + * @param nonFiniteResult + * @returns {String} + */ +export const formattedChangeInPercent = (firstY, lastY, { nonFiniteResult = '-' } = {}) => { + const change = changeInPercent(firstY, lastY); + + if (!Number.isFinite(change)) { + return nonFiniteResult; + } + + return `${change >= 0 ? '+' : ''}${change}%`; +}; diff --git a/app/assets/javascripts/lib/utils/text_utility.js b/app/assets/javascripts/lib/utils/text_utility.js index d13fbeb5fc7..0c194d67bce 100644 --- a/app/assets/javascripts/lib/utils/text_utility.js +++ b/app/assets/javascripts/lib/utils/text_utility.js @@ -36,25 +36,26 @@ export const humanize = string => export const dasherize = str => str.replace(/[_\s]+/g, '-'); /** - * Replaces whitespaces with hyphens, convert to lower case and remove non-allowed special characters - * @param {String} str + * Replaces whitespace and non-sluggish characters with a given separator + * @param {String} str - The string to slugify + * @param {String=} separator - The separator used to separate words (defaults to "-") * @returns {String} */ -export const slugify = str => { +export const slugify = (str, separator = '-') => { const slug = str .trim() .toLowerCase() - .replace(/[^a-zA-Z0-9_.-]+/g, '-'); + .replace(/[^a-zA-Z0-9_.-]+/g, separator); - return slug === '-' ? '' : slug; + return slug === separator ? '' : slug; }; /** - * Replaces whitespaces with underscore and converts to lower case + * Replaces whitespace and non-sluggish characters with underscores * @param {String} str * @returns {String} */ -export const slugifyWithUnderscore = str => str.toLowerCase().replace(/\s+/g, '_'); +export const slugifyWithUnderscore = str => slugify(str, '_'); /** * Truncates given text @@ -139,6 +140,14 @@ export const stripHtml = (string, replace = '') => { export const convertToCamelCase = string => string.replace(/(_\w)/g, s => s[1].toUpperCase()); /** + * Converts camelCase string to snake_case + * + * @param {*} string + */ +export const convertToSnakeCase = string => + slugifyWithUnderscore(string.match(/([a-zA-Z][^A-Z]*)/g).join(' ')); + +/** * Converts a sentence to lower case from the second word onwards * e.g. Hello World => Hello world * diff --git a/app/assets/javascripts/lib/utils/tick_formats.js b/app/assets/javascripts/lib/utils/tick_formats.js deleted file mode 100644 index af3ca714400..00000000000 --- a/app/assets/javascripts/lib/utils/tick_formats.js +++ /dev/null @@ -1,39 +0,0 @@ -import { createDateTimeFormat } from '../../locale'; - -let dateTimeFormats; - -export const initDateFormats = () => { - const dayFormat = createDateTimeFormat({ month: 'short', day: 'numeric' }); - const monthFormat = createDateTimeFormat({ month: 'long' }); - const yearFormat = createDateTimeFormat({ year: 'numeric' }); - - dateTimeFormats = { - dayFormat, - monthFormat, - yearFormat, - }; -}; - -initDateFormats(); - -/** - Formats a localized date in way that it can be used for d3.js axis.tickFormat(). - - That is, it displays - - 4-digit for first of January - - full month name for first of every month - - day and abbreviated month otherwise - - see also https://github.com/d3/d3-3.x-api-reference/blob/master/SVG-Axes.md#tickFormat - */ -export const dateTickFormat = date => { - if (date.getDate() !== 1) { - return dateTimeFormats.dayFormat.format(date); - } - - if (date.getMonth() > 0) { - return dateTimeFormats.monthFormat.format(date); - } - - return dateTimeFormats.yearFormat.format(date); -}; |