Add tags to modal, fix layout

dev
gravel 1 year ago
parent a16e6dc887
commit 6c9afe90b8
Signed by: gravel
GPG Key ID: C0538F3C906B308F

@ -113,7 +113,7 @@ html:not(.js) .js-only {
/* box-shadow: 0.05em 0.05em 0.1em 0 #4444;*/ /* box-shadow: 0.05em 0.05em 0.1em 0 #4444;*/
} }
#tbl_communities .room-label { #tbl_communities .room-label, #details-modal .room-label {
color: black; color: black;
} }
@ -424,9 +424,9 @@ label[for=toggle-show-room-ids]::after {
#details-modal-contents { #details-modal-contents {
display: flex; display: flex;
position: relative; flex-direction: column;
flex-direction: row;
padding: 3em; padding: 3em;
box-sizing: border-box;
} }
#details-modal-close { #details-modal-close {
@ -440,6 +440,11 @@ label[for=toggle-show-room-ids]::after {
text-align: center; text-align: center;
} }
#details-modal-pane {
display: flex;
flex-direction: row;
}
#details-modal-start { #details-modal-start {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@ -463,10 +468,16 @@ label[for=toggle-show-room-ids]::after {
font-style: italic; font-style: italic;
} }
#details-modal-start #details-modal-language-flag:empty::after {
content: "Unknown";
font-style: italic;
}
#details-modal-end #details-modal-qr-code { #details-modal-end #details-modal-qr-code {
aspect-ratio: 1;
width: 20em; width: 20em;
height: 20em; height: 20em;
margin-bottom: 1em; margin: 1em;
} }
#details-modal-end #details-modal-qr-code-label { #details-modal-end #details-modal-qr-code-label {
@ -480,6 +491,10 @@ label[for=toggle-show-room-ids]::after {
padding: var(--cell-padding-small); padding: var(--cell-padding-small);
} }
#details-modal-qr-code-label-name {
display: block;
}
/* <Snackbar> */ /* <Snackbar> */
/* The snackbar - position it at the bottom and in the middle of the screen */ /* The snackbar - position it at the bottom and in the middle of the screen */
#copy-snackbar { #copy-snackbar {
@ -554,15 +569,44 @@ label[for=toggle-show-room-ids]::after {
} }
} }
@media (max-width: 950px) {
#details-modal-pane {
flex-direction: column;
}
#details-modal-end {
align-items: start;
}
#details-modal #details-modal-qr-code {
width: 12.5em;
height: 12.5em;
}
#details-modal-qr-code-label-name {
display: inline;
}
#details-modal-language, #details-modal-users {
display: inline-block;
text-align: center;
}
#details-modal-room-info > * {
margin-block: 0.5em;
}
#details-modal-language::after {
content: "•";
margin-inline: 1em;
}
}
@media (max-width: 500px) { @media (max-width: 500px) {
:root { :root {
/* ! For when descriptions don't wrap and 100vw doesn't work. */ /* ! For when descriptions don't wrap and 100vw doesn't work. */
--dynamic-columns-width: 15rem; --dynamic-columns-width: 15rem;
} }
#details-modal-contents {
flex-direction: column;
}
} }
/* Animations to fade the snackbar in and out */ /* Animations to fade the snackbar in and out */

@ -19,13 +19,15 @@ export const dom = {
join_link: row.querySelector('.td_join_url a[href]').getAttribute('href'), join_link: row.querySelector('.td_join_url a[href]').getAttribute('href'),
hostname: row.getAttribute(ATTRIBUTES.ROW.HOSTNAME), hostname: row.getAttribute(ATTRIBUTES.ROW.HOSTNAME),
public_key: row.getAttribute(ATTRIBUTES.ROW.PUBLIC_KEY), public_key: row.getAttribute(ATTRIBUTES.ROW.PUBLIC_KEY),
staff: row.getAttribute(ATTRIBUTES.ROW.STAFF_DATA) staff: row.getAttribute(ATTRIBUTES.ROW.STAFF_DATA),
tags: row.getAttribute(ATTRIBUTES.ROW.TAGS)
}; };
}, },
meta_timestamp: () => document.querySelector('meta[name=timestamp]'), meta_timestamp: () => document.querySelector('meta[name=timestamp]'),
last_checked: () => document.getElementById("last_checked_value"), last_checked: () => document.getElementById("last_checked_value"),
/** @return {HTMLDialogElement | null} */ /** @return {HTMLDialogElement | null} */
details_modal: () => document.getElementById('details-modal'), details_modal: () => document.getElementById('details-modal'),
details_modal_tag_container: () => document.getElementById('details-modal-room-tags'),
details_modal_qr_code: () => document.getElementById('details-modal-qr-code'), details_modal_qr_code: () => document.getElementById('details-modal-qr-code'),
join_urls: () => document.getElementsByClassName("join_url_container"), join_urls: () => document.getElementsByClassName("join_url_container"),
servers_hidden: () => document.getElementById("servers_hidden"), servers_hidden: () => document.getElementById("servers_hidden"),
@ -56,6 +58,7 @@ export const COMPARISON = {
export const ATTRIBUTES = { export const ATTRIBUTES = {
ROW: { ROW: {
TAGS: 'data-tags',
IDENTIFIER: 'data-identifier', IDENTIFIER: 'data-identifier',
PUBLIC_KEY: 'data-pubkey', PUBLIC_KEY: 'data-pubkey',
HOSTNAME: 'data-hostname', HOSTNAME: 'data-hostname',

@ -75,6 +75,13 @@ function onLoad() {
preloadQRCodes(); preloadQRCodes();
} }
const tagBody = ({text, type, description}) => element.span({
// todo: truncate
textContent: text,
className: `room-label room-label-${type} badge`,
title: description
});
function displayQRModal(communityID) { function displayQRModal(communityID) {
const modal = dom.details_modal(); const modal = dom.details_modal();
@ -109,6 +116,14 @@ function displayQRModal(communityID) {
} }
} }
const tagContainer = dom.details_modal_tag_container();
tagContainer.innerHTML = "";
tagContainer.append(
...JSON.parse(rowInfo.tags).map(tag => tagBody(tag))
);
dom.details_modal_qr_code().src = communityQRCodeURL(communityID); dom.details_modal_qr_code().src = communityQRCodeURL(communityID);
modal.showModal(); modal.showModal();
@ -123,10 +138,19 @@ function addQRModalHandlers() {
if (!rows) throw new Error("Rows not found"); if (!rows) throw new Error("Rows not found");
for (const row of rows) { for (const row of rows) {
const communityID = row.getAttribute(ATTRIBUTES.ROW.IDENTIFIER); const communityID = row.getAttribute(ATTRIBUTES.ROW.IDENTIFIER);
row.querySelector('.td_qr_code').addEventListener( for (const cell of ['.td_qr_code', '.td_description', '.td_language', '.td_users']) {
row.querySelector(cell).addEventListener(
'click',
() => displayQRModal(communityID)
);
}
row.addEventListener(
'click', 'click',
() => displayQRModal(communityID) (e) => {
); if (e.target != row) { return; }
displayQRModal(communityID);
}
)
row.querySelector('.td_name').addEventListener( row.querySelector('.td_name').addEventListener(
'click', 'click',
(e) => { (e) => {

@ -110,6 +110,7 @@
function jsonSerialize(): array { function jsonSerialize(): array {
$details = get_object_vars($this); $details = get_object_vars($this);
unset($details['server']); unset($details['server']);
$details['tags'] = CommunityTag::cacheable_room_tags($details['tags']);
return $details; return $details;
} }

@ -34,10 +34,25 @@
} }
public function jsonSerialize(): mixed { public function jsonSerialize(): mixed {
if ($this->type != TagType::USER_TAG) { // Only used for passing to DOM
throw new LogicException("Should not serialize derived tags."); $details = get_object_vars($this);
} $details['text'] = html_sanitize($details['text']);
return $this->text; $details['description'] = html_sanitize($details['description']);
$details['type'] = $this->get_tag_type();
return $details;
}
/**
* @param \CommunityTag[] $tags
* @return string[]
*/
public static function cacheable_room_tags(array $tags) {
return array_map(
'CommunityTag::__toString',
array_filter($tags, function(\CommunityTag $tag) {
return $tag->type == TagType::USER_TAG;
})
);
} }
private static function preprocess_tag(?string $tag) { private static function preprocess_tag(?string $tag) {

@ -5,70 +5,79 @@
<dialog id="details-modal"> <dialog id="details-modal">
<div id="details-modal-contents"> <div id="details-modal-contents">
<div id="details-modal-close"> <div id="details-modal-close">
&times; &times;
</div> </div>
<div id="details-modal-start"> <div id="details-modal-pane">
<h1 id="details-modal-title">
<a <div id="details-modal-start">
id="details-modal-community-name" <h1 id="details-modal-title">
data-hydrate-with="name;preview_link:href"
title="Open preview in new tab"
></a>
</h1>
<p id="details-modal-description">
<span>Description:</span>
<span id="details-modal-description-inner" data-hydrate-with="description"></span>
</p>
<gap></gap>
<div id="details-modal-room-info">
<p>
Language: <span data-hydrate-with="language_flag"></span>
</p>
<p>
Users: <span data-hydrate-with="users"></span>
</p>
<p>
Server:
<a <a
title="Open server in new tab" id="details-modal-community-name"
data-hydrate-with="hostname;hostname:href" data-hydrate-with="name;preview_link:href"
target="_blank" title="Open preview in new tab"
rel="noopener noreferrer"
></a> ></a>
</h1>
<p id="details-modal-description">
<span id="details-modal-description-inner" data-hydrate-with="description"></span>
</p> </p>
<gap></gap>
<div id="details-modal-room-info">
<p id="details-modal-room-tags">
<p> </p>
<button <p id="details-modal-language">
id="details-modal-copy-button" Language: <span
data-hydrate-with="join_link:data-href" id="details-modal-language-flag"
title="Click here to copy this Community's join link" data-hydrate-with="language_flag"
> ></span>
Copy join link </p>
</button> <p id="details-modal-users">
Users: <span data-hydrate-with="users"></span>
<button </p>
id="details-modal-copy-staff-id" <p id="details-modal-host">
data-hydrate-with="staff:data-staff" Server:
title="Copy the mention for a random staff member" <a
> title="Open server in new tab"
Copy mod ID data-hydrate-with="hostname;hostname:href"
</button> target="_blank"
</p> rel="noopener noreferrer"
></a>
</p>
</div>
</div>
<gap></gap>
<div id="details-modal-end">
<img
src=""
id="details-modal-qr-code"
title="Community join link encoded as QR code"
>
<div id="details-modal-qr-code-label">
Scan QR code in Session to join
<span
id="details-modal-qr-code-label-name"
>'<span data-hydrate-with="name"></span>'</span>
</div>
</div> </div>
</div> </div>
<gap></gap> <gap></gap>
<div id="details-modal-end"> <p>
<img <button
src="" id="details-modal-copy-button"
id="details-modal-qr-code" data-hydrate-with="join_link:data-href"
title="Community join link encoded as QR code" title="Click here to copy this Community's join link"
> >
<div id="details-modal-qr-code-label"> Copy join link
Scan QR code in Session to join </button>
<br>
'<span data-hydrate-with="name"></span>' <button
</div> id="details-modal-copy-staff-id"
</div> data-hydrate-with="staff:data-staff"
title="Copy the mention for a random staff member"
>
Copy mod ID
</button>
</p>
</div> </div>
</dialog> </dialog>

@ -66,6 +66,7 @@
$hostname = html_sanitize($hostname); $hostname = html_sanitize($hostname);
$staff_json = json_encode(array_map('html_sanitize', $room->get_staff())); $staff_json = json_encode(array_map('html_sanitize', $room->get_staff()));
$tags_json = json_encode($room->get_room_tags());
?> ?>
<tr id="<?=$id?>" class="room-row" itemscope itemtype="https://schema.org/EntryPoint" <tr id="<?=$id?>" class="room-row" itemscope itemtype="https://schema.org/EntryPoint"
@ -73,6 +74,7 @@
data-pubkey="<?=$pubkey?>" data-pubkey="<?=$pubkey?>"
data-hostname="<?=$hostname?>" data-hostname="<?=$hostname?>"
data-staff='<?=$staff_json?>' data-staff='<?=$staff_json?>'
data-tags='<?=$tags_json?>'
> >
<td class="td_identifier" itemprop="identifier"><?=$id?></td> <td class="td_identifier" itemprop="identifier"><?=$id?></td>
<td class="td_language" title="Language flag for '<?=$name?>'"><?=$language?></td> <td class="td_language" title="Language flag for '<?=$name?>'"><?=$language?></td>
@ -90,14 +92,14 @@
$name $name
?></a> ?></a>
<span class="room-labels-container"> <span class="room-labels-container">
<?php foreach ($room->get_room_tags() as $tag): ?> <?php foreach ($room->get_room_tags() as $tag): if (CommunityTag::is_showcased_tag($tag->text)): ?>
<span <span
class="room-label <?=$tag->get_tag_classname()?> badge" class="room-label <?=$tag->get_tag_classname()?> badge"
title="<?=$tag->description?>" title="<?=$tag->description?>"
><?= ><?=
truncate($tag->text, 16) truncate($tag->text, 16)
?></span> ?></span>
<?php endforeach; ?> <?php endif; endforeach; ?>
</span> </span>
</td> </td>
<td <td

Loading…
Cancel
Save