167 lines
8.8 KiB
HTML
167 lines
8.8 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="ru">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<title>Домашняя страница</title>
|
|
<link rel="icon" href="/static/favicon.ico">
|
|
<link rel="apple-touch-icon" href="/static/apple-touch-icon.png">
|
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
<link rel="stylesheet" href="/static/main.289a6408.css">
|
|
<link rel="stylesheet" href="/static/flame.css">
|
|
<script src="https://unpkg.com/feather-icons"></script>
|
|
</head>
|
|
<body style="--color-primary: #FFFDEA; --color-accent: #5c5c5c; --color-background: #1a1a1a;">
|
|
<div id="root">
|
|
<div class="Layout_Container__HIHX7">
|
|
<div><input type="text" class="SearchBar_SearchBar__MQiwu" placeholder="Поиск..."></div>
|
|
<header class="Header_Header__GCJdR">
|
|
<span class="Header_HeaderMain__oLoBB">
|
|
<div style="display:flex; flex-direction:column; align-items:flex-start; gap:4px;">
|
|
<span style="font-size:2.2em; font-weight:bold;">{{ current_time }}</span>
|
|
<span style="font-size:1.1em;">{{ now }}</span>
|
|
</div>
|
|
<div class="WeatherWidget_WeatherWidget__3XlYt">
|
|
<div><canvas id="weather-icon" width="50" height="50"></canvas></div>
|
|
<div class="WeatherWidget_WeatherDetails__1y3CA">
|
|
{% if weather %}
|
|
<span>{{ weather.temp }}°C</span>
|
|
<span>{{ weather.cloud }}% облачность</span>
|
|
{% else %}
|
|
<span>--°C</span>
|
|
<span>--% облачность</span>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</span>
|
|
</header>
|
|
<a href="/applications"><h2 class="SectionHeadline_SectionHeadline__xa0oJ">Applications</h2></a>
|
|
<div class="AppGrid_AppGrid__ZxiaC">
|
|
{% for app in applications %}
|
|
<a href="{{ app.url }}" target="_blank" rel="noreferrer" class="AppCard_AppCard__NPTM5">
|
|
<div class="AppCard_AppCardIcon__ThrUl">
|
|
<i data-feather="{{ app.icon_name }}" class="AppCard_CustomIcon__+Tc3I" width="32" height="32"></i>
|
|
</div>
|
|
<div class="AppCard_AppCardDetails__HgNoY">
|
|
<h5>{{ app.name }}</h5>
|
|
<span>{{ app.description }}</span>
|
|
</div>
|
|
</a>
|
|
{% endfor %}
|
|
</div>
|
|
<div class="Home_HomeSpace__--hVj"></div>
|
|
<a href="/bookmarks"><h2 class="SectionHeadline_SectionHeadline__xa0oJ">Bookmarks</h2></a>
|
|
<div class="BookmarkGrid_BookmarkGrid__i3Tj4">
|
|
{% for group in bookmarks %}
|
|
<div class="BookmarkCard_BookmarkCard__ooGTe">
|
|
<h3 class="">{{ group.group }}</h3>
|
|
<div class="BookmarkCard_Bookmarks__alLCe">
|
|
{% for link in group.links %}
|
|
<a href="{{ link.url }}" target="_blank" rel="noreferrer">
|
|
<div class="BookmarkCard_BookmarkIcon__yWkUU">
|
|
<i data-feather="{{ link.icon_name }}" class="BookmarkCard_CustomIcon__D7Xys" width="16" height="16"></i>
|
|
</div>{{ link.name }}
|
|
</a>
|
|
{% endfor %}
|
|
</div>
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
<a class="Home_SettingsButton__DrUPz" href="#" id="edit-config-btn">
|
|
<svg viewBox="0 0 24 24" role="presentation" class="Icon_Icon__jzcrU"><path d="M12,15.5A3.5,3.5 0 0,1 8.5,12A3.5,3.5 0 0,1 12,8.5A3.5,3.5 0 0,1 15.5,12A3.5,3.5 0 0,1 12,15.5M19.43,12.97C19.47,12.65 19.5,12.33 19.5,12C19.5,11.67 19.47,11.34 19.43,11L21.54,9.37C21.73,9.22 21.78,8.95 21.66,8.73L19.66,5.27C19.54,5.05 19.27,4.96 19.05,5.05L16.56,6.05C16.04,5.66 15.5,5.32 14.87,5.07L14.5,2.42C14.46,2.18 14.25,2 14,2H10C9.75,2 9.54,2.18 9.5,2.42L9.13,5.07C8.5,5.32 7.96,5.66 7.44,6.05L4.95,5.05C4.73,4.96 4.46,5.05 4.34,5.27L2.34,8.73C2.21,8.95 2.27,9.22 2.46,9.37L4.57,11C4.53,11.34 4.5,11.67 4.5,12C4.5,12.33 4.53,12.65 4.57,12.97L2.46,14.63C2.27,14.78 2.21,15.05 2.34,15.27L4.34,18.73C4.46,18.95 4.73,19.03 4.95,18.95L7.44,17.94C7.96,18.34 8.5,18.68 9.13,18.93L9.5,21.58C9.54,21.82 9.75,22 10,22H14C14.25,22 14.46,21.82 14.5,21.58L14.87,18.93C15.5,18.67 16.04,18.34 16.56,17.94L19.05,18.95C19.27,19.03 19.54,18.95 19.66,18.73L21.66,15.27C21.78,15.05 21.73,14.78 21.54,14.63L19.43,12.97Z" style="fill: var(--color-background);"></path></svg>
|
|
<span style="margin-left:8px;">Редактировать настройки</span>
|
|
</a>
|
|
</div>
|
|
<div id="config-modal" style="display:none; position:fixed; z-index:1000; left:0; top:0; width:100vw; height:100vh; background:rgba(0,0,0,0.7); align-items:center; justify-content:center;">
|
|
<div id="config-modal-content" style="background:#fff; color:#222; padding:24px; border-radius:8px; min-width:320px; max-width:90vw; max-height:90vh; display:flex; flex-direction:column; gap:12px; resize:both; overflow:auto; width:60vw; height:60vh;">
|
|
<h2>Редактировать config.yaml</h2>
|
|
<div style="flex:1 1 auto; display:flex; flex-direction:column; min-height:200px;">
|
|
<div id="monaco-editor" style="flex:1 1 auto; min-width:300px; min-height:200px; max-width:100%; max-height:100%; height:100%; border:1px solid #ccc;"></div>
|
|
</div>
|
|
<div style="display:flex; gap:16px; margin-top:8px;">
|
|
<button id="save-config-btn" style="padding:10px 24px; font-size:1.1em;">Сохранить</button>
|
|
<button id="cancel-config-btn" style="padding:10px 24px; font-size:1.1em;">Отмена</button>
|
|
</div>
|
|
<div id="config-error" style="color:red;"></div>
|
|
</div>
|
|
</div>
|
|
<div class="NotificationCenter_NotificationCenter__Tfgzh" style="height: 0px;"></div>
|
|
</div>
|
|
<script src="https://cdn.jsdelivr.net/npm/monaco-editor@0.44.0/min/vs/loader.js"></script>
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/js-yaml/4.1.0/js-yaml.min.js"></script>
|
|
<script>feather.replace()</script>
|
|
<script>
|
|
let monacoEditor;
|
|
const editBtn = document.getElementById('edit-config-btn');
|
|
const modal = document.getElementById('config-modal');
|
|
const modalContent = document.getElementById('config-modal-content');
|
|
const saveBtn = document.getElementById('save-config-btn');
|
|
const cancelBtn = document.getElementById('cancel-config-btn');
|
|
const errorDiv = document.getElementById('config-error');
|
|
|
|
function resizeMonaco() {
|
|
if (monacoEditor) {
|
|
const editorDiv = document.getElementById('monaco-editor');
|
|
const rect = editorDiv.getBoundingClientRect();
|
|
monacoEditor.layout({ width: rect.width, height: rect.height });
|
|
}
|
|
}
|
|
|
|
// Drag/resize поддерживается через CSS (resize:both)
|
|
|
|
editBtn.onclick = function(e) {
|
|
e.preventDefault();
|
|
fetch('/api/config').then(r => r.json()).then(data => {
|
|
errorDiv.textContent = '';
|
|
modal.style.display = 'flex';
|
|
require.config({ paths: { 'vs': 'https://cdn.jsdelivr.net/npm/monaco-editor@0.44.0/min/vs' } });
|
|
require(['vs/editor/editor.main'], function () {
|
|
if (monacoEditor) {
|
|
monacoEditor.setValue(data.content);
|
|
setTimeout(resizeMonaco, 100);
|
|
} else {
|
|
monacoEditor = monaco.editor.create(document.getElementById('monaco-editor'), {
|
|
value: data.content,
|
|
language: 'yaml',
|
|
theme: 'vs-dark',
|
|
automaticLayout: false,
|
|
minimap: { enabled: false },
|
|
});
|
|
setTimeout(resizeMonaco, 100);
|
|
}
|
|
});
|
|
});
|
|
};
|
|
|
|
cancelBtn.onclick = function() {
|
|
modal.style.display = 'none';
|
|
};
|
|
|
|
saveBtn.onclick = function() {
|
|
const yamlText = monacoEditor.getValue();
|
|
try {
|
|
window.jsyaml.load(yamlText); // Проверка синтаксиса
|
|
fetch('/api/config', {
|
|
method: 'POST',
|
|
headers: {'Content-Type': 'application/json'},
|
|
body: JSON.stringify({content: yamlText})
|
|
}).then(r => r.json().then(data => ({ok: r.ok, data}))).then(res => {
|
|
if(res.ok) {
|
|
modal.style.display = 'none';
|
|
location.reload();
|
|
} else {
|
|
errorDiv.textContent = res.data.error || 'Ошибка сохранения';
|
|
}
|
|
});
|
|
} catch (e) {
|
|
errorDiv.textContent = 'Ошибка YAML: ' + e.message;
|
|
}
|
|
};
|
|
|
|
// Следим за изменением размера окна редактора
|
|
let resizeObserver = new ResizeObserver(() => {
|
|
resizeMonaco();
|
|
});
|
|
resizeObserver.observe(document.getElementById('config-modal-content'));
|
|
</script>
|
|
</body>
|
|
</html> |