Refactor Nav component

This commit is contained in:
Jeremie Pardou-Piquemal 2022-12-15 22:42:21 +01:00
parent bbbe0f5e2d
commit c9fa5599b4
3 changed files with 395 additions and 117 deletions

View File

@ -99,8 +99,7 @@ test('Nav component is displaying with another configuration and can rerender',
/>,
);
expect(mock$).toHaveBeenCalledWith('.me-icon-wrap');
expect(mock$).toHaveBeenLastCalledWith('.owner-icon-wrap');
expect(asFragment()).toMatchSnapshot();
});
test('Can copy room url', async () => {
@ -127,13 +126,13 @@ test('Can copy room url', async () => {
fireEvent.click(getByText(`/testRoom`));
expect(document.execCommand).toHaveBeenLastCalledWith('copy');
expect(mock$).toHaveBeenCalledTimes(15);
expect(mock$).toHaveBeenCalledTimes(12);
expect(mockTooltip).toHaveBeenLastCalledWith('show');
// Wait tooltip closing
vi.runAllTimers();
expect(mock$).toHaveBeenCalledTimes(18);
expect(mock$).toHaveBeenCalledTimes(15);
expect(mockTooltip).toHaveBeenLastCalledWith('hide');
});

View File

@ -529,3 +529,291 @@ exports[`Nav component is displaying with another configuration and can rerender
</nav>
</DocumentFragment>
`;
exports[`Nav component is displaying with another configuration and can rerender 2`] = `
<DocumentFragment>
<nav
class="navbar navbar-expand-md navbar-dark"
>
<div
class="meta"
>
<img
alt="Darkwire"
class="logo"
src="/src/img/logo.png"
/>
<button
class="btn btn-plain btn-link clipboard-trigger room-id ellipsis"
data-clipboard-text="http://localhost:3000/testRoom_3"
data-placement="bottom"
data-toggle="tooltip"
>
/testRoom_3
</button>
<span
class="lock-room-container"
>
<button
class="lock-room btn btn-link btn-plain"
data-placement="bottom"
data-toggle="tooltip"
title="You must be the owner to lock or unlock the room"
>
<svg
fill="none"
height="24"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
viewBox="0 0 24 24"
width="24"
xmlns="http://www.w3.org/2000/svg"
>
<rect
height="11"
rx="2"
ry="2"
width="18"
x="3"
y="11"
/>
<path
d="M7 11V7a5 5 0 0 1 10 0v4"
/>
</svg>
</button>
</span>
<div
class="dropdown members-dropdown"
>
<a
class="dropdown__trigger "
>
<button
class="btn btn-link btn-plain members-action"
title="Users"
>
<svg
class="users-icon"
fill="none"
height="24"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
viewBox="0 0 24 24"
width="24"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"
/>
<circle
cx="9"
cy="7"
r="4"
/>
<path
d="M23 21v-2a4 4 0 0 0-3-3.87"
/>
<path
d="M16 3.13a4 4 0 0 1 0 7.75"
/>
</svg>
</button>
<span>
2
</span>
</a>
<div
class="dropdown__content "
>
<ul
class="plain"
>
<li>
<span
class="username"
style="color: rgb(192, 202, 249);"
>
alan
</span>
<span
class="icon-container"
>
<span
class="owner-icon-wrap"
data-placement="bottom"
data-toggle="tooltip"
title="Owner"
>
<svg
class="owner-icon"
fill="none"
height="24"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
viewBox="0 0 24 24"
width="24"
xmlns="http://www.w3.org/2000/svg"
>
<polygon
points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"
/>
</svg>
</span>
</span>
</li>
<li>
<span
class="username"
style="color: rgb(156, 252, 223);"
>
dan
</span>
<span
class="icon-container"
/>
</li>
</ul>
</div>
</div>
</div>
<button
aria-controls="navbarSupportedContent"
aria-expanded="false"
aria-label="Toggle navigation"
class="navbar-toggler"
data-target="#navbarSupportedContent"
data-toggle="collapse"
type="button"
>
<span
class="navbar-toggler-icon"
/>
</button>
<div
class="collapse navbar-collapse"
id="navbarSupportedContent"
>
<ul
class="navbar-nav ml-auto"
>
<li
class="nav-item"
>
<button
class="btn btn-plain nav-link"
target="blank"
>
<svg
fill="none"
height="24"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
viewBox="0 0 24 24"
width="24"
xmlns="http://www.w3.org/2000/svg"
>
<circle
cx="12"
cy="12"
r="10"
/>
<line
x1="12"
x2="12"
y1="8"
y2="16"
/>
<line
x1="8"
x2="16"
y1="12"
y2="12"
/>
</svg>
<span />
</button>
</li>
<li
class="nav-item"
>
<button
class="btn btn-plain nav-link"
>
<svg
fill="none"
height="24"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
viewBox="0 0 24 24"
width="24"
xmlns="http://www.w3.org/2000/svg"
>
<circle
cx="12"
cy="12"
r="3"
/>
<path
d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"
/>
</svg>
<span />
</button>
</li>
<li
class="nav-item"
>
<button
class="btn btn-plain nav-link"
>
<svg
fill="none"
height="24"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
viewBox="0 0 24 24"
width="24"
xmlns="http://www.w3.org/2000/svg"
>
<circle
cx="12"
cy="12"
r="10"
/>
<line
x1="12"
x2="12"
y1="16"
y2="12"
/>
<line
x1="12"
x2="12.01"
y1="8"
y2="8"
/>
</svg>
<span />
</button>
</li>
</ul>
</div>
</nav>
</DocumentFragment>
`;

View File

@ -1,4 +1,4 @@
import React, { Component } from 'react';
import React from 'react';
import PropTypes from 'prop-types';
import { nanoid } from 'nanoid';
import { Info, Settings, PlusCircle, User, Users, Lock, Unlock, Star } from 'react-feather';
@ -9,8 +9,8 @@ import $ from 'jquery';
import logoImg from '@/img/logo.png';
import Username from '@/components/Username';
class Nav extends Component {
componentDidMount() {
const Nav = ({ members, roomId, userId, roomLocked, toggleLockRoom, openModal, iAmOwner, translations }) => {
React.useEffect(() => {
const clip = new Clipboard('.clipboard-trigger');
clip.on('success', () => {
@ -28,133 +28,124 @@ class Nav extends Component {
trigger: 'manual',
});
});
}
}, []);
componentDidUpdate() {
$(() => {
$('.me-icon-wrap').tooltip();
$('.owner-icon-wrap').tooltip();
});
}
newRoom() {
const newRoom = () => {
$('.navbar-collapse').collapse('hide');
window.open(`/${nanoid()}`);
}
};
handleSettingsClick() {
const handleSettingsClick = () => {
$('.navbar-collapse').collapse('hide');
this.props.openModal('Settings');
}
openModal('Settings');
};
handleAboutClick() {
const handleAboutClick = () => {
$('.navbar-collapse').collapse('hide');
this.props.openModal('About');
}
openModal('About');
};
handleToggleLock() {
if (!this.props.iAmOwner) {
const handleToggleLock = () => {
if (!iAmOwner) {
$('.lock-room').tooltip('show');
setTimeout(() => $('.lock-room').tooltip('hide'), 3000);
return;
}
this.props.toggleLockRoom();
}
toggleLockRoom();
};
render() {
return (
<nav className="navbar navbar-expand-md navbar-dark">
<div className="meta">
<img src={logoImg} alt="Darkwire" className="logo" />
<button
data-toggle="tooltip"
data-placement="bottom"
title={this.props.translations.copyButtonTooltip}
data-clipboard-text={`${window.location.origin}/${this.props.roomId}`}
className="btn btn-plain btn-link clipboard-trigger room-id ellipsis"
>
{`/${this.props.roomId}`}
</button>
<span className="lock-room-container">
<button
onClick={this.handleToggleLock.bind(this)}
className="lock-room btn btn-link btn-plain"
data-toggle="tooltip"
data-placement="bottom"
title="You must be the owner to lock or unlock the room"
>
{this.props.roomLocked && <Lock />}
{!this.props.roomLocked && <Unlock className="muted" />}
</button>
</span>
<Dropdown className="members-dropdown">
<DropdownTrigger>
<button className="btn btn-link btn-plain members-action" title="Users">
<Users className="users-icon" />
</button>
<span>{this.props.members.length}</span>
</DropdownTrigger>
<DropdownContent>
<ul className="plain">
{this.props.members.map((member, index) => (
<li key={`user-${index}`}>
<Username username={member.username} />
<span className="icon-container">
{member.id === this.props.userId && (
<span data-toggle="tooltip" data-placement="bottom" title="Me" className="me-icon-wrap">
<User className="me-icon" />
</span>
)}
{member.isOwner && (
<span data-toggle="tooltip" data-placement="bottom" title="Owner" className="owner-icon-wrap">
<Star className="owner-icon" />
</span>
)}
</span>
</li>
))}
</ul>
</DropdownContent>
</Dropdown>
</div>
return (
<nav className="navbar navbar-expand-md navbar-dark">
<div className="meta">
<img src={logoImg} alt="Darkwire" className="logo" />
<button
className="navbar-toggler"
type="button"
data-toggle="collapse"
data-target="#navbarSupportedContent"
aria-controls="navbarSupportedContent"
aria-expanded="false"
aria-label="Toggle navigation"
data-toggle="tooltip"
data-placement="bottom"
title={translations.copyButtonTooltip}
data-clipboard-text={`${window.location.origin}/${roomId}`}
className="btn btn-plain btn-link clipboard-trigger room-id ellipsis"
>
<span className="navbar-toggler-icon" />
{`/${roomId}`}
</button>
<div className="collapse navbar-collapse" id="navbarSupportedContent">
<ul className="navbar-nav ml-auto">
<li className="nav-item">
<button className="btn btn-plain nav-link" onClick={this.newRoom.bind(this)} target="blank">
<PlusCircle /> <span>{this.props.translations.newRoomButton}</span>
</button>
</li>
<li className="nav-item">
<button onClick={this.handleSettingsClick.bind(this)} className="btn btn-plain nav-link">
<Settings /> <span>{this.props.translations.settingsButton}</span>
</button>
</li>
<li className="nav-item">
<button onClick={this.handleAboutClick.bind(this)} className="btn btn-plain nav-link">
<Info /> <span>{this.props.translations.aboutButton}</span>
</button>
</li>
</ul>
</div>
</nav>
);
}
}
<span className="lock-room-container">
<button
onClick={handleToggleLock}
className="lock-room btn btn-link btn-plain"
data-toggle="tooltip"
data-placement="bottom"
title="You must be the owner to lock or unlock the room"
>
{roomLocked && <Lock />}
{!roomLocked && <Unlock className="muted" />}
</button>
</span>
<Dropdown className="members-dropdown">
<DropdownTrigger>
<button className="btn btn-link btn-plain members-action" title="Users">
<Users className="users-icon" />
</button>
<span>{members.length}</span>
</DropdownTrigger>
<DropdownContent>
<ul className="plain">
{members.map((member, index) => (
<li key={`user-${index}`}>
<Username username={member.username} />
<span className="icon-container">
{member.id === userId && (
<span data-toggle="tooltip" data-placement="bottom" title="Me" className="me-icon-wrap">
<User className="me-icon" />
</span>
)}
{member.isOwner && (
<span data-toggle="tooltip" data-placement="bottom" title="Owner" className="owner-icon-wrap">
<Star className="owner-icon" />
</span>
)}
</span>
</li>
))}
</ul>
</DropdownContent>
</Dropdown>
</div>
<button
className="navbar-toggler"
type="button"
data-toggle="collapse"
data-target="#navbarSupportedContent"
aria-controls="navbarSupportedContent"
aria-expanded="false"
aria-label="Toggle navigation"
>
<span className="navbar-toggler-icon" />
</button>
<div className="collapse navbar-collapse" id="navbarSupportedContent">
<ul className="navbar-nav ml-auto">
<li className="nav-item">
<button className="btn btn-plain nav-link" onClick={newRoom} target="blank">
<PlusCircle /> <span>{translations.newRoomButton}</span>
</button>
</li>
<li className="nav-item">
<button onClick={handleSettingsClick} className="btn btn-plain nav-link">
<Settings /> <span>{translations.settingsButton}</span>
</button>
</li>
<li className="nav-item">
<button onClick={handleAboutClick} className="btn btn-plain nav-link">
<Info /> <span>{translations.aboutButton}</span>
</button>
</li>
</ul>
</div>
</nav>
);
};
Nav.propTypes = {
members: PropTypes.array.isRequired,