@mythpe/js-helpers
Version:
Library of plugins & shortcuts that use JavaScript, also includes the Vue3 plugin with quasar apps
316 lines (308 loc) • 11.3 kB
text/typescript
/*
* MyTh Ahmed Faiz Copyright © 2016-2024 All rights reserved.
* Email: mythpe@gmail.com
* Mobile: +966590470092
* Website: https://www.4myth.com
* Github: https://github.com/mythpe
*/
import { AxiosInstance, AxiosRequestConfig } from 'axios'
import lodash from 'lodash'
import { openURL, scroll } from 'quasar'
import { ConfigType, DownloadFromResponse, DownloadFromResponseCode, HelpersStubSchema, ParamsType, UrlType } from '../types'
import { nextTick } from 'vue'
export const Helpers = {
appendArray (formData: FormData, values: File | Blob | Record<string, any> | any, name?: string | null | undefined) {
let value: never | any
if ((values instanceof File || values instanceof Blob) && name) {
const _name = values instanceof File ? values.name : name
formData.append(name, values, _name)
} else {
for (const key in values) {
value = values[key]
if (value !== null && value !== undefined && typeof value === 'object') {
const k = name ? name + '[' + key + ']' : key
if (lodash.isArray(value) && value.length < 1) {
formData.append(`${key}`, '')
} else {
this.appendArray(formData, value, k)
}
} else {
if (value === !0) {
value = 1
}
if (value === false) {
value = 0
}
if (value === null || value === undefined) {
value = ''
// console.log('null----', name,key, value)
}
// if (value !== undefined) {
if (name) {
formData.append(name + '[' + key + ']', value)
} else {
formData.append(key, value)
}
// }
}
}
}
return formData
},
Stub (baseUrl: UrlType, axios: () => AxiosInstance): HelpersStubSchema {
const makeUrl = Helpers.StubUrl(baseUrl)
return {
async index (config?: ConfigType) {
const u = makeUrl()
return axios().get(u, config)
// return typeof config === 'boolean' ? u : axios().get(u, config)
},
async staticIndex (config?: ConfigType) {
const u = `Static${baseUrl ? `/${baseUrl}` : ''}`
return axios().get(u, config)
// config = config || {}
// config.params = {
// page: 1,
// itemsPerPage: -1,
// ...(config.params ?? {})
// }
// return axios().get(u, config)
},
async export (data?: ParamsType, config?: AxiosRequestConfig) {
return axios().post(makeUrl('Export'), data, config)
},
async store (data?: ParamsType, config?: AxiosRequestConfig) {
const u = makeUrl()
// if (typeof data === 'boolean') {
// return u
// }
const formData = new FormData()
data && Helpers.appendArray(formData, data)
return axios().post(u, formData, config)
},
async show (id: UrlType, config?: AxiosRequestConfig) {
const u = makeUrl(id)
return axios().get(u, config)
// return typeof id === 'boolean' ? u : axios().get(u, config)
},
async staticShow (id: UrlType, config?: AxiosRequestConfig) {
// const m = baseUrl ? baseUrl.toString().split('/').pop() : ''
// const u = 'Static' + (m ? `/${m}` : '') + `/${id}`
const u = `Static${baseUrl ? `/${baseUrl}` : ''}` + `/${id}`
// if (typeof id === 'boolean') {
// return u
// }
return axios().get(u, config)
},
async update (id: UrlType, data?: ParamsType, config?: AxiosRequestConfig) {
const u = makeUrl(id)
// if (typeof id === 'boolean') {
// return u
// }
const formData = new FormData()
formData.append('_method', 'put')
data && Helpers.appendArray(formData, data)
return axios().post(u, formData, config)
},
async destroy (id: UrlType, config?: AxiosRequestConfig) {
const u = makeUrl(id)
return axios().delete(u, config)
// return typeof id === 'boolean' ? u : axios().delete(u, config)
},
async destroyAll (ids?: UrlType[], config?: AxiosRequestConfig) {
const u = makeUrl('DestroyAll')
return axios().post(u, { ids: (ids || []) }, config)
},
getUploadAttachmentsUrl: (id: UrlType) => makeUrl(`${id}/Attachment/Upload`),
async uploadAttachments (id: UrlType, data: Record<string, any>, config?: AxiosRequestConfig) {
const _url = makeUrl(`${id}/Attachment/Upload`)
return axios().post(_url, data, config)
},
async deleteAttachment (id: UrlType, fileId: string | number, config?: AxiosRequestConfig) {
const _url = makeUrl(`${id}/Attachment/${fileId}/Delete`)
return axios().delete(_url, config)
},
async updateAttachment (id: UrlType, fileId: string | number, data: Record<string, any>, config?: AxiosRequestConfig) {
const _url = makeUrl(`${id}/Attachment/${fileId}/Update`)
return axios().post(_url, data, config)
}
}
},
StubUrl: (group?: UrlType): ((segments?: UrlType, parent?: UrlType) => string) => (
segments?: UrlType,
parent?: UrlType
): string => ((parent ?? '') + (parent && group ? '/' : '')) + (group ?? '') + ((group && segments ? '/' : '') + (segments ?? '')),
findBy (search: any, value: any, column: string | number = 'id') {
return lodash.find(search, (e: any) => lodash.isPlainObject(e) ? e[column] === value : e === value)
},
// queryStringify: (v: never) => new URLSearchParams(qs.stringify(v, {
// arrayFormat: 'indices'
// // encodeValuesOnly: true,
// // encode: false,
// })),
/**
* Open unique window popup of application
*
* @param url
* @param reject
* @param windowFeatures
*/
openWindow <F extends (...args: any[]) => any>(url: string, reject?: F, windowFeatures?: object) {
return openURL(url, reject, windowFeatures)
},
/**
* Customized helper to download blob from axios response
* @param response
* @param callback
*/
downloadFromResponse (response: any, callback?: ((url: string, response: any) => void)) {
return new Promise<DownloadFromResponse>((resolve, reject) => {
const rejectPromise = (e?: { code: DownloadFromResponseCode }) => reject(e ?? { status: !1, code: 'unknown' })
const resolvePromise = (response: DownloadFromResponse['response']) => resolve({ status: !0, response })
try {
if (!response) {
rejectPromise({ code: 'no_response' })
return
}
if (response?.data?.data?.url) {
const url = response?.data?.data?.url
if (callback) {
callback(url, response)
resolvePromise(response)
return
}
const elm = document.createElement('a')
elm.setAttribute('href', url)
elm.setAttribute('target', '_blank')
document.body.appendChild(elm)
elm.click()
resolvePromise(response)
return
}
const name = (response.headers['content-disposition'] || '').split('filename=').pop().replace(/^"+|"+$/g, '')
if (!name) {
rejectPromise({ code: 'no_file_name' })
return
}
const file = new Blob([response.data])
const fileURL = window.URL.createObjectURL(file)
const fileLink = document.createElement('a')
if (!fileLink || !fileURL) {
rejectPromise({ code: 'no_file_url' })
return
}
fileLink.href = fileURL
fileLink.setAttribute('download', name)
document.body.appendChild(fileLink)
fileLink.click()
resolvePromise(response)
setTimeout(() => {
try {
document.body.removeChild(fileLink)
URL.revokeObjectURL(fileURL)
} catch (e: any) {
console.log(e)
if (e?.message) {
alert(e.message)
}
}
}, 3000)
} catch (e: any) {
console.log(e)
rejectPromise(e)
}
})
},
async scrollToElement (el: HTMLElement | string, opt?: { target?: HTMLElement | string, duration?: number; }) {
await nextTick()
const { getScrollTarget, setVerticalScrollPosition, getVerticalScrollPosition } = scroll
const scrollTo = typeof el === 'string' ? document.querySelector(el) as HTMLElement : el
if (!scrollTo) {
return
}
await nextTick()
const { target: t } = opt || {}
const targetSelector = typeof t === 'string' ? document.querySelector(t) as HTMLElement : t
const target = getScrollTarget(scrollTo, targetSelector || window.document.documentElement)
// console.log(targetSelector, target)
// let offset = 0
// try {
// let parent = scrollTo
// do {
// // console.log(parent.getBoundingClientRect().top)
// offset += parent?.offsetTop || 0
// parent = parent.offsetParent as HTMLElement
// } while (parent?.offsetParent)
// } catch (e) {
// offset = scrollTo?.offsetTop || 0
// }
// offset = scrollTo.getBoundingClientRect().top
const current = getVerticalScrollPosition(target)
// console.log(current, target)
// const offset = scrollTo.getBoundingClientRect().top
const duration = opt?.duration || 1000
let offset = 0
let parent = scrollTo
try {
do {
offset = parent.getBoundingClientRect().top
if (offset === 0 && !parent.parentElement) {
offset = parent.scrollTop
break
} else if (offset !== 0 && parent.parentElement) {
break
}
parent = parent.parentElement as HTMLElement
} while (parent)
} catch (e) {
console.log(e)
offset = scrollTo?.offsetTop || 0
}
// console.log(offset, parent, current)
// const position = offset
// if (offset > current) {
// position = (current - offset) + current
// } else if (offset < current) {
// position = current + offset
// }
// console.log({
// target,
// scrollTo,
// position,
// offset,
// current
// })
setVerticalScrollPosition(target, (offset + current) - 100, duration)
},
async scrollToElementFromErrors (errors?: Partial<Record<string, string[] | string | null | undefined>>, elm?: any, target?: any) {
if (!errors) {
return
}
for (const [name, value] of Object.entries(errors)) {
const val = value && Array.isArray(value) ? value[0] : value
if (val?.toString?.()?.length) {
if (!elm) {
const selector = `[data-input-name='${name}']`
const e = document.querySelector(selector) as HTMLElement
// console.log(e)
await this.scrollToElement(e || `[name='${name}']`, { target })
} else {
await this.scrollToElement(elm, { target })
}
break
}
}
},
makeUrl (path: string) {
path = path || ''
if (path.slice(0, 1) === '/') {
path = path.slice(1)
}
if (window) {
const l = window.location
return `${l.protocol}//${l.host}/${path}`
}
return `//${path}`
}
}
export default {}