294 lines
7.4 KiB
JavaScript
294 lines
7.4 KiB
JavaScript
import TaskStatusIcon from '@/components/Icons/TaskStatusIcon.vue'
|
|
import TaskPriorityIcon from '@/components/Icons/TaskPriorityIcon.vue'
|
|
import { useDateFormat, useTimeAgo } from '@vueuse/core'
|
|
import { usersStore } from '@/stores/users'
|
|
import { gemoji } from 'gemoji'
|
|
import { toast } from 'frappe-ui'
|
|
import { h } from 'vue'
|
|
|
|
export function createToast(options) {
|
|
toast({
|
|
position: 'bottom-right',
|
|
...options,
|
|
})
|
|
}
|
|
|
|
export function formatTime(seconds) {
|
|
const days = Math.floor(seconds / (3600 * 24))
|
|
const hours = Math.floor((seconds % (3600 * 24)) / 3600)
|
|
const minutes = Math.floor((seconds % 3600) / 60)
|
|
const remainingSeconds = Math.floor(seconds % 60)
|
|
|
|
let formattedTime = ''
|
|
|
|
if (days > 0) {
|
|
formattedTime += `${days}d `
|
|
}
|
|
|
|
if (hours > 0 || days > 0) {
|
|
formattedTime += `${hours}h `
|
|
}
|
|
|
|
if (minutes > 0 || hours > 0 || days > 0) {
|
|
formattedTime += `${minutes}m `
|
|
}
|
|
|
|
formattedTime += `${remainingSeconds}s`
|
|
|
|
return formattedTime.trim()
|
|
}
|
|
|
|
export function dateFormat(date, format) {
|
|
const _format = format || 'DD-MM-YYYY HH:mm:ss'
|
|
return useDateFormat(date, _format).value
|
|
}
|
|
|
|
export function timeAgo(date) {
|
|
return useTimeAgo(date).value
|
|
}
|
|
|
|
export const dateTooltipFormat = 'ddd, MMM D, YYYY h:mm A'
|
|
|
|
export function taskStatusOptions(action, data) {
|
|
return ['Backlog', 'Todo', 'In Progress', 'Done', 'Canceled'].map(
|
|
(status) => {
|
|
return {
|
|
icon: () => h(TaskStatusIcon, { status }),
|
|
label: status,
|
|
onClick: () => action && action(status, data),
|
|
}
|
|
},
|
|
)
|
|
}
|
|
|
|
export function taskPriorityOptions(action, data) {
|
|
return ['Low', 'Medium', 'High'].map((priority) => {
|
|
return {
|
|
label: priority,
|
|
icon: () => h(TaskPriorityIcon, { priority }),
|
|
onClick: () => action && action(priority, data),
|
|
}
|
|
})
|
|
}
|
|
|
|
export function openWebsite(url) {
|
|
if (!url.startsWith('http://') && !url.startsWith('https://')) {
|
|
url = 'https://' + url
|
|
}
|
|
window.open(url, '_blank')
|
|
}
|
|
|
|
export function website(url) {
|
|
return url && url.replace(/^(?:https?:\/\/)?(?:www\.)?/i, '')
|
|
}
|
|
|
|
export function htmlToText(html) {
|
|
const div = document.createElement('div')
|
|
div.innerHTML = html
|
|
return div.textContent || div.innerText || ''
|
|
}
|
|
|
|
export function secondsToDuration(seconds) {
|
|
const hours = Math.floor(seconds / 3600)
|
|
const minutes = Math.floor((seconds % 3600) / 60)
|
|
const _seconds = Math.floor((seconds % 3600) % 60)
|
|
|
|
if (hours == 0 && minutes == 0) {
|
|
return `${_seconds}s`
|
|
} else if (hours == 0) {
|
|
return `${minutes}m ${_seconds}s`
|
|
}
|
|
return `${hours}h ${minutes}m ${_seconds}s`
|
|
}
|
|
|
|
export function formatNumberIntoCurrency(value, currency = 'INR') {
|
|
if (value) {
|
|
return value.toLocaleString('en-IN', {
|
|
maximumFractionDigits: 0,
|
|
style: 'currency',
|
|
currency: currency ? currency : 'INR',
|
|
})
|
|
}
|
|
return ''
|
|
}
|
|
|
|
export function startCase(str) {
|
|
return str.charAt(0).toUpperCase() + str.slice(1)
|
|
}
|
|
|
|
export function validateEmail(email) {
|
|
let regExp =
|
|
/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
|
|
return regExp.test(email)
|
|
}
|
|
|
|
export function setupAssignees(data) {
|
|
let { getUser } = usersStore()
|
|
let assignees = data._assign || []
|
|
data._assignedTo = assignees.map((user) => ({
|
|
name: user,
|
|
image: getUser(user).user_image,
|
|
label: getUser(user).full_name,
|
|
}))
|
|
}
|
|
|
|
async function getFromScript(script, obj) {
|
|
let scriptFn = new Function(script + '\nreturn setupForm')()
|
|
let formScript = await scriptFn(obj)
|
|
return formScript || {}
|
|
}
|
|
|
|
export async function setupCustomizations(data, obj) {
|
|
if (!data._form_script) return []
|
|
|
|
let statuses = []
|
|
let actions = []
|
|
if (Array.isArray(data._form_script)) {
|
|
for (let script of data._form_script) {
|
|
let _script = await getFromScript(script, obj)
|
|
actions = actions.concat(_script?.actions || [])
|
|
statuses = statuses.concat(_script?.statuses || [])
|
|
}
|
|
} else {
|
|
let _script = await getFromScript(data._form_script, obj)
|
|
actions = _script?.actions || []
|
|
statuses = _script?.statuses || []
|
|
}
|
|
|
|
data._customStatuses = statuses
|
|
data._customActions = actions
|
|
return { statuses, actions }
|
|
}
|
|
|
|
async function getListScript(script, obj) {
|
|
let scriptFn = new Function(script + '\nreturn setupList')()
|
|
let listScript = await scriptFn(obj)
|
|
return listScript || {}
|
|
}
|
|
|
|
export async function setupListCustomizations(data, obj = {}) {
|
|
if (!data.list_script) return []
|
|
|
|
let actions = []
|
|
let bulkActions = []
|
|
|
|
if (Array.isArray(data.list_script)) {
|
|
for (let script of data.list_script) {
|
|
let _script = await getListScript(script, obj)
|
|
actions = actions.concat(_script?.actions || [])
|
|
bulkActions = bulkActions.concat(_script?.bulk_actions || [])
|
|
}
|
|
} else {
|
|
let _script = await getListScript(data.list_script, obj)
|
|
actions = _script?.actions || []
|
|
bulkActions = _script?.bulk_actions || []
|
|
}
|
|
|
|
data.listActions = actions
|
|
data.bulkActions = bulkActions
|
|
return { actions, bulkActions }
|
|
}
|
|
|
|
export function errorMessage(title, message) {
|
|
createToast({
|
|
title: title || 'Error',
|
|
text: message,
|
|
icon: 'x',
|
|
iconClasses: 'text-red-600',
|
|
})
|
|
}
|
|
|
|
export function copyToClipboard(text) {
|
|
if (navigator.clipboard && window.isSecureContext) {
|
|
navigator.clipboard.writeText(text).then(show_success_alert)
|
|
} else {
|
|
let input = document.createElement('textarea')
|
|
document.body.appendChild(input)
|
|
input.value = text
|
|
input.select()
|
|
document.execCommand('copy')
|
|
show_success_alert()
|
|
document.body.removeChild(input)
|
|
}
|
|
function show_success_alert() {
|
|
createToast({
|
|
title: 'Copied to clipboard',
|
|
text: text,
|
|
icon: 'check',
|
|
iconClasses: 'text-green-600',
|
|
})
|
|
}
|
|
}
|
|
|
|
export function isEmoji(str) {
|
|
const emojiList = gemoji.map((emoji) => emoji.emoji)
|
|
return emojiList.includes(str)
|
|
}
|
|
|
|
export function isTouchScreenDevice() {
|
|
return 'ontouchstart' in document.documentElement
|
|
}
|
|
|
|
export function convertArrayToString(array) {
|
|
return array.map((item) => item).join(',')
|
|
}
|
|
|
|
export function _eval(code, context = {}) {
|
|
let variable_names = Object.keys(context)
|
|
let variables = Object.values(context)
|
|
code = `let out = ${code}; return out`
|
|
try {
|
|
let expression_function = new Function(...variable_names, code)
|
|
return expression_function(...variables)
|
|
} catch (error) {
|
|
console.log('Error evaluating the following expression:')
|
|
console.error(code)
|
|
throw error
|
|
}
|
|
}
|
|
|
|
export function evaluateDependsOnValue(expression, doc) {
|
|
if (!expression) return true
|
|
if (!doc) return true
|
|
|
|
let out = null
|
|
|
|
if (typeof expression === 'boolean') {
|
|
out = expression
|
|
} else if (typeof expression === 'function') {
|
|
out = expression(doc)
|
|
} else if (expression.substr(0, 5) == 'eval:') {
|
|
try {
|
|
out = _eval(expression.substr(5), { doc })
|
|
} catch (e) {
|
|
out = true
|
|
}
|
|
} else {
|
|
let value = doc[expression]
|
|
if (Array.isArray(value)) {
|
|
out = !!value.length
|
|
} else {
|
|
out = !!value
|
|
}
|
|
}
|
|
|
|
return out
|
|
}
|
|
|
|
export function convertSize(size) {
|
|
const units = ['B', 'KB', 'MB', 'GB', 'TB']
|
|
let unitIndex = 0
|
|
while (size > 1024) {
|
|
size /= 1024
|
|
unitIndex++
|
|
}
|
|
return `${size?.toFixed(2)} ${units[unitIndex]}`
|
|
}
|
|
|
|
export function isImage(extention) {
|
|
if (!extention) return false
|
|
return ['png', 'jpg', 'jpeg', 'gif', 'svg', 'bmp', 'webp'].includes(
|
|
extention.toLowerCase(),
|
|
)
|
|
}
|