upstream: integrar Oasis 1.3.1
Base del merge a tres bandas: git 0.9.5 de epsylon, esta rama y el src de la
APK oficial 1.3.1 (la variante movil: OASIS_MOBILE, regex sin \p{}, audio y
video de Android). Corre en el mismo nodejs-mobile 18.20.4 que ya usabamos.
Se conserva de la rama: Karvan, identidades y multicuenta, topbar y barra
inferior, borrado de EXIF sin sharp, filtro hot del foro, RTC sin STUN y los
modulos apagados en movil (wallet, banking, torrents).
Se toma de upstream lo que ya hace de serie: respuesta citada en chats, ssb-lan
en movil, configuracion en ~/.ssb/oasis (sobrevive a reinstalar el backend).
El asistente de bienvenida deja elegir workflow tambien en movil.
This commit is contained in:
parent
8d838dd8b1
commit
c332afd6ea
265 changed files with 80970 additions and 29167 deletions
|
|
@ -1,20 +1,21 @@
|
|||
const { div, h2, p, section, button, form, input, select, option, a, br, textarea, label, span, table, tr, td, img, video } = require("../server/node_modules/hyperaxe");
|
||||
const { renderCommentsSection: renderSharedCommentsSection } = require("./comments_view");
|
||||
const moment = require("../server/node_modules/moment");
|
||||
const { template, i18n, renderOpinionsVoting, renderEngagement, userLink, renderStateChip, renderPrivacyChip, renderLifespanChip, renderEcoTax, renderSpreadButton, renderSpreadEditWarning, renderContentActions, renderDocumentActions } = require("./main_views");
|
||||
const { renderPhotoGallery, renderGalleryFields, imagesOf } = require("./gallery_view");
|
||||
const { template, i18n, renderOpinionsVoting, renderEngagement, userLink, renderStateChip, renderPrivacyChip, renderLifespanChip, renderEcoTax, renderSpreadButton, renderSpreadEditWarning, renderContentActions, renderDocumentActions, renderModuleStatsBy, moduleIsEmpty, contentDeleteAction, paged, renderCreatedRows } = require("./main_views");
|
||||
const { renderPhotoGallery, renderGalleryFields, imagesOf, renderZoomableImage } = require("./gallery_view");
|
||||
const { renderTribeOriginChip } = require("./clearnet_view");
|
||||
const { config } = require("../server/SSB_server.js");
|
||||
const { renderUrl } = require("../backend/renderUrl");
|
||||
const { renderStyledText } = require("../backend/renderStyledText");
|
||||
|
||||
const renderTaskMediaBlob = (value, attrs = {}) => {
|
||||
if (!value) return null;
|
||||
const s = String(value).trim();
|
||||
if (!s) return null;
|
||||
if (s.startsWith('&')) return img({ src: `/blob/${encodeURIComponent(s)}`, ...attrs });
|
||||
if (s.startsWith('&')) return renderZoomableImage(`/blob/${encodeURIComponent(s)}`, { imgClass: attrs.class || 'post-image', alt: attrs.alt || '' });
|
||||
const mImg = s.match(/!\[[^\]]*\]\(\s*(&[^)\s]+\.sha256)\s*\)/);
|
||||
if (mImg) return img({ src: `/blob/${encodeURIComponent(mImg[1])}`, class: attrs.class || 'post-image' });
|
||||
if (mImg) return renderZoomableImage(`/blob/${encodeURIComponent(mImg[1])}`, { imgClass: attrs.class || 'post-image', alt: attrs.alt || '' });
|
||||
const mVideo = s.match(/\[video:[^\]]*\]\(\s*(&[^)\s]+\.sha256)\s*\)/);
|
||||
if (mVideo) return video({ controls: true, class: attrs.class || 'post-video', src: `/blob/${encodeURIComponent(mVideo[1])}` });
|
||||
if (mVideo) return video({ controls: true, class: attrs.class || 'post-video', src: `/blob/${encodeURIComponent(mVideo[1])}`, preload: 'metadata' });
|
||||
return null;
|
||||
};
|
||||
|
||||
|
|
@ -54,21 +55,16 @@ const renderTaskOwnerActions = (task, returnTo) => {
|
|||
input({ type: "hidden", name: "returnTo", value: returnTo }),
|
||||
button({ type: "submit", class: "update-btn" }, i18n.taskUpdateButton)
|
||||
),
|
||||
form(
|
||||
{ method: "POST", action: `/tasks/delete/${encodeURIComponent(task.id)}` },
|
||||
input({ type: "hidden", name: "returnTo", value: returnTo }),
|
||||
button({ type: "submit", class: "delete-btn" }, i18n.taskDeleteButton)
|
||||
),
|
||||
];
|
||||
};
|
||||
|
||||
const renderTaskStatusRow = (task, returnTo) => {
|
||||
const renderTaskStatusRow = exports.renderTaskStatusRow = (task, returnTo, action = null) => {
|
||||
const st = normalizeStatus(task.status || "OPEN");
|
||||
return div({ class: "tribe-side-actions housing-status-row" },
|
||||
span({ class: "card-label" }, `${i18n.taskStatus}: `),
|
||||
renderStateChip(st === "CLOSED" ? "hidden" : "mutuals", st === "CLOSED" ? "🔒" : "👁", statusLabel(task.status)),
|
||||
form(
|
||||
{ method: "POST", action: `/tasks/status/${encodeURIComponent(task.id)}`, class: "project-control-form project-control-form--status" },
|
||||
{ method: "POST", action: action || `/tasks/status/${encodeURIComponent(task.id)}`, class: "project-control-form project-control-form--status" },
|
||||
input({ type: "hidden", name: "returnTo", value: returnTo }),
|
||||
select(
|
||||
{ name: "status", class: "project-control-select" },
|
||||
|
|
@ -81,7 +77,7 @@ const renderTaskStatusRow = (task, returnTo) => {
|
|||
);
|
||||
};
|
||||
|
||||
const renderTaskAssignAction = (task, isAssignedToMe, returnTo) => {
|
||||
const renderTaskAssignAction = exports.renderTaskAssignAction = (task, isAssignedToMe, returnTo, action = null) => {
|
||||
const st = normalizeStatus(task.status || "OPEN");
|
||||
if (st === "CLOSED") return null;
|
||||
return [
|
||||
|
|
@ -89,7 +85,7 @@ const renderTaskAssignAction = (task, isAssignedToMe, returnTo) => {
|
|||
renderStateChip(isAssignedToMe ? "mutuals" : "whole", isAssignedToMe ? "👤" : "○",
|
||||
String(isAssignedToMe ? i18n.taskAssignedChip : i18n.taskUnassignedChip).toUpperCase()),
|
||||
form(
|
||||
{ method: "POST", action: `/tasks/assign/${encodeURIComponent(task.id)}`, class: "project-control-form" },
|
||||
{ method: "POST", action: action || `/tasks/assign/${encodeURIComponent(task.id)}`, class: "project-control-form" },
|
||||
input({ type: "hidden", name: "returnTo", value: returnTo }),
|
||||
button({ type: "submit", class: "status-btn project-control-btn" }, isAssignedToMe ? i18n.taskUnassignButton : i18n.taskAssignButton)
|
||||
)
|
||||
|
|
@ -116,11 +112,12 @@ const renderTaskPriorityChip = (priority) => {
|
|||
const p = String(priority || "").toUpperCase();
|
||||
if (!p) return null;
|
||||
const variant =
|
||||
p === "URGENT" ? "closed" :
|
||||
p === "URGENT" || p === "CRITICAL" ? "closed" :
|
||||
p === "HIGH" ? "lifespan-orange" :
|
||||
p === "MEDIUM" ? "whole" :
|
||||
"mutuals";
|
||||
const localized =
|
||||
p === "CRITICAL" ? i18n.tribePriorityCritical :
|
||||
p === "URGENT" ? i18n.taskPriorityUrgent :
|
||||
p === "HIGH" ? i18n.taskPriorityHigh :
|
||||
p === "MEDIUM" ? i18n.taskPriorityMedium :
|
||||
|
|
@ -128,12 +125,15 @@ const renderTaskPriorityChip = (priority) => {
|
|||
return renderStateChip(variant, "⚑", localized || p);
|
||||
};
|
||||
|
||||
const renderTaskItem = (task, filter, spreadInfo) => {
|
||||
const renderTaskItem = exports.renderTaskItem = (task, filter, spreadInfo, opts = {}) => {
|
||||
const currentFilter = filter || "all";
|
||||
const assignees = safeArray(task.assignees);
|
||||
const isPrivate = String(task.isPublic || "").toUpperCase() === "PRIVATE";
|
||||
const isAuthor = String(task.author) === String(userId);
|
||||
const origin = task.tribeOrigin || null;
|
||||
const href = opts.href !== undefined ? opts.href : (origin ? origin.href : `/tasks/${encodeURIComponent(task.id)}`);
|
||||
|
||||
const cover = imagesOf(task)[0]
|
||||
const cover = origin ? null : imagesOf(task)[0]
|
||||
const heroNode = cover
|
||||
? div({ class: "tribe-card-image-wrapper" },
|
||||
a({ href: `/tasks/${encodeURIComponent(task.id)}` },
|
||||
|
|
@ -149,36 +149,49 @@ const renderTaskItem = (task, filter, spreadInfo) => {
|
|||
: null;
|
||||
|
||||
const chips = [
|
||||
renderTaskStatusChip(task.status),
|
||||
isPrivate ? renderPrivacyChip(true, i18n) : null,
|
||||
renderTaskStatusChip(task.status),
|
||||
renderTaskPriorityChip(task.priority),
|
||||
renderLifespanChip(task.lifetime, i18n)
|
||||
renderLifespanChip(task.lifetime, i18n),
|
||||
origin ? renderTribeOriginChip(origin) : null,
|
||||
...(Array.isArray(opts.extraChips) ? opts.extraChips : [])
|
||||
].filter(Boolean);
|
||||
|
||||
const start = task.startTime ? moment(task.startTime).format("YYYY/MM/DD HH:mm") : "";
|
||||
const end = task.endTime ? moment(task.endTime).format("YYYY/MM/DD HH:mm") : "";
|
||||
const headerActions = opts.headerActions !== undefined
|
||||
? opts.headerActions
|
||||
: origin ? null : renderContentActions(task.id, `/tasks/${encodeURIComponent(task.id)}`, { spread: spreadInfo || null, author: task.author, favKind: 'tasks', isFavorite: task.isFavorite, reportTitle: task.title, returnTo: `/tasks?filter=${encodeURIComponent(currentFilter)}`, deleteAction: isAuthor ? contentDeleteAction('task', task.id) : undefined });
|
||||
|
||||
return div({ class: "tribe-card task-card" },
|
||||
div({ class: "card-header activity-card-header" },
|
||||
span(),
|
||||
renderContentActions(task.id, `/tasks/${encodeURIComponent(task.id)}`, { spread: spreadInfo || null, author: task.author, favKind: 'tasks', isFavorite: task.isFavorite, reportTitle: task.title })
|
||||
),
|
||||
return div({ class: "tribe-card task-card" + (isAuthor ? " own-content" : "") },
|
||||
headerActions ? div({ class: "card-header activity-card-header" }, span(), headerActions) : null,
|
||||
heroNode,
|
||||
div({ class: "tribe-card-body" },
|
||||
div({ class: "shop-title-row" },
|
||||
h2({ class: "tribe-card-title" },
|
||||
a({ href: `/tasks/${encodeURIComponent(task.id)}` }, task.title || i18n.tasksTitle)
|
||||
href ? a({ href }, task.title || i18n.tasksTitle) : (task.title || i18n.tasksTitle)
|
||||
)
|
||||
),
|
||||
chips.length ? div({ class: "card-chips-row" }, ...chips) : null,
|
||||
(start || end) ? p({ class: "card-date-highlight" }, start && end ? `${start} → ${end}` : (start || end)) : null,
|
||||
div({ class: "tribe-card-members" },
|
||||
origin ? null : div({ class: "tribe-card-members" },
|
||||
span({ class: "tribe-members-count" }, `${i18n.taskAssignedTo}: ${assignees.length}`)
|
||||
)
|
||||
),
|
||||
...(Array.isArray(opts.bodyExtra) ? opts.bodyExtra.filter(Boolean) : [])
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
const taskChipFor = (currentFilter, visible) => (mode) => {
|
||||
if (mode === currentFilter) return true;
|
||||
if (!Array.isArray(visible)) return true;
|
||||
if (mode === "mine") return visible.some((t) => t.author === userId);
|
||||
if (mode === "recent") return visible.length > 0;
|
||||
if (mode === "assigned") return visible.some((t) => safeArray(t.assignees).includes(userId));
|
||||
if (mode === "open") return visible.some((t) => normalizeStatus(t.status) === "OPEN");
|
||||
if (mode === "in-progress") return visible.some((t) => normalizeStatus(t.status) === "IN-PROGRESS");
|
||||
if (mode === "closed") return visible.some((t) => normalizeStatus(t.status) === "CLOSED");
|
||||
if (mode.indexOf("priority-") === 0) { const pr = mode.slice(9).toUpperCase(); return visible.some((t) => String(t.priority).toUpperCase() === pr); }
|
||||
return true;
|
||||
};
|
||||
|
||||
exports.taskView = async (tasks, filter, taskId, returnTo, params = {}) => {
|
||||
const list = Array.isArray(tasks) ? tasks : [tasks];
|
||||
const currentFilter = filter || "all";
|
||||
|
|
@ -195,7 +208,8 @@ exports.taskView = async (tasks, filter, taskId, returnTo, params = {}) => {
|
|||
const visible = list.filter(canSee);
|
||||
|
||||
let filtered;
|
||||
if (currentFilter === "mine") filtered = visible.filter((t) => t.author === userId);
|
||||
if (currentFilter === "recent") filtered = visible.filter((t) => (Date.parse(t.createdAt || "") || 0) >= Date.now() - 86400000);
|
||||
else if (currentFilter === "mine") filtered = visible.filter((t) => t.author === userId);
|
||||
else if (currentFilter === "assigned") filtered = visible.filter((t) => safeArray(t.assignees).includes(userId));
|
||||
else if (currentFilter === "open") filtered = visible.filter((t) => normalizeStatus(t.status) === "OPEN");
|
||||
else if (currentFilter === "in-progress") filtered = visible.filter((t) => normalizeStatus(t.status) === "IN-PROGRESS");
|
||||
|
|
@ -216,12 +230,14 @@ exports.taskView = async (tasks, filter, taskId, returnTo, params = {}) => {
|
|||
const ret = typeof returnTo === "string" && returnTo.startsWith("/tasks")
|
||||
? returnTo
|
||||
: "/tasks?filter=mine";
|
||||
const emptyMod = moduleIsEmpty(filtered, currentFilter, "all", params.q);
|
||||
const taskChipVisible = taskChipFor(currentFilter, visible);
|
||||
|
||||
return template(
|
||||
title,
|
||||
section(
|
||||
div(
|
||||
{ class: "tags-header" },
|
||||
{ class: "tags-header module-header-line" },
|
||||
h2(i18n.tasksTitle),
|
||||
p(i18n.tasksDescription)
|
||||
),
|
||||
|
|
@ -229,22 +245,26 @@ exports.taskView = async (tasks, filter, taskId, returnTo, params = {}) => {
|
|||
{ class: "filters" },
|
||||
form(
|
||||
{ method: "GET", action: "/tasks" },
|
||||
...(emptyMod ? [] : [
|
||||
button({ type: "submit", name: "filter", value: "all", class: currentFilter === "all" ? "filter-btn active" : "filter-btn" }, String(i18n.taskFilterAll).toUpperCase()),
|
||||
button({ type: "submit", name: "filter", value: "mine", class: currentFilter === "mine" ? "filter-btn active" : "filter-btn" }, String(i18n.taskFilterMine).toUpperCase()),
|
||||
button({ type: "submit", name: "filter", value: "assigned", class: currentFilter === "assigned" ? "filter-btn active" : "filter-btn" }, String(i18n.taskFilterAssigned).toUpperCase()),
|
||||
button({ type: "submit", name: "filter", value: "open", class: currentFilter === "open" ? "filter-btn active" : "filter-btn" }, String(i18n.taskFilterOpen).toUpperCase()),
|
||||
button({ type: "submit", name: "filter", value: "in-progress", class: currentFilter === "in-progress" ? "filter-btn active" : "filter-btn" }, String(i18n.taskFilterInProgress).toUpperCase()),
|
||||
button({ type: "submit", name: "filter", value: "closed", class: currentFilter === "closed" ? "filter-btn active" : "filter-btn" }, String(i18n.taskFilterClosed).toUpperCase()),
|
||||
button({ type: "submit", name: "filter", value: "priority-low", class: currentFilter === "priority-low" ? "filter-btn active" : "filter-btn" }, String(i18n.taskFilterLow).toUpperCase()),
|
||||
button({ type: "submit", name: "filter", value: "priority-medium", class: currentFilter === "priority-medium" ? "filter-btn active" : "filter-btn" }, String(i18n.taskFilterMedium).toUpperCase()),
|
||||
button({ type: "submit", name: "filter", value: "priority-high", class: currentFilter === "priority-high" ? "filter-btn active" : "filter-btn" }, String(i18n.taskFilterHigh).toUpperCase()),
|
||||
button({ type: "submit", name: "filter", value: "priority-urgent", class: currentFilter === "priority-urgent" ? "filter-btn active" : "filter-btn" }, String(i18n.taskFilterUrgent).toUpperCase()),
|
||||
...(taskChipVisible("recent") ? [button({ type: "submit", name: "filter", value: "recent", class: currentFilter === "recent" ? "filter-btn active" : "filter-btn" }, String(i18n.taskFilterRecent).toUpperCase())] : []),
|
||||
...(taskChipVisible("mine") ? [button({ type: "submit", name: "filter", value: "mine", class: currentFilter === "mine" ? "filter-btn active" : "filter-btn" }, String(i18n.taskFilterMine).toUpperCase())] : []),
|
||||
...(taskChipVisible("assigned") ? [button({ type: "submit", name: "filter", value: "assigned", class: currentFilter === "assigned" ? "filter-btn active" : "filter-btn" }, String(i18n.taskFilterAssigned).toUpperCase())] : []),
|
||||
...(taskChipVisible("open") ? [button({ type: "submit", name: "filter", value: "open", class: currentFilter === "open" ? "filter-btn active" : "filter-btn" }, String(i18n.taskFilterOpen).toUpperCase())] : []),
|
||||
...(taskChipVisible("in-progress") ? [button({ type: "submit", name: "filter", value: "in-progress", class: currentFilter === "in-progress" ? "filter-btn active" : "filter-btn" }, String(i18n.taskFilterInProgress).toUpperCase())] : []),
|
||||
...(taskChipVisible("closed") ? [button({ type: "submit", name: "filter", value: "closed", class: currentFilter === "closed" ? "filter-btn active" : "filter-btn" }, String(i18n.taskFilterClosed).toUpperCase())] : []),
|
||||
...(taskChipVisible("priority-low") ? [button({ type: "submit", name: "filter", value: "priority-low", class: currentFilter === "priority-low" ? "filter-btn active" : "filter-btn" }, String(i18n.taskFilterLow).toUpperCase())] : []),
|
||||
...(taskChipVisible("priority-medium") ? [button({ type: "submit", name: "filter", value: "priority-medium", class: currentFilter === "priority-medium" ? "filter-btn active" : "filter-btn" }, String(i18n.taskFilterMedium).toUpperCase())] : []),
|
||||
...(taskChipVisible("priority-high") ? [button({ type: "submit", name: "filter", value: "priority-high", class: currentFilter === "priority-high" ? "filter-btn active" : "filter-btn" }, String(i18n.taskFilterHigh).toUpperCase())] : []),
|
||||
...(taskChipVisible("priority-urgent") ? [button({ type: "submit", name: "filter", value: "priority-urgent", class: currentFilter === "priority-urgent" ? "filter-btn active" : "filter-btn" }, String(i18n.taskFilterUrgent).toUpperCase())] : []),
|
||||
]),
|
||||
button({ type: "submit", name: "filter", value: "create", class: "create-button" }, i18n.taskCreateButton)
|
||||
)
|
||||
),
|
||||
currentFilter === "edit" || currentFilter === "create"
|
||||
? null
|
||||
: div({ class: "filters" },
|
||||
: emptyMod ? null : div({ class: "filters activity-filter-chips activity-toolbar-row" },
|
||||
renderModuleStatsBy(filtered, t => normalizeStatus(t.status || 'OPEN'), [{ value: 'OPEN', label: i18n.taskStatusOpen }, { value: 'IN-PROGRESS', label: i18n.taskStatusInProgress }, { value: 'CLOSED', label: i18n.taskStatusClosed }]),
|
||||
form({ method: "GET", action: "/tasks", class: "filter-box" },
|
||||
input({ type: "hidden", name: "filter", value: currentFilter }),
|
||||
input({ type: "text", name: "q", value: params.q || "", placeholder: i18n.taskSearchPlaceholder, class: "filter-box__input" }),
|
||||
|
|
@ -265,7 +285,7 @@ exports.taskView = async (tasks, filter, taskId, returnTo, params = {}) => {
|
|||
label(i18n.taskTitleLabel), br(),
|
||||
input({ type: "text", name: "title", maxlength: "100", required: true, value: formData.title || params.prefillTitle || "" }), br(),
|
||||
label(i18n.taskDescriptionLabel), br(),
|
||||
textarea({ name: "description", required: true, placeholder: i18n.taskDescriptionPlaceholder, rows: "4" }, formData.description || params.prefillDescription || ""), br(),
|
||||
textarea({ maxlength: "5000", name: "description", required: true, placeholder: i18n.taskDescriptionPlaceholder, rows: "4" }, formData.description || params.prefillDescription || ""), br(),
|
||||
...renderGalleryFields(formData, currentFilter === "edit"),
|
||||
br(),
|
||||
label(i18n.taskStartTimeLabel), br(),
|
||||
|
|
@ -273,7 +293,7 @@ exports.taskView = async (tasks, filter, taskId, returnTo, params = {}) => {
|
|||
type: "datetime-local",
|
||||
name: "startTime",
|
||||
required: true,
|
||||
min: currentFilter === "create" ? minCreate : undefined,
|
||||
min: minCreate,
|
||||
value: formData.startTime ? moment(formData.startTime).format("YYYY-MM-DDTHH:mm") : ""
|
||||
}), br(), br(),
|
||||
label(i18n.taskEndTimeLabel), br(),
|
||||
|
|
@ -281,7 +301,7 @@ exports.taskView = async (tasks, filter, taskId, returnTo, params = {}) => {
|
|||
type: "datetime-local",
|
||||
name: "endTime",
|
||||
required: true,
|
||||
min: currentFilter === "create" ? minCreate : undefined,
|
||||
min: minCreate,
|
||||
value: formData.endTime ? moment(formData.endTime).format("YYYY-MM-DDTHH:mm") : ""
|
||||
}), br(), br(),
|
||||
label(i18n.taskPriorityLabel), br(),
|
||||
|
|
@ -306,13 +326,14 @@ exports.taskView = async (tasks, filter, taskId, returnTo, params = {}) => {
|
|||
)
|
||||
)
|
||||
: filtered.length > 0
|
||||
? div({ class: "jobs-grid" }, filtered.map((t) => renderTaskItem(t, currentFilter, params.spreadMap && params.spreadMap.get(t.id))))
|
||||
: p(i18n.notasks)
|
||||
? div({ class: "jobs-grid" }, paged(filtered).map((t) => renderTaskItem(t, currentFilter, params.spreadMap && params.spreadMap.get(t.id))))
|
||||
: div({ class: "no-content-box" }, p(i18n.notasks))
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
exports.singleTaskView = async (task, filter, comments = [], params = {}) => {
|
||||
const taskChipVisible = (mode) => taskChipFor(currentFilter, Array.isArray(params.censusList) ? params.censusList : null)(mode);
|
||||
const currentFilter = filter || "all";
|
||||
const assignees = safeArray(task.assignees);
|
||||
const commentCount = typeof task.commentCount === "number" ? task.commentCount : 0;
|
||||
|
|
@ -326,15 +347,16 @@ exports.singleTaskView = async (task, filter, comments = [], params = {}) => {
|
|||
form(
|
||||
{ method: "GET", action: "/tasks" },
|
||||
button({ type: "submit", name: "filter", value: "all", class: currentFilter === "all" ? "filter-btn active" : "filter-btn" }, String(i18n.taskFilterAll).toUpperCase()),
|
||||
button({ type: "submit", name: "filter", value: "mine", class: currentFilter === "mine" ? "filter-btn active" : "filter-btn" }, String(i18n.taskFilterMine).toUpperCase()),
|
||||
button({ type: "submit", name: "filter", value: "assigned", class: currentFilter === "assigned" ? "filter-btn active" : "filter-btn" }, String(i18n.taskFilterAssigned).toUpperCase()),
|
||||
button({ type: "submit", name: "filter", value: "open", class: currentFilter === "open" ? "filter-btn active" : "filter-btn" }, String(i18n.taskFilterOpen).toUpperCase()),
|
||||
button({ type: "submit", name: "filter", value: "in-progress", class: currentFilter === "in-progress" ? "filter-btn active" : "filter-btn" }, String(i18n.taskFilterInProgress).toUpperCase()),
|
||||
button({ type: "submit", name: "filter", value: "closed", class: currentFilter === "closed" ? "filter-btn active" : "filter-btn" }, String(i18n.taskFilterClosed).toUpperCase()),
|
||||
button({ type: "submit", name: "filter", value: "priority-low", class: currentFilter === "priority-low" ? "filter-btn active" : "filter-btn" }, String(i18n.taskFilterLow).toUpperCase()),
|
||||
button({ type: "submit", name: "filter", value: "priority-medium", class: currentFilter === "priority-medium" ? "filter-btn active" : "filter-btn" }, String(i18n.taskFilterMedium).toUpperCase()),
|
||||
button({ type: "submit", name: "filter", value: "priority-high", class: currentFilter === "priority-high" ? "filter-btn active" : "filter-btn" }, String(i18n.taskFilterHigh).toUpperCase()),
|
||||
button({ type: "submit", name: "filter", value: "priority-urgent", class: currentFilter === "priority-urgent" ? "filter-btn active" : "filter-btn" }, String(i18n.taskFilterUrgent).toUpperCase()),
|
||||
...(taskChipVisible("recent") ? [button({ type: "submit", name: "filter", value: "recent", class: currentFilter === "recent" ? "filter-btn active" : "filter-btn" }, String(i18n.taskFilterRecent).toUpperCase())] : []),
|
||||
...(taskChipVisible("mine") ? [button({ type: "submit", name: "filter", value: "mine", class: currentFilter === "mine" ? "filter-btn active" : "filter-btn" }, String(i18n.taskFilterMine).toUpperCase())] : []),
|
||||
...(taskChipVisible("assigned") ? [button({ type: "submit", name: "filter", value: "assigned", class: currentFilter === "assigned" ? "filter-btn active" : "filter-btn" }, String(i18n.taskFilterAssigned).toUpperCase())] : []),
|
||||
...(taskChipVisible("open") ? [button({ type: "submit", name: "filter", value: "open", class: currentFilter === "open" ? "filter-btn active" : "filter-btn" }, String(i18n.taskFilterOpen).toUpperCase())] : []),
|
||||
...(taskChipVisible("in-progress") ? [button({ type: "submit", name: "filter", value: "in-progress", class: currentFilter === "in-progress" ? "filter-btn active" : "filter-btn" }, String(i18n.taskFilterInProgress).toUpperCase())] : []),
|
||||
...(taskChipVisible("closed") ? [button({ type: "submit", name: "filter", value: "closed", class: currentFilter === "closed" ? "filter-btn active" : "filter-btn" }, String(i18n.taskFilterClosed).toUpperCase())] : []),
|
||||
...(taskChipVisible("priority-low") ? [button({ type: "submit", name: "filter", value: "priority-low", class: currentFilter === "priority-low" ? "filter-btn active" : "filter-btn" }, String(i18n.taskFilterLow).toUpperCase())] : []),
|
||||
...(taskChipVisible("priority-medium") ? [button({ type: "submit", name: "filter", value: "priority-medium", class: currentFilter === "priority-medium" ? "filter-btn active" : "filter-btn" }, String(i18n.taskFilterMedium).toUpperCase())] : []),
|
||||
...(taskChipVisible("priority-high") ? [button({ type: "submit", name: "filter", value: "priority-high", class: currentFilter === "priority-high" ? "filter-btn active" : "filter-btn" }, String(i18n.taskFilterHigh).toUpperCase())] : []),
|
||||
...(taskChipVisible("priority-urgent") ? [button({ type: "submit", name: "filter", value: "priority-urgent", class: currentFilter === "priority-urgent" ? "filter-btn active" : "filter-btn" }, String(i18n.taskFilterUrgent).toUpperCase())] : []),
|
||||
button({ type: "submit", name: "filter", value: "create", class: "create-button" }, i18n.taskCreateButton)
|
||||
)
|
||||
);
|
||||
|
|
@ -355,8 +377,8 @@ exports.singleTaskView = async (task, filter, comments = [], params = {}) => {
|
|||
const ecoTaxChipNode = renderEcoTax(task.msgSize, task.id);
|
||||
|
||||
const chips = [
|
||||
renderTaskStatusChip(task.status),
|
||||
renderPrivacyChip(isPrivate, i18n),
|
||||
renderTaskStatusChip(task.status),
|
||||
renderTaskPriorityChip(task.priority),
|
||||
lifespanChipNode,
|
||||
ecoTaxChipNode
|
||||
|
|
@ -392,14 +414,14 @@ exports.singleTaskView = async (task, filter, comments = [], params = {}) => {
|
|||
|
||||
const taskSide = div({ class: "tribe-side" },
|
||||
div({ class: "card-header activity-card-header" },
|
||||
renderContentActions(task.id, null, { spread: params.spreads || null, author: task.author, favKind: 'tasks', isFavorite: task.isFavorite, reportTitle: task.title })
|
||||
renderContentActions(task.id, `/tasks/${encodeURIComponent(task.id)}`, { spread: params.spreads || null, author: task.author, favKind: 'tasks', isFavorite: task.isFavorite, reportTitle: task.title, deleteAction: isAuthor ? contentDeleteAction('task', task.id) : undefined })
|
||||
),
|
||||
div({ class: "shop-title-row" },
|
||||
h2({ class: "tribe-card-title" }, task.title)
|
||||
),
|
||||
chips.length ? div({ class: "card-chips-row" }, ...chips) : null,
|
||||
renderPhotoGallery(task, 'task'),
|
||||
table({ class: "tribe-info-table jobs-info-table" }, ...infoRows),
|
||||
table({ class: "tribe-info-table jobs-info-table" }, ...infoRows, ...renderCreatedRows(task.createdAt, task.author)),
|
||||
assignNode ? div({ class: "tribe-side-actions housing-status-row task-assign-row" }, ...assignNode) : null,
|
||||
isAuthor ? renderTaskStatusRow(task, returnToSelf) : null,
|
||||
tagsNode,
|
||||
|
|
@ -419,20 +441,16 @@ exports.singleTaskView = async (task, filter, comments = [], params = {}) => {
|
|||
task.description
|
||||
? div({ class: "job-section" },
|
||||
h2({ class: "job-section-title" }, i18n.taskDescriptionLabel),
|
||||
p({ class: "tribe-side-description" }, ...renderUrl(task.description))
|
||||
p({ class: "tribe-side-description" }, ...renderStyledText(task.description))
|
||||
)
|
||||
: null,
|
||||
p({ class: "card-footer" },
|
||||
span({ class: "date-link" }, `${moment(task.createdAt).format("YYYY/MM/DD HH:mm")} ${i18n.performed} `),
|
||||
userLink(task.author)
|
||||
),
|
||||
renderEngagement(task.id, opinionsBar, renderTaskCommentsSection(task.id, comments, currentFilter))
|
||||
);
|
||||
|
||||
return template(
|
||||
task.title,
|
||||
section(
|
||||
div({ class: "tags-header" }, h2(i18n.tasksTitle), p(i18n.tasksDescription)),
|
||||
div({ class: "tags-header module-header-line" }, h2(i18n.tasksTitle), p(i18n.tasksDescription)),
|
||||
filterBar,
|
||||
div({ class: "tribe-details" }, taskSide, taskMain)
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue