solid-panes
Version:
Solid-compatible Panes: applets and views for the mashlib and databrowser
317 lines (312 loc) • 12.9 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.createAllFriendsSection = createAllFriendsSection;
exports.createHeaderSection = createHeaderSection;
exports.createMutualSection = createMutualSection;
var _profilePane = require("profile-pane");
var _solidUi = require("solid-ui");
var _editProfileDetails = require("./editProfileDetails");
var _icons = require("./icons");
function createHeaderSection(context, subject, controls, stats, getProfileData) {
const dom = context.dom;
const kb = context.session.store;
const header = document.createElement('header');
header.className = 'social-pane__header';
let headerControls = controls;
const renderHeader = function () {
header.replaceChildren();
const profileData = getProfileData();
const headerContent = dom.createElement('div');
headerContent.className = 'social-pane__header-content';
if (headerControls.canEdit) {
header.appendChild((0, _editProfileDetails.createEditProfileDetailsButton)({
dom,
store: kb,
subject,
header,
onSaved: renderHeader
}));
} else if (headerControls.viewerMode === 'authenticated') {
const addToFriendsButton = (0, _profilePane.createAddMeToYourFriendsButton)(subject, context);
addToFriendsButton.classList.add('social-pane__friend-action', 'profile__action-button', 'profile__btn-friends', 'flex-center');
// header.appendChild(addToFriendsButton)
headerContent.appendChild(addToFriendsButton);
}
header.appendChild(headerContent);
const headerMedia = dom.createElement('div');
headerMedia.className = 'social-pane__header-media';
headerContent.appendChild(headerMedia);
if (profileData) {
headerMedia.appendChild(createImage(profileData.imageUrl, profileData.name));
}
const headerDetails = dom.createElement('div');
headerDetails.className = 'social-pane__header-details';
headerContent.appendChild(headerDetails);
const headerSummary = dom.createElement('div');
headerSummary.classList.add('social-pane__header-summary', 'flex-column');
headerDetails.appendChild(headerSummary);
const name = profileData?.name || '???';
const h1 = dom.createElement('h1');
h1.classList.add('social-pane__header-name');
h1.appendChild(dom.createTextNode(name));
headerSummary.appendChild(h1);
const jobAndOrganization = [profileData?.jobTitle, profileData?.organization].filter(Boolean).join(' | ');
if (jobAndOrganization) {
const jobLine = dom.createElement('div');
jobLine.className = 'social-pane__header-job-org';
jobLine.textContent = jobAndOrganization;
headerSummary.appendChild(jobLine);
}
if (profileData?.location) {
const locationLine = dom.createElement('div');
locationLine.className = 'social-pane__header-location';
const locationIconSpan = dom.createElement('span');
locationIconSpan.classList.add('social-pane__header-location-icon', 'inline-flex-row');
locationIconSpan.innerHTML = _icons.locationIcon;
locationLine.appendChild(locationIconSpan);
locationLine.appendChild(dom.createTextNode(profileData.location));
headerSummary.appendChild(locationLine);
}
const statsRow = dom.createElement('div');
statsRow.className = 'social-pane__header-stats';
const friendCount = dom.createElement('button');
friendCount.className = 'social-pane__header-stat';
friendCount.type = 'button';
const friendCountLabel = dom.createElement('span');
friendCountLabel.className = 'social-pane__header-stat-label';
friendCountLabel.textContent = `${stats.friendCount} friend${stats.friendCount === 1 ? '' : 's'}`;
friendCount.appendChild(friendCountLabel);
if (stats.onSelectFriends) {
friendCount.addEventListener('click', stats.onSelectFriends);
}
statsRow.appendChild(friendCount);
if (typeof stats.mutualFriendCount === 'number') {
const mutualCount = dom.createElement('button');
mutualCount.className = 'social-pane__header-stat';
mutualCount.type = 'button';
const mutualCountLabel = dom.createElement('span');
mutualCountLabel.className = 'social-pane__header-stat-label';
mutualCountLabel.textContent = `${stats.mutualFriendCount} mutual friend${stats.mutualFriendCount === 1 ? '' : 's'}`;
mutualCount.appendChild(mutualCountLabel);
if (stats.onSelectMutual) {
mutualCount.addEventListener('click', stats.onSelectMutual);
}
statsRow.appendChild(mutualCount);
}
headerSummary.appendChild(statsRow);
(0, _editProfileDetails.appendProfileLinks)(headerMedia, dom, kb, subject);
};
header.refreshSocialHeader = function (nextControls) {
headerControls = nextControls;
renderHeader();
};
renderHeader();
return header;
}
function createImage(src, alt = '') {
if (src) {
const img = document.createElement('img');
img.className = 'social-pane__header-hero';
img.src = src;
img.alt = alt;
img.width = 180;
img.height = 180;
img.loading = 'eager';
return img;
}
const fallback = document.createElement('div');
fallback.className = 'social-pane__header-hero-alt flex-center';
fallback.setAttribute('role', 'img');
fallback.setAttribute('aria-label', alt);
fallback.tabIndex = 0;
const icon = document.createElement('span');
icon.classList.add('social-pane__header-hero-icon', 'inline-flex-row');
icon.innerHTML = _icons.personInCircleIcon;
fallback.appendChild(icon);
return fallback;
}
function createMutualSection(options) {
const {
dom,
subject,
familiar,
meUri,
incoming,
outgoing,
mutualConnections,
link,
text,
renderSupportingInfo,
renderNameSuffix
} = options;
// Mutual confirm UI is intentionally hidden for now.
// The related options remain in the function contract so that block can be
// restored later without reshaping callers.
let refreshMutualFriends = function () {};
const mutualSection = dom.createElement('section');
mutualSection.className = 'social-pane__mutual-friends social-primary__panel';
mutualSection.id = 'social-panel-mutual';
mutualSection.setAttribute('role', 'tabpanel');
mutualSection.setAttribute('aria-labelledby', 'social-tab-mutual');
const mutualContent = mutualSection.appendChild(dom.createElement('div'));
mutualContent.classList.add('social-main', 'social-main--mutual', 'flex-column');
const relationshipSummary = dom.createElement('div');
relationshipSummary.classList.add('social-mutual-summary', 'flex-column');
mutualContent.appendChild(relationshipSummary);
const createRelationshipLine = function () {
const line = relationshipSummary.appendChild(dom.createElement('div'));
line.classList.add('social-mutual-summary-line');
return line;
};
const youAndThem = function () {
const line = createRelationshipLine();
line.appendChild(link(text('You'), meUri));
line.appendChild(text(' and '));
line.appendChild(link(text(familiar), subject.uri));
return line;
};
if (!incoming) {
if (!outgoing) {
const line = youAndThem();
line.appendChild(text(' have not said you know each other.'));
/* NOTE: hiding the outgoing-only unconfirmed message for now.
} else {
relationshipSummary.appendChild(link(text('You'), meUri))
relationshipSummary.appendChild(text(' know '))
relationshipSummary.appendChild(link(text(familiar), subject.uri))
relationshipSummary.appendChild(text(' (unconfirmed)'))
*/
}
/* NOTE: hiding the incoming-only unconfirmed message for now.
} else if (!outgoing) {
relationshipSummary.classList.add('social-mutual-summary--confirm')
const incomingLine = relationshipSummary.appendChild(dom.createElement('div'))
incomingLine.classList.add('social-mutual-summary-line')
incomingLine.appendChild(link(text(familiar), subject.uri))
incomingLine.appendChild(text(' knows '))
incomingLine.appendChild(link(text('you'), meUri))
incomingLine.appendChild(text(' (unconfirmed).'))
*/
} else {
const line = youAndThem();
line.appendChild(text(' say you know each other.'));
}
/* NOTE: hiding the confirm-friend checkbox for now.
const shouldShowCheckboxPreview = editable || (Boolean(incoming) && !outgoing)
if (shouldShowCheckboxPreview) {
const confirmLabel = dom.createElement('span')
confirmLabel.appendChild(text('Confirm you know '))
confirmLabel.appendChild(link(text(familiar), subject.uri))
const relationshipForm = buildCheckboxForm(
confirmLabel,
new Statement(me, knows, subject, profile ?? undefined),
Boolean(outgoing),
{
disabled: !editable,
disabledTitle: !editable ? 'Your profile is not editable' : undefined
}
)
relationshipForm.classList.add('social-mutual-checkbox-form')
mutualContent.appendChild(relationshipForm)
}
*/
if (mutualConnections.length) {
const mutualFriendsTable = mutualContent.appendChild(dom.createElement('table'));
mutualFriendsTable.className = 'social-main social-friends-list social-friends-grid';
const createMutualRow = function (target) {
return _solidUi.widgets.personTR(dom, _solidUi.ns.foaf('knows'), target, {
renderSupportingInfo,
renderNameSuffix
});
};
refreshMutualFriends = function () {
const sortedMutualConnections = [...mutualConnections].sort((left, right) => {
const leftLabel = _solidUi.utils.label(left) || left.value;
const rightLabel = _solidUi.utils.label(right) || right.value;
return leftLabel.localeCompare(rightLabel);
});
_solidUi.utils.syncTableToArray(mutualFriendsTable, sortedMutualConnections, createMutualRow, function (row, thing) {
const replacement = createMutualRow(thing);
return replacement;
});
};
refreshMutualFriends();
}
return {
section: mutualSection,
content: mutualContent,
refreshMutualFriends
};
}
function createAllFriendsSection(options) {
const {
dom,
subject,
profile,
editable,
renderSupportingInfo,
renderNameSuffix
} = options;
const allFriends = dom.createElement('section');
allFriends.className = 'social-pane__all-friends social-primary__panel';
allFriends.id = 'social-panel-all-friends';
allFriends.setAttribute('role', 'tabpanel');
allFriends.setAttribute('aria-labelledby', 'social-tab-all-friends');
const mainTable = allFriends.appendChild(dom.createElement('table'));
mainTable.className = 'social-main';
const friendsList = _solidUi.widgets.attachmentList(dom, subject, mainTable, {
doc: profile,
modify: !!editable,
predicate: _solidUi.ns.foaf('knows'),
noun: 'friend',
renderSupportingInfo,
renderNameSuffix
});
friendsList.classList.add('social-friends-list');
friendsList.style.marginTop = '0';
const friendsListRow = friendsList.querySelector('tr');
const friendsListPromptCell = friendsListRow?.children?.[0];
const friendsListRightCell = friendsListRow?.children?.[1];
const friendsHeaderActions = dom.createElement('div');
friendsHeaderActions.classList.add('social-friends-header-actions');
if (friendsListPromptCell instanceof HTMLElement) {
while (friendsListPromptCell.firstChild) {
friendsHeaderActions.appendChild(friendsListPromptCell.firstChild);
}
friendsListPromptCell.remove();
}
if (friendsHeaderActions.childNodes.length > 0) {
const friendDropButtons = friendsHeaderActions.querySelectorAll('button');
friendDropButtons.forEach(button => {
button.setAttribute('title', 'Drop friend here');
button.setAttribute('aria-label', 'Drop friend here');
const buttonImages = button.querySelectorAll('img');
buttonImages.forEach(image => {
image.setAttribute('title', 'Drop friend here');
image.setAttribute('alt', 'Drop friend here');
});
});
const friendsActionsRow = dom.createElement('div');
friendsActionsRow.className = 'social-friends-header-actions social-friends-header-actions--standalone';
friendsActionsRow.appendChild(friendsHeaderActions);
const dropHint = dom.createElement('span');
dropHint.className = 'social-friends-header-hint';
dropHint.textContent = 'Drag a WebId on the target to add a friend.';
friendsActionsRow.appendChild(dropHint);
allFriends.prepend(friendsActionsRow);
}
if (friendsListRightCell instanceof HTMLTableCellElement) {
friendsListRightCell.colSpan = 2;
}
const friendsItemsTable = friendsList.querySelector('td table');
if (friendsItemsTable instanceof HTMLTableElement) {
friendsItemsTable.classList.add('social-friends-grid');
}
return {
section: allFriends,
mainTable,
friendsList
};
}