diff --git a/packages/client/src/components/panels/EditLinkPanel/PasswordAccessBlock.js b/packages/client/src/components/panels/EditLinkPanel/PasswordAccessBlock.js
index aa3216f61a..942ed9ec43 100644
--- a/packages/client/src/components/panels/EditLinkPanel/PasswordAccessBlock.js
+++ b/packages/client/src/components/panels/EditLinkPanel/PasswordAccessBlock.js
@@ -24,6 +24,7 @@
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
+import { useRef } from "react";
import ToggleBlock from "./ToggleBlock";
import { IconButton } from "@docspace/shared/components/icon-button";
import { Link } from "@docspace/shared/components/link";
@@ -31,8 +32,8 @@ import RefreshReactSvgUrl from "PUBLIC_DIR/images/refresh.react.svg?url";
import { FieldContainer } from "@docspace/shared/components/field-container";
import copy from "copy-to-clipboard";
import { toastr } from "@docspace/shared/components/toast";
-import SimulatePassword from "../../../components/SimulatePassword";
-import { getNewPassword } from "@docspace/shared/utils";
+import { ALLOWED_PASSWORD_CHARACTERS } from "@docspace/shared/constants";
+import { PasswordInput } from "@docspace/shared/components/password-input";
const PasswordAccessBlock = (props) => {
const {
@@ -43,15 +44,21 @@ const PasswordAccessBlock = (props) => {
setPasswordValue,
isPasswordValid,
setIsPasswordValid,
+ passwordSettings,
+ isPasswordErrorShow,
+ setIsPasswordErrorShow,
} = props;
+ const passwordInputRef = useRef(null);
+
const onGeneratePasswordClick = () => {
- const password = getNewPassword();
- setPasswordValue(password);
+ passwordInputRef.current.onGeneratePassword();
};
- const onCleanClick = () => {
+ const onCleanClick = (e) => {
+ e.stopPropagation();
setPasswordValue("");
+ setIsPasswordValid(false);
};
const onCopyClick = () => {
@@ -62,9 +69,36 @@ const PasswordAccessBlock = (props) => {
}
};
- const onChangePassword = (password) => {
- setPasswordValue(password);
+ const onChangePassword = (e, value) => {
+ setPasswordValue(value);
setIsPasswordValid(true);
+ setIsPasswordErrorShow(false);
+ };
+
+ // const onBlurPassword = () => {
+ // setIsPasswordErrorShow(true);
+ // };
+
+ const onValidatePassword = (isValidate) => {
+ setIsPasswordValid(isValidate);
+ };
+
+ const errorMessage = !passwordValue
+ ? t("Common:RequiredField")
+ : t("Common:IncorrectPassword");
+
+ const hasError = isPasswordErrorShow && !isPasswordValid;
+
+ const tooltipData = {
+ tooltipPasswordTitle: `${t("Common:PasswordLimitMessage")}:`,
+ tooltipPasswordLength: `${t("Common:PasswordMinimumLength")}: ${
+ passwordSettings ? passwordSettings.minLength : 8
+ }`,
+ tooltipPasswordDigits: `${t("Common:PasswordLimitDigits")}`,
+ tooltipPasswordCapital: `${t("Common:PasswordLimitUpperCase")}`,
+ tooltipPasswordSpecial: `${t("Common:PasswordLimitSpecialSymbols")}`,
+ generatePasswordTitle: t("Wizard:GeneratePassword"),
+ tooltipAllowedCharacters: `${t("Common:AllowedCharacters")}: ${ALLOWED_PASSWORD_CHARACTERS}`,
};
return (
@@ -74,17 +108,26 @@ const PasswordAccessBlock = (props) => {
-
diff --git a/packages/client/src/components/panels/EditLinkPanel/index.js b/packages/client/src/components/panels/EditLinkPanel/index.js
index 91b4c51bdc..ac34828e0b 100644
--- a/packages/client/src/components/panels/EditLinkPanel/index.js
+++ b/packages/client/src/components/panels/EditLinkPanel/index.js
@@ -65,6 +65,8 @@ const EditLinkPanel = (props) => {
isFormRoom,
currentDeviceType,
setLinkParams,
+ passwordSettings,
+ getPortalPasswordSettings,
} = props;
const [isLoading, setIsLoading] = useState(false);
@@ -80,6 +82,7 @@ const EditLinkPanel = (props) => {
const [isExpired, setIsExpired] = useState(isExpiredDate);
const [isPasswordValid, setIsPasswordValid] = useState(true);
+ const [isPasswordErrorShow, setIsPasswordErrorShow] = useState(false);
const [linkValue, setLinkValue] = useState(shareLink);
const [hasChanges, setHasChanges] = useState(false);
@@ -101,10 +104,12 @@ const EditLinkPanel = (props) => {
const onClose = () => setIsVisible(false);
const onSave = () => {
- const isPasswordValid = !!passwordValue.trim();
-
- if (!isPasswordValid && passwordAccessIsChecked) {
+ if (
+ (!passwordValue.trim() || !isPasswordValid) &&
+ passwordAccessIsChecked
+ ) {
setIsPasswordValid(false);
+ setIsPasswordErrorShow(true);
return;
}
@@ -140,11 +145,14 @@ const EditLinkPanel = (props) => {
toastr.success(t("Files:LinkSuccessfullyCreatedAndCopied"));
}
+ onClose();
+ })
+ .catch((err) => {
+ const error = err?.response?.data?.error?.message ?? err?.message;
+ toastr.error(error);
})
- .catch((err) => toastr.error(err?.message))
.finally(() => {
setIsLoading(false);
- onClose();
});
};
@@ -183,6 +191,18 @@ const EditLinkPanel = (props) => {
return () => window.removeEventListener("keydown", onKeyPress);
}, [onKeyPress]);
+ const getPasswordSettings = async () => {
+ setIsLoading(true);
+ await getPortalPasswordSettings();
+ setIsLoading(false);
+ };
+
+ useEffect(() => {
+ if (!passwordSettings) {
+ getPasswordSettings();
+ }
+ }, [passwordSettings]);
+
const linkNameIsValid = !!linkNameValue.trim();
const expiredLinkText = isExpired
@@ -239,6 +259,9 @@ const EditLinkPanel = (props) => {
setPasswordValue={setPasswordValue}
setIsPasswordValid={setIsPasswordValid}
onChange={onPasswordAccessChange}
+ passwordSettings={passwordSettings}
+ isPasswordErrorShow={isPasswordErrorShow}
+ setIsPasswordErrorShow={setIsPasswordErrorShow}
/>
{!isFormRoom && (
l?.sharedTo?.id === linkId);
-
const shareLink = link?.sharedTo?.shareLink;
return {
@@ -340,10 +365,14 @@ export default inject(
language: authStore.language,
isPublic,
isFormRoom,
- currentDeviceType: settingsStore.currentDeviceType,
+ currentDeviceType,
setLinkParams,
+ passwordSettings,
+ getPortalPasswordSettings,
};
},
)(
- withTranslation(["SharingPanel", "Common", "Files"])(observer(EditLinkPanel)),
+ withTranslation(["SharingPanel", "Common", "Files", "Wizard"])(
+ observer(EditLinkPanel),
+ ),
);
diff --git a/packages/shared/components/password-input/PasswordInput.tsx b/packages/shared/components/password-input/PasswordInput.tsx
index 8ea516b831..e96cf75b98 100644
--- a/packages/shared/components/password-input/PasswordInput.tsx
+++ b/packages/shared/components/password-input/PasswordInput.tsx
@@ -32,6 +32,7 @@ import React, {
ChangeEvent,
FocusEvent,
MouseEvent,
+ useEffect,
} from "react";
import { TooltipRefProps } from "react-tooltip";
@@ -109,6 +110,16 @@ const PasswordInput = React.forwardRef(
}: PasswordInputProps,
ref,
) => {
+ const usePrevious = (value: string) => {
+ const inputValueRef = useRef();
+ useEffect(() => {
+ inputValueRef.current = value;
+ });
+ return inputValueRef.current;
+ };
+
+ const prevInputValue = usePrevious(inputValue ?? "");
+
const [state, setState] = useState({
type: inputType,
value: inputValue,
@@ -276,6 +287,8 @@ const PasswordInput = React.forwardRef(
(newPassword: string) => {
let newValue;
+ if (!state.value) return newPassword;
+
const oldPassword = state.value ?? "";
const oldPasswordLength = oldPassword.length;
const newCaretPosition = document.getElementById(
@@ -465,6 +478,14 @@ const PasswordInput = React.forwardRef(
}
}, [caretPosition, state.type, state.value, isSimulateType]);
+ useEffect(() => {
+ if (inputValue !== prevInputValue) {
+ onChangeAction?.({
+ target: { value: inputValue },
+ } as ChangeEvent);
+ }
+ }, [inputValue, prevInputValue, onChangeAction]);
+
React.useImperativeHandle(
ref,
() => {