fixes alignment of the emojis and thumbnails

This commit is contained in:
Joao Victor 2021-12-13 14:50:10 -03:00
parent 44b6e2d62e
commit b2075b5bd1

View File

@ -5,9 +5,8 @@ import UserAvatar from './UserAvatar';
class StatusTable extends React.Component {
componentDidMount() {
// This code is needed to prevent the emoji in the first cell
// after the username from overflowing
const emojis = document.getElementsByClassName('emojiOnFirstCell');
// This code is needed to prevent the emojis from overflowing
const emojis = document.getElementsByClassName('timeline-emoji');
for (let i = 0; i < emojis.length; i += 1) {
const emojiStyle = window.getComputedStyle(emojis[i]);
let offsetLeft = emojiStyle
@ -16,13 +15,28 @@ class StatusTable extends React.Component {
.trim();
offsetLeft = Number(offsetLeft);
if (offsetLeft < 0) {
emojis[i].style.offsetLeft = '0px';
emojis[i].style.left = '0';
}
}
}
componentDidUpdate() {
// This code is needed to prevent the emojis from overflowing
const emojis = document.getElementsByClassName('timeline-emoji');
for (let i = 0; i < emojis.length; i += 1) {
const emojiStyle = window.getComputedStyle(emojis[i]);
let offsetLeft = emojiStyle
.left
.replace(/px/g, '')
.trim();
offsetLeft = Number(offsetLeft);
if (offsetLeft < 0) {
emojis[i].style.left = '0';
}
}
}
render() {
const spanMinutes = 10 * 60000; // 10 minutes default
const {
allUsers, slides, meetingId, intl,
} = this.props;
@ -40,24 +54,28 @@ class StatusTable extends React.Component {
const firstRegisteredOnTime = Math.min(...usersRegisteredTimes);
const lastLeftOnTime = Math.max(...usersLeftTimes);
const hasSlides = slides && Array.isArray(slides) && slides.length > 0;
const periods = [];
let currPeriod = firstRegisteredOnTime;
while (currPeriod < lastLeftOnTime) {
periods.push(currPeriod);
currPeriod += spanMinutes;
}
function getSlidesOnPeriod(start = null, end = null) {
if (start == null && end == null) return slides;
const filteredSlides = slides.filter((slide) => {
if (slide.presentationId === '') return false;
if (start == null && slide.setOn <= end) return true;
if (end == null && slide.setOn >= start) return true;
if (slide.setOn >= start && slide.setOn < end) return true;
return false;
if (hasSlides) {
const filteredSlides = slides.filter((slide) => slide.presentationId !== '');
if (firstRegisteredOnTime < slides[0].setOn) {
periods.push({
start: firstRegisteredOnTime,
end: slides[0].setOn - 1,
});
}
filteredSlides.forEach((slide, index, slidesArray) => {
periods.push({
slide,
start: slide.setOn,
end: slidesArray[index + 1]?.setOn - 1 || lastLeftOnTime,
});
});
} else {
periods.push({
start: firstRegisteredOnTime,
end: lastLeftOnTime,
});
return filteredSlides;
}
return (
@ -66,42 +84,58 @@ class StatusTable extends React.Component {
<tr className="text-xs font-semibold tracking-wide text-gray-500 uppercase border-b bg-gray-100">
<th className="px-4 py-3 col-text-left sticky left-0 z-30 bg-inherit">
<FormattedMessage id="app.learningDashboard.user" defaultMessage="User" />
<svg
xmlns="http://www.w3.org/2000/svg"
className="h-4 w-4 inline"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M17 13l-5 5m0 0l-5-5m5 5V6" />
</svg>
</th>
{ periods.map((period) => <th className="px-4 py-3 col-text-left">{ `${tsToHHmmss(period - firstRegisteredOnTime)}` }</th>) }
<th
className="bg-inherit"
colSpan={periods.length}
>
<span
className="invisible"
aria-label={intl.formatMessage({
id: 'app.learningDashboard.indicators.timeline',
defaultMessage: 'Timeline',
})}
>
<FormattedMessage id="app.learningDashboard.indicators.timeline" defaultMessage="Timeline" />
</span>
</th>
</tr>
</thead>
<tbody className="bg-white divide-y">
{ slides && Array.isArray(slides) && slides.length > 0 ? (
<tr>
<td />
{ hasSlides ? (
<tr className="bg-inherit">
<td className="bg-inherit sticky left-0 z-30" />
{ periods.map((period) => {
const slidesOnPeriod = getSlidesOnPeriod(period, period + spanMinutes);
const screenshots = slidesOnPeriod.map((slide) => (
<div
className="my-2"
aria-label={`Slide set on ${tsToHHmmss(slide.setOn - firstRegisteredOnTime)}`}
>
<img
src={`/bigbluebutton/presentation/${meetingId}/${meetingId}/${slide.presentationId}/svg/${slide.pageNum}`}
alt="Slide"
className="w-36 h-auto"
/>
<div className="text-xs text-center m-1 text-gray-500">{tsToHHmmss(slide.setOn - firstRegisteredOnTime)}</div>
</div>
));
const { slide, start, end } = period;
return (
<td>
<td
style={{
paddingRight: `${(end - start) / 1000}px`,
}}
>
<div className="flex">
{screenshots}
<div
className="my-4"
aria-label={`Slide set on ${tsToHHmmss(slide.setOn - periods[0].start)}`}
>
<a
href={`/bigbluebutton/presentation/${meetingId}/${meetingId}/${slide.presentationId}/svg/${slide.pageNum}`}
className="block border-2 border-gray-300"
target="_blank"
rel="noreferrer"
>
<img
src={`/bigbluebutton/presentation/${meetingId}/${meetingId}/${slide.presentationId}/thumbnail/${slide.pageNum}`}
alt="Slide"
style={{
maxWidth: '150px',
width: '150px',
height: 'auto',
}}
/>
</a>
<div className="text-xs text-center mt-1 text-gray-500">{tsToHHmmss(slide.setOn - periods[0].start)}</div>
</div>
</div>
</td>
);
@ -133,81 +167,75 @@ class StatusTable extends React.Component {
{ periods.map((period) => {
const userEmojisInPeriod = filterUserEmojis(user,
null,
period,
period + spanMinutes);
period.start,
period.end);
const { registeredOn, leftOn } = user;
const boundaryLeft = period;
const boundaryRight = period + spanMinutes - 1;
const boundaryLeft = period.start;
const boundaryRight = period.end;
const interval = period.end - period.start;
return (
<td className="relative px-4 py-3 text-sm col-text-left">
{
(registeredOn >= boundaryLeft && registeredOn <= boundaryRight)
{ (registeredOn >= boundaryLeft && registeredOn <= boundaryRight)
|| (leftOn >= boundaryLeft && leftOn <= boundaryRight)
|| (boundaryLeft > registeredOn && boundaryRight < leftOn)
|| (boundaryLeft >= registeredOn && leftOn === 0)
? (
(function makeLineThrough() {
let roundedLeft = registeredOn >= boundaryLeft
&& registeredOn <= boundaryRight ? 'rounded-l' : '';
let roundedRight = leftOn > boundaryLeft
&& leftOn < boundaryRight ? 'rounded-r' : '';
let offsetLeft = 0;
let offsetRight = 0;
if (registeredOn >= boundaryLeft && registeredOn <= boundaryRight) {
offsetLeft = ((registeredOn - boundaryLeft) * 100) / spanMinutes;
}
if (leftOn >= boundaryLeft && leftOn <= boundaryRight) {
offsetRight = ((boundaryRight - leftOn) * 100) / spanMinutes;
}
let width = '';
if (offsetLeft === 0 && offsetRight >= 99) {
|| (boundaryLeft >= registeredOn && leftOn === 0) ? (
(function makeLineThrough() {
let roundedLeft = registeredOn >= boundaryLeft
&& registeredOn <= boundaryRight ? 'rounded-l' : '';
let roundedRight = leftOn > boundaryLeft
&& leftOn < boundaryRight ? 'rounded-r' : '';
let offsetLeft = 0;
let offsetRight = 0;
if (registeredOn >= boundaryLeft && registeredOn <= boundaryRight) {
offsetLeft = ((registeredOn - boundaryLeft) * 100) / (interval);
}
if (leftOn >= boundaryLeft && leftOn <= boundaryRight) {
offsetRight = ((boundaryRight - leftOn) * 100) / (interval);
}
let width = '';
if (offsetLeft === 0 && offsetRight >= 99) {
width = 'w-1.5';
}
if (offsetRight === 0 && offsetLeft >= 99) {
width = 'w-1.5';
}
if (offsetLeft && offsetRight) {
const variation = offsetLeft - offsetRight;
if (variation > -1 && variation < 1) {
width = 'w-1.5';
}
if (offsetRight === 0 && offsetLeft >= 99) {
width = 'w-1.5';
}
if (offsetLeft && offsetRight) {
const variation = offsetLeft - offsetRight;
if (
variation > -1 && variation < 1
) {
width = 'w-1.5';
}
}
const isRTL = document.dir === 'rtl';
if (isRTL) {
const aux = roundedRight;
}
const isRTL = document.dir === 'rtl';
if (isRTL) {
const aux = roundedRight;
if (roundedLeft !== '') roundedRight = 'rounded-r';
else roundedRight = '';
if (roundedLeft !== '') roundedRight = 'rounded-r';
else roundedRight = '';
if (aux !== '') roundedLeft = 'rounded-l';
else roundedLeft = '';
}
// height / 2
const redress = '(0.375rem / 2)';
return (
<div
className={`h-1.5 ${width} bg-gray-200 absolute inset-x-0 z-10 ${roundedLeft} ${roundedRight}`}
style={{
top: `calc(50% - ${redress})`,
left: `${isRTL ? offsetRight : offsetLeft}%`,
right: `${isRTL ? offsetLeft : offsetRight}%`,
}}
/>
);
})()
) : null
}
if (aux !== '') roundedLeft = 'rounded-l';
else roundedLeft = '';
}
const redress = '(0.375rem / 2)';
return (
<div
className={`h-1.5 ${width} bg-gray-200 absolute inset-x-0 z-10 ${roundedLeft} ${roundedRight}`}
style={{
top: `calc(50% - ${redress})`,
left: `${isRTL ? offsetRight : offsetLeft}%`,
right: `${isRTL ? offsetLeft : offsetRight}%`,
}}
/>
);
})()
) : null }
{ userEmojisInPeriod.map((emoji) => {
const offset = ((emoji.sentOn - period) * 100) / spanMinutes;
const offset = ((emoji.sentOn - period.start) * 100)
/ (period.end - period.start);
const origin = document.dir === 'rtl' ? 'right' : 'left';
const onFirstCell = period === firstRegisteredOnTime;
// font-size / 2 + padding right/left + border-width
const redress = '(0.875rem / 2 + 0.25rem + 2px)';
return (
<div
className={`flex absolute p-1 border-white border-2 rounded-full text-sm z-20 bg-purple-500 text-purple-200 ${onFirstCell ? 'emojiOnFirstCell' : ''}`}
className="flex absolute p-1 border-white border-2 rounded-full text-sm z-20 bg-purple-500 text-purple-200 timeline-emoji"
role="status"
style={{
top: `calc(50% - ${redress})`,
@ -221,7 +249,7 @@ class StatusTable extends React.Component {
<i className={`${emojiConfigs[emoji.name].icon} text-sm bbb-icon-timeline`} />
</div>
);
})}
}) }
</td>
);
}) }