void;
onSave?: (server: UniqueServer) => void;
server?: UniqueServer;
- currentServers?: UniqueServer[];
editMode?: boolean;
show?: boolean;
restoreFocus?: boolean;
@@ -29,11 +31,15 @@ type State = {
serverId?: string;
serverOrder: number;
saveStarted: boolean;
+ validationStarted: boolean;
+ validationResult?: URLValidationResult;
}
class NewServerModal extends React.PureComponent
{
wasShown?: boolean;
serverUrlInputRef?: HTMLInputElement;
+ validationTimeout?: NodeJS.Timeout;
+ mounted: boolean;
static defaultProps = {
restoreFocus: true,
@@ -43,48 +49,37 @@ class NewServerModal extends React.PureComponent {
super(props);
this.wasShown = false;
+ this.mounted = false;
this.state = {
serverName: '',
serverUrl: '',
serverOrder: props.currentOrder || 0,
saveStarted: false,
+ validationStarted: false,
};
}
- initializeOnShow() {
+ componentDidMount(): void {
+ this.mounted = true;
+ }
+
+ componentWillUnmount(): void {
+ this.mounted = false;
+ }
+
+ initializeOnShow = () => {
this.setState({
serverName: this.props.server ? this.props.server.name : '',
serverUrl: this.props.server ? this.props.server.url : '',
serverId: this.props.server?.id,
saveStarted: false,
+ validationStarted: false,
+ validationResult: undefined,
});
- }
- getServerNameValidationError() {
- if (!this.state.saveStarted) {
- return null;
+ if (this.props.editMode && this.props.server) {
+ this.validateServerURL(this.props.server.url);
}
- if (this.props.currentServers) {
- const currentServers = [...this.props.currentServers];
- if (currentServers.find((server) => server.id !== this.state.serverId && server.name === this.state.serverName)) {
- return (
-
- );
- }
- }
- return this.state.serverName.length > 0 ? null : (
-
- );
- }
-
- getServerNameValidationState() {
- return this.getServerNameValidationError() === null ? null : 'error';
}
handleServerNameChange = (e: React.ChangeEvent) => {
@@ -93,108 +88,205 @@ class NewServerModal extends React.PureComponent {
});
}
- getServerUrlValidationError() {
- if (!this.state.saveStarted) {
- return null;
- }
- if (this.props.currentServers) {
- const currentServers = [...this.props.currentServers];
- if (currentServers.find((server) => server.id !== this.state.serverId && server.url === this.state.serverUrl)) {
- return (
-
- );
- }
- }
- if (this.state.serverUrl.length === 0) {
- return (
-
- );
- }
- if (!(/^https?:\/\/.*/).test(this.state.serverUrl.trim())) {
- return (
-
- );
- }
- if (!isValidURL(this.state.serverUrl.trim())) {
- return (
-
- );
- }
- return null;
- }
-
- getServerUrlValidationState() {
- return this.getServerUrlValidationError() === null ? null : 'error';
- }
-
handleServerUrlChange = (e: React.ChangeEvent) => {
const serverUrl = e.target.value;
- this.setState({serverUrl});
+ this.setState({serverUrl, validationResult: undefined});
+ this.validateServerURL(serverUrl);
}
- addProtocolToUrl = (serverUrl: string): Promise => {
- if (serverUrl.startsWith('http://') || serverUrl.startsWith('https://')) {
- return Promise.resolve(undefined);
+ validateServerURL = (serverUrl: string) => {
+ clearTimeout(this.validationTimeout as unknown as number);
+ this.validationTimeout = setTimeout(() => {
+ if (!this.mounted) {
+ return;
+ }
+ const currentTimeout = this.validationTimeout;
+ this.setState({validationStarted: true});
+ window.desktop.validateServerURL(serverUrl, this.props.server?.id).then((validationResult) => {
+ if (!this.mounted) {
+ return;
+ }
+ if (currentTimeout !== this.validationTimeout) {
+ return;
+ }
+ this.setState({validationResult, validationStarted: false, serverUrl: validationResult.validatedURL ?? serverUrl, serverName: this.state.serverName ? this.state.serverName : validationResult.serverName ?? ''});
+ });
+ }, 1000);
+ }
+
+ isServerURLErrored = () => {
+ return this.state.validationResult?.status === URLValidationStatus.Invalid ||
+ this.state.validationResult?.status === URLValidationStatus.Missing;
+ }
+
+ getServerURLMessage = () => {
+ if (this.state.validationStarted) {
+ return (
+
+
+
+
+ );
}
- return window.desktop.modals.pingDomain(serverUrl).
- then((result: string) => {
- this.setState({serverUrl: `${result}://${this.state.serverUrl}`});
- }).
- catch(() => {
- console.error(`Could not ping url: ${serverUrl}`);
- });
+ if (!this.state.validationResult) {
+ return null;
+ }
+
+ switch (this.state.validationResult?.status) {
+ case URLValidationStatus.Missing:
+ return (
+
+
+
+
+ );
+ case URLValidationStatus.Invalid:
+ return (
+
+
+
+
+ );
+ case URLValidationStatus.URLExists:
+ return (
+
+
+
+
+ );
+ case URLValidationStatus.Insecure:
+ return (
+
+
+
+
+ );
+ case URLValidationStatus.NotMattermost:
+ return (
+
+
+
+
+ );
+ case URLValidationStatus.URLNotMatched:
+ return (
+
+
+
+
+ );
+ case URLValidationStatus.URLUpdated:
+ return (
+
+
+
+
+ );
+ }
+
+ return (
+
+
+
+
+ );
}
- getError() {
- const nameError = this.getServerNameValidationError();
- const urlError = this.getServerUrlValidationError();
-
- if (nameError && urlError) {
+ getServerNameMessage = () => {
+ if (!this.state.serverName.length) {
return (
- <>
- {nameError}
-
- {urlError}
- >
+
+
+
+
);
- } else if (nameError) {
- return nameError;
- } else if (urlError) {
- return urlError;
}
return null;
}
- validateForm() {
- return this.getServerNameValidationState() === null &&
- this.getServerUrlValidationState() === null;
- }
+ save = () => {
+ if (!this.state.validationResult) {
+ return;
+ }
+
+ if (this.isServerURLErrored()) {
+ return;
+ }
- save = async () => {
- await this.addProtocolToUrl(this.state.serverUrl);
this.setState({
saveStarted: true,
}, () => {
- if (this.validateForm()) {
- this.props.onSave?.({
- url: this.state.serverUrl,
- name: this.state.serverName,
- id: this.state.serverId,
- });
- }
+ this.props.onSave?.({
+ url: this.state.serverUrl,
+ name: this.state.serverName,
+ id: this.state.serverId,
+ });
});
}
@@ -291,7 +383,7 @@ class NewServerModal extends React.PureComponent {
this.props.setInputRef(ref);
}
}}
- isInvalid={Boolean(this.getServerUrlValidationState())}
+ isInvalid={this.isServerURLErrored()}
autoFocus={true}
/>
@@ -318,7 +410,7 @@ class NewServerModal extends React.PureComponent {
onClick={(e: React.MouseEvent) => {
e.stopPropagation();
}}
- isInvalid={Boolean(this.getServerNameValidationState())}
+ isInvalid={!this.state.serverName.length}
/>
@@ -329,15 +421,15 @@ class NewServerModal extends React.PureComponent {
+
+ {this.getServerNameMessage()}
+ {this.getServerURLMessage()}
+
-
- {this.getError()}
-
-
{this.props.onClose &&