feat(cloudron): add tirreno package artifacts
- Add CloudronStack/output/CloudronPackages-Artifacts/tirreno/ directory and its contents - Includes package manifest, Dockerfile, source code, documentation, and build artifacts - Add tirreno-1761840148.tar.gz as a build artifact - Add tirreno-cloudron-package-1761841304.tar.gz as the Cloudron package - Include all necessary files for the tirreno Cloudron package This adds the complete tirreno Cloudron package artifacts to the repository.
This commit is contained in:
		@@ -0,0 +1,155 @@
 | 
			
		||||
const MAX_STRING_LONG_NETNAME_IN_TABLE = 48;
 | 
			
		||||
const MAX_STRING_SHORT_NETNAME_IN_TABLE = 25;
 | 
			
		||||
const MAX_STRING_LENGTH_IN_TABLE = 18;
 | 
			
		||||
const MAX_STRING_USERID_LENGTH_IN_TABLE = 15;
 | 
			
		||||
const MAX_STRING_USER_SHORT_LENGTH_IN_TABLE = 19;
 | 
			
		||||
const MAX_STRING_USER_MEDIUM_LENGTH_IN_TABLE = 23;
 | 
			
		||||
const MAX_STRING_USER_LONG_LENGTH_IN_TABLE = 32;
 | 
			
		||||
const MAX_STRING_USER_LONG_LENGTH_IN_TILE = 26;
 | 
			
		||||
const MAX_STRING_USER_NAME_IN_TABLE = 10;
 | 
			
		||||
const MAX_STRING_LENGTH_IN_TABLE_ON_DASHBOARD = 24;
 | 
			
		||||
const MAX_STRING_LENGTH_FOR_EMAIL = 14;
 | 
			
		||||
const MAX_STRING_LENGTH_FOR_PHONE = 17;
 | 
			
		||||
const MAX_STRING_LENGTH_FULL_COUNTRY = 23;
 | 
			
		||||
const MAX_STRING_LENGTH_FOR_TILE = 15;
 | 
			
		||||
const MAX_STRING_DEVICE_OS_LENGTH = 10;
 | 
			
		||||
const MAX_STRING_LENGTH_URL = 32;
 | 
			
		||||
const MAX_TOOLTIP_URL_LENGTH = 50;
 | 
			
		||||
const MAX_TOOLTIP_LENGTH = 121;
 | 
			
		||||
 | 
			
		||||
const COLOR_RED    = '#FB6E88';
 | 
			
		||||
const COLOR_GREEN  = '#01EE99';
 | 
			
		||||
const COLOR_YELLOW = '#F5B944';
 | 
			
		||||
const COLOR_PURPLE = '#BE95EB';
 | 
			
		||||
 | 
			
		||||
const COLOR_LIGHT_GREEN = 'rgba(64,220,97,0.03)';
 | 
			
		||||
const COLOR_LIGHT_YELLOW = 'rgba(225,224,137,0.03)';
 | 
			
		||||
const COLOR_LIGHT_RED = 'rgba(255,51,102,0.03)';
 | 
			
		||||
const COLOR_LIGHT_PURPLE = 'rgba(190,149,235,0.03)';
 | 
			
		||||
 | 
			
		||||
const USER_LOW_TRUST_SCORE_INF    = 0;
 | 
			
		||||
const USER_LOW_TRUST_SCORE_SUP    = 33;
 | 
			
		||||
const USER_MEDIUM_TRUST_SCORE_INF = 33;
 | 
			
		||||
const USER_MEDIUM_TRUST_SCORE_SUP = 67;
 | 
			
		||||
const USER_HIGH_TRUST_SCORE_INF   = 67;
 | 
			
		||||
 | 
			
		||||
const USER_IPS_CRITICAL_VALUE       = 9;
 | 
			
		||||
const USER_EVENTS_CRITICAL_VALUE    = Infinity;
 | 
			
		||||
const USER_DEVICES_CRITICAL_VALUE   = 4;
 | 
			
		||||
const USER_COUNTRIES_CRITICAL_VALUE = 3;
 | 
			
		||||
 | 
			
		||||
const MAX_HOURS_CHART = 96;
 | 
			
		||||
const MIN_HOURS_CHART = 3;
 | 
			
		||||
const DAYS_IN_RANGE = 1;
 | 
			
		||||
const X_AXIS_SERIFS = 8;
 | 
			
		||||
 | 
			
		||||
const ASN_OVERRIDE = {
 | 
			
		||||
    '0':        'LAN',
 | 
			
		||||
    '64496':    'N/A',
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const COUNTRIES_EXCEPTIONS = [null, undefined, 'N/A', 'AN', 'CS', 'YU'];
 | 
			
		||||
 | 
			
		||||
const NORMAL_DEVICES = ['smartphone', 'desktop', 'bot', 'tablet'];
 | 
			
		||||
 | 
			
		||||
const PHONE_LANDLINE = [
 | 
			
		||||
    'landline',
 | 
			
		||||
    'FIXED_LINE',
 | 
			
		||||
    'FIXED_LINE_OR_MOBILE',
 | 
			
		||||
    'TOLL_FREE',
 | 
			
		||||
    'SHARED_COST',
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
const NO_RULES_MSG = {
 | 
			
		||||
    value:      'No rule',
 | 
			
		||||
    tooltip:    'User currently doesn\'t correspond to selected rules.',
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const UNDEFINED_RULES_MSG = {
 | 
			
		||||
    value:      'In queue',
 | 
			
		||||
    tooltip:    'Waiting for a score to be calculated.',
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const MIDLINE_HELLIP = '\u22EF';
 | 
			
		||||
const HELLIP = '\u2026';
 | 
			
		||||
const HYPHEN = '\uFF0D';
 | 
			
		||||
 | 
			
		||||
const COLOR_MAP = {
 | 
			
		||||
    'red':      {
 | 
			
		||||
        'main':     COLOR_RED,
 | 
			
		||||
        'light':    COLOR_LIGHT_RED,
 | 
			
		||||
    },
 | 
			
		||||
    'yellow':   {
 | 
			
		||||
        'main':     COLOR_YELLOW,
 | 
			
		||||
        'light':    COLOR_LIGHT_YELLOW,
 | 
			
		||||
    },
 | 
			
		||||
    'green':    {
 | 
			
		||||
        'main':     COLOR_GREEN,
 | 
			
		||||
        'light':    COLOR_LIGHT_GREEN,
 | 
			
		||||
    },
 | 
			
		||||
    'purple':   {
 | 
			
		||||
        'main':     COLOR_PURPLE,
 | 
			
		||||
        'light':    COLOR_LIGHT_PURPLE,
 | 
			
		||||
    },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export {
 | 
			
		||||
    MAX_STRING_LONG_NETNAME_IN_TABLE,
 | 
			
		||||
    MAX_STRING_SHORT_NETNAME_IN_TABLE,
 | 
			
		||||
    MAX_STRING_LENGTH_IN_TABLE,
 | 
			
		||||
    MAX_STRING_USERID_LENGTH_IN_TABLE,
 | 
			
		||||
    MAX_STRING_USER_SHORT_LENGTH_IN_TABLE,
 | 
			
		||||
    MAX_STRING_USER_MEDIUM_LENGTH_IN_TABLE,
 | 
			
		||||
    MAX_STRING_USER_LONG_LENGTH_IN_TABLE,
 | 
			
		||||
    MAX_STRING_USER_LONG_LENGTH_IN_TILE,
 | 
			
		||||
    MAX_STRING_USER_NAME_IN_TABLE,
 | 
			
		||||
    MAX_STRING_LENGTH_IN_TABLE_ON_DASHBOARD,
 | 
			
		||||
    MAX_STRING_LENGTH_FOR_EMAIL,
 | 
			
		||||
    MAX_STRING_LENGTH_FOR_PHONE,
 | 
			
		||||
    MAX_STRING_LENGTH_FULL_COUNTRY,
 | 
			
		||||
    MAX_STRING_LENGTH_FOR_TILE,
 | 
			
		||||
    MAX_STRING_DEVICE_OS_LENGTH,
 | 
			
		||||
    MAX_STRING_LENGTH_URL,
 | 
			
		||||
    MAX_TOOLTIP_URL_LENGTH,
 | 
			
		||||
    MAX_TOOLTIP_LENGTH,
 | 
			
		||||
 | 
			
		||||
    COLOR_RED,
 | 
			
		||||
    COLOR_GREEN,
 | 
			
		||||
    COLOR_YELLOW,
 | 
			
		||||
    COLOR_PURPLE,
 | 
			
		||||
 | 
			
		||||
    COLOR_LIGHT_GREEN,
 | 
			
		||||
    COLOR_LIGHT_YELLOW,
 | 
			
		||||
    COLOR_LIGHT_RED,
 | 
			
		||||
    COLOR_LIGHT_PURPLE,
 | 
			
		||||
 | 
			
		||||
    USER_LOW_TRUST_SCORE_INF,
 | 
			
		||||
    USER_LOW_TRUST_SCORE_SUP,
 | 
			
		||||
    USER_MEDIUM_TRUST_SCORE_INF,
 | 
			
		||||
    USER_MEDIUM_TRUST_SCORE_SUP,
 | 
			
		||||
    USER_HIGH_TRUST_SCORE_INF,
 | 
			
		||||
 | 
			
		||||
    USER_IPS_CRITICAL_VALUE,
 | 
			
		||||
    USER_EVENTS_CRITICAL_VALUE,
 | 
			
		||||
    USER_DEVICES_CRITICAL_VALUE,
 | 
			
		||||
    USER_COUNTRIES_CRITICAL_VALUE,
 | 
			
		||||
 | 
			
		||||
    MAX_HOURS_CHART,
 | 
			
		||||
    MIN_HOURS_CHART,
 | 
			
		||||
    DAYS_IN_RANGE,
 | 
			
		||||
    X_AXIS_SERIFS,
 | 
			
		||||
 | 
			
		||||
    ASN_OVERRIDE,
 | 
			
		||||
 | 
			
		||||
    COUNTRIES_EXCEPTIONS,
 | 
			
		||||
    NORMAL_DEVICES,
 | 
			
		||||
    PHONE_LANDLINE,
 | 
			
		||||
    NO_RULES_MSG,
 | 
			
		||||
    UNDEFINED_RULES_MSG,
 | 
			
		||||
 | 
			
		||||
    MIDLINE_HELLIP,
 | 
			
		||||
    HELLIP,
 | 
			
		||||
    HYPHEN,
 | 
			
		||||
 | 
			
		||||
    COLOR_MAP,
 | 
			
		||||
};
 | 
			
		||||
@@ -0,0 +1,20 @@
 | 
			
		||||
const getQueryParams = (params) => {
 | 
			
		||||
    const data = {};
 | 
			
		||||
    Object.assign(data, params);
 | 
			
		||||
 | 
			
		||||
    if (params.dateRange) {
 | 
			
		||||
        data['dateTo']    = params.dateRange.dateTo;
 | 
			
		||||
        data['dateFrom']  = params.dateRange.dateFrom;
 | 
			
		||||
        data['keepDates'] = params.dateRange.keepDates;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (params.searchValue) {
 | 
			
		||||
        data['search'] = {
 | 
			
		||||
            value: params.searchValue
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return data;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export {getQueryParams};
 | 
			
		||||
@@ -0,0 +1,85 @@
 | 
			
		||||
const addDays = (date, days) => {
 | 
			
		||||
    const dateCopy = new Date(date);
 | 
			
		||||
    dateCopy.setDate(date.getDate() + days);
 | 
			
		||||
 | 
			
		||||
    return dateCopy;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const addHours = (date, hours) => {
 | 
			
		||||
    const ms = hours * 60 * 60 * 1000;
 | 
			
		||||
 | 
			
		||||
    const dateCopy = new Date(date);
 | 
			
		||||
    dateCopy.setTime(date.getTime() + ms);
 | 
			
		||||
 | 
			
		||||
    return dateCopy;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
//https://stackoverflow.com/a/12550320
 | 
			
		||||
const padZero = (n, s = 2) => {
 | 
			
		||||
    return (s > 0) ? ('000'+n).slice(-s) : (n+'000').slice(0, -s);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const notificationTime = () => {
 | 
			
		||||
    const dt        = new Date();
 | 
			
		||||
    const day       = padZero(dt.getDate());
 | 
			
		||||
    const month     = padZero(dt.getMonth() + 1);
 | 
			
		||||
    const year      = padZero(dt.getFullYear(), 4);
 | 
			
		||||
    const hours     = padZero(dt.getHours());
 | 
			
		||||
    const minutes   = padZero(dt.getMinutes());
 | 
			
		||||
    const seconds   = padZero(dt.getSeconds());
 | 
			
		||||
 | 
			
		||||
    return `[${day}/${month}/${year} ${hours}:${minutes}:${seconds}]`;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// offsetInSeconds is not inverted as .getTimezoneOffset() result
 | 
			
		||||
const formatIntTimeUtc = (ts, useTime, offsetInSeconds = 0) => {
 | 
			
		||||
    const dt = new Date(ts + ((new Date()).getTimezoneOffset() * 60 + offsetInSeconds) * 1000);
 | 
			
		||||
 | 
			
		||||
    let m = dt.getMonth() + 1;
 | 
			
		||||
    let d = dt.getDate();
 | 
			
		||||
    let y = dt.getFullYear();
 | 
			
		||||
    m = padZero(m);
 | 
			
		||||
    d = padZero(d);
 | 
			
		||||
    y = padZero(y, 4);
 | 
			
		||||
 | 
			
		||||
    if (!useTime) {
 | 
			
		||||
        return `${d}/${m}/${y}`;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let h = dt.getHours();
 | 
			
		||||
    let i = dt.getMinutes();
 | 
			
		||||
    let s = dt.getSeconds();
 | 
			
		||||
    h = padZero(h);
 | 
			
		||||
    i = padZero(i);
 | 
			
		||||
    s = padZero(s);
 | 
			
		||||
 | 
			
		||||
    return `${d}/${m}/${y} ${h}:${i}:${s}`;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const formatStringTime = (dt) => {
 | 
			
		||||
 | 
			
		||||
    let m = dt.getMonth() + 1;
 | 
			
		||||
    let d = dt.getDate();
 | 
			
		||||
    let y = dt.getFullYear();
 | 
			
		||||
    m = padZero(m);
 | 
			
		||||
    d = padZero(d);
 | 
			
		||||
    y = padZero(y, 4);
 | 
			
		||||
 | 
			
		||||
    let h = dt.getHours();
 | 
			
		||||
    let i = dt.getMinutes();
 | 
			
		||||
    let s = dt.getSeconds();
 | 
			
		||||
    h = padZero(h);
 | 
			
		||||
    i = padZero(i);
 | 
			
		||||
    s = padZero(s);
 | 
			
		||||
 | 
			
		||||
    return `${y}-${m}-${d}T${h}:${i}:${s}`;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export {
 | 
			
		||||
    formatIntTimeUtc,
 | 
			
		||||
    formatStringTime,
 | 
			
		||||
    notificationTime,
 | 
			
		||||
    padZero,
 | 
			
		||||
    addDays,
 | 
			
		||||
    addHours,
 | 
			
		||||
};
 | 
			
		||||
@@ -0,0 +1,43 @@
 | 
			
		||||
import {notificationTime} from './Date.js?v=2';
 | 
			
		||||
 | 
			
		||||
const handleAjaxError = (xhr, status, error) => {
 | 
			
		||||
    // ignore abort, but not network issues
 | 
			
		||||
    if ((xhr.status === 0 && xhr.readyState === 0) || (status && status.status === 0)) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (xhr.status === 401 || xhr.status === 403) {
 | 
			
		||||
        window.location.href = escape('/login');
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const time = notificationTime();
 | 
			
		||||
    const msg = 'An error occurred while requesting resource. Please try again later.';
 | 
			
		||||
    const notificationEl = document.getElementById('client-error');
 | 
			
		||||
 | 
			
		||||
    const frag = document.createDocumentFragment();
 | 
			
		||||
 | 
			
		||||
    const span = document.createElement('span');
 | 
			
		||||
    span.className = 'faded';
 | 
			
		||||
    span.textContent = time;
 | 
			
		||||
 | 
			
		||||
    const el = document.createTextNode('\u00A0\u00A0' + msg);
 | 
			
		||||
 | 
			
		||||
    const button = document.createElement('button');
 | 
			
		||||
    button.className = 'delete';
 | 
			
		||||
 | 
			
		||||
    frag.appendChild(span);
 | 
			
		||||
    frag.appendChild(el);
 | 
			
		||||
    frag.appendChild(button);
 | 
			
		||||
 | 
			
		||||
    notificationEl.replaceChildren(frag);
 | 
			
		||||
 | 
			
		||||
    const deleteButton = notificationEl.querySelector('.delete');
 | 
			
		||||
    deleteButton.addEventListener('click', () => {
 | 
			
		||||
        notificationEl.classList.add('is-hidden');
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    notificationEl.classList.remove('is-hidden');
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export {handleAjaxError};
 | 
			
		||||
@@ -0,0 +1,8 @@
 | 
			
		||||
const fireEvent = (name, data) => {
 | 
			
		||||
    const details = {detail: data};
 | 
			
		||||
    const event = new CustomEvent(name, details);
 | 
			
		||||
 | 
			
		||||
    dispatchEvent(event);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export {fireEvent};
 | 
			
		||||
@@ -0,0 +1,10 @@
 | 
			
		||||
const debounce = callback => {
 | 
			
		||||
    let timeout;
 | 
			
		||||
 | 
			
		||||
    return (...args) => {
 | 
			
		||||
        clearTimeout(timeout);
 | 
			
		||||
        timeout = setTimeout(() => callback.apply(this, args), 500);
 | 
			
		||||
    };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export {debounce};
 | 
			
		||||
@@ -0,0 +1,71 @@
 | 
			
		||||
 | 
			
		||||
const replaceAll = (str, search, replacement) => {
 | 
			
		||||
    return str.split(search).join(replacement);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const getRuleClass = (value) => {
 | 
			
		||||
    switch (value) {
 | 
			
		||||
        case -20:
 | 
			
		||||
            return 'positive';
 | 
			
		||||
        case 10:
 | 
			
		||||
            return 'medium';
 | 
			
		||||
        case 20:
 | 
			
		||||
            return 'high';
 | 
			
		||||
        case 70:
 | 
			
		||||
            return 'extreme';
 | 
			
		||||
        default:
 | 
			
		||||
            return 'none';
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const formatTime = (str) => {
 | 
			
		||||
    const dayPattern = /(\d+)\s+days?/;
 | 
			
		||||
 | 
			
		||||
    let days = 0;
 | 
			
		||||
    const dayMatch = str.match(dayPattern);
 | 
			
		||||
    if (dayMatch) {
 | 
			
		||||
        days = parseInt(dayMatch[1], 10);
 | 
			
		||||
        str = str.replace(dayPattern, '').trim();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // remove milliseconds part if exists
 | 
			
		||||
    str = str.split('.')[0];
 | 
			
		||||
 | 
			
		||||
    const timePattern = /^\d{2}:\d{2}:\d{2}$/;
 | 
			
		||||
    if (!timePattern.test(str)) {
 | 
			
		||||
        return '';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const parts = str.split(':');
 | 
			
		||||
    const hours = parseInt(parts[0], 10);
 | 
			
		||||
    let minutes = parseInt(parts[1], 10);
 | 
			
		||||
    const seconds = parseInt(parts[2], 10);
 | 
			
		||||
 | 
			
		||||
    let humanTime = '';
 | 
			
		||||
    if (days > 0) {
 | 
			
		||||
        humanTime += `${days} d ${hours} h `;
 | 
			
		||||
    } else {
 | 
			
		||||
        minutes += 60 * hours;
 | 
			
		||||
    }
 | 
			
		||||
    if (minutes > 0) humanTime += `${minutes} min `;
 | 
			
		||||
    if (seconds > 0) humanTime += `${seconds} s`;
 | 
			
		||||
 | 
			
		||||
    if (humanTime === '') humanTime = '1 s';
 | 
			
		||||
 | 
			
		||||
    return humanTime.trim();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const openJson = (str) => {
 | 
			
		||||
    try {
 | 
			
		||||
        return JSON.parse(str);
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export {
 | 
			
		||||
    replaceAll,
 | 
			
		||||
    getRuleClass,
 | 
			
		||||
    formatTime,
 | 
			
		||||
    openJson,
 | 
			
		||||
};
 | 
			
		||||
		Reference in New Issue
	
	Block a user