mirror of
https://github.com/makeplane/plane.git
synced 2025-12-25 08:09:33 +01:00
* chore: migrations and backmigration to move attachments to file asset * chore: move attachments to file assets * chore: update migration file to include created by and updated by and size * chore: remove uninmport errors * chore: make size as float field * fix: file asset uploads * chore: asset uploads migration changes * chore: v2 assets endpoint * chore: remove unused imports * chore: issue attachments * chore: issue attachments * chore: workspace logo endpoints * chore: private bucket changes * chore: user asset endpoint * chore: add logo_url validation * chore: cover image urlk * chore: change asset max length * chore: pages endpoint * chore: store the storage_metadata only when none * chore: attachment asset apis * chore: update create private bucket * chore: make bucket private * chore: fix response of user uploads * fix: response of user uploads * fix: job to fix file asset uploads * fix: user asset endpoints * chore: avatar for user profile * chore: external apis user url endpoint * chore: upload workspace and user asset actions updated * chore: analytics endpoint * fix: analytics export * chore: avatar urls * chore: update user avatar instances * chore: avatar urls for assignees and creators * chore: bucket permission script * fix: all user avatr instances in the web app * chore: update project cover image logic * fix: issue attachment endpoint * chore: patch endpoint for issue attachment * chore: attachments * chore: change attachment storage class * chore: update issue attachment endpoints * fix: issue attachment * chore: update issue attachment implementation * chore: page asset endpoints * fix: web build errors * chore: attachments * chore: page asset urls * chore: comment and issue asset endpoints * chore: asset endpoints * chore: attachment endpoints * chore: bulk asset endpoint * chore: restore endpoint * chore: project assets endpoints * chore: asset url * chore: add delete asset endpoints * chore: fix asset upload endpoint * chore: update patch endpoints * chore: update patch endpoint * chore: update editor image handling * chore: asset restore endpoints * chore: avatar url for space assets * chore: space app assets migration * fix: space app urls * chore: space endpoints * fix: old editor images rendering logic * fix: issue archive and attachment activity * chore: asset deletes * chore: attachment delete * fix: issue attachment * fix: issue attachment get * chore: cover image url for projects * chore: remove duplicate py file * fix: url check function * chore: chore project cover asset delete * fix: migrations * chore: delete migration files * chore: update bucket * fix: build errors * chore: add asset url in intake attachment * chore: project cover fix * chore: update next.config * chore: delete old workspace logos * chore: workspace assets * chore: asset get for space * chore: update project modal * chore: remove unused imports * fix: space app editor helper * chore: update rich-text read-only editor * chore: create multiple column for entity identifiers * chore: update migrations * chore: remove entity identifier * fix: issue assets * chore: update maximum file size logic * chore: update editor max file size logic * fix: close modal after removing workspace logo * chore: update uploaded asstes' status post issue creation * chore: added file size limit to the space app * dev: add file size limit restriction on all endpoints * fix: remove old workspace logo and user avatar --------- Co-authored-by: pablohashescobar <nikhilschacko@gmail.com>
103 lines
3.3 KiB
TypeScript
103 lines
3.3 KiB
TypeScript
import DOMPurify from "dompurify";
|
|
|
|
export const addSpaceIfCamelCase = (str: string) => str.replace(/([a-z])([A-Z])/g, "$1 $2");
|
|
|
|
const fallbackCopyTextToClipboard = (text: string) => {
|
|
const textArea = document.createElement("textarea");
|
|
textArea.value = text;
|
|
|
|
// Avoid scrolling to bottom
|
|
textArea.style.top = "0";
|
|
textArea.style.left = "0";
|
|
textArea.style.position = "fixed";
|
|
|
|
document.body.appendChild(textArea);
|
|
textArea.focus();
|
|
textArea.select();
|
|
|
|
try {
|
|
// FIXME: Even though we are using this as a fallback, execCommand is deprecated 👎. We should find a better way to do this.
|
|
// https://developer.mozilla.org/en-US/docs/Web/API/Document/execCommand
|
|
document.execCommand("copy");
|
|
} catch (err) {}
|
|
|
|
document.body.removeChild(textArea);
|
|
};
|
|
|
|
export const copyTextToClipboard = async (text: string) => {
|
|
if (!navigator.clipboard) {
|
|
fallbackCopyTextToClipboard(text);
|
|
return;
|
|
}
|
|
await navigator.clipboard.writeText(text);
|
|
};
|
|
|
|
/**
|
|
* @returns {boolean} true if email is valid, false otherwise
|
|
* @description Returns true if email is valid, false otherwise
|
|
* @param {string} email string to check if it is a valid email
|
|
* @example checkEmailIsValid("hello world") => false
|
|
* @example checkEmailIsValid("example@plane.so") => true
|
|
*/
|
|
export const checkEmailValidity = (email: string): boolean => {
|
|
if (!email) return false;
|
|
|
|
const isEmailValid =
|
|
/^(([^<>()[\]\\.,;:\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,}))$/.test(
|
|
email
|
|
);
|
|
|
|
return isEmailValid;
|
|
};
|
|
|
|
export const isEmptyHtmlString = (htmlString: string, allowedHTMLTags: string[] = []) => {
|
|
// Remove HTML tags using regex
|
|
const cleanText = DOMPurify.sanitize(htmlString, { ALLOWED_TAGS: allowedHTMLTags });
|
|
// Trim the string and check if it's empty
|
|
return cleanText.trim() === "";
|
|
};
|
|
|
|
/**
|
|
* @description this function returns whether a comment is empty or not by checking for the following conditions-
|
|
* 1. If comment is undefined
|
|
* 2. If comment is an empty string
|
|
* 3. If comment is "<p></p>"
|
|
* @param {string | undefined} comment
|
|
* @returns {boolean}
|
|
*/
|
|
export const isCommentEmpty = (comment: string | undefined): boolean => {
|
|
// return true if comment is undefined
|
|
if (!comment) return true;
|
|
return (
|
|
comment?.trim() === "" ||
|
|
comment === "<p></p>" ||
|
|
isEmptyHtmlString(comment ?? "", ["img", "mention-component", "image-component"])
|
|
);
|
|
};
|
|
|
|
export const replaceUnderscoreIfSnakeCase = (str: string) => str.replace(/_/g, " ");
|
|
|
|
export const capitalizeFirstLetter = (str: string) => str.charAt(0).toUpperCase() + str.slice(1);
|
|
|
|
/**
|
|
* @description
|
|
* This function test whether a URL is valid or not.
|
|
*
|
|
* It accepts URLs with or without the protocol.
|
|
* @param {string} url
|
|
* @returns {boolean}
|
|
* @example
|
|
* checkURLValidity("https://example.com") => true
|
|
* checkURLValidity("example.com") => true
|
|
* checkURLValidity("example") => false
|
|
*/
|
|
export const checkURLValidity = (url: string): boolean => {
|
|
if (!url) return false;
|
|
|
|
// regex to support complex query parameters and fragments
|
|
const urlPattern =
|
|
/^(https?:\/\/)?((([a-z\d-]+\.)*[a-z\d-]+\.[a-z]{2,6})|(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}))(:\d+)?(\/[\w.-]*)*(\?[^#\s]*)?(#[\w-]*)?$/i;
|
|
|
|
return urlPattern.test(url);
|
|
};
|