update project with new architecture
This commit is contained in:
216
asupsetup/data/domain/apixpress/www/app/webapp/js/auth.js
Executable file
216
asupsetup/data/domain/apixpress/www/app/webapp/js/auth.js
Executable file
@@ -0,0 +1,216 @@
|
||||
"use strict";
|
||||
var pwa = pwa || {};
|
||||
/*
|
||||
Manage user authentification and registration
|
||||
________________________
|
||||
pwa.auth.route()
|
||||
manage from state.json route if authenticated or not
|
||||
redirect public page or app page
|
||||
________________________
|
||||
pwa.auth.screenlogin()
|
||||
show login modal
|
||||
________________________
|
||||
pwa.auth.getlinkwithoutpsw()
|
||||
special get with token and uuid workeable for 24h this link is une onetime
|
||||
_________________________
|
||||
pwa.auth.isAuthenticate()
|
||||
test if token is still ok or not return false/true
|
||||
_________________________
|
||||
pwa.auth.authentification({LOGIN,PASSWORD})
|
||||
if ok => load pwa.state.data.app .headers .userlogin
|
||||
_________________________
|
||||
pwa.auth.login()
|
||||
Manage login modal to get login psw value and submit it to pwa.auth.authentification()
|
||||
_________________________
|
||||
pwa.auth.logout()
|
||||
Remove localstorage and reload
|
||||
_________________________
|
||||
pwa.auth.register()
|
||||
@TODO
|
||||
__________________________
|
||||
pwa.auth.forgetpsw()
|
||||
Request to send an email with a unique get link to access from this link to the app
|
||||
|
||||
*/
|
||||
/*MODULEJS*/
|
||||
//--##
|
||||
pwa.auth = {};
|
||||
// Refresh browser state if exist else get pwa.state defaults
|
||||
//pwa.state.ready( pwa.auth.check );
|
||||
|
||||
pwa.auth.Checkjson = () => {
|
||||
if( pwa.state.data.login.isAuthenticated ) {
|
||||
if( !pwa.auth.isAuthenticate() ) {
|
||||
// Then reinit local storage and refresh page
|
||||
pwa.state.data.login.isAuthenticated = false;
|
||||
pwa.state.save();
|
||||
//alert( 'reload page cause no more auth' )
|
||||
window.location.reload();
|
||||
};
|
||||
}
|
||||
};
|
||||
pwa.auth.route = ( destination ) => {
|
||||
console.log( 'auth.route to', destination );
|
||||
//if check Authenticated && exist #signin button[data-routeto] then redirect browser to button[data-routeto]
|
||||
//else manage component action auth
|
||||
if( pwa.state && pwa.state.data && pwa.state.data.login && pwa.state.data.login.isAuthenticated ) {
|
||||
if( destination )
|
||||
window.location.pathname = `${pwa.state.data.ctx.urlbase}/${destination}`;
|
||||
} else {
|
||||
[ "#signin", "#resetpsw", "#register" ].forEach( e => {
|
||||
if( e == destination ) {
|
||||
document.querySelector( e )
|
||||
.classList.remove( 'd-none' );
|
||||
} else {
|
||||
document.querySelector( e )
|
||||
.classList.add( 'd-none' );
|
||||
}
|
||||
} )
|
||||
}
|
||||
}
|
||||
pwa.auth.isAuthenticate = async function () {
|
||||
// in any request, if middleware isAuthenticated return false
|
||||
// then headers Xuuid is set to 1
|
||||
// then try pwa.auth.isAuthenticate if rememberMe auto reconnect
|
||||
// if jwt is ok then return true in other case => false
|
||||
// this is the first test then depending of action see ACCESSRIGHTS of user
|
||||
console.log( 'lance isauth', {
|
||||
headers: pwa.state.data.headers.xpaganid
|
||||
} )
|
||||
//alert( 'uuid ' + pwa.state.data.headers.xpaganid )
|
||||
console.log( `https://${pwa.state.data.ctx.urlbackoffice}/users/isauth`, {
|
||||
headers: pwa.state.data.headers
|
||||
} )
|
||||
try {
|
||||
const repisauth = await axios.get( `https://${pwa.state.data.ctx.urlbackoffice}/users/isauth`, {
|
||||
headers: pwa.state.data.headers
|
||||
} )
|
||||
console.log( repisauth )
|
||||
console.log( 'isAauthenticate: yes' )
|
||||
return true;
|
||||
} catch ( err ) {
|
||||
if( err.response ) { console.log( "response err ", err.response.data ) }
|
||||
if( err.request ) { console.log( "request err", err.request ) }
|
||||
console.log( 'isAuthenticate: no' )
|
||||
pwa.state.data.headers.xpaganid = "1";
|
||||
if( pwa.state.data.login.rememberMe.login ) {
|
||||
if( await pwa.auth.authentification( pwa.state.data.login.rememberMe ) ) {
|
||||
return await pwa.auth.isAuthenticate();
|
||||
};
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
pwa.auth.authentification = async function ( data ) {
|
||||
// Core client function to chech auth from login & psw
|
||||
// In case of 403 error lauch pwa.authentification(pwa.app.rememberMe)
|
||||
// in case of sucess update paw.state.data.login
|
||||
console.groupCollapsed( "Post Authentification for standard on : https://" + pwa.state.data.ctx.urlbackoffice + "/users/login param data", data )
|
||||
|
||||
console.log( 'header de login', pwa.state.data.headers )
|
||||
let auth;
|
||||
try {
|
||||
auth = await axios.post( `https://${pwa.state.data.ctx.urlbackoffice }/users/login`, data, {
|
||||
headers: pwa.state.data.headers
|
||||
} );
|
||||
console.log( "retour de login successfull ", auth );
|
||||
//Maj variable globale authentifié
|
||||
pwa.state.data.headers.xpaganid = auth.data.payload.data.UUID;
|
||||
pwa.state.data.headers.xauth = auth.data.payload.data.TOKEN;
|
||||
pwa.state.data.headers.xtribe = auth.data.payload.data.tribeid;
|
||||
pwa.state.data.headers.xworkon = auth.data.payload.data.tribeid;
|
||||
// Save local authentification uuid/token info user
|
||||
pwa.state.data.login.user = auth.data.payload.data;
|
||||
//request a refresh after a login
|
||||
pwa.state.data.ctx.refreshstorage = true;
|
||||
pwa.state.save();
|
||||
//alert( 'pwa.state.save() fait avec uuid' + pwa.state.data.headers.xpaganid )
|
||||
console.groupEnd();
|
||||
return true;
|
||||
} catch ( err ) {
|
||||
if( err.response ) { console.log( "resp", err.response.data ) }
|
||||
if( err.request ) { console.log( "req", err.request.data ) }
|
||||
console.log( 'erreur de login reinit de rememberMe', err )
|
||||
pwa.state.data.login.rememberMe = {};
|
||||
document.querySelector( "#signin p.msginfo" )
|
||||
.innerHTML = document.querySelector( "#signin [data-msgko]" )
|
||||
.getAttribute( 'data-msgko' );
|
||||
console.groupEnd();
|
||||
return false;
|
||||
}
|
||||
};
|
||||
pwa.auth.logout = function () {
|
||||
console.log( "remove ", pwa.state.data.ctx.website );
|
||||
localStorage.removeItem( pwa.state.data.ctx.website );
|
||||
window.location.href = "/";
|
||||
}
|
||||
pwa.auth.login = async function () {
|
||||
/*
|
||||
Check login/psw
|
||||
see auth.mustache & data_auth_lg.json for parameters
|
||||
Context info used:
|
||||
#signin p.msginfo contain message interaction with user
|
||||
#signin data-msgok data-msgko
|
||||
#signin button[data-routeto] is a redirection if authentification is successful
|
||||
*/
|
||||
document.querySelector( '#signin p.msginfo' )
|
||||
.innerHTML = "";
|
||||
const data = {
|
||||
LOGIN: document.querySelector( "#signin input[name='login']" )
|
||||
.value,
|
||||
PASSWORD: document.querySelector( "#signin input[name='password']" )
|
||||
.value
|
||||
}
|
||||
console.log( 'check password', Checkjson.test.password( "", data.PASSWORD ) )
|
||||
if( data.LOGIN.length < 4 || !Checkjson.test.password( "", data.PASSWORD ) ) {
|
||||
/*$("#loginpart p.msginfo")
|
||||
.html("")
|
||||
.fadeOut(2000)*/
|
||||
document.querySelector( '#signin p.msginfo' )
|
||||
.innerHTML = document.querySelector( '#signin [data-msgko]' )
|
||||
.getAttribute( 'data-msgko' );
|
||||
} else {
|
||||
if( document.querySelector( "[name='rememberme']" )
|
||||
.checked ) {
|
||||
pwa.state.data.login.rememberMe = data;
|
||||
}
|
||||
if( await pwa.auth.authentification( data ) ) {
|
||||
console.log( 'Authentification VALIDE' )
|
||||
document.querySelector( '#signin p.msginfo' )
|
||||
.innerHTML = document.querySelector( "#signin [data-msgok]" )
|
||||
.getAttribute( 'data-msgok' );
|
||||
//state l'état isAuthenticated et check la route
|
||||
pwa.state.data.login.isAuthenticated = true;
|
||||
pwa.state.save();
|
||||
console.log( pwa.state.data.login )
|
||||
console.log( 'Auth ok route to ', document.querySelector( '#signin button[data-routeto]' )
|
||||
.getAttribute( 'data-routeto' ) );
|
||||
pwa.auth.route( document.querySelector( '#signin button[data-routeto]' )
|
||||
.getAttribute( 'data-routeto' ) );
|
||||
}
|
||||
}
|
||||
};
|
||||
pwa.auth.register = async function ( event ) {
|
||||
event.preventDefault();
|
||||
// gérer la cration du user
|
||||
}
|
||||
pwa.auth.forgetpsw = async function ( event ) {
|
||||
event.preventDefault();
|
||||
const tribeid = $( ".loginregister" )
|
||||
.getAttribute( "data-tribeid" );
|
||||
const email = $( '.forgetpsw .email' )
|
||||
.val();
|
||||
console.log( `Reinit email: ${email} for tribeid: ${tribeid}` )
|
||||
try {
|
||||
console.log( `https://${pwa.state.data.ctx.urlbackoffice }/users/getlinkwithoutpsw/${email}` )
|
||||
const reinit = await axios.get( `https://${pwa.state.data.ctx.urlbackoffice }/users/getlinkwithoutpsw/${email}`, {
|
||||
headers: pwa.state.data.headers
|
||||
} )
|
||||
$( "#forgetpswpart p.msginfo" )
|
||||
.html( "Regardez votre boite email" );
|
||||
return true;
|
||||
} catch ( er ) {
|
||||
console.log( "Pb d'accès au back check apiamaildigit" )
|
||||
return false;
|
||||
}
|
||||
};
|
9
asupsetup/data/domain/apixpress/www/app/webapp/js/axios.min.js
vendored
Executable file
9
asupsetup/data/domain/apixpress/www/app/webapp/js/axios.min.js
vendored
Executable file
File diff suppressed because one or more lines are too long
5046
asupsetup/data/domain/apixpress/www/app/webapp/js/bootstrap.js
vendored
Executable file
5046
asupsetup/data/domain/apixpress/www/app/webapp/js/bootstrap.js
vendored
Executable file
File diff suppressed because it is too large
Load Diff
184
asupsetup/data/domain/apixpress/www/app/webapp/js/checkdata.js
Executable file
184
asupsetup/data/domain/apixpress/www/app/webapp/js/checkdata.js
Executable file
@@ -0,0 +1,184 @@
|
||||
/*
|
||||
This module have to be independant of any external package
|
||||
it is shared between back and front and is usefull
|
||||
to apply common check in front before sending it in back
|
||||
can be include in project with
|
||||
<script src="https://apiback.maildigit.fr/js/Checkjson.js"></script>
|
||||
or with const Checkjson = require('../public/js/Checkjson.js')
|
||||
|
||||
*/
|
||||
|
||||
// --##
|
||||
|
||||
const Checkjson = {};
|
||||
// each Checkjson.test. return true or false
|
||||
Checkjson.test = {};
|
||||
|
||||
Checkjson.test.emailadress = ( ctx, email ) => {
|
||||
const regExp = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
|
||||
return regExp.test( email );
|
||||
};
|
||||
/*
|
||||
* @emaillist = "email1,email2, email3"
|
||||
* it check if each eamil separate by , are correct
|
||||
*/
|
||||
Checkjson.test.emailadresslist = ( ctx, emaillist ) => {
|
||||
//console.log(emaillist.split(','))
|
||||
if( emaillist.length > 0 ) {
|
||||
const emails = emaillist.split( ',' );
|
||||
for( var i in emails ) {
|
||||
//console.log(emails[i])
|
||||
if( !Checkjson.test.emailadress( "", emails[ i ].trim() ) ) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
};
|
||||
return true;
|
||||
};
|
||||
|
||||
Checkjson.test.password = ( ctx, pwd ) => {
|
||||
const regExp = new RegExp(
|
||||
/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[$@$!%*?&.])[A-Za-z\d$@$!%*?&.{}:|\s]{8,}/
|
||||
);
|
||||
return regExp.test( pwd );
|
||||
};
|
||||
Checkjson.test.required = ( ctx, val ) =>
|
||||
val != null && val != 'undefined' && val.length > 0;
|
||||
|
||||
Checkjson.test.isNumber = ( ctx, n ) => typeof n === 'number';
|
||||
Checkjson.test.isInt = ( ctx, n ) => n != '' && !isNaN( n ) && Math.round( n ) == n;
|
||||
Checkjson.test.isFloat = ( ctx, n ) => n != '' && !isNaN( n ) && Math.round( n ) != n;
|
||||
Checkjson.test.unique = ( ctx, val ) => {
|
||||
if( ctx.list[ ctx.currentfield ] ) {
|
||||
return !ctx.list[ ctx.currentfield ].includes( val );
|
||||
} else {
|
||||
console.log( 'ERR no list for field:' + ctx.currentfield );
|
||||
return false;
|
||||
}
|
||||
};
|
||||
Checkjson.test.isDateDay = ( ctx, dateDay ) => true;
|
||||
/* Checkjson.test.filterInvalidInArray = (array, validate) =>
|
||||
array ? array.filter(el => !validate(el)) : true;
|
||||
// return true when every elements is valid
|
||||
*/
|
||||
|
||||
Checkjson.test.postalCode = ( ctx, postalCode ) => {
|
||||
if( postalCode.length == 0 ) return true;
|
||||
const regExp = new RegExp( /(^\d{5}$)|(^\d{5}-\d{4}$)/ );
|
||||
return regExp.test( postalCode );
|
||||
};
|
||||
/**
|
||||
* PHONE
|
||||
*/
|
||||
Checkjson.test.phoneNumber = ( ctx, phoneNumber ) => {
|
||||
if( phoneNumber.length == 0 ) return true;
|
||||
phoneNumber = phoneNumber.trim()
|
||||
.replace( /[- .]/g, '' )
|
||||
//french number
|
||||
const regExpfr = new RegExp( /^0[1-9][0-9]{9}$/ );
|
||||
const regExpInternational = new RegExp( /^\+*(\d{3})*[0-9,\-]{8,}/ );
|
||||
return regExpfr.test( phoneNumber ) || regExpInternational.test( phoneNumber );
|
||||
};
|
||||
/*
|
||||
* @phonelist = "phone1,phone2,phone3"
|
||||
* it check if each phone separate by , are correct
|
||||
*/
|
||||
Checkjson.test.phoneNumberlist = ( ctx, phonelist ) => {
|
||||
//console.log(emaillist.split(','))
|
||||
if( phonelist.length > 0 ) {
|
||||
const phones = phonelist.split( ',' );
|
||||
for( var i in phones ) {
|
||||
//console.log(emails[i])
|
||||
if( !Checkjson.test.phoneNumber( "", phones[ i ].trim() ) ) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
};
|
||||
return true;
|
||||
};
|
||||
|
||||
// Checkjson.normalize take a correct data then reformat it to harmonise it
|
||||
Checkjson.normalize = {};
|
||||
Checkjson.normalize.phoneNumber = ( ctx, phone ) => {
|
||||
phone = phone.trim()
|
||||
.replace( /[- .]/g, '' );
|
||||
if( Checkjson.test.phoneNumber( '', phone ) && phone.length == 10 && phone[ 0 ] == "0" ) {
|
||||
phone = '+33 ' + phone.substring( 1 );
|
||||
}
|
||||
return phone;
|
||||
}
|
||||
Checkjson.normalize.upperCase = ( ctx, txt ) => txt.toUpperCase();
|
||||
Checkjson.normalize.lowerCase = ( ctx, txt ) => txt.toLowerCase();
|
||||
// fixe 10 position et complete par des 0 devant
|
||||
Checkjson.normalize.zfill10 = ( ctx, num ) => {
|
||||
let s = num + '';
|
||||
while( s.length < 10 ) s = '0' + s;
|
||||
return s;
|
||||
};
|
||||
/*let tt = "+33 1 02.03 04 05";
|
||||
console.log(Checkjson.test.phoneNumber('', tt))
|
||||
console.log(Checkjson.normalize.phoneNumber('', tt))
|
||||
*/
|
||||
Checkjson.evaluate = ( contexte, referential, data ) => {
|
||||
/*
|
||||
* contexte object {} with full info for evaluation
|
||||
* file referential path to get object to apply
|
||||
* data related to object
|
||||
- return {validefor =[keyword of error] if empty no error,
|
||||
clean data eventually reformated
|
||||
updateDatabase}
|
||||
*/
|
||||
console.log( 'contexte', contexte );
|
||||
console.log( 'referentiel', referential );
|
||||
console.log( 'data', data );
|
||||
const invalidefor = [];
|
||||
const objectdef = {};
|
||||
const listfield = referential.map( ch => {
|
||||
objectdef[ ch.idfield ] = ch;
|
||||
return ch.idfield;
|
||||
} );
|
||||
|
||||
Object.keys( data )
|
||||
.forEach( field => {
|
||||
if( !listfield.includes( field ) ) {
|
||||
// some data can be inside an object with no control at all
|
||||
// they are used for process only
|
||||
// i leave it in case it will become a non sens
|
||||
// invalidefor.push('ERRFIELD unknown of referentials ' + field);
|
||||
} else {
|
||||
if( objectdef[ field ].check ) {
|
||||
// check data with rule list in check
|
||||
objectdef[ field ].Checkjson.forEach( ctrl => {
|
||||
console.log( 'ctrl', ctrl );
|
||||
contexte.currentfield = field;
|
||||
if( !Checkjson.test[ ctrl ] ) {
|
||||
invalidefor.push( 'ERR check function does not exist :' + ctrl + '___' + field )
|
||||
} else {
|
||||
if( !Checkjson.test[ ctrl ]( contexte, data[ field ] ) )
|
||||
invalidefor.push( 'ERR' + ctrl + '___' + field );
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
if( objectdef[ field ].nouserupdate ) {
|
||||
// check if user can modify this information
|
||||
console.log(
|
||||
'evaluation :' + field + ' -- ' + objectdef[ field ].nouserupdate,
|
||||
eval( objectdef[ field ].nouserupdate )
|
||||
);
|
||||
const evalright = eval( objectdef[ field ].nouserupdate );
|
||||
objectdef[ field ].nouserupdate = evalright;
|
||||
}
|
||||
}
|
||||
} );
|
||||
console.log( {
|
||||
invalidefor,
|
||||
data
|
||||
} );
|
||||
return {
|
||||
invalidefor,
|
||||
data
|
||||
};
|
||||
};
|
||||
|
||||
if( typeof module !== 'undefined' ) module.exports = Checkjson;
|
13
asupsetup/data/domain/apixpress/www/app/webapp/js/feather.min.js
vendored
Executable file
13
asupsetup/data/domain/apixpress/www/app/webapp/js/feather.min.js
vendored
Executable file
File diff suppressed because one or more lines are too long
150
asupsetup/data/domain/apixpress/www/app/webapp/js/main.js
Executable file
150
asupsetup/data/domain/apixpress/www/app/webapp/js/main.js
Executable file
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
After state.js / auth.js and all external js lib
|
||||
Load
|
||||
|
||||
*/
|
||||
var pwa = pwa || {};
|
||||
pwa.main = pwa.main || {};
|
||||
pwa.main.tpldata = pwa.main.tpldata || {};
|
||||
pwa.main.tpl = pwa.main.tpl || {};
|
||||
pwa.main.tpldata = pwa.main.tpldata || {};
|
||||
pwa.main.ref = pwa.main.ref || {};
|
||||
|
||||
pwa.main.tpl.appsidebarmenu = 'static/components/appmesa/appsidebarmenu.mustache';
|
||||
pwa.main.tpl.apptopbarmenu = 'static/components/appmesa/apptopbarmenu.mustache';
|
||||
pwa.main.tpldata.sidebar = `static/components/appmesa/data_sidebar`;
|
||||
pwa.main.tpldata.topbar = `static/components/appmesa/data_topbar`;
|
||||
pwa.main.tpldata.topbarLogin = `static/components/appmesa/data_topbarLogin`;
|
||||
|
||||
pwa.main.init = () => {
|
||||
const isempty = ( obj ) => {
|
||||
return obj && Object.keys( obj )
|
||||
.length === 0 && obj.constructor === Object
|
||||
}
|
||||
|
||||
// Load public env tpl & tpldata
|
||||
//Manage action depending of html file currently show
|
||||
const currenthtml = location.pathname.split( '/' )
|
||||
.at( -1 );
|
||||
console.groupCollapsed( `pwa.main.init for ${currenthtml} html page` );
|
||||
if( currenthtml.includes( 'app_' ) ) {
|
||||
pwa.main.loadmenu()
|
||||
}
|
||||
// To manage if authenticated or not in a simple way
|
||||
/*
|
||||
if( pwa.state.data.login.isAuthenticated ) {
|
||||
//authenticated
|
||||
// identity inside pwa.state.login.user
|
||||
}else{
|
||||
//anonymous
|
||||
// can check if the url is relevant with isAuthenticated
|
||||
//route to app if exist data-routo into a signin
|
||||
//pwa.auth.route( document.querySelector( '#signin button[data-routeto]' ).getAttribute( 'data-routeto' ) );
|
||||
// add and load dynamicaly the gui.js plugin if user that request it has access
|
||||
}
|
||||
*/
|
||||
console.groupEnd();
|
||||
};
|
||||
|
||||
pwa.main.loadmenu = async () => {
|
||||
console.log( 'pwa.main.loadmenu running' );
|
||||
console.log( 'Status of pwa.state.data.login.isAuthenticated =', pwa.state.data.login.isAuthenticated );
|
||||
let datasidebar, datatopbar;
|
||||
/* Build datasidebar and datatopbar depending of list of module allowed by user in his ACCESSRIGHTS profil.
|
||||
app[`${pwa.state.data.ctx.tribeid}:${pwa.state.data.ctx.website}`].js;
|
||||
|
||||
*/
|
||||
//console.log( 'List of tpldata', pwa.main.tpldata )
|
||||
//console.log( 'List of tpl', pwa.main.tpl )
|
||||
console.log( `run pwa.state.loadfile with pwa.state.data.ctx.refreshstorage = ${pwa.state.data.ctx.refreshstorage} if true=> refresh anyway, if false refresh only if dest.name does not exist` );
|
||||
await pwa.state.loadfile( pwa.main.tpl, 'tpl' );
|
||||
await pwa.state.loadfile( pwa.main.tpldata, 'tpldata' );
|
||||
datasidebar = pwa.state.data.tpldata.sidebar;
|
||||
//any tpldata containing sidebar in pwa.state.data.tpldata is add to sbgroupmenu to be available
|
||||
Object.keys( pwa.state.data.tpldata )
|
||||
.filter( m => ( m != 'sidebar' && m.includes( 'sidebar' ) ) )
|
||||
.some( k => {
|
||||
datasidebar.sbgroupmenu.push( pwa.state.data.tpldata[ k ] )
|
||||
} );
|
||||
//merge les menu topbar
|
||||
datatopbar = pwa.state.data.tpldata.topbar;
|
||||
if( pwa.state.data.login.isAuthenticated ) {
|
||||
// update user information if needed
|
||||
datatopbar.name = pwa.state.data.login.user.LOGIN;
|
||||
datatopbar.avatarimg = pwa.state.data.login.user.AVATARIMG;
|
||||
delete pwa.state.data.tpldata.topbarLogin;
|
||||
pwa.state.save();
|
||||
}
|
||||
datatopbar.menuprofil = [];
|
||||
Object.keys( pwa.state.data.tpldata )
|
||||
.filter( m => ( m != 'topbar' && m.includes( 'topbar' ) ) )
|
||||
.some( k => {
|
||||
datatopbar.menuprofil.push( pwa.state.data.tpldata[ k ] )
|
||||
} );
|
||||
if( pwa.state.data.tpl.appsidebarmenu ) {
|
||||
document.querySelector( "#sidebar" )
|
||||
.innerHTML = Mustache.render( pwa.state.data.tpl.appsidebarmenu, datasidebar )
|
||||
document.querySelector( "#navbar" )
|
||||
.innerHTML = Mustache.render( pwa.state.data.tpl.apptopbarmenu, datatopbar )
|
||||
//active les icones svg de feather
|
||||
feather.replace();
|
||||
//active scroll presentation + sidebar animation
|
||||
pwa.main.simplebar();
|
||||
pwa.main.clickactive();
|
||||
};
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
// simplebar
|
||||
//////////////////////////////////////////////////////
|
||||
pwa.main.simplebar = () => {
|
||||
const simpleBarElement = document.getElementsByClassName( "js-simplebar" )[ 0 ];
|
||||
|
||||
if( simpleBarElement ) {
|
||||
/* Initialize simplebar */
|
||||
new SimpleBar( document.getElementsByClassName( "js-simplebar" )[ 0 ] )
|
||||
|
||||
const sidebarElement = document.getElementsByClassName( "sidebar" )[ 0 ];
|
||||
const sidebarToggleElement = document.getElementsByClassName( "sidebar-toggle" )[ 0 ];
|
||||
|
||||
sidebarToggleElement.addEventListener( "click", () => {
|
||||
sidebarElement.classList.toggle( "collapsed" );
|
||||
|
||||
sidebarElement.addEventListener( "transitionend", () => {
|
||||
window.dispatchEvent( new Event( "resize" ) );
|
||||
} );
|
||||
} );
|
||||
}
|
||||
}
|
||||
/////////////////////////////////////////////////////////
|
||||
// manage click effect
|
||||
////////////////////////////////////////////////////////
|
||||
pwa.main.clickactive = () => {
|
||||
const cleanactive = () => {
|
||||
const el = document.querySelectorAll( '.sidebar-item' )
|
||||
for( var i = 0; i < el.length; i++ ) {
|
||||
//console.log( 'clean', el[ i ].classList )
|
||||
el[ i ].classList.remove( 'active' );
|
||||
}
|
||||
}
|
||||
document.addEventListener( "click", ( e ) => {
|
||||
console.log( 'click', e );
|
||||
if( e.target.classList.contains( 'sidebar-link' ) ) {
|
||||
cleanactive();
|
||||
e.target.closest( '.sidebar-item' )
|
||||
.classList.add( 'active' );
|
||||
// remonte au menu au dessus si existe
|
||||
e.target.closest( '.sidebar-item' )
|
||||
.closest( '.sidebar-item' )
|
||||
.classList.add( 'active' );
|
||||
}
|
||||
} );
|
||||
// If enter run the research
|
||||
document.getElementById( 'globalsearch' )
|
||||
.addEventListener( 'keypress', ( e ) => {
|
||||
if( e.keyCode == 13 ) {
|
||||
pwa.search.req( 'globalsearch' );
|
||||
e.preventDefault();
|
||||
}
|
||||
} )
|
||||
};
|
1
asupsetup/data/domain/apixpress/www/app/webapp/js/mustache.min.js
vendored
Executable file
1
asupsetup/data/domain/apixpress/www/app/webapp/js/mustache.min.js
vendored
Executable file
File diff suppressed because one or more lines are too long
28
asupsetup/data/domain/apixpress/www/app/webapp/js/notification.js
Executable file
28
asupsetup/data/domain/apixpress/www/app/webapp/js/notification.js
Executable file
@@ -0,0 +1,28 @@
|
||||
"use strict";
|
||||
var pwa = pwa || {};
|
||||
/*
|
||||
Manage notification
|
||||
|
||||
Get notification after tomenu was load
|
||||
|
||||
from /components/notification
|
||||
____________________
|
||||
|
||||
*/
|
||||
//--##
|
||||
pwa.notification = {};
|
||||
|
||||
pwa.notification.update = () => {
|
||||
console.log( 'get notification update for a user' );
|
||||
axios.get( `https://${pwa.state.data.ctx.urlbackoffice}/notifications/user`, { headers: pwa.state.data.headers } )
|
||||
.then( rep => {
|
||||
console.log( "list des notifs", rep.data.payload.data )
|
||||
rep.data.payload.data.number = rep.data.payload.data.notifs.length;
|
||||
document.getElementById( "topbarmenuright" )
|
||||
.innerHTML = Mustache.render( pwa.state.data.tpl.notiflist, rep.data.payload.data ) + document.getElementById( "topbarmenuright" )
|
||||
.innerHTML;
|
||||
} )
|
||||
.catch( err => {
|
||||
console.log( `Err pwa.notification.update data for user into header ${pwa.state.data.headers}`, err );
|
||||
} );
|
||||
};
|
10
asupsetup/data/domain/apixpress/www/app/webapp/js/simplebar.min.js
vendored
Executable file
10
asupsetup/data/domain/apixpress/www/app/webapp/js/simplebar.min.js
vendored
Executable file
File diff suppressed because one or more lines are too long
261
asupsetup/data/domain/apixpress/www/app/webapp/js/state.js
Executable file
261
asupsetup/data/domain/apixpress/www/app/webapp/js/state.js
Executable file
@@ -0,0 +1,261 @@
|
||||
"use strict";
|
||||
var pwa = pwa || {};
|
||||
/*
|
||||
FROM ndda/plugins/maildigitcreator/appjs/state.js
|
||||
Manage state of the webapp
|
||||
author: Phil Colzy - yzlocp@gmail.com
|
||||
____________________________
|
||||
pwa.state.save(): save in localstorage pwa.state.data avec le Nom du projet
|
||||
____________________________
|
||||
pwa.state.update(): update localstorage data from referential version
|
||||
____________________________
|
||||
pwa.state.ready(callback): await DOM loaded before running the callback
|
||||
____________________________
|
||||
pwa.state.refresh(): check if newversion of webapp to refresh page for dev purpose (do not use to refresh data)
|
||||
____________________________
|
||||
pwa.state.route(); check url and reroute it to function(urlparameter) or hide show part into a onepage website.
|
||||
____________________________
|
||||
pwa.state.loadfile({key:url},'dest') store in pwa.state.data.dest.key= file from url await all key to store result
|
||||
___________________________
|
||||
pwa.state.confdev() if ENV is dev then change urlbase for axios to looking for relevant file and refresh at a frequency pwa.state.refresh()
|
||||
|
||||
*/
|
||||
//--##
|
||||
pwa.state = {};
|
||||
|
||||
pwa.state.refresh = () => {
|
||||
//console.warn(`Lance le refresh de${pwa.state.env.page}`)
|
||||
//console.warn( 'ggg', pwa.state.data.ctx.urlbase )
|
||||
const currenthtml = location.pathname.split( '/' )
|
||||
.at( -1 )
|
||||
.replace( '.html', '.json' );
|
||||
//console.log( currenthtml )
|
||||
axios.get( ` ${pwa.state.data.ctx.urlbase}/static/lastchange/${currenthtml}` )
|
||||
.then(
|
||||
data => {
|
||||
//console.log( data.data.time, pwa.state.data.ctx.version )
|
||||
if( data.data.time > pwa.state.data.ctx.version ) {
|
||||
//console.log( "reload la page pour cause de lastchange detecté" );
|
||||
pwa.state.data.ctx.version = data.data.time;
|
||||
pwa.state.data.ctx.refreshstorage = true;
|
||||
pwa.state.save();
|
||||
location.reload();
|
||||
} else {
|
||||
//console.log( 'nothing change' )
|
||||
}
|
||||
},
|
||||
error => {
|
||||
console.log( error );
|
||||
}
|
||||
);
|
||||
};
|
||||
pwa.state.ready = callback => {
|
||||
// Equivalent of jquery Document.ready()
|
||||
// in case the document is already rendered
|
||||
if( document.readyState != "loading" ) callback();
|
||||
// modern browsers
|
||||
else if( document.addEventListener )
|
||||
document.addEventListener( "DOMContentLoaded", callback );
|
||||
// IE <= 8
|
||||
else
|
||||
document.attachEvent( "onreadystatechange", function () {
|
||||
if( document.readyState == "complete" ) callback();
|
||||
} );
|
||||
};
|
||||
pwa.state.route = async () => {
|
||||
/* Allow to create dynamic content
|
||||
?action=pwa object&id=&hh& => pwa.action("?action=pwa object&id=&hh&")
|
||||
ex: ?action=test.toto&id=1&t=123
|
||||
Each function that can be called have to start with
|
||||
if (e[1]=="?"){
|
||||
const urlpar = new URLSearchParams( loc.search );
|
||||
Then set param with urlpar.get('variable name')
|
||||
}
|
||||
OR ?pagemd=name used into .html (div)
|
||||
Then it hide all <div class="pagemd" and show the one with <div id="page"+name
|
||||
*/
|
||||
console.groupCollapsed( `pwa.state.route with window.location` );
|
||||
console.log( 'List of pwa available ', Object.keys( pwa ) );
|
||||
if( !pwa.auth ) {
|
||||
console.log( 'Warning, no auth.js, not a pb if no authentification need, if not check js order to be sur auth.js load before state.js' )
|
||||
} else {
|
||||
// check if still authenticated
|
||||
if( pwa.state.data.login.isAuthenticated ) {
|
||||
pwa.state.data.login.isAuthenticated = await pwa.auth.isAuthenticate();
|
||||
}
|
||||
//check if need authentification to show this page
|
||||
if( pwa.state.data.ctx.pageneedauthentification && !pwa.state.data.login.isAuthenticated ) {
|
||||
console.log( 'reload page cause not auth and page require an auth' )
|
||||
window.location = `${pwa.state.data.ctx.pageredirectforauthentification}_${pwa.state.data.ctx.lang}.html`;
|
||||
}
|
||||
}
|
||||
const loc = window.location;
|
||||
if( loc.search ) {
|
||||
console.log( Object.keys( pwa ) )
|
||||
const urlpar = new URLSearchParams( loc.search );
|
||||
if( urlpar.get( 'action' ) ) {
|
||||
const act = 'pwa.' + urlpar.get( 'action' ) + '("' + loc.search + '")';
|
||||
try {
|
||||
eval( act );
|
||||
console.log( 'Specific action request to pwa.' + act )
|
||||
} catch ( err ) {
|
||||
console.log( err )
|
||||
console.error( `You request ${act}, this action does not exist ` );
|
||||
alert( `Sorry but you have no access to ${act}, ask your admin` );
|
||||
}
|
||||
}
|
||||
let pgid = "pageindex"
|
||||
if( urlpar.get( 'pagemd' ) ) {
|
||||
pgid = "page" + urlpar.get( 'pagemd' )
|
||||
}
|
||||
//route to page content
|
||||
Array.from( document.getElementsByClassName( "pagemd" ) )
|
||||
.forEach( e => {
|
||||
console.log( "detect pagemd", e.getAttribute( 'data-url' ) );
|
||||
e.classList.add( "d-none" );
|
||||
} );
|
||||
if( document.getElementById( pgid ) ) {
|
||||
document.getElementById( pgid )
|
||||
.classList.remove( 'd-none' );
|
||||
}
|
||||
}
|
||||
console.groupEnd();
|
||||
// If pwa.main exist then start pwa.main.init();
|
||||
if( pwa.main ) pwa.main.init();
|
||||
}
|
||||
pwa.state.loadfile = async ( list, dest ) => {
|
||||
// load external file if flag pwa.state.data.ctx.refreshstorage is true from pwa.state.refresh();
|
||||
//from list = {name:url} request are done with ctx.urlbase/url and store in localstorage pwa.state.data[dest][name]=data
|
||||
// if dest=='js' then it eval the js and store origin in pwa.state.data.js={name:url}
|
||||
//For at true refreshstorage if destination pwa.state.dest does not exist
|
||||
|
||||
//console.log( 'list', list )
|
||||
//console.log( 'pwa.state.data.ctx.refreshstorage', pwa.state.data.ctx.refreshstorage )
|
||||
if( pwa.state.data.ctx.refreshstorage || !pwa.state.data[ dest ] || Object.keys( pwa.state.data[ dest ] )
|
||||
.length == 0 ) {
|
||||
if( !pwa.state.data[ dest ] ) pwa.state.data[ dest ] = {};
|
||||
try {
|
||||
let reqname = [];
|
||||
let reqload = [];
|
||||
for( const [ k, v ] of Object.entries( list ) ) {
|
||||
if( !pwa.state.data[ dest ][ k ] || pwa.state.data.ctx.refreshstorage ) {
|
||||
// if still not exist or refresstorage is set to true then add to load
|
||||
//@TODO check it works well on production
|
||||
reqname.push( k );
|
||||
reqload.push( v );
|
||||
}
|
||||
};
|
||||
//console.log( pwa.state.data.ctx.urlbase, reqload )
|
||||
let resload = await Promise.all( reqload.map( r => {
|
||||
if( dest == 'tpldata' ) r = `${r}_${pwa.state.data.ctx.lang}.json`;
|
||||
return axios.get( `${pwa.state.data.ctx.urlbase}/${r}`, { headers: pwa.state.data.headers } )
|
||||
} ) );
|
||||
resload.forEach( ( d, i ) => {
|
||||
pwa.state.data[ dest ][ reqname[ i ] ] = d.data;
|
||||
pwa.state.save();
|
||||
} )
|
||||
} catch ( err ) {
|
||||
console.error( 'FATAL ERROR check that list exist remove if not', list, err.message )
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
pwa.state.save = function () {
|
||||
localStorage.setItem( pwa.state.data.ctx.website, JSON.stringify( pwa.state.data ) );
|
||||
};
|
||||
pwa.state.update = async function () {
|
||||
const domhtml = document.querySelector( "html" );
|
||||
const ctx = {
|
||||
tribeid: domhtml.getAttribute( 'data-tribeid' ),
|
||||
website: domhtml.getAttribute( "data-website" ),
|
||||
nametpl: domhtml.getAttribute( "data-nametpl" ),
|
||||
pagename: domhtml.getAttribute( "data-pagename" ),
|
||||
urlbackoffice: domhtml.getAttribute( "data-urlbackoffice" ),
|
||||
pageneedauthentification: true,
|
||||
pageredirectforauthentification: "",
|
||||
lang: domhtml.getAttribute( "lang" ),
|
||||
env: domhtml.getAttribute( "data-env" ),
|
||||
version: domhtml.getAttribute( "data-version" ),
|
||||
refreshstorage: false
|
||||
}
|
||||
if( !domhtml.getAttribute( 'data-pageneedauthentification' ) || domhtml.getAttribute( 'data-pageneedauthentification' ) == 'false' ) {
|
||||
ctx.pageneedauthentification = false;
|
||||
}
|
||||
if( domhtml.getAttribute( 'data-pageforauthentification' ) ) {
|
||||
ctx.pageforauthentification = domhtml.getAttribute( 'data-pageforauthentification' );
|
||||
}
|
||||
console.groupCollapsed( `update pwa.state with html attribut or from localstorage into ${ctx.website}` );
|
||||
console.log( 'html context:', ctx );
|
||||
if( localStorage.getItem( ctx.website ) ) {
|
||||
pwa.state.data = JSON.parse( localStorage.getItem( ctx.website ) );
|
||||
//alert( 'recupere pwa.state.data xpaganid:' + pwa.state.data.headers.xpaganid )
|
||||
}
|
||||
if( !( pwa.state.data && pwa.state.data.ctx.tribeid == ctx.tribeid && pwa.state.data.ctx.website == ctx.website ) ) {
|
||||
console.log( " reinitialise localstorage cause work on a different project or first access" );
|
||||
delete pwa.state.data;
|
||||
localStorage.removeItem( ctx.website )
|
||||
}
|
||||
/*
|
||||
if( pwa.state.data && statejson.data.app.version && ( parseInt( pwa.state.data.app.version ) < parseInt( statejson.data.app.version ) ) ) {
|
||||
// le numero de version en mémoire est < au numero disponible sur le serveur
|
||||
// force un logout pour reinitialiser les menus
|
||||
delete pwa.state.data;
|
||||
localStorage.removeItem( pwa.PROJET )
|
||||
}
|
||||
*/
|
||||
if( !pwa.state.data ) {
|
||||
// No localstorage available et one by default
|
||||
pwa.state.data = {
|
||||
ctx,
|
||||
login: {
|
||||
isAuthenticated: false,
|
||||
user: {},
|
||||
rememberMe: {}
|
||||
},
|
||||
headers: {
|
||||
'xauth': '1',
|
||||
'xpaganid': '1',
|
||||
'xtribe': ctx.tribeid,
|
||||
'xlang': ctx.lang,
|
||||
'xworkon': ctx.tribeid,
|
||||
'xapp': `${ctx.tribeid}:${ctx.website}`
|
||||
}
|
||||
}
|
||||
console.log( 'load new state.data', pwa.state.data )
|
||||
}
|
||||
// Check if external component need to be load
|
||||
const app = `${pwa.state.data.ctx.tribeid}:${pwa.state.data.ctx.website}`;
|
||||
if( pwa.state.data.login.isAuthenticated &&
|
||||
pwa.state.data.login.user.ACCESSRIGHTS.app[ app ] &&
|
||||
pwa.state.data.login.user.ACCESSRIGHTS.app[ app ].js
|
||||
) {
|
||||
console.log( 'tttt', pwa.state.data.login.isAuthenticated, pwa.state.data.login.user.ACCESSRIGHTS.app[ app ].js )
|
||||
pwa.state.data.login.user.ACCESSRIGHTS.app[ app ].js.some( ( u ) => {
|
||||
console.log( `load from user ACCESSRIGHTS app[${pwa.state.data.ctx.tribeid}:${pwa.state.data.ctx.website}].js : ${u}` )
|
||||
const script = document.createElement( 'script' );
|
||||
script.src = u;
|
||||
script.async = false;
|
||||
document.body.appendChild( script );
|
||||
} );
|
||||
}
|
||||
//Check dev to set parameter to simplify dev app
|
||||
//check in confdev version and set pwa.state.data.ctx.refreshstorage at true if new version
|
||||
pwa.state.confdev();
|
||||
console.groupEnd();
|
||||
pwa.state.route();
|
||||
pwa.state.save();
|
||||
};
|
||||
pwa.state.confdev = () => {
|
||||
if( pwa.state.data.ctx.env == 'dev' ) {
|
||||
pwa.state.data.ctx.urlbase = `/space/${pwa.state.data.ctx.tribeid}/${pwa.state.data.ctx.website}/dist`;
|
||||
// check each 3 sec if new version to reload
|
||||
setInterval( "pwa.state.refresh()", 3000 );
|
||||
} else {
|
||||
//pwa.state.axios = axios.create();
|
||||
pwa.state.data.ctx.urlbase = "/";
|
||||
// check and refresh if new version only one time
|
||||
pwa.state.refresh();
|
||||
}
|
||||
}
|
||||
// Refresh browser state if exist else get pwa.state defaults
|
||||
pwa.state.ready( pwa.state.update );
|
Reference in New Issue
Block a user