OASIS_MOBILE/src/views/AI_view.js
SITO f964e61a1c upstream: integrar 0.9.5 en lo que no diverge (57 ficheros) + dependencias nuevas
Primera tanda de la integracion 0.9.1 -> 0.9.5. Se actualizan los 57 ficheros que
upstream cambio y la rama no tocaba, entre ellos los 11 de traduccion: eso ya solo
es posible gracias al overlay de i18n, antes eran 11 conflictos garantizados.

Se portan ademas las dependencias que 0.9.5 introduce y de las que dependen los
ficheros actualizados: pdfDocument, content_favorites, recurrence, media_gallery,
comments_view, gallery_view y polls (modelo, limites y vista).

Quedan 48 ficheros con divergencia real por resolver a mano (backend.js,
main_views.js, OasisMobile.css y 45 vistas y modelos).

Verificado: 0 errores de sintaxis en src/, 0 requires relativos rotos, la app
arranca declarando 0.9.5 y las 47 rutas principales responden 200/302.
2026-08-18 21:42:59 +02:00

95 lines
4.4 KiB
JavaScript

const { div, h2, p, section, button, form, textarea, br, span, input, label, select, option } = require("../server/node_modules/hyperaxe");
const { template, i18n } = require('./main_views');
const { renderUrl } = require('../backend/renderUrl');
exports.aiView = (history = [], userPrompt = '') => {
return template(
i18n.aiTitle,
section(
div({ class: "tags-header" },
h2(i18n.aiTitle),
p(i18n.aiDescription),
userPrompt ? div({ class: 'user-prompt' },
`${i18n.aiPromptUsed || 'System Prompt'}: `,
span({ class: 'user-prompt-text' }, `"${userPrompt}"`)
) : null,
form({ method: 'POST', action: '/ai', class: 'ai-prompt-form' },
textarea({ name: 'input', rows: 4, placeholder: i18n.aiInputPlaceholder, required: true }),
br(),
div({ class: 'ai-submit-row' },
button({ type: 'submit' }, i18n.aiSubmitButton)
)
),
div({ class: 'ai-clear-row' },
form({ method: 'POST', action: '/ai/clear', class: 'ai-clear-form' },
button({ type: 'submit', class: 'ai-clear-btn' }, i18n.aiClearHistory)
)
),
br(),
...history.map(entry =>
div({ class: 'chat-entry' },
entry.timestamp
? span({ class: 'chat-entry-timestamp' }, new Date(entry.timestamp).toLocaleString())
: null,
br(), br(),
div({ class: 'user-question' },
h2(`${i18n.aiUserQuestion}:`),
p(...renderUrl(entry.question))
),
div({ class: 'ai-response' },
h2(`${i18n.aiResponseTitle}:`),
...String(entry.answer || '')
.split('\n\n')
.flatMap(paragraph =>
paragraph
.split('\n')
.map(line =>
p(...renderUrl(line.trim()))
)
)
),
div({ class: 'ai-train-bar' },
Array.isArray(entry.snippets) && entry.snippets.length
? span({ class: 'ai-snippets-used' }, `${i18n.aiSnippetsUsed}: ${entry.snippets.length}`)
: null,
h2(`${i18n.statsAITraining}:`),
entry.trainStatus === 'approved'
? span({ class: 'ai-train-approved' }, i18n.aiTrainApproved)
: entry.trainStatus === 'rejected'
? span({ class: 'ai-train-rejected' }, i18n.aiTrainRejected)
: null,
entry.trainStatus === 'approved' || entry.trainStatus === 'rejected'
? null
: div({ class: 'ai-approve-block' },
form({ method: 'POST', action: '/ai/approve', class: 'ai-approve-form' },
input({ type: 'hidden', name: 'ts', value: String(entry.timestamp) }),
div({ class: 'ai-approve-meta' },
label({ class: 'ai-approve-meta-label' }, i18n.aiApproveTagsLabel || 'Tags (comma-separated)'),
input({ type: 'text', name: 'tags', placeholder: i18n.aiApproveTagsPlaceholder || 'e.g. oasis, governance, ecology', maxlength: '160' }),
label({ class: 'ai-approve-meta-label' }, i18n.aiApproveRatingLabel || 'Rating'),
select({ name: 'rating' },
option({ value: '0' }, '—'),
option({ value: '1' }, '★'),
option({ value: '2' }, '★★'),
option({ value: '3' }, '★★★'),
option({ value: '4' }, '★★★★'),
option({ value: '5' }, '★★★★★')
)
),
textarea({ name: 'custom', rows: 3, placeholder: i18n.aiCustomAnswerPlaceholder, class: 'ai-approve-custom' }),
div({ class: 'ai-approve-actions' },
button({ type: 'submit', class: 'approve-btn' }, i18n.aiApproveTrain)
)
),
form({ method: 'POST', action: '/ai/reject', class: 'ai-approve-reject' },
input({ type: 'hidden', name: 'ts', value: String(entry.timestamp) }),
button({ type: 'submit', class: 'reject-btn' }, i18n.aiRejectTrain)
)
)
)
)
)
)
)
);
};