app/frontend/shared/utils/formatter.ts
// Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
/**
* Creates an oxford-comma separated list of items.
* @param args - items to list out
* @param conjunction - in: x, y, and z "and" is the conjunction to use
* @returns
*/
export const commaSeparatedList = (
items: string[],
conjunction = 'or',
): string => {
return items.reduce((oxford, item, index) => {
let oxfordList = oxford + item
if (index <= items.length - 2 && items.length > 2) {
oxfordList += ', '
}
if (index === items.length - 2) {
oxfordList += `${items.length === 2 ? ' ' : ''}${conjunction} `
}
return oxfordList
}, '')
}
/**
* Orders two variables smallest to largest.
* @param first - first argument
* @param second - Second argument
* @returns
*/
export const order = (
first: string | number,
second: string | number,
): [smaller: number | string, larger: number | string] => {
return Number(first) >= Number(second) ? [second, first] : [first, second]
}
export const camelize = (str: string) => {
return str.replace(/[_.-](\w|$)/g, (_, x) => x.toUpperCase())
}
export const capitalize = (str: string) => {
return str[0].toUpperCase() + str.slice(1)
}
export const toClassName = (str: string) => {
return str.replace(
/([a-z])([A-Z])/g,
(_, lowerCase, upperCase) => `${lowerCase}::${upperCase}`,
)
}
// app/assets/javascripts/app/lib/app_post/utils.coffee:230
export const phoneify = (phone: string) => {
return phone.replace(/[^0-9,+,#,*]+/g, '').replace(/(.)\+/, '$1')
}
/**
* Returns user's initials based on their first name, last name and email, if any present.
* @param firstname - user's first name
* @param lastname - user's last name
* @param email - user's email address
* @param phone - user's phone number
* @param mobile - user's mobile number
*/
export const getInitials = (
firstname?: Maybe<string>,
lastname?: Maybe<string>,
email?: Maybe<string>,
phone?: Maybe<string>,
mobile?: Maybe<string>,
) => {
if (firstname && lastname) {
return firstname[0] + lastname[0]
}
if (firstname || lastname || email) {
return (firstname || lastname || email)?.substring(0, 2).toUpperCase()
}
if (phone || mobile) {
return (phone || mobile)?.slice(-2).toUpperCase()
}
return '??'
}
/**
* Replaces code inside `#{obj.key}` with the value of the corresponding object.
* @param template - string to replace
* @param objects - reference object
* @param encodeLink - should result be encoded
*/
export const replaceTags = (
template: string,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
objects: any,
encodeLink = false,
): string => {
return template.replace(/#\{\s{0,2}(.+?)\s{0,2}\}/g, (index, key) => {
const levels = key.replace(/<.+?>/g, '').split(/\./)
let dataRef = objects
for (const level of levels) {
if (typeof dataRef === 'object' && level in dataRef) {
dataRef = dataRef[level]
} else {
dataRef = ''
break
}
}
let value
// if value is a function, execute function
if (typeof dataRef === 'function') {
value = dataRef()
}
// if value has content
else if (dataRef != null && dataRef.toString) {
// in case if we have a references object, check what datatype the attribute has
// and e. g. convert timestamps/dates to browser locale
// if dataRefLast?.constructor?.className
// localClassRef = App[dataRefLast.constructor.className]
// if localClassRef?.attributesGet
// attributes = localClassRef.attributesGet()
// if attributes?[level]
// if attributes[level]['tag'] is 'datetime'
// value = App.i18n.translateTimestamp(dataRef)
// else if attributes[level]['tag'] is 'date'
// value = App.i18n.translateDate(dataRef)
// as fallback use value of toString()
if (!value) value = dataRef.toString()
} else {
value = ''
}
if (value === '') value = '-'
if (encodeLink) value = encodeURIComponent(value)
return value
})
}