redesing + resolved #8, resolved #9, resolved #10

This commit is contained in:
Arsen Mirzaev Tatyano-Muradovich 2025-01-12 20:15:37 +07:00
parent 97c8c58ce0
commit 1c6bbe3474
33 changed files with 1070 additions and 306 deletions

View File

@ -1,2 +1,13 @@
# works
Main site of the Svoboda organisation
## Installation
### NGINX
1. Create a NGINX server
You can copy an example of server file from here: `/examples/nginx/svoboda.conf`
2. Add support for javascript modules
Edit the file `/etc/nginx/mime.types`<br>
`application/javascript js;` -> `application/javascript js mjs;`

1
damper.mjs Submodule

@ -0,0 +1 @@
Subproject commit 68589e968cbc043f35c2948a9c90293b6f5f9cb9

View File

@ -2,7 +2,7 @@ server {
listen 80;
listen [::]:80;
server_name svoboda.dev.mirzaev.sexy;
server_name svoboda.works;
# 301 302
return 301 https://$server_name$request_uri;
@ -14,7 +14,7 @@ server {
listen [::]:443 ssl;
listen [::]:443 quic;
server_name svoboda.dev.mirzaev.sexy;
server_name svoboda.works;
http2 on;
http3 on;
@ -31,7 +31,7 @@ server {
keepalive_timeout 60;
include snippets/ssl-params.conf;
include snippets/ssl-mirzaev.conf;
include snippets/ssl-svoboda.conf;
include snippets/php8_4.conf;
location / {
@ -44,7 +44,7 @@ server {
add_header Cache-Control "max-age=2629746, public";
}
location ~* \.(?:css|js)$ {
location ~* \.(?:css|js|mjs|min)$ {
expires 1y;
access_log off;
add_header Cache-Control "max-age=31556952, public";

1
graph.mjs Submodule

@ -0,0 +1 @@
Subproject commit 0300f3376550b9d0a07d1c41db88452af67e366b

1
hotline.mjs Submodule

@ -0,0 +1 @@
Subproject commit 81aca4001629e8f3cab8a849c1e892dbac74c88a

View File

@ -1,10 +1,37 @@
#!/bin/bash
# Renaming project folder
if [ -d author/project ]; then
mv author/project author/works
fi
# Renaming project author folder
if [ -d author ]; then
mv author svoboda
fi
# Initializing the javascript modules folder
if [ ! -d svoboda/works/system/public/js/modules ]; then
mkdir -p ./svoboda/works/system/public/js/modules
fi
# Updating repositories
cd damper.mjs && git pull
cd ../hotline.mjs && git pull
cd ../graph.mjs && git pull
cd ../
# Installing "damper.min.mjs"
if [ ! -h svoboda/works/system/public/js/modules/damper.min.mjs ]; then
ln -s ../../../../../../damper.mjs/damper.min.mjs svoboda/works/system/public/js/modules/damper.min.mjs
fi
# installing "hotline.min.mjs"
if [ ! -h svoboda/works/system/public/js/modules/hotline.min.mjs ]; then
ln -s ../../../../../../hotline.mjs/hotline.min.mjs svoboda/works/system/public/js/modules/hotline.min.mjs
fi
# Installing "graph.min.mjs"
if [ ! -h svoboda/works/system/public/js/modules/graph.min.mjs ]; then
ln -s ../../../../../../graph.mjs/graph.min.mjs svoboda/works/system/public/js/modules/graph.min.mjs
fi

View File

@ -44,6 +44,78 @@ final class index extends core
if (str_contains($this->request->headers['accept'], content::any->value)) {
// Request for any response
// Initializing distributions
$this->view->distributions = [
[
'identifier' => 1,
'name' => 'Dreamers',
'members' => [
[
'identifier' => 1,
'name' => [
'first' => 'Arsen',
'second' => 'Mirzaev',
'other' => 'Tatyano-Muradovich'
]
],
[
'identifier' => 2,
'name' => [
'first' => 'Margarita',
'second' => 'Esenina',
'other' => ''
]
],
[
'identifier' => 5,
'name' => [
'first' => 'Maxim',
'second' => '',
'other' => ''
]
],
[
'identifier' => 6,
'name' => [
'first' => 'Hidden',
'second' => '',
'other' => ''
]
],
[
'identifier' => 7,
'name' => [
'first' => 'Hidden',
'second' => '',
'other' => ''
]
]
]
],
[
'identifier' => 2,
'name' => 'Unnamed',
'members' => [
[
'identifier' => 3,
'name' => [
'first' => 'Pavel',
'second' => '',
'other' => ''
]
],
[
'identifier' => 4,
'name' => [
'first' => 'Georgiy',
'second' => '',
'other' => ''
]
]
]
]
];
// Render page
$page = $this->view->render('/pages/statistics/total.html');

View File

@ -0,0 +1,274 @@
/**
* @name Core
*
* @description
* Core of the project
*
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
*/
class core {
// Domain
static domain = window.location.hostname;
// Language
static language = "ru";
/**
* Request
*
* @param {string} uri
* @param {string} body
* @param {string} method POST, GET...
* @param {object} headers
* @param {string} type Format of response (json, text...)
*
* @return {Promise}
*/
static async request(
uri = "/",
body,
method = "GET",
headers = {
"Content-Type": "application/x-www-form-urlencoded",
"Accept": "application/json",
},
type = "json",
) {
return await fetch(encodeURI(uri), { method, headers, body })
.then((response) => type === null || response[type]());
}
/**
* @name Modules
*
* @method connect(modules) Connect modules
*
* @return {Array} List of initialized modules
*/
static modules() {
return Object.keys(this).filter((module) =>
this[module]?.type === "module"
);
}
/**
* Сгенерировать окно выбора действия
*
* @param {string} title Верхний колонтинул
* @param {string} text Основное содержимое окна
* @param {string} left Содержимое левой кнопки
* @param {object} left_css Перечисление CSS-классов левой кнопки (массив)
* @param {function} left_click Действие после нажатия на левую кнопку
* @param {string} right Содержимое правой кнопки
* @param {object} right_css Перечисление CSS-классов правой кнопки (массив)
* @param {function} right_click Действие после нажатия на правую кнопку
*
* @return {void}
*/
/* static choose = core.damper(
(
title = "Выбор действия",
text = "",
left = "Да",
left_css = ["grass"],
left_click = () => {},
right = "Нет",
right_css = ["clay"],
right_click = () => {},
) => {
// Инициализация оболочки всплывающего окна
this.popup_body.wrap = document.createElement("div");
this.popup_body.wrap.setAttribute("id", "popup");
// Инициализация всплывающего окна
const popup = document.createElement("section");
popup.classList.add("list", "small");
// Инициализация заголовка всплывающего окна
const title_h3 = document.createElement("h3");
title_h3.classList.add("unselectable");
title_h3.innerText = title;
// Инициализация оболочки с основной информацией
const main = document.createElement("section");
main.classList.add("main");
// Инициализация колонки
const column = document.createElement("div");
column.classList.add("column");
// Инициализация текста
const text_p = document.createElement("p");
text_p.innerText = text;
// Инициализация строки
const row = document.createElement("div");
row.classList.add("row", "buttons");
// Инициализация левой кнопки
const left_button = document.createElement("button");
left_button.classList.add(...left_css);
left_button.innerText = left;
left_button.addEventListener("click", left_click);
// Инициализация правой кнопки
const right_button = document.createElement("button");
right_button.classList.add(...right_css);
right_button.innerText = right;
right_button.addEventListener("click", right_click);
// Инициализация окна с ошибками
this.popup_body.errors = document.createElement("section");
this.popup_body.errors.classList.add(
"errors",
"window",
"list",
"calculated",
"hidden",
);
this.popup_body.errors.setAttribute("data-errors", true);
// Инициализация элемента-тела (оболочки) окна с ошибками
const errors = document.createElement("section");
errors.classList.add("body");
// Инициализация элемента-списка ошибок
const dl = document.createElement("dl");
// Инициализация активного всплывающего окна
const old = document.getElementById("popup");
if (old instanceof HTMLElement) {
// Найдено активное окно
// Деинициализация быстрых действий по кнопкам
document.removeEventListener("keydown", this.buttons);
// Сброс блокировки
this.freeze = false;
// Удаление активного окна
old.remove();
}
// Запись в документ
popup.appendChild(title_h3);
column.appendChild(text_p);
row.appendChild(left_button);
row.appendChild(right_button);
column.appendChild(row);
main.appendChild(column);
popup.appendChild(main);
this.popup_body.wrap.appendChild(popup);
document.body.appendChild(this.popup_body.wrap);
errors.appendChild(dl);
this.popup_body.errors.appendChild(errors);
this.popup_body.wrap.appendChild(this.popup_body.errors);
// Инициализация ширины окна с ошибками
this.popup_body.errors.style.setProperty(
"--calculated-width",
popup.offsetWidth + "px",
);
// Инициализация переменных для окна с ошибками (12 - это значение gap из div#popup)
function top(errors) {
errors.style.setProperty("transition", "0s");
errors.style.setProperty(
"--top",
popup.offsetTop + popup.offsetHeight + 12 + "px",
);
setTimeout(() => errors.style.removeProperty("transition"), 100);
}
top(this.popup_body.errors);
const resize = new ResizeObserver(() => top(this.popup_body.errors));
resize.observe(this.popup_body.wrap);
// Инициализация функции закрытия всплывающего окна
const click = () => {
// Блокировка
if (this.freeze) return;
// Удаление всплывающего окна
this.popup_body.wrap.remove();
// Удаление статуса активной строки
row.removeAttribute("data-selected");
// Деинициализация быстрых действий по кнопкам
document.removeEventListener("keydown", this.buttons);
// Сброс блокировки
this.freeze = false;
};
// Инициализация функции добавления функции закрытия всплывающего окна
const enable = () =>
this.popup_body.wrap.addEventListener("click", click);
// Инициализация функции удаления функции закрытия всплывающего окна
const disable = () =>
this.popup_body.wrap.removeEventListener("click", click);
// Первичная активация функции удаления всплывающего окна
enable();
// Добавление функции удаления всплывающего окна по событиям
popup.addEventListener("mouseenter", disable);
popup.addEventListener("mouseleave", enable);
// Добавление функции удаления всплывающего окна по кнопкам
left_button.addEventListener("click", click);
right_button.addEventListener("click", click);
// Фокусировка
right_button.focus();
},
300,
); */
}
Object.assign(
core.modules,
{
/**
* @name Connect modules
*
* @param {(Array|string)} modules Names of modules or name of the module
* @param {boolean} [minified=false] Is this a minified module? (add ".min")
*
* @return {Prommise}
*/
async connect(modules, minified = false) {
// Normalisation required argiments
if (typeof modules === "string") modules = [modules];
if (modules instanceof Array) {
// Received and validated required arguments
// Initializing the registry of loaded modules
const loaded = [];
for (const module of modules) {
// Iterating over modules
// Downloading, importing and writing the module into a core property and into registry of loaded modules
core[module] =
loaded[module] =
await (await import(
`./modules/${module}` + (minified ? ".min.mjs" : ".mjs")
));
}
// Exit (success)
return loaded;
}
},
},
);

12
svoboda/works/system/public/js/elements/aside.js Normal file → Executable file
View File

@ -1,11 +1,17 @@
try {
import("https://codepen.io/mirzaev-sexy/pen/gOzBZOP.js").then((hotline) => {
core.modules.connect("hotline", true).then(
() => {
// Imported the hotline module
const element = document.getElementsByTagName("aside")[0];
element.instance = new hotline.default(element);
element.instance = new core.hotline.hotline(element);
element.instance.step = -1;
element.instance.start();
});
},
() => {
},
);
} catch (e) {}

0
svoboda/works/system/public/js/elements/diagram.js Normal file → Executable file
View File

View File

@ -0,0 +1,87 @@
try {
// Initializing the graph shell <section> element
const shell = document.getElementById("distributions");
// Initializing the initial node destination coordinates
const destination = {
left: window.innerWidth / 100 * 65,
top: window.innerHeight / 100 * 55,
};
// Initializing loading shell
const loading = shell.nextElementSibling;
if (loading instanceof HTMLElement) {
// Initialized loading shell
// Writing the initial node destination coordinates
loading.style.setProperty("--left", destination.left + "px");
loading.style.setProperty("--top", destination.top + "px");
}
core.modules.connect("graph", true).then(
() => {
// Imported the damper module
if (shell instanceof HTMLElement) {
// Initialized the graph shell <section> element
// Initializing the graph instance
const instance = new core.graph.core(shell);
// Writing settings of the graph instance
instance.living = 2000;
// instance.camera = true;
instance.operate = true;
//instance.left = window.innerWidth * 250; // 250vw (width 500vw)
//instance.top = window.innerHeight * 250; // 250vh (height 500vh)
// Registering every node
[...shell.children].forEach((node) =>
instance.node(new core.graph.node(node))
);
// Writing settings for every node
/* instance.nodes.forEach((node) => {
node.variables.get("inputs").type = "deg";
}); */
// temporary
shell.instance = instance;
const nodes = [...instance.nodes];
instance.edge(new core.graph.edge(nodes[1], nodes[0]));
instance.edge(new core.graph.edge(nodes[2], nodes[0]));
instance.edge(new core.graph.edge(nodes[3], nodes[0]));
instance.edge(new core.graph.edge(nodes[4], nodes[0]));
instance.edge(new core.graph.edge(nodes[5], nodes[0]));
instance.edge(new core.graph.edge(nodes[6], nodes[0]));
instance.edge(new core.graph.edge(nodes[7], nodes[6]));
instance.edge(new core.graph.edge(nodes[8], nodes[6]));
/* var max;
[...temp0.instance.nodes].forEach((node) => {
if (node.inputs.size > (max?.inputs.size || 0)) max = node;
}); */
nodes[0].move(
destination.left - nodes[0].radius,
destination.top - nodes[0].radius,
);
nodes[0].interactions.movement.active = false;
// nodes[0].interactions.pushing.active = false;
// nodes[0].interactions.pulling.active = false;
setTimeout(() => {
shell.classList.add("appearance", "animated");
nodes[0].interactions.movement.active = true;
}, 3000);
}
},
() => {
},
);
} catch (e) {}

0
svoboda/works/system/public/js/elements/eye.js Normal file → Executable file
View File

View File

@ -0,0 +1 @@
../../../../../../damper.mjs/damper.min.mjs

View File

@ -0,0 +1 @@
../../../../../../graph.mjs/graph.min.mjs

View File

@ -0,0 +1 @@
../../../../../../hotline.mjs/hotline.min.mjs

View File

@ -1,7 +1,7 @@
@charset "UTF-8";
aside {
z-index: 100;
z-index: 200;
margin-top: var(--gap);
grid-row: 1 / 2;
grid-column: 1 / 4;

View File

@ -6,8 +6,12 @@ body {
height: 100vh;
display: grid;
grid-template-rows: max(200px, 20vh) auto;
grid-template-columns: 60px auto 60px;
grid-template-columns: 60px auto 60px auto;
gap: var(--gap);
overflow: hidden;
background-color: var(--background-color);
background: -moz-linear-gradient(180deg, var(--background-color-top) 0%, var(--background-color-bottom) 100%);
background: -webkit-linear-gradient(180deg, var(--background-color-top) 0%, var(--background-color-bottom) 100%);
background: linear-gradient(180deg, var(--background-color-top) 0%, var(--background-color-bottom) 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr="var(--background-color-top)",endColorstr="var(--background-color-bottom)",GradientType=1);
}

View File

@ -16,14 +16,19 @@
--button-background-color: #9f9b39;
--section-border-color: #593535;
--section-background-color: #593535;
--section-block-background-color: #522d2d;
--section-block-background-color: #592727;
/* --section-background-color: #593535; */
--section-background-color: #4d2323;
--section-menu-background-color: #4b2828;
--section-menu-button-color: #fbffb6;
--section-menu-button-background-color-hover: #592c2c;
--section-menu-button-background-color-active: #412222;
--section-menu-button-background-color-selected: #412222;
/* --section-menu-button-background-color-selected: #412222; */
/* --section-menu-button-background-color-selected: #220c0c; */
--section-menu-button-background-color-selected: #5b3d2b;
/* --section-menu-background-color: #4b2828; */
/* --section-menu-background-color: #311515; */
--section-menu-background-color: #4f2b22;
--section-timeline-background-color: #143531;
--section-timeline-button-color: #859779;
@ -37,9 +42,8 @@
--section-aside-button-background-color: rgb(255 237 189 / 30%);
--section-aside-button-background-color-hover: rgb(77 9 9 / 70%);
--section-aside-button-background-color-active: rgb(77 9 9 / 70%);
--header-background-color: #351d1d;
--footer-background-color: #351d1d;
--background-color: #654949;
--header-background-color: #1e0a0a;
--footer-background-color: #1e0a0a;
--diagram-text-color: #c3a275;
--diagram-text-color-hover: #e5bb83;
@ -59,6 +63,12 @@
--diagram-legend-color-0: #461d1d;
color: var(--text-color);
/* --background-color: #654949; */
/* --background-color: #6f3d3d; */
--background-color: #402821;
--background-color-top: #402821;
--background-color-bottom: #2a1414;
}
}

View File

@ -0,0 +1,63 @@
@charset "UTF-8";
/* body:active {
cursor: move;
} */
section#distributions {
z-index: 50;
left: var(--graph-shell-left);
top: var(--graph-shell-top);
width: 100vw;
height: 100vh;
position: absolute;
}
section#distributions>article.node {
z-index: calc(500 + var(--graph-node-layer, 0) - var(--graph-node-inputs, 0));
left: var(--graph-node-from-left, var(--graph-node-left));
top: var(--graph-node-from-top, var(--graph-node-top));
width: var(--graph-node-augmented, 100px);
height: var(--graph-node-augmented, 100px);
position: absolute;
display: flex;
cursor: grab;
border-radius: 100%;
-webkit-box-shadow: 0px 3px 12px 2px rgba(0, 0, 0, 0.1);
-moz-box-shadow: 0px 3px 12px 2px rgba(0, 0, 0, 0.1);
box-shadow: 0px 3px 12px 2px rgba(0, 0, 0, 0.1);
}
section#distributions>article.node.distribution {
background-color: rgb(calc(140 + var(--graph-node-inputs) * 10), 110, 60);
}
section#distributions>article.node.member {
background-color: rgb(calc(140 + var(--graph-node-inputs) * 10), 100, 70);
}
section#distributions>article.node:active {
cursor: grabbing;
}
section#distributions>article.node>a:first-of-type {
margin: auto;
text-align: center;
text-decoration: unset;
font-weight: bold;
cursor: pointer;
color: black;
}
section#distributions>svg.edge {
z-index: -500;
position: absolute;
width: 100%;
height: 100%;
pointer-events: none;
}
section#distributions>svg.edge>line {
stroke: #443225;
stroke-width: 8px;
}

View File

@ -0,0 +1,82 @@
@charset "UTF-8";
@keyframes appearance {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
@keyframes disappearance {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
@keyframes node-movement {
0% {
left: var(--graph-node-from-left);
top: var(--graph-node-from-top);
}
100% {
left: var(--graph-node-to-left);
top: var(--graph-node-to-top);
}
}
section.graph:not(.appearance) {
opacity: 0;
}
section.graph.appearance:not(.animated) {
opacity: 1;
}
section.graph.appearance.animated {
animation-name: appearance;
animation-fill-mode: forwards;
animation-duration: 0.2s;
animation-timing-function: ease-in;
}
section.graph.dissapearance:not(.appearance.animated),
section.graph:not(.dissapearance).appearance.animated + div.loading {
animation-name: appearance;
animation-fill-mode: forwards;
animation-duration: 0.2s;
animation-timing-function: ease-in;
animation-direction: reverse;
}
section.graph .node.movement {
animation-name: node-movement;
animation-fill-mode: forwards;
animation-duration: 0.6s;
animation-timing-function: cubic-bezier(0, 1, 1, 1);
}
section.graph+div.loading {
z-index: 60;
position: absolute;
width: 100vw;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
pointer-events: none;
background-color: #00000040;
}
section.graph+div.loading>i.icon.loading {
position: absolute;
left: var(--left, -100vw);
top: var(--top, -100vh);
}

View File

@ -0,0 +1,35 @@
@charset "UTF-8";
main>section.row>section.main#total>div#diagram.column {
margin-top: auto;
width: 100%;
height: fit-content;
display: flex;
flex-direction: column;
gap: var(--gap);
}
main>section.row>section.main#total>div#diagram.column:has(svg.chart) {
padding-left: 1rem;
}
main>section.row>section.main#total>div#diagram.column>svg.pie {
height: min(30%, 300px);
}
main>section.row>section.main#total>div#diagram.column>small.formula {
margin: 0 1.4rem;
padding-right: 4rem;
font-size: 0.8rem;
color: var(--diagram-legend-text-color);
}
main>section.row>section.main#total>div#diagram.column>svg.chart {
margin: -2.5rem -1rem -3rem;
width: calc(100% + 1rem);
}
main>section.row>section.main#total>div#diagram.column>div.background {
width: 100%;
height: 170px;
}

View File

@ -0,0 +1,39 @@
@charset "UTF-8";
@keyframes spinner {
0% {
transform: rotate(0deg);
}
to {
transform: rotate(359deg);
}
}
i.icon.loading,
i.icon.loading::after,
i.icon.loading::before {
position: relative;
width: 20px;
height: 20px;
display: block;
box-sizing: border-box;
}
i.icon.loading::after,
i.icon.loading::before {
content: "";
position: absolute;
border-radius: 100px;
}
i.icon.loading::before {
border: 3px solid transparent;
border-top-color: currentColor;
animation: spinner 1s cubic-bezier(0.6, 0, 0.4, 1) infinite;
}
i.icon.loading::after {
opacity: 0.2;
border: 3px solid;
}

View File

@ -0,0 +1,26 @@
@charset "UTF-8";
i.icon.work,
i.icon.work::after {
display: block;
box-sizing: border-box;
box-shadow: 0 0 0 2px;
}
i.icon.work {
position: relative;
width: 14px;
height: 10px;
border-radius: 1px;
}
i.icon.work::after {
content: "";
position: absolute;
left: 4px;
top: -3px;
width: 6px;
height: 1px;
border-top-left-radius: 1px;
border-top-right-radius: 1px;
}

View File

@ -1,13 +1,14 @@
@charset "UTF-8";
main {
z-index: 200;
z-index: 100;
margin-bottom: var(--gap);
grid-row: 2 / 3;
grid-column: 2 / 3;
display: grid;
grid-template-rows: 2rem 43px auto;
gap: var(--gap);
pointer-events: none;
}
main>nav {
@ -15,6 +16,7 @@ main > nav {
display: flex;
align-items: center;
overflow: hidden;
pointer-events: all;
}
main>nav>* {
@ -58,6 +60,7 @@ main > nav#timeline > *.selected:active {
main>nav#menu {
grid-row: 2 / 3;
max-width: var(--section-main-width);
border-radius: 0.75rem;
background-color: var(--section-menu-background-color);
-webkit-box-shadow: 0px 0px 12px 2px rgba(0, 0, 0, 0.1);
@ -89,31 +92,40 @@ main > nav#menu > *:active {
background-color: var(--section-menu-button-background-color-active);
}
main > section {
main>section.row {
z-index: 200;
grid-row: 3 / 4;
padding: 1rem;
display: flex;
flex-direction: column;
gap: var(--gap);
border-radius: 0.75rem;
pointer-events: none;
}
main>section.row>section.main {
--padding: 1rem;
max-width: calc(var(--section-main-width) - var(--padding) * 2);
width: 100%;
padding: var(--padding);
display: flex;
gap: var(--gap);
pointer-events: all;
border-radius: 0.75rem;
background-color: var(--section-background-color);
-webkit-box-shadow: 0px 3px 12px 2px rgba(0, 0, 0, 0.1);
-moz-box-shadow: 0px 3px 12px 2px rgba(0, 0, 0, 0.1);
box-shadow: 0px 3px 12px 2px rgba(0, 0, 0, 0.1);
}
main > section > h1 {
main>section.row>section.main>h1 {
margin: 0.5rem 1rem 0.5rem 1rem;
font-size: 1.2rem;
}
main > section > h1.row {
main>section.row>section.main>h1.row {
align-items: center;
gap: var(--gap);
}
main > section > h1 > a {
main>section.row>section.main>h1>a {
min-width: 1rem;
height: 100%;
padding: 0.2rem;
@ -122,55 +134,55 @@ main > section > h1 > a {
align-items: center;
}
main > section > h1 > a:first-of-type {
main>section.row>section.main>h1>a:first-of-type {
margin-left: auto;
}
main > section > div.row {
main>section.row>section.main>div.row {
padding: 0rem 1rem;
justify-content: space-between;
}
main > section .block {
main>section.row>section.main .block {
background: var(--section-block-background-color);
}
main > section .block.text {
main>section.row>section.main .block.text {
padding: 0.6rem 0.8rem;
display: inline-flex;
flex-flow: row wrap;
}
main > section .block.text > a.continue {
main>section.row>section.main .block.text>a.continue {
margin-left: auto;
align-self: flex-end;
}
main > section p.block {
main>section.row>section.main p.block {
margin: unset;
}
main > section ul.block {
main>section.row>section.main ul.block {
min-width: 200px;
height: fit-content;
}
main > section > div.footer > small.phrase {
main>section.row>section.main>div.footer>small.phrase {
flex-grow: 1;
text-align: center;
}
main > section > div.footer > small#views {
main>section.row>section.main>div.footer>small#views {
position: relative;
margin-left: auto;
align-items: center;
}
main > section > div.footer > small#views > * {
main>section.row>section.main>div.footer>small#views>* {
z-index: 500;
}
main > section > div.footer > small#views > div.visibility {
main>section.row>section.main>div.footer>small#views>div.visibility {
z-index: 300;
position: absolute;
right: calc(-100px + 10.5px + 0rem);
@ -180,36 +192,16 @@ main > section > div.footer > small#views > div.visibility {
/* pointer-events: none; */
}
main > section#total > div#diagram.column {
margin-top: auto;
main>section.row>section.second {
--padding: 1rem;
max-width: calc(var(--section-main-width) - var(--padding) * 2);
width: 100%;
height: fit-content;
padding: var(--padding);
display: flex;
flex-direction: column;
gap: var(--gap);
}
main > section#total > div#diagram.column:has(svg.chart) {
padding-left: 1rem;
}
main > section#total > div#diagram.column > svg.pie {
height: min(30%, 300px);
}
main > section#total > div#diagram.column > small.formula {
margin: 0 1.4rem;
padding-right: 4rem;
font-size: 0.8rem;
color: var(--diagram-legend-text-color);
}
main > section#total > div#diagram.column > svg.chart {
margin: -2.5rem -1rem -3rem;
width: calc(100% + 1rem);
}
main > section#total > div#diagram.column > div.background {
width: 100%;
height: 170px;
border-radius: 0.75rem;
background-color: var(--section-background-color);
-webkit-box-shadow: 0px 3px 12px 2px rgba(0, 0, 0, 0.1);
-moz-box-shadow: 0px 3px 12px 2px rgba(0, 0, 0, 0.1);
box-shadow: 0px 3px 12px 2px rgba(0, 0, 0, 0.1);
}

View File

@ -2,6 +2,8 @@
:root {
--gap: min(12px, 1rem);
--section-main-width: 800px;
transition: 0.1s ease-out;
}
@ -113,3 +115,7 @@ li > span.value:last-child:before {
text-decoration: line-through;
color: var(--text-notice-color);
}
div.loading {
display: none;
}

View File

@ -61,4 +61,5 @@
{% endblock %}
{% block js %}
<script src="/js/elements/aside.js"></script>
{% endblock %}

0
svoboda/works/system/views/themes/default/eclipse.html Normal file → Executable file
View File

View File

View File

View File

@ -23,4 +23,5 @@
<link type="text/css" rel="stylesheet" href="/themes/default/css/aside.css" />
<link type="text/css" rel="stylesheet" href="/themes/default/css/footer.css" />
<link type="text/css" rel="stylesheet" href="/themes/default/css/colors.css" />
<link type="text/css" rel="stylesheet" href="/themes/default/css/icons/loading.css" />
{% endblock %}

View File

@ -19,6 +19,8 @@
{{ main|raw }}
{% endblock %}
</main>
{% block graph %}
{% endblock %}
{{ block('footer') }}
{% endblock %}

View File

@ -1,6 +1,6 @@
{% block js %}
<script src="/js/core.js"></script>
{% for element in js %}
<script {% if element.src %}src="{{ element.src }}"{% endif %} {% if element.type %}type="{{ element.type }}"{% endif %}>{{ element.innerText }}</script>
{% endfor %}
<script src="/js/elements/aside.js"></script>
{% endblock %}

View File

@ -8,13 +8,17 @@
<link type="text/css" rel="stylesheet" href="/themes/default/css/icons/controller.css" />
<link type="text/css" rel="stylesheet" href="/themes/default/css/icons/slash.css" />
<link type="text/css" rel="stylesheet" href="/themes/default/css/icons/camera.css" />
<link type="text/css" rel="stylesheet" href="/themes/default/css/elements/total.css" />
<link type="text/css" rel="stylesheet" href="/themes/default/css/diagram.css" />
<link type="text/css" rel="stylesheet" href="/themes/default/css/elements/graph.css" />
<link type="text/css" rel="stylesheet" href="/themes/default/css/elements/distributions.css" />
{% endblock %}
{% block main %}
{% include '/themes/default/elements/timeline.html' %}
{% include '/themes/default/elements/menu.html' %}
<section id="total" class="column rounded">
<section class="row">
<section id="total" class="column rounded main">
<h1 class="unselectable row">Общие показатели за 2024 год<a title="Поделиться"><i class="icon share"></i></a><a
title="Скачать XSLX-документ"><i class="icon document"></i></a></h1>
<div class="grow row">
@ -141,9 +145,25 @@
</small>
</div>
</section>
</section>
{% endblock %}
{% block graph %}
<section id="distributions" class="graph">
{% for distribution in distributions %}
<article id="{{ distribution.identifier }}" class="node distribution unselectable"><a>{{ distribution.name }}</a></article>
{% for member in distribution.members %}
<article id="{{ member.identifier }}" class="node member unselectable"><a>{{ member.name.second is empty ? member.name.first
: member.name.second }}</a></article>
{% endfor %}
{% endfor %}
</section>
<div class="loading"><i class="icon loading"></i></div>
{% endblock %}
{% block js %}
{{ parent() }}
<script src="/js/elements/distributions.js"></script>
<script src="/js/elements/diagram.js"></script>
<script src="/js/elements/eye.js"></script>
{% endblock %}