colour settings start

This commit is contained in:
2025-05-25 21:15:28 +02:00
parent a8aeb2dbee
commit 3fe3037aed
14 changed files with 221 additions and 57 deletions

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,56 @@
"""Add ColorSettings table
Revision ID: ca9026520dad
Revises: 76da0573e84b
Create Date: 2025-05-25 21:08:37.158900
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import postgresql
# revision identifiers, used by Alembic.
revision = 'ca9026520dad'
down_revision = '76da0573e84b'
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('color_settings',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('primary_color', sa.String(length=7), nullable=True),
sa.Column('secondary_color', sa.String(length=7), nullable=True),
sa.Column('updated_at', sa.DateTime(), nullable=True),
sa.PrimaryKeyConstraint('id')
)
with op.batch_alter_table('room_file', schema=None) as batch_op:
batch_op.alter_column('deleted',
existing_type=sa.BOOLEAN(),
nullable=True,
existing_server_default=sa.text('false'))
with op.batch_alter_table('trashed_file', schema=None) as batch_op:
batch_op.alter_column('deleted_at',
existing_type=postgresql.TIMESTAMP(),
nullable=True)
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('trashed_file', schema=None) as batch_op:
batch_op.alter_column('deleted_at',
existing_type=postgresql.TIMESTAMP(),
nullable=False)
with op.batch_alter_table('room_file', schema=None) as batch_op:
batch_op.alter_column('deleted',
existing_type=sa.BOOLEAN(),
nullable=False,
existing_server_default=sa.text('false'))
op.drop_table('color_settings')
# ### end Alembic commands ###

View File

@@ -321,4 +321,9 @@ def init_routes(main_bp):
@main_bp.route('/trash') @main_bp.route('/trash')
@login_required @login_required
def trash(): def trash():
return render_template('trash/trash.html') return render_template('trash/trash.html')
@main_bp.route('/settings')
@login_required
def settings():
return render_template('settings/settings.html')

View File

@@ -1,12 +1,8 @@
:root { /* Import color variables */
--primary-color: #16767b; @import 'colors.css';
--secondary-color: #741b5f;
--primary-light: #1a8a90;
--secondary-light: #8a2170;
}
body { body {
background-color: #f8f9fa; background-color: var(--bg-color);
} }
.auth-container { .auth-container {
@@ -17,12 +13,12 @@ body {
.auth-card { .auth-card {
border: none; border: none;
border-radius: 10px; border-radius: 10px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); box-shadow: 0 4px 6px var(--shadow-color);
} }
.auth-header { .auth-header {
background: linear-gradient(135deg, var(--primary-color) 0%, var(--secondary-color) 100%); background: linear-gradient(135deg, var(--primary-color) 0%, var(--secondary-color) 100%);
color: white; color: var(--white);
padding: 20px; padding: 20px;
border-radius: 10px 10px 0 0; border-radius: 10px 10px 0 0;
} }
@@ -39,7 +35,7 @@ body {
.form-control:focus { .form-control:focus {
border-color: var(--primary-color); border-color: var(--primary-color);
box-shadow: 0 0 0 0.2rem rgba(22, 118, 123, 0.25); box-shadow: 0 0 0 0.2rem var(--shadow-color-light);
} }
.alert { .alert {

View File

@@ -1,12 +1,8 @@
:root { /* Import color variables */
--primary-color: #16767b; @import 'colors.css';
--secondary-color: #741b5f;
--primary-light: #1a8a90;
--secondary-light: #8a2170;
}
body { body {
background-color: #f8f9fa; background-color: var(--bg-color);
} }
.navbar { .navbar {
@@ -17,9 +13,9 @@ body {
} }
.sidebar { .sidebar {
background-color: white; background-color: var(--white);
min-height: calc(100vh - 56px); min-height: calc(100vh - 56px);
box-shadow: 2px 0 5px rgba(0, 0, 0, 0.1); box-shadow: 2px 0 5px var(--shadow-color);
position: sticky; position: sticky;
top: 56px; /* Height of the navbar */ top: 56px; /* Height of the navbar */
height: calc(100vh - 56px); height: calc(100vh - 56px);
@@ -27,19 +23,19 @@ body {
} }
.sidebar .nav-link { .sidebar .nav-link {
color: #333; color: var(--text-dark);
padding: 0.8rem 1rem; padding: 0.8rem 1rem;
border-radius: 0.25rem; border-radius: 0.25rem;
margin: 0.2rem 0; margin: 0.2rem 0;
} }
.sidebar .nav-link:hover { .sidebar .nav-link:hover {
background-color: #f8f9fa; background-color: var(--bg-color);
} }
.sidebar .nav-link.active { .sidebar .nav-link.active {
background-color: var(--primary-color); background-color: var(--primary-color);
color: white; color: var(--white);
} }
.sidebar .nav-link i { .sidebar .nav-link i {
@@ -53,7 +49,7 @@ body {
.card { .card {
border: none; border: none;
border-radius: 10px; border-radius: 10px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); box-shadow: 0 2px 4px var(--shadow-color);
} }
.btn-primary { .btn-primary {

51
static/css/colors.css Normal file
View File

@@ -0,0 +1,51 @@
:root {
/* Primary Colors */
--primary-color: #16767b;
--primary-light: #1a8a90;
/* Secondary Colors */
--secondary-color: #741b5f;
--secondary-light: #8a2170;
/* Background Colors */
--bg-color: #f8f9fa;
--white: #ffffff;
--primary-bg-light: #e6f3f4;
/* Text Colors */
--text-dark: #333333;
--text-muted: #6c757d;
/* Status Colors */
--warning-color: #ffd700;
--danger-color: #dc3545;
/* Shadow Colors */
--shadow-color: rgba(0, 0, 0, 0.1);
--shadow-color-light: rgba(0, 0, 0, 0.25);
/* Border Colors */
--border-color: #dee2e6;
--border-light: #e9ecef;
/* Opacity Colors */
--primary-opacity-8: rgba(22, 118, 123, 0.08);
--primary-opacity-12: rgba(22, 118, 123, 0.12);
--primary-opacity-15: rgba(22, 118, 123, 0.15);
--primary-opacity-20: rgba(22, 118, 123, 0.2);
--warning-opacity-15: rgba(255, 215, 0, 0.15);
--danger-opacity-15: rgba(220, 53, 69, 0.15);
/* Chart Colors */
--chart-primary: #16767b;
--chart-secondary: #741b5f;
--chart-warning: #ffd700;
--chart-primary-light: #2c9da9;
--chart-primary-lighter: #43c4d3;
--chart-primary-lightest: #5ad9e8;
--chart-primary-pale: #71eefd;
--chart-secondary-light: #8a2b73;
--chart-secondary-lighter: #a03b87;
--chart-secondary-lightest: #b64b9b;
--chart-secondary-pale: #cc5baf;
}

View File

@@ -1,11 +1,5 @@
:root { /* Import color variables */
--primary-color: #16767b; @import 'colors.css';
--secondary-color: #741b5f;
--primary-light: #1a8a90;
--secondary-light: #8a2170;
--warning-color: #ffd700;
--danger-color: #dc3545;
}
/* Masonry Layout */ /* Masonry Layout */
.masonry { .masonry {
@@ -31,7 +25,7 @@
.card { .card {
border: none; border: none;
border-radius: 10px; border-radius: 10px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); box-shadow: 0 2px 4px var(--shadow-color);
} }
.card-title { .card-title {
@@ -77,24 +71,24 @@
/* Badge Styles */ /* Badge Styles */
.badge-starred { .badge-starred {
background-color: rgba(255, 215, 0, 0.15) !important; background-color: var(--warning-opacity-15) !important;
color: var(--warning-color) !important; color: var(--warning-color) !important;
} }
.badge-trash { .badge-trash {
background-color: rgba(220, 53, 69, 0.15) !important; background-color: var(--danger-opacity-15) !important;
color: var(--danger-color) !important; color: var(--danger-color) !important;
} }
/* Contact Link Styles */ /* Contact Link Styles */
.contact-link { .contact-link {
background-color: rgba(22, 118, 123, 0.08); background-color: var(--primary-opacity-8);
color: var(--primary-color); color: var(--primary-color);
transition: all 0.2s; transition: all 0.2s;
} }
.contact-link:hover { .contact-link:hover {
background-color: rgba(22, 118, 123, 0.12); background-color: var(--primary-opacity-12);
color: var(--primary-color); color: var(--primary-color);
} }
@@ -106,8 +100,8 @@
/* Alert Styles */ /* Alert Styles */
.alert-info { .alert-info {
background-color: rgba(22, 118, 123, 0.08); background-color: var(--primary-opacity-8);
border-color: rgba(22, 118, 123, 0.2); border-color: var(--primary-opacity-20);
color: var(--primary-color); color: var(--primary-color);
} }
@@ -118,7 +112,7 @@
} }
.list-group-item:not(:last-child) { .list-group-item:not(:last-child) {
border-bottom: 1px solid rgba(0, 0, 0, 0.05); border-bottom: 1px solid var(--shadow-color);
} }
/* Download Button */ /* Download Button */
@@ -126,14 +120,14 @@
background-color: var(--primary-color); background-color: var(--primary-color);
border: none; border: none;
border-radius: 6px; border-radius: 6px;
box-shadow: 0 1px 2px rgba(22, 118, 123, 0.08); box-shadow: 0 1px 2px var(--primary-opacity-8);
color: white; color: var(--white);
transition: all 0.2s; transition: all 0.2s;
} }
.btn-download:hover { .btn-download:hover {
background-color: var(--primary-light); background-color: var(--primary-light);
color: white; color: var(--white);
transform: translateY(-1px); transform: translateY(-1px);
box-shadow: 0 2px 4px rgba(22, 118, 123, 0.12); box-shadow: 0 2px 4px var(--primary-opacity-12);
} }

View File

@@ -1,11 +1,14 @@
/* Import color variables */
@import 'colors.css';
.btn-group .btn.active { .btn-group .btn.active {
background-color: #e6f3f4 !important; background-color: var(--primary-bg-light) !important;
border-color: #16767b !important; border-color: var(--primary-color) !important;
color: #16767b !important; color: var(--primary-color) !important;
} }
.btn-group .btn:not(.active) { .btn-group .btn:not(.active) {
background-color: #fff !important; background-color: var(--white) !important;
border-color: #e9ecef !important; border-color: var(--border-light) !important;
color: #6c757d !important; color: var(--text-muted) !important;
} }

View File

@@ -27,6 +27,13 @@
<i class="fas fa-bell text-xl" style="width: 2rem; height: 2rem; display: flex; align-items: center; justify-content: center;"></i> <i class="fas fa-bell text-xl" style="width: 2rem; height: 2rem; display: flex; align-items: center; justify-content: center;"></i>
</a> </a>
</li> </li>
{% if current_user.is_admin %}
<li class="nav-item">
<a class="nav-link flex items-center justify-center" href="{{ url_for('main.settings') }}">
<i class="fas fa-cog text-xl" style="width: 2rem; height: 2rem; display: flex; align-items: center; justify-content: center;"></i>
</a>
</li>
{% endif %}
<li class="nav-item dropdown"> <li class="nav-item dropdown">
<a class="nav-link dropdown-toggle flex items-center gap-2" href="#" id="navbarDropdown" role="button" data-bs-toggle="dropdown"> <a class="nav-link dropdown-toggle flex items-center gap-2" href="#" id="navbarDropdown" role="button" data-bs-toggle="dropdown">
<img src="{{ url_for('profile_pic', filename=current_user.profile_picture) if current_user.profile_picture else url_for('static', filename='default-avatar.png') }}" <img src="{{ url_for('profile_pic', filename=current_user.profile_picture) if current_user.profile_picture else url_for('static', filename='default-avatar.png') }}"
@@ -37,7 +44,9 @@
</a> </a>
<ul class="dropdown-menu dropdown-menu-end"> <ul class="dropdown-menu dropdown-menu-end">
<li><a class="dropdown-item" href="{{ url_for('main.profile') }}"><i class="fas fa-user"></i> Profile</a></li> <li><a class="dropdown-item" href="{{ url_for('main.profile') }}"><i class="fas fa-user"></i> Profile</a></li>
<li><a class="dropdown-item" href="#"><i class="fas fa-cog"></i> Settings</a></li> {% if current_user.is_admin %}
<li><a class="dropdown-item" href="{{ url_for('main.settings') }}"><i class="fas fa-cog"></i> Settings</a></li>
{% endif %}
<li><hr class="dropdown-divider"></li> <li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item" href="{{ url_for('auth.logout') }}"><i class="fas fa-sign-out-alt"></i> Logout</a></li> <li><a class="dropdown-item" href="{{ url_for('auth.logout') }}"><i class="fas fa-sign-out-alt"></i> Logout</a></li>
</ul> </ul>

View File

@@ -62,6 +62,26 @@
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script> <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script> <script>
document.addEventListener('DOMContentLoaded', function() { document.addEventListener('DOMContentLoaded', function() {
// Helper function to get computed CSS variable value
function getCssVar(varName) {
return getComputedStyle(document.documentElement).getPropertyValue(varName).trim();
}
// Get all chart colors
const chartColors = {
primary: getCssVar('--chart-primary'),
secondary: getCssVar('--chart-secondary'),
warning: getCssVar('--chart-warning'),
primaryLight: getCssVar('--chart-primary-light'),
primaryLighter: getCssVar('--chart-primary-lighter'),
primaryLightest: getCssVar('--chart-primary-lightest'),
primaryPale: getCssVar('--chart-primary-pale'),
secondaryLight: getCssVar('--chart-secondary-light'),
secondaryLighter: getCssVar('--chart-secondary-lighter'),
secondaryLightest: getCssVar('--chart-secondary-lightest'),
secondaryPale: getCssVar('--chart-secondary-pale')
};
// Contact Status Chart // Contact Status Chart
const statusCtx = document.getElementById('statusChart'); const statusCtx = document.getElementById('statusChart');
if (statusCtx) { if (statusCtx) {
@@ -71,7 +91,7 @@ document.addEventListener('DOMContentLoaded', function() {
labels: ['Active', 'Inactive'], labels: ['Active', 'Inactive'],
datasets: [{ datasets: [{
data: [{{ active_count }}, {{ inactive_count }}], data: [{{ active_count }}, {{ inactive_count }}],
backgroundColor: ['#16767b', '#741b5f'], backgroundColor: [chartColors.primary, chartColors.secondary],
borderWidth: 0, borderWidth: 0,
hoverOffset: 4 hoverOffset: 4
}] }]
@@ -98,7 +118,7 @@ document.addEventListener('DOMContentLoaded', function() {
labels: ['Starred', 'Unstarred'], labels: ['Starred', 'Unstarred'],
datasets: [{ datasets: [{
data: [{{ starred_count }}, {{ file_count - starred_count }}], data: [{{ starred_count }}, {{ file_count - starred_count }}],
backgroundColor: ['#ffd700', '#16767b'], backgroundColor: [chartColors.warning, chartColors.primary],
borderWidth: 0, borderWidth: 0,
hoverOffset: 4 hoverOffset: 4
}] }]
@@ -124,8 +144,16 @@ document.addEventListener('DOMContentLoaded', function() {
datasets: [{ datasets: [{
data: [{% for type in storage_by_type %}{{ type.total_size }}{% if not loop.last %}, {% endif %}{% endfor %}], data: [{% for type in storage_by_type %}{{ type.total_size }}{% if not loop.last %}, {% endif %}{% endfor %}],
backgroundColor: [ backgroundColor: [
'#16767b', '#2c9da9', '#43c4d3', '#5ad9e8', '#71eefd', chartColors.primary,
'#741b5f', '#8a2b73', '#a03b87', '#b64b9b', '#cc5baf' chartColors.primaryLight,
chartColors.primaryLighter,
chartColors.primaryLightest,
chartColors.primaryPale,
chartColors.secondary,
chartColors.secondaryLight,
chartColors.secondaryLighter,
chartColors.secondaryLightest,
chartColors.secondaryPale
], ],
borderWidth: 0, borderWidth: 0,
hoverOffset: 4 hoverOffset: 4
@@ -156,8 +184,16 @@ document.addEventListener('DOMContentLoaded', function() {
datasets: [{ datasets: [{
data: [{% for type in trash_by_type %}{{ type.count }}{% if not loop.last %}, {% endif %}{% endfor %}], data: [{% for type in trash_by_type %}{{ type.count }}{% if not loop.last %}, {% endif %}{% endfor %}],
backgroundColor: [ backgroundColor: [
'#16767b', '#2c9da9', '#43c4d3', '#5ad9e8', '#71eefd', chartColors.primary,
'#741b5f', '#8a2b73', '#a03b87', '#b64b9b', '#cc5baf' chartColors.primaryLight,
chartColors.primaryLighter,
chartColors.primaryLightest,
chartColors.primaryPale,
chartColors.secondary,
chartColors.secondaryLight,
chartColors.secondaryLighter,
chartColors.secondaryLightest,
chartColors.secondaryPale
], ],
borderWidth: 0, borderWidth: 0,
hoverOffset: 4 hoverOffset: 4

View File

@@ -0,0 +1,18 @@
{% extends "common/base.html" %}
{% from "components/header.html" import header %}
{% block title %}Settings - DocuPulse{% endblock %}
{% block content %}
{{ header(
title="Settings",
description="Manage your docupulse settings",
button_text="",
button_url="",
icon="fa-cog"
) }}
<div class="container-fluid">
<!-- Settings content will go here -->
</div>
{% endblock %}