Diferencia 1.3.1 -> 1.3.3 del codigo de la APK oficial aplicada a tres bandas encima de la rama: karma en el perfil, salas con directo, fotos selladas, visibilidad de menciones, telefono por stream en Android y las traducciones nuevas. Sin dependencias nuevas. OasisMobile.css sigue siendo el del fork; del oficial solo se traen al final las reglas de las piezas nuevas (karma, directo a pantalla completa, salas en vivo, graphos).
382 lines
21 KiB
JavaScript
382 lines
21 KiB
JavaScript
const { div, h2, h3, p, section, button, form, a, span, br, textarea, input, label, select, option, ul, li, img } = require("../server/node_modules/hyperaxe");
|
||
const { clearnetItemHref, template, i18n, userLink, renderStateChip, renderContentActions, renderSubscriptionBox, renderModuleStats, moduleIsEmpty, renderCardMetaRow, paged } = require("./main_views");
|
||
const { renderEncryptedChip, renderReachChip, renderClearnetSelector, renderClearnetSwitch, renderLicenseChip, renderLicenseSelect, renderTribeOriginChip } = require("./clearnet_view");
|
||
const { renderStyledText, richTextarea } = require("../backend/renderStyledText");
|
||
const { WIKILINK_RE, slugify, linkTarget } = require("../models/wiki_model");
|
||
const moment = require("../server/node_modules/moment");
|
||
const { config } = require("../server/SSB_server.js");
|
||
|
||
const userId = config.keys.id;
|
||
const FILTERS = ["all", "recent", "mine", "linked"];
|
||
|
||
const pageHref = (idOrSlug, tribeId = null) =>
|
||
`/wiki/${encodeURIComponent(idOrSlug)}${tribeId ? `?tribeId=${encodeURIComponent(tribeId)}` : ""}`;
|
||
|
||
const listHref = (filter, q, tribeId = null) => {
|
||
const parts = [`filter=${encodeURIComponent(filter || "all")}`];
|
||
if (q) parts.push(`q=${encodeURIComponent(q)}`);
|
||
if (tribeId) parts.push(`tribeId=${encodeURIComponent(tribeId)}`);
|
||
return `/wiki?${parts.join("&")}`;
|
||
};
|
||
|
||
const renderWikiBody = (body, opts = {}) => {
|
||
const missing = new Set(opts.missing || []);
|
||
const tribeId = opts.tribeId || null;
|
||
const wikiLink = (target, slug, label) => {
|
||
const isMissing = missing.has(slug);
|
||
return a({
|
||
href: isMissing ? `/wiki?filter=create&title=${encodeURIComponent(target)}${tribeId ? `&tribeId=${encodeURIComponent(tribeId)}` : ""}` : pageHref(slug, tribeId),
|
||
class: isMissing ? "wiki-link wiki-link-missing" : "wiki-link",
|
||
title: isMissing ? (i18n.wikiMissingLink || "Page does not exist yet") : label
|
||
}, label);
|
||
};
|
||
const paragraphs = String(body || "").replace(/\r\n/g, "\n").split(/\n{2,}/);
|
||
return div({ class: "wiki-body" },
|
||
...paragraphs.filter(par => par.trim()).map(par =>
|
||
p({ class: "wiki-paragraph" }, ...renderStyledText(par, { wikiLink, zoomImages: true }))
|
||
)
|
||
);
|
||
};
|
||
|
||
const diffLines = (oldText, newText) => {
|
||
const a = String(oldText || "").replace(/\r\n/g, "\n").split("\n");
|
||
const b = String(newText || "").replace(/\r\n/g, "\n").split("\n");
|
||
const n = a.length, m = b.length;
|
||
const lcs = Array.from({ length: n + 1 }, () => new Array(m + 1).fill(0));
|
||
for (let i = n - 1; i >= 0; i--) {
|
||
for (let j = m - 1; j >= 0; j--) {
|
||
lcs[i][j] = a[i] === b[j] ? lcs[i + 1][j + 1] + 1 : Math.max(lcs[i + 1][j], lcs[i][j + 1]);
|
||
}
|
||
}
|
||
const out = [];
|
||
let i = 0, j = 0;
|
||
while (i < n && j < m) {
|
||
if (a[i] === b[j]) { out.push({ type: "ctx", text: a[i] }); i++; j++; }
|
||
else if (lcs[i + 1][j] >= lcs[i][j + 1]) { out.push({ type: "del", text: a[i] }); i++; }
|
||
else { out.push({ type: "add", text: b[j] }); j++; }
|
||
}
|
||
while (i < n) { out.push({ type: "del", text: a[i++] }); }
|
||
while (j < m) { out.push({ type: "add", text: b[j++] }); }
|
||
return out;
|
||
};
|
||
|
||
const renderDiff = (oldText, newText) =>
|
||
div({ class: "wiki-diff" },
|
||
...diffLines(oldText, newText).map(l =>
|
||
div({ class: `wiki-diff-line wiki-diff-${l.type}` }, span({ class: "wiki-diff-sign" }, l.type === "add" ? "+" : l.type === "del" ? "−" : " "), span({ class: "wiki-diff-text" }, l.text || " "))
|
||
)
|
||
);
|
||
|
||
const reachChip = (page) =>
|
||
page.tribeId || page.encrypted
|
||
? null
|
||
: renderReachChip(!!page.clearnet, i18n, page.clearnet ? clearnetItemHref('wiki', page.title, page.id) : null);
|
||
|
||
const statusChip = (page) =>
|
||
renderStateChip(page.editPolicy === "author" ? "closed" : "open", "", page.editPolicy === "author" ? i18n.wikiStatusClosed : i18n.wikiStatusOpen);
|
||
|
||
const pageChips = (page, params = {}, { withStatus = true } = {}) => [
|
||
page.encrypted ? renderEncryptedChip(i18n) : null,
|
||
withStatus ? statusChip(page) : null,
|
||
page.versionCount > 1 ? renderStateChip("neutral", "", `${page.versionCount} ${i18n.wikiVersions || "versions"}`) : null,
|
||
page.isLinked ? renderStateChip("open", "", i18n.wikiLinkedChip || "Linked") : null
|
||
].filter(Boolean);
|
||
|
||
const renderTags = (tags) => (Array.isArray(tags) && tags.length)
|
||
? div({ class: "card-tags" }, ...tags.map(t => a({ href: `/search?query=%23${encodeURIComponent(t)}`, class: "tag-link" }, `#${t}`)))
|
||
: null;
|
||
|
||
const renderPageCard = (page, params = {}) => {
|
||
const origin = page.tribeOrigin || null;
|
||
const href = origin ? origin.href : pageHref(page.tribeId ? page.id : page.slug, page.tribeId);
|
||
return div({ class: "tribe-card wiki-card" },
|
||
div({ class: "card-header activity-card-header" },
|
||
span(),
|
||
renderContentActions(page.id, href, origin
|
||
? { author: page.author, reportTitle: page.title }
|
||
: { author: page.author, reportTitle: page.title, favKind: 'wiki', isFavorite: page.isFavorite, spread: (params.spreadMap && params.spreadMap.get(page.id)) || null, deleteAction: !page.tribeId && String(page.author) === String(userId) ? `/wiki/delete/${encodeURIComponent(page.id)}` : undefined })
|
||
),
|
||
div({ class: "tribe-card-body" },
|
||
page.image ? a({ href }, img({ loading: 'lazy', class: "wiki-card-cover", src: `/blob/${encodeURIComponent(page.image)}`, alt: page.title || "" })) : null,
|
||
div({ class: "shop-title-row" }, h2({ class: "tribe-card-title" }, a({ href }, page.title || "—"))),
|
||
div({ class: "card-chips-row" }, ...(origin ? [renderTribeOriginChip(origin)] : pageChips(page)), !origin && page.clearnet === true ? reachChip(page) : null, renderLicenseChip(page.license)),
|
||
origin && params.withBody && page.body ? renderWikiBody(page.body) : null
|
||
)
|
||
);
|
||
};
|
||
|
||
const renderFilters = (filter, q, params = {}, census = []) => {
|
||
const tribeId = params.tribeId || null;
|
||
const chipVisible = (mode) => {
|
||
if (mode === filter || mode === "all") return true;
|
||
if (mode === "mine") return census.some(p => String(p.author) === String(userId) || (p.versions || []).some(v => String(v.author) === String(userId)));
|
||
if (mode === "recent") return census.length > 0;
|
||
if (mode === "linked") return census.some(p => p.isLinked);
|
||
return true;
|
||
};
|
||
const labelOf = (mode) => String(i18n[`wikiFilter${mode.charAt(0).toUpperCase() + mode.slice(1)}`] || mode).toUpperCase();
|
||
return div({ class: "filters" },
|
||
form({ method: "GET", action: "/wiki", class: "ui-toolbar ui-toolbar--filters" },
|
||
tribeId ? input({ type: "hidden", name: "tribeId", value: tribeId }) : null,
|
||
...(params.emptyMod ? [] : [
|
||
...FILTERS.filter(chipVisible).map(mode => button({ type: "submit", name: "filter", value: mode, class: filter === mode ? "filter-btn active" : "filter-btn" }, labelOf(mode))),
|
||
...((census.length > 0 || filter === "changes") ? [button({ type: "submit", name: "filter", value: "changes", class: filter === "changes" ? "filter-btn active" : "filter-btn" }, String(i18n.wikiChanges || "Recent changes").toUpperCase())] : [])
|
||
]),
|
||
button({ type: "submit", name: "filter", value: "create", class: "create-button" }, i18n.wikiCreate)
|
||
)
|
||
);
|
||
};
|
||
|
||
const renderForm = (page, params = {}) => {
|
||
const tribeId = (page && page.tribeId) || params.tribeId || "";
|
||
const draft = params.draft || null;
|
||
const status = draft ? (String(draft.status || "OPEN").toUpperCase() === "CLOSED" ? "CLOSED" : "OPEN") : (page && page.editPolicy === "author" ? "CLOSED" : "OPEN");
|
||
const titleValue = draft ? draft.title : (page ? page.title : (params.title || ""));
|
||
const bodyValue = draft ? draft.body : (page ? page.body : "");
|
||
const tagsValue = draft ? draft.tags : (page ? page.tags.join(", ") : "");
|
||
const summaryValue = draft ? draft.summary : "";
|
||
const licenseValue = draft && draft.license ? draft.license : (page ? page.license : "");
|
||
const canLicense = !page || String(page.author) === String(userId);
|
||
const statusOptions = [
|
||
{ value: "OPEN", label: i18n.wikiStatusOpen },
|
||
{ value: "CLOSED", label: i18n.wikiStatusClosed }
|
||
];
|
||
return div({ class: "div-center audio-form" },
|
||
h2(page ? i18n.wikiUpdateSectionTitle : i18n.wikiCreateSectionTitle),
|
||
draft
|
||
? section({ class: "post-preview wiki-preview" },
|
||
div({ class: "preview-content" },
|
||
h2(i18n.messagePreview),
|
||
h3({ class: "wiki-page-title" }, titleValue || "—"),
|
||
renderWikiBody(bodyValue, { missing: [], tribeId: tribeId || null })
|
||
)
|
||
)
|
||
: null,
|
||
form({ method: "POST", action: page ? `/wiki/update/${encodeURIComponent(page.id)}` : "/wiki/create", enctype: "multipart/form-data" },
|
||
tribeId ? input({ type: "hidden", name: "tribeId", value: tribeId }) : null,
|
||
page ? input({ type: "hidden", name: "pageId", value: page.id }) : null,
|
||
params.returnTo ? input({ type: "hidden", name: "returnTo", value: params.returnTo }) : null,
|
||
label(i18n.wikiTitleLabel), br(),
|
||
input({ type: "text", name: "title", maxlength: "100", required: true, placeholder: i18n.wikiTitlePlaceholder, value: titleValue }), br(),
|
||
label(i18n.wikiBodyLabel), br(),
|
||
richTextarea({ name: "body", rows: 14, maxlength: "20000", placeholder: i18n.wikiBodyPlaceholder }, bodyValue), br(),
|
||
label(i18n.uploadMedia), br(),
|
||
input({ type: "file", name: "blob", accept: "image/*,video/*,audio/*,application/pdf,.torrent" }), br(), br(),
|
||
page ? [label(i18n.wikiSummaryLabel), br(), input({ type: "text", name: "summary", maxlength: "200", placeholder: i18n.wikiSummaryPlaceholder, value: summaryValue }), br()] : null,
|
||
page
|
||
? null
|
||
: [label(i18n.wikiStatusLabel), br(), select({ name: "status" }, ...statusOptions.map(o => option({ value: o.value, ...(o.value === status ? { selected: true } : {}) }, o.label))), br(), br()],
|
||
label(i18n.wikiTagsLabel), br(),
|
||
input({ type: "text", name: "tags", maxlength: "200", placeholder: i18n.wikiTagsPlaceholder, value: tagsValue }), br(),
|
||
canLicense ? renderLicenseSelect(licenseValue, i18n) : null,
|
||
!tribeId && canLicense ? renderClearnetSelector(draft ? draft.clearnet === true : !!(page && page.clearnet), i18n) : null,
|
||
br(),
|
||
button({ type: "submit", class: "filter-btn", formaction: "/wiki/preview", attrs: { formmethod: "POST" } }, i18n.wikiPreview),
|
||
" ",
|
||
button({ type: "submit", class: "create-button" }, page ? i18n.wikiUpdate : i18n.wikiCreate)
|
||
)
|
||
);
|
||
};
|
||
|
||
const renderHeader = (tribe = null) =>
|
||
div({ class: "tags-header module-header-line" },
|
||
h2(tribe ? `${i18n.wikiTitle} · ${tribe.title}` : i18n.wikiTitle),
|
||
p(i18n.wikiDescription)
|
||
);
|
||
|
||
exports.wikiView = async (pages, filter = "all", params = {}) => {
|
||
const list = Array.isArray(pages) ? pages : [];
|
||
const q = String(params.q || "").trim();
|
||
const census = Array.isArray(params.censusList) ? params.censusList : list;
|
||
const isForm = filter === "create" || filter === "edit";
|
||
const emptyMod = !isForm && census.length === 0 && !q;
|
||
return template(
|
||
i18n.wikiTitle,
|
||
section(
|
||
div({ class: "tags-header module-header-line" },
|
||
h2(params.tribe ? `${i18n.wikiTitle} · ${params.tribe.title}` : i18n.wikiTitle),
|
||
p(i18n.wikiDescription)
|
||
),
|
||
renderFilters(isForm ? "all" : filter, q, { ...params, emptyMod }, census)
|
||
),
|
||
section(
|
||
isForm
|
||
? renderForm(filter === "edit" ? params.page : null, params)
|
||
: [
|
||
emptyMod ? null : div({ class: "filters activity-filter-chips activity-toolbar-row" },
|
||
renderModuleStats(list.length),
|
||
form({ method: "GET", action: "/wiki", class: "filter-box" },
|
||
input({ type: "hidden", name: "filter", value: filter }),
|
||
params.tribeId ? input({ type: "hidden", name: "tribeId", value: params.tribeId }) : null,
|
||
input({ type: "text", name: "q", value: q, placeholder: i18n.wikiSearchPlaceholder, class: "filter-box__input" }),
|
||
div({ class: "filter-box__controls" }, button({ type: "submit", class: "filter-box__button" }, i18n.searchButton))
|
||
)
|
||
),
|
||
div({ class: "tribe-grid" },
|
||
list.length ? paged(list).map(pg => renderPageCard(pg, params)) : p(i18n.wikiNoPages)
|
||
)
|
||
]
|
||
)
|
||
);
|
||
};
|
||
|
||
exports.wikiChangesView = async (changes, params = {}) => {
|
||
const list = Array.isArray(changes) ? changes : [];
|
||
const census = Array.isArray(params.censusList) ? params.censusList : [];
|
||
return template(
|
||
i18n.wikiTitle,
|
||
section(renderHeader(params.tribe || null), renderFilters("changes", "", { ...params, emptyMod: census.length === 0 }, census)),
|
||
section(
|
||
div({ class: "tags-header" }, h2(i18n.wikiChanges)),
|
||
list.length
|
||
? div({ class: "wiki-changes" }, ...paged(list).map(c =>
|
||
div({ class: "card-section wiki-change" },
|
||
div({ class: "card-field" },
|
||
span({ class: "card-label" }, `#${c.index}`),
|
||
span({ class: "card-value" }, a({ href: `${pageHref(c.pageId, c.tribeId)}${c.tribeId ? "&" : "?"}version=${encodeURIComponent(c.versionKey)}` }, c.title || c.slug))
|
||
),
|
||
c.summary ? p({ class: "wiki-change-summary" }, c.summary.startsWith("restore:") ? i18n.wikiRestoredSummary : c.summary) : null,
|
||
p({ class: "card-footer" }, span({ class: "date-link" }, `${moment(c.createdAt).format("YYYY/MM/DD HH:mm")}`), userLink(c.author))
|
||
)
|
||
))
|
||
: div({ class: "no-content-box" }, p({ class: "no-content" }, i18n.wikiNoChanges))
|
||
)
|
||
);
|
||
};
|
||
|
||
const versionRow = (page, v, idx, current, tribeId) => {
|
||
const isCurrent = v.key === page.tipId;
|
||
const base = pageHref(page.tribeId ? page.id : page.slug, tribeId);
|
||
const sep = tribeId ? "&" : "?";
|
||
return div({ class: "card-section wiki-version" + (isCurrent ? " wiki-version-current" : "") },
|
||
div({ class: "card-field" },
|
||
span({ class: "card-label" }, `${i18n.wikiVersion} ${idx + 1}`),
|
||
isCurrent ? span({ class: "card-value" }, renderStateChip("mutuals", "", i18n.wikiCurrentVersion)) : span({ class: "card-value" })
|
||
),
|
||
v.summary ? [br(), p({ class: "wiki-change-summary" }, v.summary.startsWith("restore:") ? i18n.wikiRestoredSummary : v.summary), br()] : null,
|
||
div({ class: "tribe-side-actions wiki-version-actions" },
|
||
form({ method: "GET", action: base },
|
||
tribeId ? input({ type: "hidden", name: "tribeId", value: tribeId }) : null,
|
||
input({ type: "hidden", name: "version", value: v.key }),
|
||
button({ type: "submit", class: "update-btn" }, i18n.wikiViewVersion)),
|
||
idx > 0
|
||
? form({ method: "GET", action: base },
|
||
tribeId ? input({ type: "hidden", name: "tribeId", value: tribeId }) : null,
|
||
input({ type: "hidden", name: "diff", value: v.key }),
|
||
button({ type: "submit", class: "update-btn" }, i18n.wikiDiff))
|
||
: null,
|
||
!isCurrent && page.canEdit
|
||
? form({ method: "POST", action: `/wiki/restore/${encodeURIComponent(page.id)}` },
|
||
input({ type: "hidden", name: "version", value: v.key }),
|
||
tribeId ? input({ type: "hidden", name: "tribeId", value: tribeId }) : null,
|
||
button({ type: "submit", class: "update-btn" }, i18n.wikiRestore))
|
||
: null
|
||
),
|
||
p({ class: "card-footer" }, span({ class: "date-link" }, `${moment(v.createdAt).format("YYYY/MM/DD HH:mm")}`), userLink(v.author))
|
||
);
|
||
};
|
||
|
||
exports.wikiHistoryView = async (page, params = {}) => {
|
||
const tribeId = page.tribeId || null;
|
||
const versions = page.versions.slice().reverse();
|
||
const census = Array.isArray(params.censusList) ? params.censusList : [];
|
||
return template(
|
||
page.title,
|
||
section(renderHeader(params.tribe || null), renderFilters("all", "", { ...params, emptyMod: census.length === 0 }, census)),
|
||
section(
|
||
div({ class: "tags-header" }, h2(i18n.wikiHistory)),
|
||
div({ class: "wiki-history" }, ...versions.map((v, i) => versionRow(page, v, page.versions.length - 1 - i, page.tipId, tribeId)))
|
||
)
|
||
);
|
||
};
|
||
|
||
exports.wikiPageView = async (page, params = {}) => {
|
||
const tribeId = page.tribeId || null;
|
||
const base = pageHref(tribeId ? page.id : page.slug, tribeId);
|
||
const sep = tribeId ? "&" : "?";
|
||
const version = params.version || null;
|
||
const diffVersion = params.diff || null;
|
||
const shownTitle = version ? version.title : page.title;
|
||
const shownBody = version ? version.body : page.body;
|
||
const census = Array.isArray(params.censusList) ? params.censusList : [];
|
||
const subscriptionNodes = params.subscription
|
||
? renderSubscriptionBox({ target: page.id, scope: "wiki", subscribed: params.subscription.subscribed, count: params.subscription.count, isOwner: page.isOwner, returnTo: base, inline: true, compact: true })
|
||
: null;
|
||
const barChips = [reachChip(page), statusChip(page)].filter(Boolean);
|
||
const actions = div({ class: "tribe-side-actions wiki-actions-top" },
|
||
span({ class: "wiki-actions-left" }, ...barChips),
|
||
page.isOwner && !tribeId && !page.encrypted ? renderClearnetSwitch("wiki", page.rootId || page.id, !!page.clearnet) : null,
|
||
...(subscriptionNodes && subscriptionNodes.length ? subscriptionNodes : []),
|
||
page.canEdit && !version
|
||
? form({ method: "GET", action: "/wiki" },
|
||
input({ type: "hidden", name: "filter", value: "edit" }),
|
||
input({ type: "hidden", name: "id", value: page.id }),
|
||
tribeId ? input({ type: "hidden", name: "tribeId", value: tribeId }) : null,
|
||
button({ type: "submit", class: "update-btn" }, i18n.wikiEdit))
|
||
: null,
|
||
form({ method: "GET", action: `/wiki/${encodeURIComponent(page.id)}/history` },
|
||
tribeId ? input({ type: "hidden", name: "tribeId", value: tribeId }) : null,
|
||
button({ type: "submit", class: "update-btn" }, `${i18n.wikiHistory} (${page.versionCount})`)),
|
||
form({ method: "GET", action: `/wiki/${encodeURIComponent(page.id)}/pdf` },
|
||
button({ type: "submit", class: "update-btn" }, i18n.generatePdf)),
|
||
page.isOwner && tribeId
|
||
? form({ method: "POST", action: `/wiki/delete/${encodeURIComponent(page.id)}` }, input({ type: "hidden", name: "tribeId", value: tribeId }), button({ type: "submit", class: "delete-btn" }, i18n.wikiDelete))
|
||
: null
|
||
);
|
||
let diffBlock = null;
|
||
if (diffVersion) {
|
||
const idx = page.versions.findIndex(v => v.key === diffVersion.key);
|
||
const prev = idx > 0 ? page.versions[idx - 1] : null;
|
||
diffBlock = div({ class: "card-section" },
|
||
h3(`${i18n.wikiDiff}: ${i18n.wikiVersion} ${idx} → ${idx + 1}`),
|
||
renderDiff(prev ? prev.body : "", diffVersion.body)
|
||
);
|
||
}
|
||
return template(
|
||
page.title,
|
||
section(renderHeader(params.tribe || null), renderFilters("all", "", { ...params, emptyMod: census.length === 0 }, census)),
|
||
section(
|
||
div({ class: "trending-card wiki-page" },
|
||
div({ class: "card-header activity-card-header" },
|
||
span(),
|
||
renderContentActions(page.id, base, { author: page.author, reportTitle: page.title, favKind: 'wiki', isFavorite: page.isFavorite, spread: params.spread || null, deleteAction: page.isOwner && !tribeId ? `/wiki/delete/${encodeURIComponent(page.id)}` : undefined })
|
||
),
|
||
div({ class: "card-section" },
|
||
actions,
|
||
div({ class: "shop-title-row" }, h2({ class: "wiki-page-title" }, shownTitle), renderLicenseChip(page.license)),
|
||
(() => { const rest = pageChips(page, params, { withStatus: false }); return rest.length ? div({ class: "card-chips-row" }, ...rest) : null; })(),
|
||
version ? p({ class: "wiki-version-notice" }, `${i18n.wikiViewingVersion} (${moment(version.createdAt).format("YYYY/MM/DD HH:mm")}) — `, a({ href: base }, i18n.wikiBackToPage)) : null,
|
||
diffBlock || renderWikiBody(shownBody, { missing: page.missingLinks, tribeId }),
|
||
renderTags(page.tags),
|
||
renderCardMetaRow(p({ class: "card-footer" },
|
||
span({ class: "date-link" }, `${moment(page.createdAt).format("YYYY/MM/DD HH:mm")}`),
|
||
userLink(page.author)
|
||
))
|
||
),
|
||
),
|
||
div({ class: "card-section wiki-backlinks" },
|
||
h3(i18n.wikiLinkedPages),
|
||
page.linkedPages && page.linkedPages.length
|
||
? ul(...page.linkedPages.map(b => li(a({ href: pageHref(b.tribeId ? b.id : b.slug, b.tribeId) }, b.title))))
|
||
: p(i18n.wikiNoLinkedPages)
|
||
)
|
||
)
|
||
);
|
||
};
|
||
|
||
exports.renderTribeWikiSection = (tribe, pages, toolbar = null, wrap = (pg, card) => card) => {
|
||
const items = Array.isArray(pages) ? pages : [];
|
||
const createBtn = form({ method: "GET", action: "/wiki" },
|
||
input({ type: "hidden", name: "filter", value: "create" }),
|
||
input({ type: "hidden", name: "tribeId", value: tribe.id }),
|
||
button({ type: "submit", class: "create-button" }, i18n.tribeWikiCreate));
|
||
const header = toolbar || div({ class: "tribe-content-header" }, h2(i18n.tribeSectionWiki), createBtn);
|
||
if (!items.length) return div({ class: "tribe-content-list" }, header, div({ class: "no-content-box" }, p(i18n.tribeWikiEmpty)));
|
||
return div({ class: "tribe-content-list" },
|
||
header,
|
||
div({ class: "tribe-grid" }, ...paged(items).map(pg => wrap(pg, renderPageCard(pg, { tribeId: tribe.id, withBody: true }))))
|
||
);
|
||
};
|
||
|
||
exports.renderWikiBody = renderWikiBody;
|
||
exports.diffLines = diffLines;
|