frontera con upstream: lo del movil sale de los ficheros del dev

docs/FRONTERA_UPSTREAM.md mide como cambia upstream (39 releases de la 1.0.1 a
la 1.3.3; backend.js en 34, main_views en 31, OasisMobile.css en 21) y fija que
se toca: backend, middleware, modelos, server y traducciones de upstream, no;
vistas de upstream, solo una linea de gancho; hojas, vistas, router y modelos
propios, si.

Fase A, lo del 19/10:
- backend.js, workflows_model.js y modules_view.js vuelven a como estaban
- seccion apagada, /modules/enable y ?saved=1: en el router propio, que envuelve
  las redirecciones de upstream en vez de cambiar checkMod
- Modulos del movil en views/mobile_modules_view.js, servida por el router propio
- workflow propio "acampada" registrado desde models/fork_workflows.js en vez de
  redefinir "activists"
- votaciones, tribus, ajustes, borrar, pie y bienvenida: la logica en
  views/mobile_ui.js; en cada vista de upstream queda la llamada
This commit is contained in:
SITO 2026-10-19 13:04:38 +02:00
parent 9b391cfc3d
commit d04d99ece2
14 changed files with 571 additions and 267 deletions

View file

@ -1,21 +1,13 @@
const { div, h2, p, section, button, form, a, textarea, br, input, table, tr, th, td, label, span, progress } = require("../server/node_modules/hyperaxe");
const { div, h2, p, section, button, form, a, textarea, br, input, table, tr, th, td, label, span } = require("../server/node_modules/hyperaxe");
const { renderCommentsSection: renderSharedCommentsSection } = require("./comments_view");
const { template, i18n, renderOpinionsVoting, renderEngagement, renderOpenClosedChip, renderLifespanChip, renderEcoTax, renderSpreadButton, renderContentActions, renderSpreadEditWarning, renderDocumentActions, renderModuleStatsBy, moduleIsEmpty, contentDeleteAction, paged, renderCreatedRows } = require("./main_views");
const moment = require("../server/node_modules/moment");
const { config } = require("../server/SSB_server.js");
const { renderTribeOriginChip } = require("./clearnet_view");
const mobileUi = require("./mobile_ui");
const userId = config.keys.id;
const VOTE_QUORUM = 2;
const isMobile = process.env.OASIS_MOBILE === "1";
// tipos de votacion en el movil: el servidor ya guarda las opciones que se le
// pasen (campo options), aqui solo se ofrecen las que usan las asambleas
const VOTE_KINDS = [
{ key: "classic", options: null },
{ key: "traffic", options: ["GREEN", "YELLOW", "RED"] },
{ key: "scale", options: ["1", "2", "3", "4", "5"] }
];
const safeArray = (v) => Array.isArray(v) ? v : [];
@ -166,22 +158,6 @@ exports.renderVoteOptionsBlock = (v, voteOptions, action, returnTo, canVote) =>
];
};
// en el movil los resultados son barras, una por opcion: la tabla de 6 columnas
// no cabia y partia las palabras por silabas
const renderVoteBars = (voteOptions, baseCounts) => {
const total = voteOptions.reduce((s, o) => s + (Number(baseCounts[o]) || 0), 0);
return div({ class: "vote-bars" },
...voteOptions.map((opt) => {
const n = Number(baseCounts[opt]) || 0;
return div({ class: `vote-bar vote-bar-${String(opt).toLowerCase()}` },
span({ class: "vote-bar-label" }, voteLabel(opt)),
span({ class: "vote-bar-count" }, String(n)),
progress({ class: "vote-bar-meter", max: String(Math.max(total, 1)), value: String(n) })
);
})
);
};
const renderVoteDetail = (v, voteOptionsDefault, firstRow, secondRow, mode, activeFilter, params = {}) => {
const voteOptions = Array.isArray(v.options) && v.options.length ? v.options : voteOptionsDefault;
const baseCounts = voteOptions.reduce((acc, opt) => {
@ -237,12 +213,8 @@ const renderVoteDetail = (v, voteOptionsDefault, firstRow, secondRow, mode, acti
const voteButtonsNode = renderVoteButtons(v, voteOptions, firstRow, secondRow, returnTo);
const ownOpenNote = isMobile && !voteButtonsNode && isVoteAuthor(v) && normalizeStatus(v.status) === "OPEN"
? p({ class: "vote-own-note" }, i18n.voteOwnNote || "You created this vote, so you cannot vote in it.")
: null;
const voteMain = div({ class: "tribe-main" },
ownOpenNote,
mobileUi.isMobile() && !voteButtonsNode && isVoteAuthor(v) && normalizeStatus(v.status) === "OPEN" ? mobileUi.voteOwnNote() : null,
voteButtonsNode
? div({ class: "job-section" },
h2({ class: "job-section-title" }, i18n.voteCastTitle || "Cast Vote"),
@ -254,7 +226,7 @@ const renderVoteDetail = (v, voteOptionsDefault, firstRow, secondRow, mode, acti
`${i18n.voteResults || "Results"}: `,
span({ class: `vote-outcome vote-outcome-${outcome.variant}` }, outcome.text)
),
isMobile ? renderVoteBars(voteOptions, baseCounts) : div({ class: "vote-table" },
mobileUi.isMobile() ? mobileUi.voteBars(voteOptions, baseCounts, voteLabel) : div({ class: "vote-table" },
table(
tr(...voteOptions.map((opt) => th(voteLabel(opt)))),
tr(...voteOptions.map((opt) => td(baseCounts[opt])))
@ -277,22 +249,6 @@ const renderCommentsSection = (voteId, comments, activeFilter) => {
});
};
const renderVoteKindPicker = (current) => {
const cur = String(current || "");
return div({ class: "vote-kind" },
label({ class: "vote-kind-title" }, i18n.voteKindLabel || "Type of vote"),
...VOTE_KINDS.map((k, i) => {
const value = k.options ? k.options.join(",") : "";
const checked = cur ? cur === value : i === 0;
return label({ class: "vote-kind-option" },
input(Object.assign({ type: "radio", name: "options", value }, checked ? { checked: "checked" } : {})),
span({ class: "vote-kind-name" }, i18n["voteKind_" + k.key] || k.key),
span({ class: "vote-kind-hint" }, i18n["voteKindHint_" + k.key] || "")
);
})
);
};
exports.voteView = async (votes, mode, voteId, comments = [], activeFilterParam, params = {}) => {
const list = Array.isArray(votes) ? votes : [votes];
@ -397,7 +353,7 @@ exports.voteView = async (votes, mode, voteId, comments = [], activeFilterParam,
}), br(), br(),
label(i18n.voteTagsLabel), br(),
input({ type: "text", name: "tags", id: "tags", value: tagsValue }), br(), br(),
isMobile && mode === "create" ? renderVoteKindPicker(draft.options) : null,
mobileUi.isMobile() && mode === "create" ? mobileUi.voteKindPicker(draft.options) : null,
button({ type: "submit" }, mode === "edit" ? i18n.voteUpdateButton : i18n.voteCreateButton)
)
)