diff --git a/src/components/EditableText.tsx b/src/components/EditableText.tsx
index 064d498..74149e1 100644
--- a/src/components/EditableText.tsx
+++ b/src/components/EditableText.tsx
@@ -120,12 +120,16 @@ export const EditableText = (props: EditableTextProps) => {
props.wrapperClassName ?? '',
!props.readOnly && 'editable-text__text-wrapper__editable',
]}
- ON_click={() => {
+ ON_click={(ev: PointerEvent) => {
+ ev.stopPropagation();
if (!props.readOnly) {
setOldText(props.text);
setIsInput(true);
}
}}
+ ON_mousedown={(ev: PointerEvent) => {
+ ev.stopPropagation();
+ }}
>
{
const DND_THRESHOLD = 10;
+let timer: number;
+
export const KanbanCard = (props: KanbanCardProps) => {
const activeBoard = useActiveBoardStore() as ActiveBoard;
const card = props.card;
@@ -76,14 +78,18 @@ export const KanbanCard = (props: KanbanCardProps) => {
[x: number, y: number] | undefined
>(undefined);
const [dragOffset, setDragOffset] = useState<[x: number, y: number]>([0, 0]);
- let timer: number;
const editCallback = () => {
clearTimeout(timer);
setIsInput(true);
};
+ const cancelDnd = () => {
+ setDragStart(undefined);
+ };
if (card.type === 'stub') {
- return
;
+ return (
+
+ );
} else {
useEffectRefs((refs) => {
// Таймаут нужен, чтобы обложка карточки, если она есть, успела загрузиться
@@ -97,10 +103,15 @@ export const KanbanCard = (props: KanbanCardProps) => {
ref="card"
class="kanban-card"
ON_mousedown={(ev: PointerEvent) => {
- setDragStart([ev.x, ev.y]);
- setDragOffset([ev.offsetX, ev.offsetY]);
+ if (!isInput) {
+ setDragStart([ev.x, ev.y]);
+ setDragOffset([ev.offsetX, ev.offsetY]);
+ }
}}
ON_mousemove={(ev: PointerEvent) => {
+ if (isInput) {
+ return;
+ }
if (dragStart !== undefined) {
if (
Math.sqrt(
@@ -114,7 +125,7 @@ export const KanbanCard = (props: KanbanCardProps) => {
type: 'card',
offset: dragOffset,
cardData: card,
- prevColIdx:props.columnIdx
+ prevColIdx: props.columnIdx,
});
console.log('offset', dragOffset);
setDragStart(undefined);
@@ -122,9 +133,8 @@ export const KanbanCard = (props: KanbanCardProps) => {
}
}
}}
- ON_mouseleave={() => {
- setDragStart(undefined);
- }}
+ ON_mouseleave={cancelDnd}
+ ON_mouseup={cancelDnd}
>
{activeBoard.myRole !== 'viewer' && (
{
initialText={card.title}
cardId={card.id}
onNewCard={(crd) => {
+ setDragStart(undefined);
activeBoard.columns[props.columnIdx].cards = activeBoard.columns[
props.columnIdx
].cards.map((oldCard) => {
@@ -177,7 +188,6 @@ export const KanbanCard = (props: KanbanCardProps) => {
timer = setTimeout(() => {
getCardDetails(card.id).then((val) => {
setCardDetailsStore(val);
- console.log(val);
});
}, 300);
}}
diff --git a/src/components/KanbanColumn.tsx b/src/components/KanbanColumn.tsx
index 97ebdd4..0802a3a 100644
--- a/src/components/KanbanColumn.tsx
+++ b/src/components/KanbanColumn.tsx
@@ -82,6 +82,9 @@ export const KanbanColumn = (props: KanbanColumnProps) => {
ON_mouseleave={() => {
setDragStart(undefined);
}}
+ ON_mouseup={() => {
+ setDragStart(undefined);
+ }}
>
{
cardPositions.push({
x: xCoord,
diff --git a/src/utils/validation.ts b/src/utils/validation.ts
index ed90e3b..0f86b9f 100644
--- a/src/utils/validation.ts
+++ b/src/utils/validation.ts
@@ -4,10 +4,19 @@ interface IValidationResult {
}
const EMAIL_ALLOWED_SYMBOLS = /[a-zA-Z0-9_.@-]*/;
-const NICKNAME_ALLOWED_SYMBOLS = /[a-zA-Z0-9_.]*/;
+const NICKNAME_ALLOWED_SYMBOLS = /^[a-zA-Z0-9_.]*$/;
const EMAIL_REGEX =
/^(([^<>()[\].,;:\s@"]+(\.[^<>()[\].,;:\s@"]+)*)|(".+"))@(([^<>()[\].,;:\s@"]+\.)+[^<>()[\].,;:\s@"]{2,})$/i;
+const hasUpperCase = /[A-Z]+/;
+
+const hasLowerCase = /[a-z]+/;
+
+const hasDigits = /\d+/;
+
+// eslint-disable-next-line no-useless-escape
+const hasSpecialSymbol = /[!#&.,?/\\(){}\[\]"'`;:|<>*^%~]+/;
+
export const validateEmail = (email: string): IValidationResult => {
if (email === '') {
return { allowed: false, validationMessage: undefined };
@@ -53,15 +62,35 @@ export const validatePassword = (password: string): IValidationResult => {
if (password === '') {
return { allowed: false, validationMessage: undefined };
}
- const validationMessage: string[] = [];
- if (password.length < 8) {
- validationMessage.push('должен быт не менее 8 символов');
- }
+
if (password.length > 50) {
return {
allowed: false,
validationMessage: 'должен быть не более 50 символов',
};
}
+
+ const validationMessage: string[] = [];
+ if (password.length < 8) {
+ validationMessage.push('должен быть не менее 8 символов');
+ }
+ if (!hasUpperCase.test(password) && !hasLowerCase.test(password)) {
+ validationMessage.push(
+ 'должен содержать заглавную и строчную латинские буквы'
+ );
+ } else if (!hasUpperCase.test(password)) {
+ validationMessage.push('должен содержать заглавную латинскую букву');
+ } else if (!hasLowerCase.test(password)) {
+ validationMessage.push('должен содержать строчную латинскую букву');
+ }
+ if (!hasDigits.test(password)) {
+ validationMessage.push('должен содержать цифру');
+ }
+ if (!hasSpecialSymbol.test(password)) {
+ validationMessage.push('должен содержать специальный символ');
+ }
+ if (validationMessage) {
+ return { allowed: false, validationMessage: validationMessage.join(', ') };
+ }
return { allowed: true, validationMessage: undefined };
};