[MM-31547] Stop users from being able to enter the same server name or URL twice (#2049)
Co-authored-by: Mattermod <mattermod@users.noreply.github.com>
This commit is contained in:
@@ -64,6 +64,22 @@ describe('Add Server Modal', function desc() {
|
|||||||
existing.should.be.true;
|
existing.should.be.true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should not be valid if a server with the same name exists', async () => {
|
||||||
|
await newServerView.type('#teamNameInput', config.teams[0].name);
|
||||||
|
await newServerView.type('#teamUrlInput', 'http://example.org');
|
||||||
|
await newServerView.click('#saveNewServerModal');
|
||||||
|
const existing = await newServerView.isVisible('#teamNameInput.is-invalid');
|
||||||
|
existing.should.be.true;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not be valid if a server with the same URL exists', async () => {
|
||||||
|
await newServerView.type('#teamNameInput', 'some-new-server');
|
||||||
|
await newServerView.type('#teamUrlInput', config.teams[0].url);
|
||||||
|
await newServerView.click('#saveNewServerModal');
|
||||||
|
const existing = await newServerView.isVisible('#teamUrlInput.is-invalid');
|
||||||
|
existing.should.be.true;
|
||||||
|
});
|
||||||
|
|
||||||
describe('Valid server name', async () => {
|
describe('Valid server name', async () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await newServerView.type('#teamNameInput', 'TestTeam');
|
await newServerView.type('#teamNameInput', 'TestTeam');
|
||||||
|
@@ -109,6 +109,18 @@ describe('EditServerModal', function desc() {
|
|||||||
existing.should.be.true;
|
existing.should.be.true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should not edit team if another server with the same name or URL exists', async () => {
|
||||||
|
await editServerView.fill('#teamNameInput', config.teams[1].name);
|
||||||
|
await editServerView.click('#saveNewServerModal');
|
||||||
|
let existing = await editServerView.isVisible('#teamNameInput.is-invalid');
|
||||||
|
existing.should.be.true;
|
||||||
|
|
||||||
|
await editServerView.fill('#teamNameInput', 'NewTestTeam');
|
||||||
|
await editServerView.fill('#teamUrlInput', config.teams[1].url);
|
||||||
|
existing = await editServerView.isVisible('#teamUrlInput.is-invalid');
|
||||||
|
existing.should.be.true;
|
||||||
|
});
|
||||||
|
|
||||||
it('MM-T4391_2 should edit team when Save is pressed and name edited', async () => {
|
it('MM-T4391_2 should edit team when Save is pressed and name edited', async () => {
|
||||||
await editServerView.fill('#teamNameInput', 'NewTestTeam');
|
await editServerView.fill('#teamNameInput', 'NewTestTeam');
|
||||||
await editServerView.click('#saveNewServerModal');
|
await editServerView.click('#saveNewServerModal');
|
||||||
|
@@ -4,7 +4,7 @@
|
|||||||
import {app, dialog, IpcMainEvent, IpcMainInvokeEvent, Menu} from 'electron';
|
import {app, dialog, IpcMainEvent, IpcMainInvokeEvent, Menu} from 'electron';
|
||||||
import log from 'electron-log';
|
import log from 'electron-log';
|
||||||
|
|
||||||
import {Team} from 'types/config';
|
import {Team, TeamWithIndex} from 'types/config';
|
||||||
import {MentionData} from 'types/notification';
|
import {MentionData} from 'types/notification';
|
||||||
|
|
||||||
import Config from 'common/config';
|
import Config from 'common/config';
|
||||||
@@ -109,7 +109,7 @@ export function handleNewServerModal() {
|
|||||||
if (!mainWindow) {
|
if (!mainWindow) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const modalPromise = ModalManager.addModal<unknown, Team>('newServer', html, modalPreload, {}, mainWindow, Config.teams.length === 0);
|
const modalPromise = ModalManager.addModal<TeamWithIndex[], Team>('newServer', html, modalPreload, Config.teams.map((team, index) => ({...team, index})), mainWindow, Config.teams.length === 0);
|
||||||
if (modalPromise) {
|
if (modalPromise) {
|
||||||
modalPromise.then((data) => {
|
modalPromise.then((data) => {
|
||||||
const teams = Config.teams;
|
const teams = Config.teams;
|
||||||
@@ -145,7 +145,15 @@ export function handleEditServerModal(e: IpcMainEvent, name: string) {
|
|||||||
if (serverIndex < 0) {
|
if (serverIndex < 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const modalPromise = ModalManager.addModal<Team, Team>('editServer', html, modalPreload, Config.teams[serverIndex], mainWindow);
|
const modalPromise = ModalManager.addModal<{currentTeams: TeamWithIndex[]; team: TeamWithIndex}, Team>(
|
||||||
|
'editServer',
|
||||||
|
html,
|
||||||
|
modalPreload,
|
||||||
|
{
|
||||||
|
currentTeams: Config.teams.map((team, index) => ({...team, index})),
|
||||||
|
team: {...Config.teams[serverIndex], index: serverIndex},
|
||||||
|
},
|
||||||
|
mainWindow);
|
||||||
if (modalPromise) {
|
if (modalPromise) {
|
||||||
modalPromise.then((data) => {
|
modalPromise.then((data) => {
|
||||||
const teams = Config.teams;
|
const teams = Config.teams;
|
||||||
|
@@ -13,6 +13,7 @@ type Props = {
|
|||||||
onClose?: () => void;
|
onClose?: () => void;
|
||||||
onSave?: (team: TeamWithIndex) => void;
|
onSave?: (team: TeamWithIndex) => void;
|
||||||
team?: TeamWithIndex;
|
team?: TeamWithIndex;
|
||||||
|
currentTeams?: TeamWithIndex[];
|
||||||
editMode?: boolean;
|
editMode?: boolean;
|
||||||
show?: boolean;
|
show?: boolean;
|
||||||
restoreFocus?: boolean;
|
restoreFocus?: boolean;
|
||||||
@@ -62,6 +63,15 @@ export default class NewTeamModal extends React.PureComponent<Props, State> {
|
|||||||
if (!this.state.saveStarted) {
|
if (!this.state.saveStarted) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
if (this.props.currentTeams) {
|
||||||
|
const currentTeams = [...this.props.currentTeams];
|
||||||
|
if (this.props.editMode && this.props.team) {
|
||||||
|
currentTeams.splice(this.props.team.index, 1);
|
||||||
|
}
|
||||||
|
if (currentTeams.find((team) => team.name === this.state.teamName)) {
|
||||||
|
return 'A server with the same name already exists.';
|
||||||
|
}
|
||||||
|
}
|
||||||
return this.state.teamName.length > 0 ? null : 'Name is required.';
|
return this.state.teamName.length > 0 ? null : 'Name is required.';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,6 +89,15 @@ export default class NewTeamModal extends React.PureComponent<Props, State> {
|
|||||||
if (!this.state.saveStarted) {
|
if (!this.state.saveStarted) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
if (this.props.currentTeams) {
|
||||||
|
const currentTeams = [...this.props.currentTeams];
|
||||||
|
if (this.props.editMode && this.props.team) {
|
||||||
|
currentTeams.splice(this.props.team.index, 1);
|
||||||
|
}
|
||||||
|
if (currentTeams.find((team) => team.url === this.state.teamUrl)) {
|
||||||
|
return 'A server with the same URL already exists.';
|
||||||
|
}
|
||||||
|
}
|
||||||
if (this.state.teamUrl.length === 0) {
|
if (this.state.teamUrl.length === 0) {
|
||||||
return 'URL is required.';
|
return 'URL is required.';
|
||||||
}
|
}
|
||||||
|
@@ -28,11 +28,13 @@ const onSave = (data: TeamWithIndex) => {
|
|||||||
|
|
||||||
const EditServerModalWrapper: React.FC = () => {
|
const EditServerModalWrapper: React.FC = () => {
|
||||||
const [server, setServer] = useState<TeamWithIndex>();
|
const [server, setServer] = useState<TeamWithIndex>();
|
||||||
|
const [currentTeams, setCurrentTeams] = useState<TeamWithIndex[]>();
|
||||||
|
|
||||||
const handleEditServerMessage = (event: {data: ModalMessage<TeamWithIndex>}) => {
|
const handleEditServerMessage = (event: {data: ModalMessage<{currentTeams: TeamWithIndex[]; team: TeamWithIndex}>}) => {
|
||||||
switch (event.data.type) {
|
switch (event.data.type) {
|
||||||
case MODAL_INFO: {
|
case MODAL_INFO: {
|
||||||
setServer(event.data.data);
|
setServer(event.data.data.team);
|
||||||
|
setCurrentTeams(event.data.data.currentTeams);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@@ -52,6 +54,7 @@ const EditServerModalWrapper: React.FC = () => {
|
|||||||
editMode={true}
|
editMode={true}
|
||||||
show={Boolean(server)}
|
show={Boolean(server)}
|
||||||
team={server}
|
team={server}
|
||||||
|
currentTeams={currentTeams}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@@ -10,7 +10,7 @@ import ReactDOM from 'react-dom';
|
|||||||
import {TeamWithIndex} from 'types/config';
|
import {TeamWithIndex} from 'types/config';
|
||||||
import {ModalMessage} from 'types/modals';
|
import {ModalMessage} from 'types/modals';
|
||||||
|
|
||||||
import {GET_MODAL_UNCLOSEABLE, MODAL_CANCEL, MODAL_RESULT, MODAL_UNCLOSEABLE} from 'common/communication';
|
import {GET_MODAL_UNCLOSEABLE, MODAL_CANCEL, MODAL_INFO, MODAL_RESULT, MODAL_UNCLOSEABLE, RETRIEVE_MODAL_INFO} from 'common/communication';
|
||||||
|
|
||||||
import NewTeamModal from '../../components/NewTeamModal'; //'./addServer.jsx';
|
import NewTeamModal from '../../components/NewTeamModal'; //'./addServer.jsx';
|
||||||
|
|
||||||
@@ -28,13 +28,17 @@ const onSave = (data: TeamWithIndex) => {
|
|||||||
|
|
||||||
const NewServerModalWrapper: React.FC = () => {
|
const NewServerModalWrapper: React.FC = () => {
|
||||||
const [unremoveable, setUnremovable] = useState<boolean>();
|
const [unremoveable, setUnremovable] = useState<boolean>();
|
||||||
|
const [currentTeams, setCurrentTeams] = useState<TeamWithIndex[]>();
|
||||||
|
|
||||||
const handleNewServerMessage = (event: {data: ModalMessage<boolean>}) => {
|
const handleNewServerMessage = (event: {data: ModalMessage<unknown>}) => {
|
||||||
switch (event.data.type) {
|
switch (event.data.type) {
|
||||||
case MODAL_UNCLOSEABLE: {
|
case MODAL_UNCLOSEABLE: {
|
||||||
setUnremovable(event.data.data);
|
setUnremovable(event.data.data as boolean);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case MODAL_INFO:
|
||||||
|
setCurrentTeams(event.data.data as TeamWithIndex[]);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -43,6 +47,7 @@ const NewServerModalWrapper: React.FC = () => {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
window.addEventListener('message', handleNewServerMessage);
|
window.addEventListener('message', handleNewServerMessage);
|
||||||
window.postMessage({type: GET_MODAL_UNCLOSEABLE}, window.location.href);
|
window.postMessage({type: GET_MODAL_UNCLOSEABLE}, window.location.href);
|
||||||
|
window.postMessage({type: RETRIEVE_MODAL_INFO}, window.location.href);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
window.removeEventListener('message', handleNewServerMessage);
|
window.removeEventListener('message', handleNewServerMessage);
|
||||||
@@ -55,6 +60,7 @@ const NewServerModalWrapper: React.FC = () => {
|
|||||||
onSave={onSave}
|
onSave={onSave}
|
||||||
editMode={false}
|
editMode={false}
|
||||||
show={true}
|
show={true}
|
||||||
|
currentTeams={currentTeams}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user