From 7c92d5521ee8e8f7338b676d9f07801e824fa3e6 Mon Sep 17 00:00:00 2001 From: philc Date: Thu, 23 Jan 2025 10:24:14 +0100 Subject: [PATCH] wwws webcomponent wco implementation --- apxtri/apxtri.js | 5 +- apxtri/models/Notifications.js | 177 +++++++++++++++++++++++---------- apxtri/models/Wwws.js | 146 +++++++++++++++++++++------ apxtri/routes/wwws.js | 92 +++++++++-------- apxtri/setup/nginx.wwwscf | 3 + schema/wco.json | 71 +++++++++++++ schema/wwws.json | 2 +- 7 files changed, 372 insertions(+), 124 deletions(-) create mode 100644 schema/wco.json diff --git a/apxtri/apxtri.js b/apxtri/apxtri.js index edc5c51..93f70c8 100755 --- a/apxtri/apxtri.js +++ b/apxtri/apxtri.js @@ -156,7 +156,9 @@ apxtri.setuptribe = async (tribe, conf) => { // check nginx conf and eventually change if not starting by user "current user"; let etcnginx = fs.readFileSync("/etc/nginx/nginx.conf", "utf8"); + let newnginxconf=false if (etcnginx.split("\n")[0] !== `user ${inittribe.sudoUser};`) { + newnginxconf=true; inittribe.mainpath = inittribe.townpath.replace( `/${inittribe.townId}-${inittribe.nationId}`, "" @@ -196,7 +198,8 @@ apxtri.setuptribe = async (tribe, conf) => { : fs.readJSONSync("../adminapi/apxtri/setup/initadminapi.json").nginx .restart; const { exec } = require("child_process"); - exec(`sudo mv /tmp/nginx.conf /etc/nginx/nginx.conf && ${nginxrestart}`, (error, stdout, stderr) => { + const nginxconfmv = newnginxconf ? "sudo mv /tmp/nginx.conf /etc/nginx/nginx.conf && ":""; + exec(`${nginxconfmv}${nginxrestart}`, (error, stdout, stderr) => { if (error) { console.log("\x1b[42m", error, stdout, stderr, "x1b[0m"); process.exit(0); diff --git a/apxtri/models/Notifications.js b/apxtri/models/Notifications.js index ffbc44e..573b13a 100644 --- a/apxtri/models/Notifications.js +++ b/apxtri/models/Notifications.js @@ -3,7 +3,7 @@ const path = require("path"); const fs = require("fs-extra"); const axios = require("axios"); const dayjs = require("dayjs"); -const Mustache = require('mustache'); +const Mustache = require("mustache"); const Checkjson = require(`./Checkjson.js`); //const smtp = require("smtp-client"); const nodemailer = require("nodemailer"); @@ -153,7 +153,11 @@ Notifications.sendsms = async (data, tribeId) => { }; } let confsms = conf.sms; - if (fs.existsSync(`../adminapi/objects/tribes/itm/${req.session.header.xtribe}.json`)) { + if ( + fs.existsSync( + `../adminapi/objects/tribes/itm/${req.session.header.xtribe}.json` + ) + ) { const conftrib = fs.readJSONSync( `../adminapi/objects/tribes/itm/${req.session.header.xtribe}.json` ); @@ -206,14 +210,32 @@ Notifications.sendsms = async (data, tribeId) => { */ }; -Notifications.manageemail = (data, template, tribe) => { +Notifications.manageemail = async (data, templatename, tribe, lg,numberpersecond) => { + const sleep = (ms) => { + return new Promise((resolve) => setTimeout(resolve, ms)); + }; /** * Manage email publipostage - * data must contain emailsto - * data optionaly can contain Cc,Bcc as array of emails and attachments as array of filename (into the server) - * Await the 1st email + * data must contain + * { + * from:"", //mandatory + * cc:[],bcc:[], present in all email sent + * emailsto:[ //mandatory + * { + * to, //mandatory + * cc,bcc, + * attachements:[{filename:"text.txt",pathfile:"/media/phil/textA.txt","contenttype":"text/plain"}], + * any properties to template + * } + * ] + * } + * emailsto contain the personnalisation data in data we can have directly cc bcc, that is added to the main + * + * template a name that exist in /tribe/{{templatename}}_{{lg}}.js + * */ //console.log(data) + const start = Date.now(); if (!data.emailsto || data.emailsto.length == 0) { return { status: 406, @@ -223,48 +245,72 @@ Notifications.manageemail = (data, template, tribe) => { }; } if (typeof data.emailsto === "string") data.emailsto = [data.emailsto]; - - if (!fs.existsSync(path.resolve(template))){ + const tplpath = `../${tribe}/template/${templatename}_${lg}.js`; + if (!fs.existsSync(tplpath)) { return { status: 404, ref: "Notification", msg: "templatenotfound", - data: { template:path.resolve(template) }, + data: { template: tplpath }, + }; + } + const results = { fail: [], success: [] }; + const emailtosend = {}; + // init with common propertie + Object.keys(data).forEach((k) => { + if (!["emailsto"].includes(k)) emailtosend[k] = data[k]; + }); + const tplemail = require(path.resolve(tplpath)); + let sendit = { status: 200, ref: "Notifications", msg: "successfullsend" }; + + for (let i = 0; i < data.emailsto.length; i++) { + const email = data.emailsto[i]; + emailtosend.to = email.to.toLowerCase().trim(); + if (!Checkjson.testformat(emailtosend.to, "email")) { + results.fail.push({ to: emailtosend.to, err: ["errorformat"] }); + } else { + emailtosend.subject = Mustache.render(tplemail.subject, email); + emailtosend.html = Mustache.render(tplemail.html, email); + emailtosend.text = Mustache.render(tplemail.text, email); + if (email.cc) { + emailtosend.cc += emailtosend.cc && emailtosend.cc != "" ? "," : ""; + emailtosend.cc += email.cc.join(","); + } + if (email.bcc) { + emailtosend.bcc += emailtosend.bcc && emailtosend.bcc != "" ? "," : ""; + emailtosend.bcc += email.bcc.join(","); + } + if (email.attachments) { + email.attachments.forEach((a) => tplemail.attachments.push(a)); + } + //console.log(emailtosend) + sendit = await Notifications.sendmail(emailtosend, tribe); + //const sendit={status:200} + if (sendit.status == 200) { + results.success.push(emailtosend.to); + } else { + results.fail.push({ tp: emailtosend.to, status: sendit.status }); + } + if ((i + 1) % numberpersecond === 0) { + console.log("Prochain lot attend 1 seconde"); + await sleep(1000); + } } } - const tplemail = require(path.resolve(template)); - let sendit={status:200,ref:"Notifications",msg:"successfullsend"}; - data.emailsto.forEach(async (e, i) => { - if (Checkjson.testformat(e, "email")) { - const dat = {}; - dat.to = e; - dat.subject = Mustache.render(tplemail.subject, data); - dat.html = Mustache.render(tplemail.html, data); - dat.text = Mustache.render(tplemail.text, data); - dat.Cc=tplemail.Cc - dat.Bcc=tplemail.Bcc - /* @TODO issue with data.Cc need to test - if (data.Cc){ - dat.Cc+=","+data.Cc.join(',') - } - if (data.Bcc){ - dat.Bcc+=","+data.Bcc.join(',') - } - */ - if (data.attachments){ - data.attachments.forEach(a=>tplemail.attachments.push(a)) - } - if (i == 0) { - sendit = await Notifications.sendmail(dat, tribe); - if (sendit.status != 200) return {status:406,ref:"Notifications",msg:"emailnotsent"}; - } else { - Notifications.sendmail(dat, tribe); - } - } else { - // not a well formated email @todo add a log file to follow it - } - }); - return sendit; + fs.outputJSONSync( + `../${tribe}/logs/campains/${templatename}_${lg}_${Date.now()}`, + results + ); + return { + status: 200, + ref: "Wwws", + msg: "campainsent", + data: { + emailsucces: results.success.length, + emailfail: results.fail.length, + timems: Date.now() - start, + }, + }; }; Notifications.sendmail = async (data, tribe) => { @@ -314,9 +360,11 @@ Notifications.sendmail = async (data, tribe) => { data: { tribe: tribe }, }; } + if (!data.from) { data.from = conf.emailcontact; } + let missingk = []; ["from", "to", "subject", "html", "text"].forEach((k) => { if (!data[k]) { @@ -335,18 +383,19 @@ Notifications.sendmail = async (data, tribe) => { const conftribfile = `../adminapi/objects/tribes/itm/${tribe}.json`; if (fs.existsSync(conftribfile)) { const conftrib = fs.readJSONSync(conftribfile); - if (!conftrib.emailcontact){ + if (!conftrib.emailcontact) { return { status: 428, ref: "Notifications", msg: "missingemailcontactinconf", data: { tribe }, - }; + }; } confsmtp = conftrib.smtp; - if (!data.from || data.from == conf.emailcontact) data.from = conftrib.emailcontact; + if (!data.from || data.from == conf.emailcontact) + data.from = conftrib.emailcontact; } - // console.log(confsmtp) + //console.log(confsmtp); const transporter = await nodemailer.createTransport(confsmtp); if (data.filelist) { data.attachments = []; @@ -368,14 +417,36 @@ Notifications.sendmail = async (data, tribe) => { //console.log("data:", data); let res; let error; - try{ - res = await transporter.sendMail(data); - }catch(err){ - console.log(err) - error=err + /*console.log( + "from:", + data.from, + " to:", + data.to, + " replyto:", + data.replyto, + " cc:", + data.cc, + " bcc:", + data.bcc, + " subject:", + data.subject + ); + */ + //fs.outputFile(`../${tribe}/template/test.html`, data.html); + + try { + res = await transporter.sendMail(data); + } catch (err) { + console.log("Erreur :", err); + if (err.code) { + error = err.code; + } else { + error = err; + } } if ( - res && res.accepted && + res && + res.accepted && data.to.split(",").reduce((acc, m) => acc && res.accepted.includes(m), true) ) { data.accepted = res.accepted; @@ -386,7 +457,7 @@ Notifications.sendmail = async (data, tribe) => { msg: "successfullsentemail", data, }; - } else if ( res && res.accepted && res.rejected) { + } else if (res && res.accepted && res.rejected) { data.accepted = res.accepted; data.rejected = res.rejected; return { status: 410, ref: "Notifications", msg: "errsendmail", data }; diff --git a/apxtri/models/Wwws.js b/apxtri/models/Wwws.js index de21831..414db88 100644 --- a/apxtri/models/Wwws.js +++ b/apxtri/models/Wwws.js @@ -11,8 +11,73 @@ const sharp = require("sharp"); const readlineSync = require("readline-sync"); const Odmdb = require("./Odmdb.js"); const conf = require(`../../../adminapi/objects/tribes/itm/adminapi.json`); +const currentmod = "Wwws"; +const log = conf.api.activelog.includes(currentmod); const Wwws = {}; +Wwws.getwco = (wconame, ctx) => { + const filereq = `../${ctx.wcotribe}/objects/wco/${wconame}/${wconame}.js`; + const wcoconf = `../${ctx.wcotribe}/objects/wco/itm/${wconame}.json`; + if (!fs.existsSync(filereq) || !fs.existsSync(wcoconf)) { + return { + status: 404, + ref: "Wwws", + msg: "filedoesnotexist", + data: { js: filereq, wcoconf: wcoconf }, + }; + } + //check in ctx.wcotribe if ctx.tribe_ctx.code exist in + console.log("@todo don't forget to manage accessright to wco in Wwws"); + //check that all tpl, tpldata, ... are available for this pagename + const webconf = `../${ctx.tribe}/objects/wwws/itm/${ctx.xapp}.json`; + const wcoinfo = fs.readJSONSync(wcoconf); + const webpage = fs.readJSONSync(webconf); + if (wcoinfo.tpl && Object.keys(wcoinfo.tpl).length > 0) { + Object.keys(wcoinfo.tpl).forEach((t) => { + if (!Object.keys(webpage.pages[ctx.pagename].tpl).includes(t)) { + webpage.pages[ctx.pagename].tpl[t] = wcoinfo.tpl[t]; + } + }); + } + if (wcoinfo.tpldatamodel && Object.keys(wcoinfo.tpldatamodel).length > 0) { + Object.keys(wcoinfo.tpldatamodel).forEach((t) => { + const pathtpldata = `../${ctx.tribe}/objects/wwws/${ctx.xapp}/src/tpldata/${wconame}/${t}`; + if (!Object.keys(webpage.pages[ctx.pagename].tpldata).includes(t)) { + webpage.pages[ctx.pagename].tpldata[t] = pathtpldata; + } + wcoinfo.lang.forEach((l) => { + if (!fs.existsSync(`${pathtpldata}_${l}.json`)) { + if (!fs.existsSync(`../${wcoinfo.tpldatamodel[t]}_${l}.json`)) { + fs.copySync( + `../${wcoinfo.tpldatamodel[t]}_${l}.json`, + `${pathtpldata}_${l}.json` + ); + } + } + }); + }); + } + if (wcoinfo.ref && Object.keys(wcoinfo.ref).length > 0) { + Object.keys(wcoinfo.ref).forEach((t) => { + t=t.replace("{{tribe}}",ctx.tribe) + if (!Object.keys(webpage.pages[ctx.pagename].ref).includes(t)) { + webpage.pages[ctx.pagename].ref[t] = wcoinfo.ref[t]; + } + }); + } + if (wcoinfo.schema && wcoinfo.schema.length > 0) + [ + wcoinfo.schema.forEach((s) => { + s = s.replace("{{tribe}}", ctx.tribe); + if (webpage.pages[ctx.pagename].schema.includes(s)) { + webpage.pages[ctx.pagename].schema.pusf(s); + } + }), + ]; + fs.outputJSONSync(webconf,webpage) + return { status: 200, ref:"Wwws",msg:"wcoupdatesuccessinpageconf",data: { file: path.resolve(filereq) } }; +}; + Wwws.build = (tribeId, webapp, srcdist, options) => { console.log(`Building ${tribeId}/objects/wwws/${webapp}/${srcdist}`); const pathto = `../${tribeId}/objects/wwws`; @@ -22,8 +87,9 @@ Wwws.build = (tribeId, webapp, srcdist, options) => { } else { confwww = { website: webapp, - appimgs:[], - commentappimg:"Image list in src that are used by app that must be copy into /dist", + appimgs: [], + commentappimg: + "Image list in src that are used by app that must be copy into /dist", apxtri: { headers: { xtrkversion: 1, @@ -60,18 +126,18 @@ Wwws.build = (tribeId, webapp, srcdist, options) => { tpl: {}, tpldata: {}, itms: {}, - ref: { - Checkjson: "adminapi/objects/tplstrings/Checkjson", - Notification: "adminapi/objects/tplstrings/Notifications", - Odmdb: "adminapi/objects/tplstrings/Odmdb", - Pagans: "adminapi/objects/tplstrings/Pagans", - Middlewares: "adminapi/objects/tplstrings/middlewares", - }, - schema: ["adminapi/objects/pagans", `${tribeId}/objects/persons`], - options: { profil: `${tribeId}/objects/options/profil` }, + ref: {}, + schema: [], + options: {}, wcodata: {}, appdata: {}, - }; + }; // test if lib exist or not if not create a symlink with node_modules + /*if ( + (src.includes("static/lib/") || src.includes("wco/")) && + !fs.existsSync(`${pathto}/${webapp}/src/${src}`) + ) { + Wwws.getsymlink(`${pathto}/${webapp}/src/${src}`, tribe); + }*/ } if (!confwww.pages[pgname].languages.includes(lg)) confwww.pages[pgname].languages.push(lg); @@ -81,7 +147,10 @@ Wwws.build = (tribeId, webapp, srcdist, options) => { const dc = pg.window.document; let pgscripts = []; dc.querySelectorAll("script[src]").forEach((s) => { - if (!pgscripts.includes(s.getAttribute("src"))) { + if ( + /\/api\/.*\/wwws\/objects\/wco\/itm\/.*/.test(s.src) && + !pgscripts.includes(s.src) + ) { pgscripts.push(s.getAttribute("src")); } }); @@ -92,9 +161,9 @@ Wwws.build = (tribeId, webapp, srcdist, options) => { imgsrc.replace(/(.*)\.(png|png|gif|bmp|jpg|jpeg)$/, "$1.webp") ); if (!appimgs[imgsrc]) { - appimgs[imgsrc]={pages:[]}; + appimgs[imgsrc] = { pages: [] }; } - appimgs[imgsrc].pages.push(pginfo) + appimgs[imgsrc].pages.push(pginfo); }); let wcojs = ""; pgscripts.forEach((s) => { @@ -129,7 +198,7 @@ Wwws.build = (tribeId, webapp, srcdist, options) => { .sync(`${pathto}/${webapp}/src/tpldata/${pgname}/*.json`) .forEach((t) => { const tpldataname = path.parse(t).name.replace(/_..$/, ""); - console.log("tpldata:",tpldataname); + console.log("tpldata:", tpldataname); confwww.pages[pgname].tpldata[tpldataname] = `${tribeId}/${t.replace( /_..\.json$/, "" @@ -172,30 +241,32 @@ Wwws.build = (tribeId, webapp, srcdist, options) => { ); } }); - console.log(appimgs) + //console.log(appimgs) const commonfilestrt = {}; // force some image to be in dist that are not existing in html mainly used by wco app - confwww.commonfiles.forEach(i=>{ + confwww.commonfiles.forEach((i) => { const src = `${pathto}/${webapp}/src/${i}`; const dist = `${pathto}/${webapp}/dist/${i}`; //console.log(imgsrc,"---------------",imgdist) - if (!fs.existsSync(src)){ - commonfilestrt[src]={ERROR:`this file does not exist request by wwws/itm/${webapp}.json`} + if (!fs.existsSync(src)) { + commonfilestrt[src] = { + ERROR: `this file does not exist request by wwws/itm/${webapp}.json`, + }; } else if (!fs.existsSync(dist)) { - fs.ensureDirSync(path.dirname(dist)) - fs.copyFileSync(src,dist) + fs.ensureDirSync(path.dirname(dist)); + fs.copyFileSync(src, dist); } - }) - const imgtrt={} + }); + const imgtrt = {}; Object.keys(appimgs).forEach(async (i) => { const imgsrc = `${pathto}/${webapp}/src/${i}`; const imgdist = `${pathto}/${webapp}/dist/${i.replace( /(.*)\.(png|png|gif|bmp|jpg|jpeg)$/i, "$1.webp" )}`; - console.log("imgsrc:",imgsrc," imgdist:",imgdist) + console.log("imgsrc:", imgsrc, " imgdist:", imgdist); if (fs.existsSync(imgsrc)) { const srcstats = fs.statfsSync(imgsrc); let newimg = sharp(imgsrc); @@ -208,7 +279,7 @@ Wwws.build = (tribeId, webapp, srcdist, options) => { ) { newimg = newimg.resize({ width: 1920, height: 1080, fit: "inside" }); } - fs.ensureDirSync(path.dirname(imgdist)) + fs.ensureDirSync(path.dirname(imgdist)); await newimg.webp({ quality: 80 }).toFile(imgdist); } const diststats = fs.statfsSync(imgdist); @@ -227,7 +298,12 @@ Wwws.build = (tribeId, webapp, srcdist, options) => { // saved new conf for updatelocaldb data fs.outputJSONSync(`${pathto}/itm/${webapp}.json`, confwww, { spaces: 2 }); console.log(imgtrt); - return { status: 200, ref: "Wwws", msg: "success", data: { imgtrt,commonfilestrt } }; + return { + status: 200, + ref: "Wwws", + msg: "success", + data: { imgtrt, commonfilestrt }, + }; }; if (process.argv && process.argv.length == 5) { @@ -306,7 +382,7 @@ Wwws.initlocaldata = (tribe, appname, pagename, version, profils, lg) => { tpl: {}, tpldata: {}, ref: {}, - schema: [], + schema: {}, }; localstorage.headers.xlang = lg; // A faire plus tard charger tous les referentiele et les data pour une page adminpage @@ -469,7 +545,7 @@ Wwws.initlocaldata = (tribe, appname, pagename, version, profils, lg) => { "/etc/nginx/proxy_params", mustache.render(proxyparams, paramconf), "utf8" - ); + );ln -s ../../../../../../../adminapi/node_modules/axios axios if (!fs.existsSync(paramconf.nginx.logs)) fs.mkdirSync(paramconf.nginx.logs); paramconf.nginx.firstinstall = true; fs.outputJsonSync("../tribes/conf.json", paramconf, { @@ -483,6 +559,18 @@ Wwws.create = (paramnginx) => { /** * Create an nginx conf to make available a spaceweb for a tribe /www/appname/ * + * create + * /dist + * /src/static/lib/ + * ln -s ../../../../../../../adminapi/node_modules/axios axios + * + * + * + * + * + * + * + * */ const res = { status: 200, diff --git a/apxtri/routes/wwws.js b/apxtri/routes/wwws.js index 6c43ec6..df839dc 100644 --- a/apxtri/routes/wwws.js +++ b/apxtri/routes/wwws.js @@ -28,29 +28,42 @@ router.post( ); /** - * @api {put} /adminapi/wwws/webcomponents - Get local web components + * @api {get} /adminapi/wwws/getwco/:wconame - Add a wco for an app * @apiGroup Wwws * @apiName getwco - * @apiDescription Get web component from backend to localstorage for development. This is anonymous but must be authenticated with accessright to other tribe to get their web component.
For production it will generate a unique id that store to add in updatelocaldb with in production space /js/uniqueid.js css/uniqueid.css pagename.html with link in it - * - * @apiBody {object} tribelistwco { wco:{tribe:[wconame]}, mode:"dev"|"prod"} -*/ -router.put( - "/updatelocalwcoanonymous", - checkHeaders, - (req, res) => { - console.log("localstorage anonymous for web component", req.session.header.xalias); - req.session.header.xprofils = ["anonymous"]; - console.log(req.session.header.xprofils); - //ajouter une detection de changement - const getlocal = Wwws.initlocalwco( - req.body, - req.session.header.xprofils, - req.session.header.xlang - ); - res.status(getlocal.status).json(getlocal); + * @apiDescription Get the wco name.js that make the wco work. It checks that the wcotribe allow the couple tribe (that request) and code exist data base from backend to localstorage for anonymous (see Get app data model) + * + * @apiParam {string} name unique wco name + * @apiQuery {string} tribe that request access to + * @apiQuery {string} wcotribe where the wco is stored + * @apiQuery {string} xapp for which website is requested + * @apiQuery {string} pagename for which page name we need to add in localdb + * @apiQuery {string} code a code for tribe + * + * + * http://admin.adminapi.newdev.ants/api/adminapi/wwws/getwco/apx.js?wcotribe=adminapi&tribe=adminapi&xapp=admin&pagename=admindata&code=enjoy + */ +router.get("/getwco/:wconame", (req, res) => { + console.log(req.params); + console.log(req.query); + const mandatoryquery= ["wcotribe","tribe","xapp","pagename","code"] + let missquery="" + mandatoryquery.forEach(q=>{ + if (!req.query[q] || req.query[q]=="") { + missquery+=q+" " + } + }) + if (missquery!=""){ + res.status(403).json({status:403,ref:"Wwws",msg:"missquery",data:{missquery}}) + }else{ + const getwco=Wwws.getwco(req.params.wconame.replace(/\.js$/,''),req.query) + if (getwco.status==200){ + res.sendFile(getwco.data.file) + }else{ + res.status(getwco.status).json(getwco); + } } -); +}); /** * @api {get} /adminapi/wwws/updatelocaldbanonymous/:tribe/:appname/:pagename/:version - Get localdb for app anonymous only @@ -58,11 +71,11 @@ router.put( * @apiName getappcontextforanonymous * @apiDescription Get data base from backend to localstorage for anonymous (see Get app data model) * - * @apiParams {string} tribe (adminapi,smatchit,..) to looking for - * @apiParams {string} appname agregate a full data referential to store localy - * @apiParams {string} pagename app page name - * @apiParams {interger} version the current version -*/ + * @apiParam {string} tribe (adminapi,smatchit,..) to looking for + * @apiParam {string} appname agregate a full data referential to store localy + * @apiParam {string} pagename app page name + * @apiParam {interger} version the current version + */ router.get( "/updatelocaldbanonymous/:tribe/:appname/:pagename/:version", checkHeaders, @@ -89,10 +102,10 @@ router.get( * @apiName getappcontext * @apiDescription Get data base from backend to localstorage for authenticated user * - * @apiParams {string} tribe (adminapi,smatchit,..) to looking for - * @apiParams {string} appname agregate a full data referential to store localy - * @apiParams {string} pagename app page name - * @apiParams {interger} version the current version + * @apiParam {string} tribe (adminapi,smatchit,..) to looking for + * @apiParam {string} appname agregate a full data referential to store localy + * @apiParam {string} pagename app page name + * @apiParam {interger} version the current version * @apiSuccess {object} contain new version data model for a local web app in a PWA logical in the language of the header or if no new version exist then return * @apiSuccessExample {json} datamodelupdate * {"status":200, "ref":"Wwws", "msg":"datamodelupdate", "data":{version,confpage,profils,schema,options,ref,tpl,tpldata}} @@ -106,7 +119,8 @@ router.get( */ router.get( "/updatelocaldb/:tribe/:appname/:pagename/:version", - checkHeaders, isAuthenticated, + checkHeaders, + isAuthenticated, (req, res) => { console.log("pass localstorage", req.session.header.xalias); console.log(req.session.header.xprofils); @@ -128,8 +142,8 @@ router.get( * @apiName createPagename * @apiDescription Create a pagename from /appscreen/template/:pagename with * - * @apiParams {string} tribe (adminapi,smatchit,..) to looking for - * @apiParams {string} appname agregate a full data referential to store localy + * @apiParam {string} tribe (adminapi,smatchit,..) to looking for + * @apiParam {string} appname agregate a full data referential to store localy * @apiSuccess {object} contain cuurent version of the data model * @apiSuccessExample {json} Success-Response: * HTTP/1.1 200 OK @@ -143,14 +157,12 @@ router.get("/buildpage/:tribe/:appname/:pagename", checkHeaders, (req, res) => { .status(404) .json({ status: 404, ref: "Wwws", msg: "localdbnotfound", data: {} }); } - res - .status(200) - .json({ - status: 200, - ref: "Wwws", - msg: "lastversion", - data: { version: fs.readJSONSync(localdbf).version }, - }); + res.status(200).json({ + status: 200, + ref: "Wwws", + msg: "lastversion", + data: { version: fs.readJSONSync(localdbf).version }, + }); }); module.exports = router; diff --git a/apxtri/setup/nginx.wwwscf b/apxtri/setup/nginx.wwwscf index 4772dd6..2a67dda 100644 --- a/apxtri/setup/nginx.wwwscf +++ b/apxtri/setup/nginx.wwwscf @@ -23,6 +23,9 @@ location ~* /trk/ { location /adminapi/Checkjson.js { alias {{{townpath}}}/adminapi/apxtri/models/Checkjson.js; } +location ~ ^/(?[^/]+)/node_modules/(?.+)$ { + alias {{{townpath}}}/$folder/node_modules/$file; +} location /setup.sh { alias {{{townpath}}}/adminapi/apxtri/setup/setup.sh; } diff --git a/schema/wco.json b/schema/wco.json new file mode 100644 index 0000000..65ac7c6 --- /dev/null +++ b/schema/wco.json @@ -0,0 +1,71 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "adminapi/schema/wco", + "title": "web components", + "description": "A web component wco is a folder with list of mustache and one name.js that deal all the business logic", + "type": "object", + "properties": { + "wconame": { + "description": "Folder name into a tribeId/objects/wco/itm", + "title": "Web component reusable in web project based with tailwindcss", + "type": "string" + }, + "owner": { + "description": "owner that earn some fees", + "type": "string" + }, + "codehash": { + "description": "Code signature of alias publickey", + "type": "string" + }, + "thumbnail":{ + "title":"Thumbnail of the component", + "type":"string" + }, + "title":{ + "title":"Short description of the wco", + "type":"string" + }, + "description":{ + "title":"Long description in html of the component", + "type":"string" + }, + "tpl":{ + "description":"list of mustache template to manage components each file must ended by _xx.mustache where xx is the language of the template, so you can add translation easily", + "type":"array" + }, + "tpldata":{ + "description":"Example of tpldata that you have to add in your local to customize the wco ended by _xx.json where xx is the language of the template", + "type":"array" + } +}, +"required": [ +"wconame", +"owner", +"title" +], +"apxid": "wconame", +"apxuniquekey": [ +"wconame" +], +"apxidx": [ +{ + "name": "lst_wconame", + "type": "array", + "keyval": "wconame" +} +], +"apxaccessrights": { +"owner": { + "D": [], + "R": [], + "U": [] +}, +"mayor": { + "C": [] +}, +"person": { + "R": [] +} +} +} \ No newline at end of file diff --git a/schema/wwws.json b/schema/wwws.json index 3dd7913..8d126c4 100644 --- a/schema/wwws.json +++ b/schema/wwws.json @@ -1,6 +1,6 @@ { "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "nationchains/schema/www", + "$id": "adminapi/schema/wwws", "title": "www", "description": "A space web available for a domaine, with accessright", "type": "object",