fixed css

This commit is contained in:
STEINNI
2025-09-18 17:55:05 +00:00
parent 190d8df334
commit b5f0fb0c5d
13 changed files with 276 additions and 98 deletions
+16 -4
View File
@@ -1,6 +1,6 @@
/* Default app color palette */ /* Default app color palette */
:root,:after,:before { :root,:after,:before {
--app-color-primary: var(--eicui-base-color-primary-100); --app-color-primary: #473;
--app-color-secondary: var(--eicui-base-color-grey-100); --app-color-secondary: var(--eicui-base-color-grey-100);
--app-color-success: var(--eicui-base-color-success-100); --app-color-success: var(--eicui-base-color-success-100);
--app-color-danger: var(--eicui-base-color-danger-100); --app-color-danger: var(--eicui-base-color-danger-100);
@@ -24,18 +24,20 @@
--app-header-height: var(--eicui-app-top-message-height); --app-header-height: var(--eicui-app-top-message-height);
--app-menu-collapsed-width: 50px; --app-menu-collapsed-width: 50px;
--app-menu-expanded-width: 240px; --app-menu-expanded-width: 160px;
--app-menu-width: var(--app-menu-expanded-width); --app-menu-width: var(--app-menu-expanded-width);
} }
body[eicapp] { body[eicapp] {
all: unset;
display: grid; display: grid;
grid-template-rows: auto; grid-template-rows: auto;
grid-template-columns: min-content auto; grid-template-columns: min-content auto;
min-height: 100vh; min-height: 100vh;
box-sizing: border-box; box-sizing: border-box;
background: repeating-linear-gradient( -45deg, #000, #555 10px, #000 10px, #555 20px );
} }
[eicapp] [eicapptoolbar] { [eicapp] [eicapptoolbar] {
@@ -101,6 +103,7 @@ body[eicapp] {
[eicapp] .app-workspace .window.active { [eicapp] .app-workspace .window.active {
z-index: 3; z-index: 3;
background: var(--app-color-primary); background: var(--app-color-primary);
border-radius: .3rem;
} }
[eicapp] .app-workspace .window > header { display: grid; } [eicapp] .app-workspace .window > header { display: grid; }
[eicapp] .app-workspace .window > header h1 { [eicapp] .app-workspace .window > header h1 {
@@ -123,7 +126,7 @@ body[eicapp] {
[eicapp] .app-workspace .window > header .controls button.shrink { display: none; } [eicapp] .app-workspace .window > header .controls button.shrink { display: none; }
[eicapp] .app-workspace .window > section { [eicapp] .app-workspace .window > section {
padding: var(--eicui-base-spacing-xs) var(--eicui-base-spacing-s); padding: var(--eicui-base-spacing-xs) var(--eicui-base-spacing-s);
background: var(--app-bg-color); /*background: var(--app-bg-color);*/
cursor: default; cursor: default;
margin: 0; margin: 0;
overflow: auto; overflow: auto;
@@ -140,7 +143,7 @@ body[eicapp] {
width: 100%; width: 100%;
max-width:none; max-width:none;
padding: 0 var(--eicui-base-spacing-2xs) var(--eicui-base-spacing-3xl) var(--eicui-base-spacing-2xs); padding: 0 var(--eicui-base-spacing-2xs) var(--eicui-base-spacing-3xl) var(--eicui-base-spacing-2xs);
background-color: var(--app-bg-color); background: repeating-linear-gradient( -45deg, #000, #555 10px, #000 10px, #555 20px );
cursor: default; cursor: default;
margin: 0; margin: 0;
overflow: visible; overflow: visible;
@@ -192,6 +195,7 @@ body[eicapp] {
[eicapp] .app-content-thesaurus [eicchip] { [eicapp] .app-content-thesaurus [eicchip] {
box-shadow: 0px 0px 14px 0px #00000066; box-shadow: 0px 0px 14px 0px #00000066;
cursor: pointer; cursor: pointer;
background: var(--app-color-primary);
} }
[eicapp] .app-content-thesaurus [eicchip] label { cursor: pointer; } [eicapp] .app-content-thesaurus [eicchip] label { cursor: pointer; }
@@ -213,6 +217,9 @@ body[eicapp] {
[eicapp] [device="mobile"] article[eiccard] { [eicapp] [device="mobile"] article[eiccard] {
margin: 0; margin: 0;
} }
article[eiccard][media] > header {
padding: var(--eicui-base-spacing-l) var(--eicui-base-spacing-m) var(--eicui-base-spacing-s) var(--eicui-base-spacing-m);
}
.eic-session { .eic-session {
padding: 0; padding: 0;
@@ -256,3 +263,8 @@ body[eicapp] {
[device="mobile"] .cols-8 { [device="mobile"] .cols-8 {
grid-template-columns: 1fr 1fr; grid-template-columns: 1fr 1fr;
} }
div.window > section:first-of-type > article[eiccard]:first-of-type{
border: 2px solid var(--app-color-primary);
border-radius: .5rem;
}
+17 -11
View File
@@ -81,11 +81,11 @@ body {
} }
.glowing span:nth-child(3n + 2) { .glowing span:nth-child(3n + 2) {
animation: rotatedots-reverse 5s alternate infinite; animation: rotatedots-reverse 9s alternate infinite;
} }
.glowing span:nth-child(3n + 3) { .glowing span:nth-child(3n + 3) {
animation: rotatedots1 11s alternate infinite; animation: rotatedots1 15s alternate infinite;
} }
@keyframes fadeaway { @keyframes fadeaway {
@@ -95,17 +95,23 @@ body {
} }
@keyframes rotatedots1 { @keyframes rotatedots1 {
0% { transform: rotate(calc(180deg * var(--i))); } 0% { transform: rotate(calc(180deg * var(--i))); scale:20%;}
50% { transform: rotate(calc(0deg * var(--i))); } 25% { transform: rotate(calc(90deg * var(--i))); scale:100%;}
100% { transform: rotate(calc(360deg * var(--i))); } 50% { transform: rotate(calc(0deg * var(--i))); scale:80%;}
100% { transform: rotate(calc(360deg * var(--i))); scale:50%;}
} }
@keyframes rotatedots-reverse { @keyframes rotatedots-reverse {
0% { transform: rotate(calc(135deg * var(--i))); } 0% { transform: rotate(calc(135deg * var(--i))); scale:20%;}
50% { transform: rotate(calc(-45deg * var(--i))); } 25% { transform: rotate(calc(45deg * var(--i))); scale:100%;}
100% { transform: rotate(calc(315deg * var(--i))); } 50% { transform: rotate(calc(-45deg * var(--i))); scale:80%;}
100% { transform: rotate(calc(315deg * var(--i))); scale:50%;}
} }
.logointro{ .logointro{
filter: blur(14px); filter: blur(14px);
opacity: 0; opacity: 0;
@@ -133,7 +139,7 @@ body {
bottom: 15vh; bottom: 15vh;
color: aliceblue; color: aliceblue;
font-style: italic; font-style: italic;
font-size: 40px; font-size: 2rem;
border-radius: 100px; border-radius: 100px;
padding: 5px 40px; padding: 5px 40px;
background: radial-gradient(#82cc50, #0a8200); background: radial-gradient(#82cc50, #0a8200);
@@ -177,11 +183,11 @@ body {
width: 15rem; width: 15rem;
border-radius: 5px; border-radius: 5px;
border: none; border: none;
font-size: 1.3rem; font-size: 1rem;
} }
#login-dialog button{ #login-dialog button{
justify-self: end; justify-self: end;
font-size: 1.3rem; font-size: 1rem;
float: right; float: right;
} }
#login-dialog div.loginerr{ #login-dialog div.loginerr{
+7 -2
View File
@@ -11,10 +11,15 @@
"controller" : "/common/errorController", "controller" : "/common/errorController",
"method": "_401" "method": "_401"
}, },
{
"url": "/dashboard",
"role": [ "admin" ],
"controller" : "/dashboard/DashboardsController"
},
{ {
"url": "/", "url": "/",
"role": "Org_Member", "role": "admin",
"exturl": "/applicant" "exturl": "/dashboard"
}, },
{ {
"url": "/", "url": "/",
+2 -6
View File
@@ -21,7 +21,7 @@
"enabled": true, "enabled": true,
"levels": ["err","warn"], "levels": ["err","warn"],
"latestErrsMax": 20, "latestErrsMax": 20,
"postUrl": "xxxhttps://api.dev.eismea.eu/logger" "postUrl": "xxxhttps://a42.internike.com/api/logger"
}, },
"userLib": { "userLib": {
"className": "myUser", "className": "myUser",
@@ -33,13 +33,9 @@
"messageBus":{ "messageBus":{
"enabled": true, "enabled": true,
"debug": true, "debug": true,
"tokenUrl": "https://api.dev.eismea.eu/stable/msgBusToken",
"pathToWorker": "/core/libs/MessageBusWorker.js", "pathToWorker": "/core/libs/MessageBusWorker.js",
"protocol": "wss://", "protocol": "wss://",
"host": "bus.dev.eismea.eu", "host": "42.internike.com",
"port": "",
"XdevotpToken": "qhsdfkjhqsgdfkqhs",
"Xhost": "eismea.internike.com",
"Xport": "4443", "Xport": "4443",
"path": "/msgbus", "path": "/msgbus",
"connectTimeout": 5, "connectTimeout": 5,
@@ -0,0 +1,31 @@
class DashboardsController extends EICController {
constructor(params) {
super(params)
}
/**
*
* @returns
*/
index() {
let models = {
// mailings: new MailingsModel(payload['/mailings'].permissions)
}
// await app.Assets.loadHtml({name:'mailing/tile.html'})
this.loadWindow(
'dashboards/MainDashboardView',
{
title: 'Main dashboard',
static: true,
expanded: true
},
{
models: models
}
)
}
}
app.registerClass('DashboardsController', DashboardsController);
@@ -0,0 +1,28 @@
{
"routes": [
{
"url": "/",
"role": [ "admin" ],
"controller" : "/dashboard/DashboardsController",
"method": "index"
}
],
"models": [
],
"views": [
"dashboards/MainDashboardView"
],
"controllerDependencies": [
"/helpers/basicDialogs",
"/helpers/validators",
"/helpers/activeAttributes",
"/thirdparty/Snaptobus/snap.svg-min",
"/thirdparty/Snaptobus/snaptobus"
],
"assets": {
"styles": [
],
"json": [
]
}
}
+8 -3
View File
@@ -126,6 +126,8 @@ class myUser extends app.LoadedClasses.User {
} else { } else {
console.log('authenticated!') console.log('authenticated!')
this.isAuthenticated = true this.isAuthenticated = true
this.identity = jsonresp.payload.userInfos.identity
this.roles = jsonresp.payload.userInfos.roles
callBack() callBack()
} }
@@ -136,7 +138,7 @@ class myUser extends app.LoadedClasses.User {
* *
* @returns {string} * @returns {string}
*/ */
getMessageBusUserInfo() { return(this.identity.uuid) } getMessageBusUserInfo() { return(this.identity.username) }
async login(){ async login(){
const response = await fetch(app.config.userLib.loginEndpoint+'?'+crypto.randomUUID(), { const response = await fetch(app.config.userLib.loginEndpoint+'?'+crypto.randomUUID(), {
@@ -154,7 +156,8 @@ class myUser extends app.LoadedClasses.User {
if(jsonresp && jsonresp.success && jsonresp.payload){ if(jsonresp && jsonresp.success && jsonresp.payload){
if(jsonresp.payload.authenticated){ if(jsonresp.payload.authenticated){
this.isAuthenticated = true this.isAuthenticated = true
this.userInfos = jsonresp.payload.userInfos this.identity = jsonresp.payload.userInfos.identity
this.roles = jsonresp.payload.userInfos.roles
return(true) return(true)
} else { } else {
document.querySelector('div.loginerr').classList.add('show') document.querySelector('div.loginerr').classList.add('show')
@@ -172,7 +175,7 @@ class myUser extends app.LoadedClasses.User {
} }
} }
this.isAuthenticated = false this.isAuthenticated = false
this.userInfos = null this.identity = null
return(false) return(false)
} }
@@ -260,6 +263,8 @@ class myUser extends app.LoadedClasses.User {
setPreference(path, value) { setPreference(path, value) {
if(app.MessageBus) { if(app.MessageBus) {
let segments = path.split('.'); let segments = path.split('.');
console.log('=====>',this, this.preferences)
let pointer = this.preferences; let pointer = this.preferences;
for(let i = 0; i < segments.length - 1; i++) { for(let i = 0; i < segments.length - 1; i++) {
File diff suppressed because one or more lines are too long
+104
View File
@@ -0,0 +1,104 @@
/**
* @classdesc The main Snaptobus class
* @author Nike
* @version 1.0
*/
class Snaptobus{
constructor(config){
this.config = this.observeObject(config, this.configChange.bind(this))
}
observeObject(obj, onChange) {
const wrap = (value) =>
(value && typeof value === 'object')
? this.observeObject(value, onChange)
: value
const handler = {
set: (target, prop, value) => {
const oldValue = target[prop]
target[prop] = wrap(value)
onChange(prop, value, oldValue, target)
return true
},
deleteProperty: (target, prop) => {
const oldValue = target[prop]
delete target[prop]
onChange(prop, undefined, oldValue, target)
return true
}
}
// Walk initial keys/elements (construction time)
for (const key of Object.keys(obj)) {
obj[key] = wrap(obj[key])
}
return new Proxy(obj, handler)
}
configChange(prop, newval, oldval){
//TODO subscribe new chans
//TODO unsubscribe removed chans
//TODO update event filters
//
console.log(prop, oldval, newval)
}
getValueByPath(obj, path) {
return(path.split('.').reduce((acc, key) => acc?.[key], obj))
}
assignFromConfig(chan, event) {
const result = {}
for (const [key, rule] of Object.entries(this.config.assign)) {
if (typeof rule === 'string') { // plain path
result[key] = this.getValueByPath(event, rule)
} else if((typeof(rule) == 'object') && (typeof(rule.transformer) == 'function')) { // transformer
const fnargs = (rule.arguments || []).map(arg => this.getValueByPath(event,arg))
result[key] = rule.transformer(...fnargs)
}
}
return result
}
}
/*
const s2bConfig = [
{ chan: 'gps:agents', // What to subscribe to
events: [ // What to select on this chan
{ eventName: 'moving',
snaps: [
{
// selector will be used as css selector for a snap element / group,
// with LAST MINUTE template resolving of event properties (with eventual dots)
selector: '#${aid}',
assign: {
x: 'coords.x', // type string: event property, eventual dots to go down object
y: 'coords.y',
},
animate: true
}
]
},
]
},
{ chan: 'agent:*', // wildcards allowed
events: [
{ eventName: 'aging',
snaps: [
{
selector: '#{aid}',
assign: {
fill: { // transformer function
arguments: [ 'age' ], // What to give from the event as function's params
transformer: i => `rgb(${Math.round(255 * i / 10)},0,${Math.round(255 * (1 - i / 10))})`
},
},
}
]
},
]
},
]
*/
@@ -0,0 +1,8 @@
<article eiccard media class="mainDashboard">
<header>
<h1>Simulation Main dashboard</h1>
</header>
<section>
hello world
</section>
</article>
+28
View File
@@ -0,0 +1,28 @@
class MainDashboardView extends EICDomContent {
constructor() {
super()
Object.assign(this, app.helpers.activeAttributes)
//this.tileMarkup = app.Assets.Store.html['/app/assets/html/mailing/tile.html']
}
DOMContentLoaded(options) {
for(let model in options.models) this[model] = options.models[model]
const components = ui.eicfy(this.el)
this.setupTriggers(components)
this.setupRefs(components)
}
DOMContentFocused(options) {
// Avoid 2nd refesh on DomContentLoaded
if(this.wasBlured){
//this.refreshSearch()
}
this.wasBlured = false
}
DOMContentBlured(options) { this.wasBlured = true }
}
app.registerClass('MainDashboardView', MainDashboardView)
+5 -71
View File
@@ -36,38 +36,7 @@ class MessageBusWorker {
this.token = false this.token = false
this.stateMachine = 'DISCONNECTED' this.stateMachine = 'DISCONNECTED'
this.noReconnect = false this.noReconnect = false
// 'DISCONNECTED' this.connect();
// -> 'LOGIN' (receive challenge & answer to it)
// -> 'READY' (received logged=true)
this.getToken()
}
/**
*
*/
getToken() {
if(!this.config.devotpToken){
fetch(this.config.tokenUrl+'?'+crypto.randomUUID(),{
credentials: 'include'
})
.then(response => response.json(), (err => {console.log('ERROR IN FETCH:',err)}))
.then(data => {
if(data.success && data.payload && data.payload.token) {
this.token = data.payload.token
if(this.config.debug && ''=='sensitive-even-for-debug') console.log(`Received Token : ${this.token}`)
this.connect();
} else {
console.warn('Could not get messagebus token !')
//TODO retry once in a while / integrate in the whole connect process
// to be part of retrials...
}
})
} else {
console.warn('!!! Using dev token for bus !!!')
this.token = this.config.devotpToken
this.connect();
}
} }
/** /**
@@ -103,23 +72,11 @@ class MessageBusWorker {
* @param {*} e * @param {*} e
*/ */
WSonOpen(e){ WSonOpen(e){
this.stateMachine = 'LOGIN' this.stateMachine = 'READY'
clearTimeout( this.ConnectTimeout); clearTimeout( this.ConnectTimeout);
console.log('Websocket connection established'); console.log('Websocket connection established');
this.curReconnectTime = 0; this.curReconnectTime = 0;
} postMessage({'event': 'connected' });
/**
*
* @param {*} challenge
*/
async login(challenge) {
let data = new TextEncoder().encode(this.token+challenge)
let bytesBuf = await crypto.subtle.digest("SHA-512", data)
let arrayBuf = Array.from(new Uint8Array(bytesBuf))
let response = arrayBuf.map((b) => b.toString(16).padStart(2, "0")).join("")
if(this.config.debug && ''=='sensitive-even-for-debug') console.log(`Answering to challenge, with userinfo:`, response, this.userInfo)
this.clientActionDispatch({'action':'LOGIN', 'userInfo': this.userInfo , 'otp': response});
} }
/** /**
@@ -141,29 +98,6 @@ class MessageBusWorker {
return; return;
} }
//if(this.config.debug) console.log(`Received MSG (in state:${this.stateMachine}) :`, data, this.stateMachine)
// LOGIN messages
if(this.stateMachine == 'LOGIN'){
if(data.action!='LOGIN') { // Non LOGIN messages in a LOGIN state are garbage
console.warn('WSS: Non-login message in a LOGIN state',data.action)
return
}
if(data.challenge) { // step1: challenge to reply
if(this.config.debug && ''=='sensitive-even-for-debug') console.log(`Got challenge ${data.challenge}...`)
this.login(data.challenge)
return
} else if(data.logged===true){ // step2 logged !
if(this.config.debug) console.log(`Logged !`)
this.stateMachine = 'READY'
postMessage({'event': 'connected' });
return
} else if(data.logged===false){ // step2 bad login !
this.noReconnect = true
console.warn('WSS-Login: challenge-response refused. (session lost?)')
return
}
}
if((data.action=='PING') && this.keepAlive){ // Keep Alive is managed here if((data.action=='PING') && this.keepAlive){ // Keep Alive is managed here
this.clientActionDispatch({'action':'PONG'}); this.clientActionDispatch({'action':'PONG'});
return return
@@ -196,8 +130,8 @@ class MessageBusWorker {
} }
var rjit = (Math.random()*reconnectJitterPercent)-(reconnectJitterPercent/2); var rjit = (Math.random()*reconnectJitterPercent)-(reconnectJitterPercent/2);
this.curReconnectTime += (this.curReconnectTime*(rjit/100)); this.curReconnectTime += (this.curReconnectTime*(rjit/100));
// Reconnect in curReconnectTime (=>getToken THEN connect) // Reconnect in curReconnectTime
setTimeout(this.getToken.bind(this), Math.floor(1000*this.curReconnectTime)); setTimeout(this.connect.bind(this), Math.floor(1000*this.curReconnectTime));
} }
} }
+1 -1
View File
@@ -104,7 +104,7 @@ class Router {
} else if(exturl && (exturl != '')) { // Internal redirect } else if(exturl && (exturl != '')) { // Internal redirect
history.replaceState(null, '', exturl); history.replaceState(null, '', exturl);
this.route(); this.route();
} else { } else {
this.execRoute(...routeinfo); this.execRoute(...routeinfo);
} }
} }