Merge pull request 'fix_test' (#11) from fix_test into main продукты
Some checks failed
Auto-update README / update-readme (push) Has been cancelled
Some checks failed
Auto-update README / update-readme (push) Has been cancelled
Reviewed-on: #11
This commit is contained in:
commit
926f20707a
@ -70,6 +70,10 @@ if not DEBUG:
|
||||
LANGUAGE_COOKIE_HTTPONLY = True
|
||||
LANGUAGE_COOKIE_SAMESITE = 'Lax'
|
||||
|
||||
# Redis
|
||||
CELERY_BROKER_URL = os.environ.get('CELERY_BROKER_URL', 'redis://localhost:6379/0')
|
||||
CELERY_RESULT_BACKEND = os.environ.get('CELERY_RESULT_BACKEND', 'redis://localhost:6379/0')
|
||||
|
||||
CSRF_TRUSTED_ORIGINS = [
|
||||
'https://nikdizell.ru',
|
||||
'https://www.nikdizell.ru',
|
||||
@ -94,6 +98,8 @@ INSTALLED_APPS = [
|
||||
'django_ckeditor_5',
|
||||
'captcha',
|
||||
'turnstile',
|
||||
'products',
|
||||
'background_task',
|
||||
]
|
||||
|
||||
MIDDLEWARE = [
|
||||
@ -132,6 +138,7 @@ TEMPLATES = [
|
||||
'django.contrib.auth.context_processors.auth',
|
||||
'django.contrib.messages.context_processors.messages',
|
||||
'programmer.context_processors.contact_info',
|
||||
'programmer.context_processors.callback_form',
|
||||
],
|
||||
},
|
||||
},
|
||||
@ -286,5 +293,5 @@ CAPTCHA_LENGTH = 6
|
||||
CAPTCHA_FONT_SIZE = 30
|
||||
CAPTCHA_IMAGE_SIZE = (150, 50)
|
||||
|
||||
TURNSTILE_SITEKEY = '0x4AAAAAAC12NGPpc4TutFWA'
|
||||
TURNSTILE_SECRET = '0x4AAAAAAC12NCpzKHKE09JaXRDv0smrSAU'
|
||||
TURNSTILE_SITEKEY = os.getenv('TURNSTILE_SITEKEY')
|
||||
TURNSTILE_SECRET = os.getenv('TURNSTILE_SECRET')
|
||||
|
||||
@ -26,6 +26,7 @@ urlpatterns = [
|
||||
path('blog/', include('blog.urls')),
|
||||
path('ckeditor5/', include('django_ckeditor_5.urls')),
|
||||
path('captcha/', include('captcha.urls')),
|
||||
path('products/', include('products.urls', namespace='products')),
|
||||
# path('', index, name='home'),
|
||||
# path('about/', about, name='about'),
|
||||
# path('solution/', solution, name='solution'),
|
||||
|
||||
@ -5,9 +5,11 @@ from django.utils.html import strip_tags
|
||||
|
||||
|
||||
class CommentForm(forms.ModelForm):
|
||||
parent_id = forms.IntegerField(widget=forms.HiddenInput, required=False)
|
||||
|
||||
class Meta:
|
||||
model = Comment
|
||||
fields = ['author_name', 'author_email', 'content']
|
||||
fields = ['author_name', 'author_email', 'content', 'parent_id']
|
||||
widgets = {
|
||||
'author_name': forms.TextInput(attrs={'class': 'form-input', 'placeholder': 'Ваше имя'}),
|
||||
'author_email': forms.EmailInput(attrs={'class': 'form-input', 'placeholder': 'Ваш email'}),
|
||||
|
||||
@ -81,6 +81,18 @@ class Comment(models.Model):
|
||||
)
|
||||
author_name = models.CharField(max_length=100, verbose_name="Имя")
|
||||
author_email = models.EmailField(verbose_name="Email")
|
||||
user = models.ForeignKey(
|
||||
User, on_delete=models.SET_NULL, null=True, blank=True,
|
||||
verbose_name="Пользователь"
|
||||
)
|
||||
parent = models.ForeignKey(
|
||||
'self',
|
||||
on_delete=models.CASCADE,
|
||||
null=True,
|
||||
blank=True,
|
||||
related_name='replies',
|
||||
verbose_name='Ответ на'
|
||||
)
|
||||
content = models.TextField(verbose_name="Комментарий")
|
||||
is_moderated = models.BooleanField(default=False, verbose_name="Промодерировано")
|
||||
time_create = models.DateTimeField(auto_now_add=True, verbose_name="Дата создания")
|
||||
|
||||
@ -2,6 +2,11 @@ from typing import Optional, List
|
||||
from django.db.models import F, QuerySet
|
||||
from django.core.cache import cache
|
||||
from .models import Article, Category, Comment
|
||||
from django.contrib.auth import get_user_model
|
||||
|
||||
|
||||
User = get_user_model()
|
||||
|
||||
|
||||
def get_published_articles(category_slug: Optional[str] = None) -> QuerySet[Article]:
|
||||
"""
|
||||
@ -29,13 +34,16 @@ def increment_article_views(article: Article) -> None:
|
||||
"""Увеличивает счётчик просмотров статьи."""
|
||||
Article.objects.filter(pk=article.pk).update(views_count=F('views_count') + 1)
|
||||
|
||||
def add_comment_to_article(article: Article, data: dict) -> Comment:
|
||||
def add_comment_to_article(article: Article, data: dict, user: User = None, parent: Comment = None) -> Comment:
|
||||
"""Создание комментария к статье (без модерации)."""
|
||||
comment = Comment.objects.create(
|
||||
article=article,
|
||||
author_name=data['author_name'],
|
||||
author_email=data['author_email'],
|
||||
content=data['content']
|
||||
content=data['content'],
|
||||
user=user,
|
||||
parent=parent,
|
||||
is_moderated=False
|
||||
)
|
||||
# Здесь можно отправить уведомление администратору
|
||||
return comment
|
||||
|
||||
13
blog/signals.py
Normal file
13
blog/signals.py
Normal file
@ -0,0 +1,13 @@
|
||||
# blog/signals.py
|
||||
from django.db.models.signals import post_save
|
||||
from django.dispatch import receiver
|
||||
from .models import Article
|
||||
from programmer.models import Profile
|
||||
from django.core.mail import send_mail
|
||||
|
||||
@receiver(post_save, sender=Article)
|
||||
def notify_about_new_article(sender, instance, created, **kwargs):
|
||||
if created and instance.is_published:
|
||||
profiles = Profile.objects.filter(notify_new_articles=True, user__is_active=True)
|
||||
emails = [p.user.email for p in profiles if p.user.email]
|
||||
# отправка письма (можно асинхронно)
|
||||
@ -88,3 +88,28 @@
|
||||
background: none;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.comment-item {
|
||||
border-left: 2px solid var(--border-light);
|
||||
padding-left: 15px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
.comment-meta {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.badge-warning {
|
||||
background-color: #ffc107;
|
||||
color: #212529;
|
||||
padding: 0.2rem 0.5rem;
|
||||
border-radius: 4px;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
.comment-content {
|
||||
margin: 5px 0;
|
||||
}
|
||||
.reply-btn {
|
||||
margin-top: 5px;
|
||||
}
|
||||
@ -2,6 +2,7 @@
|
||||
{% load static %}
|
||||
{% load django_bootstrap5 %}
|
||||
{% load seo_tags %}
|
||||
{% load blog_extras %}
|
||||
|
||||
{% block extra_css %}
|
||||
<link id="theme-css-1c" rel="stylesheet" href="{% static 'programmer/css/1c-light.min.css' %}">
|
||||
@ -29,26 +30,19 @@
|
||||
|
||||
<!-- Комментарии -->
|
||||
<h3>Комментарии</h3>
|
||||
{% for comment in moderated_comments %}
|
||||
<div class="modern-card" style="margin-bottom: 1rem;">
|
||||
<p><strong>{{ comment.author_name }}</strong> ({{ comment.time_create|date:"d.m.Y H:i" }})</p>
|
||||
<p>{{ comment.content|linebreaks }}</p>
|
||||
{% if not comment.is_moderated %}
|
||||
<p><em>Комментарий ожидает модерации</em></p>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% empty %}
|
||||
<p>Пока нет комментариев. Будьте первым!</p>
|
||||
{% endfor %}
|
||||
<div id="comments-section">
|
||||
{% show_comments comments=root_comments %}
|
||||
</div>
|
||||
|
||||
<!-- Форма добавления комментария -->
|
||||
<div class="modern-card">
|
||||
<div class="modern-card" id="comment-form">
|
||||
<h4>Добавить комментарий</h4>
|
||||
|
||||
{% if user_is_authenticated %}
|
||||
<form method="post">
|
||||
{% csrf_token %}
|
||||
{{ form.as_p }}
|
||||
{{ form.parent_id }}
|
||||
<button type="submit" class="btn btn-primary">Отправить</button>
|
||||
</form>
|
||||
{% else %}
|
||||
@ -73,7 +67,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Скрипт для модального окна -->
|
||||
<script src="{% static 'programmer/js/recall.js' %}"></script>
|
||||
|
||||
{% endblock %}
|
||||
@ -81,18 +74,41 @@
|
||||
{% block extra_js %}
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Находим все изображения внутри .content-card (основной контент статьи)
|
||||
// Клик по изображениям в контенте
|
||||
document.querySelectorAll('.content-card img').forEach(function(img) {
|
||||
// Игнорируем, если изображение уже обёрнуто в ссылку
|
||||
if (img.closest('a')) return;
|
||||
|
||||
// Меняем курсор, чтобы показать, что изображение кликабельно
|
||||
img.style.cursor = 'pointer';
|
||||
img.addEventListener('click', function() {
|
||||
// Вызываем глобальную функцию openModal из recall.js
|
||||
ImageModal.open(this.src, this.alt || 'Изображение из статьи');
|
||||
});
|
||||
});
|
||||
|
||||
// Обработка кнопок "Ответить" (делегирование)
|
||||
document.getElementById('comments-section').addEventListener('click', function(e) {
|
||||
const btn = e.target.closest('.reply-btn');
|
||||
if (!btn) return;
|
||||
e.preventDefault();
|
||||
|
||||
const parentId = btn.dataset.commentId;
|
||||
const author = btn.dataset.author;
|
||||
|
||||
// Находим текст комментария
|
||||
const commentItem = btn.closest('.comment-item');
|
||||
const contentDiv = commentItem.querySelector('.comment-content');
|
||||
let quotedText = contentDiv.textContent.trim();
|
||||
|
||||
// Формируем цитату
|
||||
const quote = `> @${author}: ${quotedText}\n\n`;
|
||||
const textarea = document.getElementById('id_content');
|
||||
textarea.value = quote;
|
||||
|
||||
// Устанавливаем parent_id
|
||||
document.getElementById('id_parent_id').value = parentId;
|
||||
|
||||
// Фокус на поле ввода и прокрутка к форме
|
||||
textarea.focus();
|
||||
document.getElementById('comment-form').scrollIntoView({ behavior: 'smooth' });
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
34
blog/templates/blog/includes/comment_tree.html
Normal file
34
blog/templates/blog/includes/comment_tree.html
Normal file
@ -0,0 +1,34 @@
|
||||
{% load blog_extras %}
|
||||
{% load static %}
|
||||
|
||||
{% for comment in comments %}
|
||||
<div class="comment-item" style="margin-left: {{ depth|add:20 }}px; border-left: 2px solid var(--border-light); padding-left: 15px; margin-bottom: 15px;">
|
||||
<div class="comment-meta">
|
||||
<strong>{{ comment.author_name }}</strong>
|
||||
<span style="color: var(--text-light); font-size: 0.9rem;">#{{ comment.id }}</span>
|
||||
<span style="color: var(--text-light); font-size: 0.9rem;">{{ comment.time_create|date:"d.m.Y H:i" }}</span>
|
||||
{% if not comment.is_moderated %}
|
||||
<span class="badge badge-warning">⏳ На модерации</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="comment-content" style="margin: 5px 0;">
|
||||
{{ comment.content|linebreaks }}
|
||||
</div>
|
||||
{% if user.is_authenticated %}
|
||||
<button class="btn btn-sm btn-outline-primary reply-btn"
|
||||
data-comment-id="{{ comment.id }}"
|
||||
data-author="{{ comment.author_name }}">
|
||||
Ответить
|
||||
</button>
|
||||
{% endif %}
|
||||
{% with replies=comment.replies.all %}
|
||||
{% if replies %}
|
||||
<div class="replies" style="margin-top: 10px;">
|
||||
{% show_comments replies depth=forloop.parentloop.counter0|add:depth %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
</div>
|
||||
{% empty %}
|
||||
<p>Комментариев пока нет.</p>
|
||||
{% endfor %}
|
||||
@ -1,10 +1,12 @@
|
||||
from django import template
|
||||
from django.utils.html import strip_tags
|
||||
from blog.models import Comment
|
||||
import html
|
||||
|
||||
|
||||
register = template.Library()
|
||||
|
||||
|
||||
@register.filter
|
||||
def clean_html(value):
|
||||
"""Удаляет HTML-теги и заменяет сущности на символы."""
|
||||
@ -12,3 +14,22 @@ def clean_html(value):
|
||||
value = html.unescape(value)
|
||||
# Удаляем все HTML-теги
|
||||
return strip_tags(value)
|
||||
|
||||
|
||||
@register.inclusion_tag('blog/includes/comment_tree.html', takes_context=True)
|
||||
def show_comments(context, comments, depth=0):
|
||||
request = context.get('request')
|
||||
user = request.user if request and request.user.is_authenticated else None
|
||||
|
||||
filtered = []
|
||||
for c in comments:
|
||||
if c.is_moderated:
|
||||
filtered.append(c)
|
||||
elif user and c.user == user:
|
||||
filtered.append(c)
|
||||
|
||||
return {
|
||||
'comments': filtered,
|
||||
'depth': depth,
|
||||
'user': user
|
||||
}
|
||||
@ -4,7 +4,7 @@ from django.urls import reverse_lazy
|
||||
from django.contrib import messages
|
||||
from django.utils.decorators import method_decorator
|
||||
from django.views.decorators.cache import cache_page
|
||||
from .models import Article, Category
|
||||
from .models import Article, Category, Comment
|
||||
from .services import (
|
||||
get_published_articles, get_article_by_slug,
|
||||
increment_article_views, add_comment_to_article
|
||||
@ -103,9 +103,21 @@ class ArticleDetailView(MenuContextMixin, BreadcrumbMixin, DetailView):
|
||||
|
||||
form = CommentForm(request.POST, request=request)
|
||||
if form.is_valid():
|
||||
|
||||
parent_id = form.cleaned_data.get('parent_id')
|
||||
parent = None
|
||||
|
||||
if parent_id:
|
||||
try:
|
||||
parent = Comment.objects.get(id=parent_id, article=self.object)
|
||||
except Comment.DoesNotExist:
|
||||
pass
|
||||
|
||||
add_comment_to_article(
|
||||
article=self.object,
|
||||
data=form.cleaned_data
|
||||
data=form.cleaned_data,
|
||||
user=request.user,
|
||||
parent=parent
|
||||
)
|
||||
messages.success(request, "✅ Ваш комментарий отправлен на модерацию.")
|
||||
return redirect(self.object.get_absolute_url())
|
||||
@ -121,6 +133,9 @@ class ArticleDetailView(MenuContextMixin, BreadcrumbMixin, DetailView):
|
||||
if 'form' not in kwargs:
|
||||
context['form'] = CommentForm(request=self.request)
|
||||
|
||||
root_comments = self.object.comments.filter(parent__isnull=True, is_moderated=True)
|
||||
context['root_comments'] = root_comments
|
||||
|
||||
context.update({
|
||||
'moderated_comments': self.object.comments.filter(is_moderated=True),
|
||||
'user_is_authenticated': self.request.user.is_authenticated,
|
||||
|
||||
0
products/__init__.py
Normal file
0
products/__init__.py
Normal file
134
products/admin.py
Normal file
134
products/admin.py
Normal file
@ -0,0 +1,134 @@
|
||||
from django.contrib import admin
|
||||
from django.utils.html import format_html
|
||||
from django.shortcuts import render
|
||||
from django_ckeditor_5.widgets import CKEditor5Widget
|
||||
from .models import ProductCategory, Configuration, Product, Order
|
||||
from programmer.utils.email_notifications import send_multiple_order_notifications, send_multiple_order_notifications_async
|
||||
|
||||
|
||||
@admin.register(ProductCategory)
|
||||
class ProductCategoryAdmin(admin.ModelAdmin):
|
||||
list_display = ('name', 'slug', 'description')
|
||||
prepopulated_fields = {'slug': ('name',)}
|
||||
search_fields = ('name',)
|
||||
|
||||
|
||||
@admin.register(Configuration)
|
||||
class ConfigurationAdmin(admin.ModelAdmin):
|
||||
list_display = ('name', 'slug', 'description')
|
||||
prepopulated_fields = {'slug': ('name',)}
|
||||
search_fields = ('name',)
|
||||
|
||||
|
||||
@admin.register(Product)
|
||||
class ProductAdmin(admin.ModelAdmin):
|
||||
|
||||
def get_form(self, request, obj=None, **kwargs):
|
||||
form = super().get_form(request, obj, **kwargs)
|
||||
form.base_fields['content'].widget = CKEditor5Widget(config_name='default')
|
||||
return form
|
||||
|
||||
list_display = ('title', 'category', 'price', 'is_published', 'time_create', 'configurations_list')
|
||||
list_filter = ('is_published', 'category', 'configurations', 'time_create')
|
||||
search_fields = ('title', 'short_description', 'content')
|
||||
prepopulated_fields = {'slug': ('title',)}
|
||||
filter_horizontal = ('configurations',)
|
||||
date_hierarchy = 'time_create'
|
||||
actions = ['make_published', 'make_unpublished']
|
||||
|
||||
fieldsets = (
|
||||
(None, {
|
||||
'fields': ('title', 'slug', 'category', 'price', 'is_published')
|
||||
}),
|
||||
('Описания', {
|
||||
'fields': ('short_description', 'content', 'image'),
|
||||
'description': 'Краткое – обычный текст для карточки; полное – HTML-редактор для детальной страницы.'
|
||||
}),
|
||||
('Совместимость', {
|
||||
'fields': ('configurations',),
|
||||
}),
|
||||
('SEO', {
|
||||
'fields': ('meta_description',),
|
||||
'classes': ('collapse',),
|
||||
}),
|
||||
)
|
||||
|
||||
def configurations_list(self, obj):
|
||||
return ", ".join(c.name for c in obj.configurations.all())
|
||||
configurations_list.short_description = "Конфигурации"
|
||||
|
||||
def make_published(self, request, queryset):
|
||||
queryset.update(is_published=True)
|
||||
make_published.short_description = "Опубликовать выбранные продукты"
|
||||
|
||||
def make_unpublished(self, request, queryset):
|
||||
queryset.update(is_published=False)
|
||||
make_unpublished.short_description = "Снять с публикации"
|
||||
|
||||
|
||||
@admin.register(Order)
|
||||
class OrderAdmin(admin.ModelAdmin):
|
||||
list_display = ('id', 'product', 'name', 'phone', 'created_at', 'is_processed', 'notification_sent')
|
||||
list_filter = ('is_processed', 'product', 'configuration', 'notification_sent')
|
||||
search_fields = ('name', 'phone', 'email')
|
||||
list_editable = ('is_processed',)
|
||||
readonly_fields = ('created_at',)
|
||||
actions = ['resend_order_notification'] # добавляем действие в выпадающий список
|
||||
|
||||
def notification_badge(self, obj):
|
||||
# Если в модели Order добавите поле notification_sent, можно показывать иконку
|
||||
# Пока просто заглушка – всегда зелёная галочка (уведомление считается отправленным при создании)
|
||||
return format_html('<span style="color:green;">✓</span>')
|
||||
notification_badge.short_description = 'Уведомление'
|
||||
|
||||
def resend_order_notification(self, request, queryset):
|
||||
"""
|
||||
Переотправляет уведомления для выбранных заказов.
|
||||
"""
|
||||
# count = send_multiple_order_notifications(queryset)
|
||||
count = send_multiple_order_notifications_async(queryset)
|
||||
self.message_user(request, f'Уведомления отправлены для {count} заказов.')
|
||||
resend_order_notification.short_description = 'Переотправить email уведомления'
|
||||
|
||||
# Опционально: добавить кастомную кнопку на страницу списка
|
||||
def get_urls(self):
|
||||
from django.urls import path
|
||||
from django.shortcuts import render
|
||||
from django.contrib import messages
|
||||
|
||||
urls = super().get_urls()
|
||||
custom_urls = [
|
||||
path(
|
||||
'order-stats/',
|
||||
self.admin_site.admin_view(self.order_stats_view),
|
||||
name='order_stats',
|
||||
),
|
||||
]
|
||||
return custom_urls + urls
|
||||
|
||||
|
||||
def notification_badge(self, obj):
|
||||
if obj.notification_sent:
|
||||
return format_html('<span style="color:green;">✓</span>')
|
||||
return format_html('<span style="color:red;">✗</span>')
|
||||
|
||||
|
||||
def order_stats_view(self, request):
|
||||
from .models import Order
|
||||
from django.utils import timezone
|
||||
today = timezone.now().date()
|
||||
week_ago = today - timezone.timedelta(days=7)
|
||||
|
||||
stats = {
|
||||
'total': Order.objects.count(),
|
||||
'today': Order.objects.filter(created_at__date=today).count(),
|
||||
'week': Order.objects.filter(created_at__date__gte=week_ago).count(),
|
||||
'unprocessed': Order.objects.filter(is_processed=False).count(),
|
||||
}
|
||||
context = {
|
||||
**self.admin_site.each_context(request),
|
||||
'title': 'Статистика заказов',
|
||||
'stats': stats,
|
||||
}
|
||||
return render(request, 'admin/order_stats.html', context)
|
||||
|
||||
6
products/apps.py
Normal file
6
products/apps.py
Normal file
@ -0,0 +1,6 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class ProductsConfig(AppConfig):
|
||||
default_auto_field = 'django.db.models.BigAutoField'
|
||||
name = 'products'
|
||||
27
products/forms.py
Normal file
27
products/forms.py
Normal file
@ -0,0 +1,27 @@
|
||||
from django import forms
|
||||
from .models import Order, Configuration
|
||||
|
||||
class OrderForm(forms.ModelForm):
|
||||
# Поле выбора конфигурации. Заполним его динамически во вьюхе.
|
||||
configuration = forms.ModelChoiceField(
|
||||
queryset=Configuration.objects.none(),
|
||||
required=True,
|
||||
label='Конфигурация 1С',
|
||||
widget=forms.Select(attrs={'class': 'form-input'})
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = Order
|
||||
fields = ['name', 'phone', 'email', 'comment', 'configuration']
|
||||
widgets = {
|
||||
'name': forms.TextInput(attrs={'class': 'form-input', 'placeholder': 'Ваше имя'}),
|
||||
'phone': forms.TextInput(attrs={'class': 'form-input', 'placeholder': '+7 (___) ___-__-__'}),
|
||||
'email': forms.EmailInput(attrs={'class': 'form-input', 'placeholder': 'your@email.com'}),
|
||||
'comment': forms.Textarea(attrs={'class': 'form-textarea', 'rows': 2, 'placeholder': 'Доп. информация, например: релиз концигурации'}),
|
||||
'configuration': forms.Select(attrs={'class': 'form-input'}),
|
||||
}
|
||||
labels = {
|
||||
'name': 'Имя *',
|
||||
'phone': 'Телефон *',
|
||||
'email': 'Email *',
|
||||
}
|
||||
0
products/migrations/__init__.py
Normal file
0
products/migrations/__init__.py
Normal file
131
products/models.py
Normal file
131
products/models.py
Normal file
@ -0,0 +1,131 @@
|
||||
from django.db import models
|
||||
from django.urls import reverse
|
||||
from django.utils.html import strip_tags
|
||||
from django.conf import settings
|
||||
import re
|
||||
|
||||
|
||||
class ProductCategory(models.Model):
|
||||
"""Категория продуктов"""
|
||||
name = models.CharField(max_length=100, unique=True, verbose_name="Название")
|
||||
slug = models.SlugField(max_length=120, unique=True, verbose_name="URL")
|
||||
description = models.TextField(blank=True, verbose_name="Описание")
|
||||
|
||||
class Meta:
|
||||
verbose_name = "Категория продуктов"
|
||||
verbose_name_plural = "Категории продуктов"
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class Configuration(models.Model):
|
||||
"""Конфигурация 1С, к которой относится продукт"""
|
||||
name = models.CharField(max_length=200, unique=True, verbose_name="Название")
|
||||
slug = models.SlugField(max_length=220, unique=True, verbose_name="URL")
|
||||
description = models.TextField(blank=True, verbose_name="Описание")
|
||||
|
||||
class Meta:
|
||||
verbose_name = "Конфигурация 1С"
|
||||
verbose_name_plural = "Конфигурации 1С"
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class Product(models.Model):
|
||||
"""Программный продукт / модуль 1С"""
|
||||
title = models.CharField(max_length=200, verbose_name="Название")
|
||||
slug = models.SlugField(max_length=220, unique=True, verbose_name="URL")
|
||||
category = models.ForeignKey(
|
||||
ProductCategory,
|
||||
on_delete=models.PROTECT,
|
||||
related_name="products",
|
||||
verbose_name="Категория"
|
||||
)
|
||||
short_description = models.TextField(
|
||||
verbose_name="Краткое описание",
|
||||
help_text="Отображается в списке продуктов"
|
||||
)
|
||||
content = models.TextField(verbose_name="Полное описание")
|
||||
price = models.DecimalField(
|
||||
max_digits=10,
|
||||
decimal_places=2,
|
||||
verbose_name="Цена",
|
||||
help_text="Будет видна только зарегистрированным пользователям"
|
||||
)
|
||||
image = models.ImageField(
|
||||
upload_to="products/%Y/%m/%d/",
|
||||
blank=True,
|
||||
verbose_name="Изображение"
|
||||
)
|
||||
configurations = models.ManyToManyField(
|
||||
Configuration,
|
||||
blank=True,
|
||||
related_name="products",
|
||||
verbose_name="Совместимые конфигурации"
|
||||
)
|
||||
is_published = models.BooleanField(default=True, verbose_name="Опубликовано")
|
||||
time_create = models.DateTimeField(auto_now_add=True, verbose_name="Дата создания")
|
||||
time_update = models.DateTimeField(auto_now=True, verbose_name="Дата изменения")
|
||||
meta_description = models.CharField(
|
||||
max_length=160,
|
||||
blank=True,
|
||||
verbose_name="Meta-описание",
|
||||
help_text="Краткое описание для поисковых систем (до 160 символов)"
|
||||
)
|
||||
|
||||
class Meta:
|
||||
verbose_name = "Продукт"
|
||||
verbose_name_plural = "Продукты"
|
||||
ordering = ["-time_create"]
|
||||
indexes = [
|
||||
models.Index(fields=["-time_create", "is_published"]),
|
||||
]
|
||||
|
||||
def __str__(self):
|
||||
return self.title
|
||||
|
||||
def get_absolute_url(self):
|
||||
return reverse("products:product_detail", kwargs={"slug": self.slug})
|
||||
|
||||
def get_seo_title(self):
|
||||
return f"{self.title} | Продукты С.Н.А. Технологии"
|
||||
|
||||
def get_seo_description(self):
|
||||
if self.meta_description:
|
||||
return self.meta_description
|
||||
clean = re.sub(r'\s+', ' ', strip_tags(self.short_description)).strip()
|
||||
return clean[:157] + '…' if len(clean) > 160 else clean
|
||||
|
||||
|
||||
class Order(models.Model):
|
||||
product = models.ForeignKey(Product, on_delete=models.CASCADE, verbose_name='Продукт')
|
||||
configuration = models.ForeignKey(
|
||||
Configuration,
|
||||
on_delete=models.SET_NULL,
|
||||
null=True, blank=True,
|
||||
verbose_name='Конфигурация 1С'
|
||||
)
|
||||
user = models.ForeignKey(
|
||||
settings.AUTH_USER_MODEL,
|
||||
on_delete=models.SET_NULL,
|
||||
null=True, blank=True,
|
||||
verbose_name='Пользователь'
|
||||
)
|
||||
name = models.CharField(max_length=100, verbose_name='Имя')
|
||||
phone = models.CharField(max_length=20, verbose_name='Телефон')
|
||||
email = models.EmailField(verbose_name='Email')
|
||||
address = models.TextField(blank=True, verbose_name='Адрес доставки')
|
||||
comment = models.TextField(blank=True, verbose_name='Комментарий')
|
||||
created_at = models.DateTimeField(auto_now_add=True, verbose_name='Дата заказа')
|
||||
is_processed = models.BooleanField(default=False, verbose_name='Обработан')
|
||||
notification_sent = models.BooleanField(default=False, verbose_name='Уведомление отправлено')
|
||||
|
||||
class Meta:
|
||||
verbose_name = 'Заказ'
|
||||
verbose_name_plural = 'Заказы'
|
||||
ordering = ['-created_at']
|
||||
|
||||
def __str__(self):
|
||||
return f'Заказ #{self.id} – {self.product.title} от {self.name}'
|
||||
237
products/static/products/css/ck_content.css
Normal file
237
products/static/products/css/ck_content.css
Normal file
@ -0,0 +1,237 @@
|
||||
/*
|
||||
* ck_content.css — общие стили для CKEditor-контента
|
||||
* Используется в блоге (.article-content) и в продуктах (.product-description).
|
||||
* Подключать вместо article_content.css / product_content.css.
|
||||
*
|
||||
* Размещение: static/core/css/ck_content.css (или аналогичное shared-место)
|
||||
*/
|
||||
|
||||
/* ===== Базовый контейнер ===== */
|
||||
.article-content,
|
||||
.product-description {
|
||||
font-size: 1rem;
|
||||
line-height: 1.7;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
/* ===== Заголовки ===== */
|
||||
.article-content h1, .product-description h1,
|
||||
.article-content h2, .product-description h2,
|
||||
.article-content h3, .product-description h3,
|
||||
.article-content h4, .product-description h4,
|
||||
.article-content h5, .product-description h5,
|
||||
.article-content h6, .product-description h6 {
|
||||
margin-top: 1.5em;
|
||||
margin-bottom: 0.5em;
|
||||
font-weight: 600;
|
||||
line-height: 1.25;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
.article-content h1, .product-description h1 { font-size: 2rem; }
|
||||
.article-content h2, .product-description h2 { font-size: 1.75rem; }
|
||||
.article-content h3, .product-description h3 { font-size: 1.5rem; }
|
||||
.article-content h4, .product-description h4 { font-size: 1.25rem; }
|
||||
.article-content h5, .product-description h5 { font-size: 1.1rem; }
|
||||
.article-content h6, .product-description h6 { font-size: 1rem; }
|
||||
|
||||
/* ===== Абзацы ===== */
|
||||
.article-content p,
|
||||
.product-description p {
|
||||
margin-bottom: 1.2em;
|
||||
}
|
||||
|
||||
/* ===== Списки ===== */
|
||||
.article-content ul, .product-description ul,
|
||||
.article-content ol, .product-description ol {
|
||||
margin-bottom: 1rem;
|
||||
padding-left: 2rem;
|
||||
}
|
||||
.article-content li,
|
||||
.product-description li {
|
||||
margin-bottom: 0.3rem;
|
||||
}
|
||||
|
||||
/* ===== Цитаты ===== */
|
||||
.article-content blockquote,
|
||||
.product-description blockquote {
|
||||
border-left: 4px solid var(--primary);
|
||||
padding: 0.5rem 1rem;
|
||||
background: var(--bg-secondary);
|
||||
margin: 1.25rem 0;
|
||||
font-style: italic;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
/* ===== Горизонтальная линия ===== */
|
||||
.article-content hr,
|
||||
.product-description hr {
|
||||
border: none;
|
||||
border-top: 2px solid var(--border-light);
|
||||
margin: 2em 0;
|
||||
}
|
||||
|
||||
/* ===== Таблицы ===== */
|
||||
.article-content table,
|
||||
.product-description table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin: 1.25rem 0;
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
.article-content th, .product-description th,
|
||||
.article-content td, .product-description td {
|
||||
border: 1px solid var(--border-light);
|
||||
padding: 0.6rem 0.8rem;
|
||||
text-align: left;
|
||||
}
|
||||
.article-content th,
|
||||
.product-description th {
|
||||
background: var(--bg-secondary);
|
||||
color: var(--text-primary);
|
||||
font-weight: 600;
|
||||
}
|
||||
.article-content tr:nth-child(even),
|
||||
.product-description tr:nth-child(even) {
|
||||
background: var(--bg-secondary);
|
||||
}
|
||||
|
||||
/* ===== Изображения ===== */
|
||||
.article-content img,
|
||||
.product-description img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
margin: 1rem 0;
|
||||
border-radius: var(--radius-sm, 4px);
|
||||
}
|
||||
|
||||
/* CKEditor 5: figure.image */
|
||||
.article-content figure.image,
|
||||
.product-description figure.image {
|
||||
display: inline-block;
|
||||
margin: 1em 0;
|
||||
max-width: 100%;
|
||||
}
|
||||
.article-content figure.image img,
|
||||
.product-description figure.image img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
.article-content figure.image figcaption,
|
||||
.product-description figure.image figcaption {
|
||||
text-align: center;
|
||||
font-size: 0.88em;
|
||||
color: var(--text-light);
|
||||
margin-top: 0.4em;
|
||||
}
|
||||
|
||||
/* Выравнивание изображений (классы CKEditor 5) */
|
||||
.article-content .image-style-align-left,
|
||||
.product-description .image-style-align-left {
|
||||
float: left;
|
||||
margin-right: 1.5em;
|
||||
margin-bottom: 1em;
|
||||
max-width: 50%;
|
||||
}
|
||||
.article-content .image-style-align-right,
|
||||
.product-description .image-style-align-right {
|
||||
float: right;
|
||||
margin-left: 1.5em;
|
||||
margin-bottom: 1em;
|
||||
max-width: 50%;
|
||||
}
|
||||
.article-content .image-style-align-center,
|
||||
.product-description .image-style-align-center {
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
/* clearfix после float-изображений */
|
||||
.article-content::after,
|
||||
.product-description::after {
|
||||
content: '';
|
||||
display: table;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
/* ===== Встроенное видео (iframe/media) ===== */
|
||||
.article-content .media,
|
||||
.product-description .media {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
padding-bottom: 56.25%; /* 16:9 */
|
||||
height: 0;
|
||||
margin: 1.5em 0;
|
||||
}
|
||||
.article-content .media iframe,
|
||||
.product-description .media iframe {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: 0;
|
||||
border-radius: var(--radius-sm, 4px);
|
||||
}
|
||||
|
||||
/* ===== Блоки кода ===== */
|
||||
.article-content pre,
|
||||
.product-description pre {
|
||||
background: #1e1e1e;
|
||||
color: #d4d4d4;
|
||||
padding: 1rem 1.25rem;
|
||||
border-radius: var(--radius-sm, 4px);
|
||||
overflow-x: auto;
|
||||
margin: 1rem 0;
|
||||
font-size: 0.9em;
|
||||
line-height: 1.5;
|
||||
}
|
||||
.article-content code,
|
||||
.product-description code {
|
||||
font-family: 'Cascadia Code', 'Fira Code', 'Courier New', monospace;
|
||||
background: var(--bg-secondary);
|
||||
color: var(--primary);
|
||||
padding: 0.15rem 0.4rem;
|
||||
border-radius: 3px;
|
||||
font-size: 0.88em;
|
||||
}
|
||||
.article-content pre code,
|
||||
.product-description pre code {
|
||||
padding: 0;
|
||||
background: none;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
/* ===== Ссылки внутри контента ===== */
|
||||
.article-content a,
|
||||
.product-description a {
|
||||
color: var(--primary);
|
||||
text-decoration: underline;
|
||||
text-underline-offset: 3px;
|
||||
transition: opacity 0.15s;
|
||||
}
|
||||
.article-content a:hover,
|
||||
.product-description a:hover {
|
||||
opacity: 0.75;
|
||||
}
|
||||
|
||||
/* ===== Адаптивность ===== */
|
||||
@media (max-width: 600px) {
|
||||
.article-content .image-style-align-left,
|
||||
.article-content .image-style-align-right,
|
||||
.product-description .image-style-align-left,
|
||||
.product-description .image-style-align-right {
|
||||
float: none;
|
||||
max-width: 100%;
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
.article-content table,
|
||||
.product-description table {
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
}
|
||||
|
||||
294
products/static/products/css/products.css
Normal file
294
products/static/products/css/products.css
Normal file
@ -0,0 +1,294 @@
|
||||
/*
|
||||
* products.css — layout и компоненты страниц продуктов.
|
||||
* Типографика CKEditor-контента вынесена в ck_content.css.
|
||||
*/
|
||||
|
||||
/* ===== Сетка продуктов ===== */
|
||||
.products-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
|
||||
gap: 1.5rem;
|
||||
margin-top: 1.5rem;
|
||||
}
|
||||
|
||||
/* ===== Карточка продукта ===== */
|
||||
.product-card {
|
||||
background: var(--bg-card);
|
||||
border-radius: var(--radius-lg);
|
||||
box-shadow: var(--shadow-md);
|
||||
border: 1px solid var(--border-light);
|
||||
transition: var(--transition);
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.product-card:hover {
|
||||
transform: translateY(-4px);
|
||||
box-shadow: var(--shadow-lg);
|
||||
}
|
||||
|
||||
.product-image {
|
||||
width: 100%;
|
||||
height: 180px;
|
||||
object-fit: cover;
|
||||
}
|
||||
.product-image-placeholder {
|
||||
width: 100%;
|
||||
height: 180px;
|
||||
background: var(--bg-secondary);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: var(--text-light);
|
||||
font-size: 2rem;
|
||||
}
|
||||
.product-image-placeholder::after {
|
||||
content: '📦';
|
||||
}
|
||||
|
||||
.product-info {
|
||||
padding: 1rem;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.product-info h3 {
|
||||
margin: 0 0 0.5rem 0;
|
||||
font-size: 1.1rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
.product-info h3 a {
|
||||
color: var(--text-primary);
|
||||
text-decoration: none;
|
||||
transition: color 0.15s;
|
||||
}
|
||||
.product-info h3 a:hover {
|
||||
color: var(--primary);
|
||||
}
|
||||
|
||||
.product-short {
|
||||
color: var(--text-secondary);
|
||||
font-size: 0.9rem;
|
||||
margin-bottom: 0.75rem;
|
||||
flex: 1;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.product-meta {
|
||||
font-size: 0.8rem;
|
||||
color: var(--text-light);
|
||||
margin-bottom: 0.75rem;
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.product-category,
|
||||
.product-configs {
|
||||
background: var(--bg-secondary);
|
||||
padding: 0.15rem 0.5rem;
|
||||
border-radius: var(--radius-sm);
|
||||
border: 1px solid var(--border-light);
|
||||
}
|
||||
|
||||
/* ===== Цена ===== */
|
||||
.product-price-block {
|
||||
margin-top: auto;
|
||||
}
|
||||
.product-price {
|
||||
font-size: 1.2rem;
|
||||
font-weight: 700;
|
||||
color: var(--primary);
|
||||
}
|
||||
|
||||
.price-restricted {
|
||||
background: var(--bg-secondary);
|
||||
padding: 0.6rem;
|
||||
border-radius: var(--radius-sm);
|
||||
text-align: center;
|
||||
}
|
||||
.price-text {
|
||||
display: block;
|
||||
margin-bottom: 0.5rem;
|
||||
font-size: 0.85rem;
|
||||
color: var(--text-light);
|
||||
}
|
||||
.price-actions {
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
justify-content: center;
|
||||
}
|
||||
.btn-small {
|
||||
padding: 0.4rem 0.8rem;
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
/* ===== Фильтры ===== */
|
||||
.filters-bar {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 1rem;
|
||||
margin-bottom: 1.5rem;
|
||||
align-items: center;
|
||||
}
|
||||
.filter-group {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.5rem;
|
||||
align-items: center;
|
||||
}
|
||||
.filter-group > span {
|
||||
font-size: 0.85rem;
|
||||
color: var(--text-light);
|
||||
font-weight: 500;
|
||||
}
|
||||
.filter-btn {
|
||||
padding: 0.3rem 0.8rem;
|
||||
border-radius: var(--radius-sm);
|
||||
background: var(--bg-secondary);
|
||||
color: var(--text-secondary);
|
||||
text-decoration: none;
|
||||
font-size: 0.85rem;
|
||||
border: 1px solid var(--border-light);
|
||||
transition: var(--transition);
|
||||
white-space: nowrap;
|
||||
}
|
||||
.filter-btn.active,
|
||||
.filter-btn:hover {
|
||||
background: var(--primary);
|
||||
color: white;
|
||||
border-color: var(--primary);
|
||||
}
|
||||
|
||||
/* ===== Детальная страница ===== */
|
||||
.product-detail {
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.product-header {
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
.product-header h1 {
|
||||
font-size: 2rem;
|
||||
margin-bottom: 0.5rem;
|
||||
color: var(--text-primary);
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.product-meta-detail {
|
||||
display: flex;
|
||||
gap: 0.75rem;
|
||||
color: var(--text-light);
|
||||
font-size: 0.875rem;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.product-detail-image {
|
||||
width: 100%;
|
||||
max-height: 420px;
|
||||
object-fit: cover;
|
||||
border-radius: var(--radius-md);
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
/* Контент CKEditor — max-width задан на .product-detail, не здесь */
|
||||
.product-description {
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
/* ===== Блок цены (детальная) ===== */
|
||||
.product-price-block-detail {
|
||||
margin: 2rem 0;
|
||||
text-align: center;
|
||||
}
|
||||
.product-price-large {
|
||||
font-size: 2rem;
|
||||
font-weight: 700;
|
||||
color: var(--primary);
|
||||
display: block;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.price-restricted-detail {
|
||||
background: var(--bg-secondary);
|
||||
padding: 1.5rem;
|
||||
border-radius: var(--radius-md);
|
||||
border: 1px solid var(--border-light);
|
||||
}
|
||||
.price-restricted-detail p {
|
||||
margin-bottom: 1rem;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.product-back {
|
||||
margin-top: 2rem;
|
||||
padding-top: 1.5rem;
|
||||
border-top: 1px solid var(--border-light);
|
||||
}
|
||||
|
||||
/* ===== Пагинация ===== */
|
||||
.pagination {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 0.4rem;
|
||||
margin-top: 2.5rem;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.pagination a,
|
||||
.pagination span {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-width: 2.2rem;
|
||||
padding: 0.45rem 0.7rem;
|
||||
border-radius: var(--radius-sm);
|
||||
background: var(--bg-secondary);
|
||||
color: var(--text-secondary);
|
||||
text-decoration: none;
|
||||
font-size: 0.9rem;
|
||||
border: 1px solid var(--border-light);
|
||||
transition: var(--transition);
|
||||
}
|
||||
.pagination a:hover {
|
||||
background: var(--primary);
|
||||
color: white;
|
||||
border-color: var(--primary);
|
||||
}
|
||||
.pagination .current {
|
||||
background: var(--primary);
|
||||
color: white;
|
||||
font-weight: 600;
|
||||
border-color: var(--primary);
|
||||
}
|
||||
.pagination .disabled {
|
||||
opacity: 0.45;
|
||||
cursor: default;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* ===== Адаптивность ===== */
|
||||
@media (max-width: 768px) {
|
||||
.product-header h1 {
|
||||
font-size: 1.6rem;
|
||||
}
|
||||
.product-price-large {
|
||||
font-size: 1.6rem;
|
||||
}
|
||||
}
|
||||
@media (max-width: 480px) {
|
||||
.products-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
.price-actions {
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
}
|
||||
.filters-bar {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
}
|
||||
}
|
||||
|
||||
.product-card {
|
||||
cursor: pointer;
|
||||
}
|
||||
10
products/templates/products/emails/order_admin.html
Normal file
10
products/templates/products/emails/order_admin.html
Normal file
@ -0,0 +1,10 @@
|
||||
<h2>🛒 Новый заказ #{{ order.id }}</h2>
|
||||
<p><strong>Продукт:</strong> {{ order.product.title }}</p>
|
||||
<p><strong>Конфигурация:</strong> {{ order.configuration.name|default:"Не указана" }}</p>
|
||||
<p><strong>Клиент:</strong> {{ order.name }}</p>
|
||||
<p><strong>Телефон:</strong> {{ order.phone }}</p>
|
||||
<p><strong>Email:</strong> {{ order.email }}</p>
|
||||
<p><strong>Комментарий:</strong> {{ order.comment|default:"—" }}</p>
|
||||
<p><strong>Дата создания:</strong> {{ order.created_at|date:"d.m.Y H:i" }}</p>
|
||||
<hr>
|
||||
<a href="{{ site_url }}/admin/products/order/{{ order.id }}/change/">Перейти к заказу в админке</a>
|
||||
9
products/templates/products/emails/order_client.html
Normal file
9
products/templates/products/emails/order_client.html
Normal file
@ -0,0 +1,9 @@
|
||||
<h2>Здравствуйте, {{ order.name }}!</h2>
|
||||
<p>Ваш заказ <strong>#{{ order.id }}</strong> на продукт <strong>{{ order.product.title }}</strong> успешно принят.</p>
|
||||
{% if order.configuration %}
|
||||
<p>Выбранная конфигурация: <strong>{{ order.configuration.name }}</strong></p>
|
||||
{% endif %}
|
||||
<p>Мы свяжемся с вами в ближайшее время по телефону <strong>{{ order.phone }}</strong> или эл. почте <strong>{{ order.email }}</strong>, указанных в заказе.</p>
|
||||
<p>Спасибо за обращение!</p>
|
||||
<hr>
|
||||
<small>С.Н.А. Технологии</small>
|
||||
17
products/templates/products/includes/pagination.html
Normal file
17
products/templates/products/includes/pagination.html
Normal file
@ -0,0 +1,17 @@
|
||||
{% if is_paginated %}
|
||||
<nav class="pagination">
|
||||
{% if page_obj.has_previous %}
|
||||
<a href="?page={{ page_obj.previous_page_number }}{% for key,value in request.GET.items %}{% if key != 'page' %}&{{ key }}={{ value }}{% endif %}{% endfor %}">«</a>
|
||||
{% endif %}
|
||||
{% for num in page_obj.paginator.page_range %}
|
||||
{% if num == page_obj.number %}
|
||||
<span class="current">{{ num }}</span>
|
||||
{% else %}
|
||||
<a href="?page={{ num }}{% for key,value in request.GET.items %}{% if key != 'page' %}&{{ key }}={{ value }}{% endif %}{% endfor %}">{{ num }}</a>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% if page_obj.has_next %}
|
||||
<a href="?page={{ page_obj.next_page_number }}{% for key,value in request.GET.items %}{% if key != 'page' %}&{{ key }}={{ value }}{% endif %}{% endfor %}">»</a>
|
||||
{% endif %}
|
||||
</nav>
|
||||
{% endif %}
|
||||
102
products/templates/products/product_detail.html
Normal file
102
products/templates/products/product_detail.html
Normal file
@ -0,0 +1,102 @@
|
||||
{% extends 'programmer/base.html' %}
|
||||
{% load static %}
|
||||
{% load django_bootstrap5 %}
|
||||
|
||||
{% block extra_css %}
|
||||
{# Единый файл для CKEditor-контента (общий с блогом) #}
|
||||
<link rel="stylesheet" href="{% static 'products/css/ck_content.css' %}">
|
||||
<link rel="stylesheet" href="{% static 'products/css/products.css' %}">
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="product-detail">
|
||||
|
||||
{# ===== Шапка ===== #}
|
||||
<div class="page-header">
|
||||
<h1 class="page-title">{{ product.title }}</h1>
|
||||
<div class="product-meta-detail">
|
||||
<span class="page-subtitle">
|
||||
Категория:
|
||||
<a href="{% url 'products:product_list' %}?category={{ product.category.slug }}">
|
||||
{{ product.category.name }}
|
||||
</a>
|
||||
</span>
|
||||
{% if product.configurations.all %}
|
||||
<span class="product-configs">{{ product.configurations.all|join:", " }}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="content-card">
|
||||
|
||||
{# ===== Изображение ===== #}
|
||||
{% if product.image %}
|
||||
<img src="{{ product.image.url }}" alt="{{ product.title }}"
|
||||
class="product-detail-image" loading="lazy">
|
||||
{% endif %}
|
||||
|
||||
{# ===== CKEditor-контент ===== #}
|
||||
<div class="product-description">
|
||||
{{ product.content|safe }}
|
||||
</div>
|
||||
|
||||
{# ===== Цена + действия ===== #}
|
||||
<div class="product-price-block-detail">
|
||||
{% if user.is_authenticated %}
|
||||
<div class="price-authenticated">
|
||||
<span class="product-price-large">Цена: {{ product.price|floatformat:0 }} ₽</span>
|
||||
<div class="price-actions">
|
||||
{# Кнопка для вызова модального окна заказа #}
|
||||
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#orderModal">
|
||||
Купить
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="price-restricted-detail">
|
||||
<p>Для просмотра цены и приобретения продукта необходимо авторизоваться.</p>
|
||||
<div class="price-actions">
|
||||
<a href="{% url 'login' %}?next={{ request.path }}" class="btn">Войти</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
</div>{# /.content-card #}
|
||||
|
||||
<div class="product-back">
|
||||
<a href="{% url 'products:product_list' %}" class="btn btn-outline">← К списку продуктов</a>
|
||||
</div>
|
||||
|
||||
</div>{# /.product-detail #}
|
||||
|
||||
{# ===== Модальное окно заказа ===== #}
|
||||
<div class="modal fade" id="orderModal" tabindex="-1" aria-labelledby="orderModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<form method="post" action="{% url 'products:order_create' product.slug %}">
|
||||
{% csrf_token %}
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="orderModalLabel">Оформление заказа: {{ product.title }}</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Закрыть"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
{# Поля формы будут рендериться через переменную order_form #}
|
||||
{{ order_form.as_p }}
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Отмена</button>
|
||||
<button type="submit" class="btn btn-primary">Отправить заказ</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="{% static 'programmer/js/floating-button.js' %}"></script>
|
||||
|
||||
{% block extra_js %}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% endblock %}
|
||||
108
products/templates/products/product_list.html
Normal file
108
products/templates/products/product_list.html
Normal file
@ -0,0 +1,108 @@
|
||||
{% extends 'programmer/base.html' %}
|
||||
{% load static %}
|
||||
{% load django_bootstrap5 %}
|
||||
|
||||
{% block extra_css %}
|
||||
{# Единый файл для CKEditor-контента (общий с блогом) #}
|
||||
<link rel="stylesheet" href="{% static 'products/css/ck_content.css' %}">
|
||||
<link rel="stylesheet" href="{% static 'products/css/products.css' %}">
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="page-header">
|
||||
<h1 class="page-title">Продукты 1С</h1>
|
||||
<p class="page-subtitle">Готовые модули, расширения и программные продукты для платформы 1С</p>
|
||||
</div>
|
||||
|
||||
{# ===== Фильтры ===== #}
|
||||
<div class="filters-bar">
|
||||
<div class="filter-group">
|
||||
<span>Категория:</span>
|
||||
<a href="?{% if current_configuration %}configuration={{ current_configuration.slug }}{% endif %}"
|
||||
class="filter-btn {% if not current_category %}active{% endif %}">Все</a>
|
||||
{% for cat in categories %}
|
||||
<a href="?category={{ cat.slug }}{% if current_configuration %}&configuration={{ current_configuration.slug }}{% endif %}"
|
||||
class="filter-btn {% if current_category == cat %}active{% endif %}">{{ cat.name }}</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<div class="filter-group">
|
||||
<span>Конфигурация:</span>
|
||||
<a href="?{% if current_category %}category={{ current_category.slug }}{% endif %}"
|
||||
class="filter-btn {% if not current_configuration %}active{% endif %}">Все</a>
|
||||
{% for conf in configurations %}
|
||||
<a href="?configuration={{ conf.slug }}{% if current_category %}&category={{ current_category.slug }}{% endif %}"
|
||||
class="filter-btn {% if current_configuration == conf %}active{% endif %}">{{ conf.name }}</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# ===== Сетка продуктов ===== #}
|
||||
<div class="products-grid">
|
||||
{% for product in products %}
|
||||
<div class="product-card" data-url="{{ product.get_absolute_url }}">
|
||||
{% if product.image %}
|
||||
<img src="{{ product.image.url }}" alt="{{ product.title }}" class="product-image" loading="lazy">
|
||||
{% else %}
|
||||
<div class="product-image-placeholder" aria-hidden="true"></div>
|
||||
{% endif %}
|
||||
|
||||
<div class="product-info">
|
||||
<h3><a href="{{ product.get_absolute_url }}">{{ product.title }}</a></h3>
|
||||
|
||||
<p class="product-short">{{ product.short_description|striptags|truncatewords:30 }}</p>
|
||||
|
||||
<div class="product-meta">
|
||||
<span class="product-category">{{ product.category.name }}</span>
|
||||
{% if product.configurations.all %}
|
||||
<span class="product-configs">{{ product.configurations.all|join:", " }}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="product-price-block">
|
||||
{% if user.is_authenticated %}
|
||||
<span class="product-price">{{ product.price|floatformat:0 }} ₽</span>
|
||||
{% else %}
|
||||
<div class="price-restricted">
|
||||
<span class="price-text">Цена доступна после авторизации</span>
|
||||
<div class="price-actions">
|
||||
<a href="{% url 'login' %}?next={{ request.path }}" class="btn btn-small">Войти</a>
|
||||
<button type="button"
|
||||
onclick="CallbackModal.open('{{ product.title|escapejs }}')"
|
||||
class="btn btn-small btn-outline">
|
||||
Запросить цену
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% empty %}
|
||||
<p class="no-results">Продуктов по выбранным фильтрам не найдено.</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<script src="{% static 'programmer/js/floating-button.js' %}"></script>
|
||||
|
||||
{% include 'products/includes/pagination.html' %}
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_js %}
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const cards = document.querySelectorAll('.product-card');
|
||||
cards.forEach(card => {
|
||||
const url = card.dataset.url;
|
||||
if (!url) return;
|
||||
|
||||
card.addEventListener('click', function(e) {
|
||||
// Если клик был по ссылке, кнопке или любому элементу с data-no-link
|
||||
const target = e.target.closest('a, button, .no-link');
|
||||
if (target) return;
|
||||
|
||||
window.location.href = url;
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
3
products/tests.py
Normal file
3
products/tests.py
Normal file
@ -0,0 +1,3 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
10
products/urls.py
Normal file
10
products/urls.py
Normal file
@ -0,0 +1,10 @@
|
||||
from django.urls import path
|
||||
from . import views
|
||||
|
||||
app_name = 'products'
|
||||
|
||||
urlpatterns = [
|
||||
path('', views.ProductListView.as_view(), name='product_list'),
|
||||
path('<slug:slug>/', views.ProductDetailView.as_view(), name='product_detail'),
|
||||
path('order/<slug:slug>/', views.order_create, name='order_create'),
|
||||
]
|
||||
170
products/views.py
Normal file
170
products/views.py
Normal file
@ -0,0 +1,170 @@
|
||||
from django.views.generic import ListView, DetailView
|
||||
from programmer.mixins import MenuContextMixin, BreadcrumbMixin
|
||||
from .models import Product, ProductCategory, Configuration
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.http import Http404
|
||||
from programmer.forms import CallbackForm
|
||||
from .forms import OrderForm
|
||||
from django.contrib import messages
|
||||
from django.shortcuts import redirect
|
||||
from programmer.utils.email_notifications import send_order_notification, send_order_notification_async
|
||||
|
||||
|
||||
class ProductListView(MenuContextMixin, BreadcrumbMixin, ListView):
|
||||
model = Product
|
||||
template_name = 'products/product_list.html'
|
||||
context_object_name = 'products'
|
||||
paginate_by = 12
|
||||
|
||||
def get_breadcrumbs(self):
|
||||
return [{'title': 'Продукты', 'url_name': None}]
|
||||
|
||||
def get_queryset(self):
|
||||
qs = (
|
||||
Product.objects
|
||||
.filter(is_published=True)
|
||||
.select_related('category')
|
||||
.prefetch_related('configurations')
|
||||
)
|
||||
|
||||
# Фильтр по категории
|
||||
category_slug = self.request.GET.get('category')
|
||||
if category_slug:
|
||||
self.current_category = get_object_or_404(ProductCategory, slug=category_slug)
|
||||
qs = qs.filter(category=self.current_category)
|
||||
else:
|
||||
self.current_category = None
|
||||
|
||||
# Фильтр по конфигурации
|
||||
config_slug = self.request.GET.get('configuration')
|
||||
if config_slug:
|
||||
self.current_configuration = get_object_or_404(Configuration, slug=config_slug)
|
||||
qs = qs.filter(configurations=self.current_configuration)
|
||||
else:
|
||||
self.current_configuration = None
|
||||
|
||||
# ordering уже задан в Meta, явный вызов order_by не нужен,
|
||||
# но оставляем для явности и возможного расширения сортировки
|
||||
return qs.order_by('-time_create')
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context['categories'] = ProductCategory.objects.all()
|
||||
context['configurations'] = Configuration.objects.all()
|
||||
context['current_category'] = self.current_category
|
||||
context['current_configuration'] = self.current_configuration
|
||||
context['title'] = "Продукты 1С | Модули и расширения | С.Н.А. Технологии"
|
||||
context['meta_description'] = (
|
||||
"Готовые модули, расширения и программные продукты для 1С: Предприятие. "
|
||||
"Фильтрация по конфигурациям и категориям."
|
||||
)
|
||||
context['meta_keywords'] = "1С модули, расширения 1С, программы 1С, купить 1С, продукты 1С"
|
||||
form = CallbackForm()
|
||||
|
||||
if self.request.user.is_authenticated:
|
||||
if 'captcha' in form.fields:
|
||||
del form.fields['captcha']
|
||||
|
||||
context.update({
|
||||
'form': form,
|
||||
})
|
||||
|
||||
|
||||
return context
|
||||
|
||||
|
||||
class ProductDetailView(MenuContextMixin, BreadcrumbMixin, DetailView):
|
||||
model = Product
|
||||
template_name = 'products/product_detail.html'
|
||||
context_object_name = 'product'
|
||||
|
||||
def get_object(self, queryset=None):
|
||||
product = super().get_object(queryset=queryset)
|
||||
if not product.is_published:
|
||||
raise Http404("Продукт не найден")
|
||||
return product
|
||||
|
||||
def get_breadcrumbs(self):
|
||||
product = self.object
|
||||
return [
|
||||
{'title': 'Продукты', 'url_name': 'products:product_list'},
|
||||
{
|
||||
'title': product.category.name,
|
||||
'url_name': 'products:product_list',
|
||||
'extra_params': f'?category={product.category.slug}',
|
||||
},
|
||||
{'title': product.title, 'url_name': None},
|
||||
]
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
product = self.object
|
||||
context['title'] = product.get_seo_title()
|
||||
context['meta_description'] = product.get_seo_description()
|
||||
context['meta_keywords'] = (
|
||||
f"1С, {product.category.name}, "
|
||||
f"{', '.join(c.name for c in product.configurations.all())}"
|
||||
)
|
||||
|
||||
# Форма заказа с предзаполнением для авторизованных
|
||||
initial = {}
|
||||
if self.request.user.is_authenticated:
|
||||
user = self.request.user
|
||||
initial['name'] = user.get_full_name() or user.username
|
||||
initial['email'] = user.email
|
||||
# Если есть профиль и телефон
|
||||
if hasattr(user, 'profile') and user.profile.phone:
|
||||
initial['phone'] = user.profile.phone
|
||||
|
||||
order_form = OrderForm(initial=initial)
|
||||
order_form.fields['configuration'].queryset = product.configurations.all()
|
||||
context['order_form'] = order_form
|
||||
form = CallbackForm()
|
||||
|
||||
if self.request.user.is_authenticated:
|
||||
if 'captcha' in form.fields:
|
||||
del form.fields['captcha']
|
||||
|
||||
context.update({
|
||||
'form': form,
|
||||
})
|
||||
|
||||
return context
|
||||
|
||||
|
||||
|
||||
def order_create(request, slug):
|
||||
product = get_object_or_404(Product, slug=slug, is_published=True)
|
||||
|
||||
if request.method == 'POST':
|
||||
form = OrderForm(request.POST)
|
||||
# Переопределяем queryset для поля configuration – только те, что связаны с продуктом
|
||||
form.fields['configuration'].queryset = product.configurations.all()
|
||||
|
||||
if form.is_valid():
|
||||
order = form.save(commit=False)
|
||||
order.product = product
|
||||
# Если пользователь авторизован, связываем заказ с ним
|
||||
if request.user.is_authenticated:
|
||||
order.user = request.user
|
||||
# Можно предзаполнить имя и email из профиля, если они пустые в форме
|
||||
if not order.name:
|
||||
order.name = request.user.get_full_name() or request.user.username
|
||||
if not order.email:
|
||||
order.email = request.user.email
|
||||
order.save()
|
||||
|
||||
# Сохраняем выбранную конфигурацию (уже сохранена в форме)
|
||||
# success = send_order_notification(order)
|
||||
# if success:
|
||||
# order.notification_sent = True
|
||||
# order.save(update_fields=['notification_sent'])
|
||||
send_order_notification_async(order)
|
||||
|
||||
messages.success(request, '✅ Ваш заказ принят! Мы свяжемся с вами в ближайшее время.')
|
||||
return redirect('products:product_detail', slug=slug)
|
||||
else:
|
||||
for field, errors in form.errors.items():
|
||||
for error in errors:
|
||||
messages.error(request, f'❌ Ошибка в поле "{field}": {error}')
|
||||
return redirect('products:product_detail', slug=slug)
|
||||
@ -1,4 +1,5 @@
|
||||
from django.conf import settings
|
||||
from .forms import CallbackForm
|
||||
|
||||
|
||||
def contact_info(request):
|
||||
@ -6,3 +7,25 @@ def contact_info(request):
|
||||
'CONTACT_EMAIL': getattr(settings, 'CONTACT_EMAIL', 'it@nserdyuk.ru'),
|
||||
'CONTACT_PHONE': getattr(settings, 'CONTACT_PHONE', '+7 (960) 469-40-88'),
|
||||
}
|
||||
|
||||
|
||||
def callback_form(request):
|
||||
initial = {}
|
||||
if request.user.is_authenticated:
|
||||
user = request.user
|
||||
# Имя: полное имя или логин
|
||||
initial['name'] = user.get_full_name() or user.username
|
||||
# Email
|
||||
initial['email'] = user.email
|
||||
# Телефон из профиля (если есть)
|
||||
if hasattr(user, 'profile') and user.profile.phone:
|
||||
initial['phone'] = user.profile.phone
|
||||
|
||||
# Создаём экземпляр формы с initial
|
||||
form = CallbackForm(initial=initial)
|
||||
|
||||
# Для авторизованных пользователей убираем captcha (как у вас в представлениях)
|
||||
if request.user.is_authenticated and 'captcha' in form.fields:
|
||||
del form.fields['captcha']
|
||||
|
||||
return {'callback_form': form}
|
||||
|
||||
@ -30,7 +30,8 @@ class MenuContextMixin(ContextMixin):
|
||||
'url_name': None,
|
||||
'children': [
|
||||
{'title': "Кейсы", 'url_name': 'solution'},
|
||||
{'title': "Статьи", 'url_name': 'blog'},
|
||||
{'title': "Статьи", 'url_name': 'blog:article_list'},
|
||||
{'title': "Продукты", 'url_name': 'products:product_list'},
|
||||
]
|
||||
},
|
||||
{'title': "Отзывы", 'url_name': 'recall'},
|
||||
|
||||
@ -196,6 +196,8 @@ class Profile(models.Model):
|
||||
specialization = models.CharField(max_length=100, blank=True, verbose_name='Специализация')
|
||||
avatar = models.ImageField(upload_to='avatars/%Y/%m/%d/', blank=True, verbose_name='Аватар')
|
||||
email_notifications = models.BooleanField(default=True, verbose_name='Получать уведомления')
|
||||
notify_new_articles = models.BooleanField(default=True, verbose_name="О новых статьях")
|
||||
notify_new_products = models.BooleanField(default=True, verbose_name="О новых продуктах")
|
||||
|
||||
def __str__(self):
|
||||
return f'Профиль {self.user.username}'
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
<<<<<<< HEAD
|
||||
select.admin-autocomplete {
|
||||
width: 20em;
|
||||
}
|
||||
@ -274,280 +273,3 @@ select.admin-autocomplete {
|
||||
display: block;
|
||||
padding: 6px;
|
||||
}
|
||||
=======
|
||||
select.admin-autocomplete {
|
||||
width: 20em;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete.select2-container {
|
||||
min-height: 30px;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete .select2-selection--single,
|
||||
.select2-container--admin-autocomplete .select2-selection--multiple {
|
||||
min-height: 30px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete.select2-container--focus .select2-selection,
|
||||
.select2-container--admin-autocomplete.select2-container--open .select2-selection {
|
||||
border-color: var(--body-quiet-color);
|
||||
min-height: 30px;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete.select2-container--focus .select2-selection.select2-selection--single,
|
||||
.select2-container--admin-autocomplete.select2-container--open .select2-selection.select2-selection--single {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete.select2-container--focus .select2-selection.select2-selection--multiple,
|
||||
.select2-container--admin-autocomplete.select2-container--open .select2-selection.select2-selection--multiple {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete .select2-selection--single {
|
||||
background-color: var(--body-bg);
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete .select2-selection--single .select2-selection__rendered {
|
||||
color: var(--body-fg);
|
||||
line-height: 30px;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete .select2-selection--single .select2-selection__clear {
|
||||
cursor: pointer;
|
||||
float: right;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete .select2-selection--single .select2-selection__placeholder {
|
||||
color: var(--body-quiet-color);
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete .select2-selection--single .select2-selection__arrow {
|
||||
height: 26px;
|
||||
position: absolute;
|
||||
top: 1px;
|
||||
right: 1px;
|
||||
width: 20px;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete .select2-selection--single .select2-selection__arrow b {
|
||||
border-color: #888 transparent transparent transparent;
|
||||
border-style: solid;
|
||||
border-width: 5px 4px 0 4px;
|
||||
height: 0;
|
||||
left: 50%;
|
||||
margin-left: -4px;
|
||||
margin-top: -2px;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
width: 0;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete[dir="rtl"] .select2-selection--single .select2-selection__clear {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete[dir="rtl"] .select2-selection--single .select2-selection__arrow {
|
||||
left: 1px;
|
||||
right: auto;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete.select2-container--disabled .select2-selection--single {
|
||||
background-color: var(--darkened-bg);
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete.select2-container--disabled .select2-selection--single .select2-selection__clear {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete.select2-container--open .select2-selection--single .select2-selection__arrow b {
|
||||
border-color: transparent transparent #888 transparent;
|
||||
border-width: 0 4px 5px 4px;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete .select2-selection--multiple {
|
||||
background-color: var(--body-bg);
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 4px;
|
||||
cursor: text;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete .select2-selection--multiple .select2-selection__rendered {
|
||||
box-sizing: border-box;
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0 10px 5px 5px;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete .select2-selection--multiple .select2-selection__rendered li {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete .select2-selection--multiple .select2-selection__placeholder {
|
||||
color: var(--body-quiet-color);
|
||||
margin-top: 5px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete .select2-selection--multiple .select2-selection__clear {
|
||||
cursor: pointer;
|
||||
float: right;
|
||||
font-weight: bold;
|
||||
margin: 5px;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete .select2-selection--multiple .select2-selection__choice {
|
||||
background-color: var(--darkened-bg);
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 4px;
|
||||
cursor: default;
|
||||
float: left;
|
||||
margin-right: 5px;
|
||||
margin-top: 5px;
|
||||
padding: 0 5px;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete .select2-selection--multiple .select2-selection__choice__remove {
|
||||
color: var(--body-quiet-color);
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
font-weight: bold;
|
||||
margin-right: 2px;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete .select2-selection--multiple .select2-selection__choice__remove:hover {
|
||||
color: var(--body-fg);
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete[dir="rtl"] .select2-selection--multiple .select2-selection__choice, .select2-container--admin-autocomplete[dir="rtl"] .select2-selection--multiple .select2-selection__placeholder, .select2-container--admin-autocomplete[dir="rtl"] .select2-selection--multiple .select2-search--inline {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete[dir="rtl"] .select2-selection--multiple .select2-selection__choice {
|
||||
margin-left: 5px;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove {
|
||||
margin-left: 2px;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete.select2-container--focus .select2-selection--multiple {
|
||||
border: solid var(--body-quiet-color) 1px;
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete.select2-container--disabled .select2-selection--multiple {
|
||||
background-color: var(--darkened-bg);
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete.select2-container--disabled .select2-selection__choice__remove {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete.select2-container--open.select2-container--above .select2-selection--single, .select2-container--admin-autocomplete.select2-container--open.select2-container--above .select2-selection--multiple {
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 0;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete.select2-container--open.select2-container--below .select2-selection--single, .select2-container--admin-autocomplete.select2-container--open.select2-container--below .select2-selection--multiple {
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete .select2-search--dropdown {
|
||||
background: var(--darkened-bg);
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete .select2-search--dropdown .select2-search__field {
|
||||
background: var(--body-bg);
|
||||
color: var(--body-fg);
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete .select2-search--inline .select2-search__field {
|
||||
background: transparent;
|
||||
color: var(--body-fg);
|
||||
border: none;
|
||||
outline: 0;
|
||||
box-shadow: none;
|
||||
-webkit-appearance: textfield;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete .select2-results > .select2-results__options {
|
||||
max-height: 200px;
|
||||
overflow-y: auto;
|
||||
color: var(--body-fg);
|
||||
background: var(--body-bg);
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete .select2-results__option[role=group] {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete .select2-results__option[aria-disabled=true] {
|
||||
color: var(--body-quiet-color);
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete .select2-results__option[aria-selected=true] {
|
||||
background-color: var(--selected-bg);
|
||||
color: var(--body-fg);
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete .select2-results__option .select2-results__option {
|
||||
padding-left: 1em;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete .select2-results__option .select2-results__option .select2-results__group {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete .select2-results__option .select2-results__option .select2-results__option {
|
||||
margin-left: -1em;
|
||||
padding-left: 2em;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
|
||||
margin-left: -2em;
|
||||
padding-left: 3em;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
|
||||
margin-left: -3em;
|
||||
padding-left: 4em;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
|
||||
margin-left: -4em;
|
||||
padding-left: 5em;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
|
||||
margin-left: -5em;
|
||||
padding-left: 6em;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete .select2-results__option--highlighted[aria-selected] {
|
||||
background-color: var(--primary);
|
||||
color: var(--primary-fg);
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete .select2-results__group {
|
||||
cursor: default;
|
||||
display: block;
|
||||
padding: 6px;
|
||||
}
|
||||
>>>>>>> master
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,3 @@
|
||||
<<<<<<< HEAD
|
||||
/* CHANGELISTS */
|
||||
|
||||
#changelist {
|
||||
@ -327,333 +326,3 @@
|
||||
#changelist .actions .button:focus, #changelist .actions .button:hover {
|
||||
border-color: var(--body-quiet-color);
|
||||
}
|
||||
=======
|
||||
/* CHANGELISTS */
|
||||
|
||||
#changelist {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
#changelist .changelist-form-container {
|
||||
flex: 1 1 auto;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
#changelist table {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.change-list .hiddenfields { display:none; }
|
||||
|
||||
.change-list .filtered table {
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
.change-list .filtered {
|
||||
min-height: 400px;
|
||||
}
|
||||
|
||||
.change-list .filtered .results, .change-list .filtered .paginator,
|
||||
.filtered #toolbar, .filtered div.xfull {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.change-list .filtered table tbody th {
|
||||
padding-right: 1em;
|
||||
}
|
||||
|
||||
#changelist-form .results {
|
||||
overflow-x: auto;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#changelist .toplinks {
|
||||
border-bottom: 1px solid var(--hairline-color);
|
||||
}
|
||||
|
||||
#changelist .paginator {
|
||||
color: var(--body-quiet-color);
|
||||
border-bottom: 1px solid var(--hairline-color);
|
||||
background: var(--body-bg);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* CHANGELIST TABLES */
|
||||
|
||||
#changelist table thead th {
|
||||
padding: 0;
|
||||
white-space: nowrap;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
#changelist table thead th.action-checkbox-column {
|
||||
width: 1.5em;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#changelist table tbody td.action-checkbox {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#changelist table tfoot {
|
||||
color: var(--body-quiet-color);
|
||||
}
|
||||
|
||||
/* TOOLBAR */
|
||||
|
||||
#toolbar {
|
||||
padding: 8px 10px;
|
||||
margin-bottom: 15px;
|
||||
border-top: 1px solid var(--hairline-color);
|
||||
border-bottom: 1px solid var(--hairline-color);
|
||||
background: var(--darkened-bg);
|
||||
color: var(--body-quiet-color);
|
||||
}
|
||||
|
||||
#toolbar form input {
|
||||
border-radius: 4px;
|
||||
font-size: 0.875rem;
|
||||
padding: 5px;
|
||||
color: var(--body-fg);
|
||||
}
|
||||
|
||||
#toolbar #searchbar {
|
||||
height: 1.1875rem;
|
||||
border: 1px solid var(--border-color);
|
||||
padding: 2px 5px;
|
||||
margin: 0;
|
||||
vertical-align: top;
|
||||
font-size: 0.8125rem;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
#toolbar #searchbar:focus {
|
||||
border-color: var(--body-quiet-color);
|
||||
}
|
||||
|
||||
#toolbar form input[type="submit"] {
|
||||
border: 1px solid var(--border-color);
|
||||
font-size: 0.8125rem;
|
||||
padding: 4px 8px;
|
||||
margin: 0;
|
||||
vertical-align: middle;
|
||||
background: var(--body-bg);
|
||||
box-shadow: 0 -15px 20px -10px rgba(0, 0, 0, 0.15) inset;
|
||||
cursor: pointer;
|
||||
color: var(--body-fg);
|
||||
}
|
||||
|
||||
#toolbar form input[type="submit"]:focus,
|
||||
#toolbar form input[type="submit"]:hover {
|
||||
border-color: var(--body-quiet-color);
|
||||
}
|
||||
|
||||
#changelist-search img {
|
||||
vertical-align: middle;
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
#changelist-search .help {
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
/* FILTER COLUMN */
|
||||
|
||||
#changelist-filter {
|
||||
flex: 0 0 240px;
|
||||
order: 1;
|
||||
background: var(--darkened-bg);
|
||||
border-left: none;
|
||||
margin: 0 0 0 30px;
|
||||
}
|
||||
|
||||
#changelist-filter h2 {
|
||||
font-size: 0.875rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
padding: 5px 15px;
|
||||
margin-bottom: 12px;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
#changelist-filter h3,
|
||||
#changelist-filter details summary {
|
||||
font-weight: 400;
|
||||
padding: 0 15px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
#changelist-filter details summary > * {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
#changelist-filter details > summary {
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
#changelist-filter details > summary::-webkit-details-marker {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#changelist-filter details > summary::before {
|
||||
content: '→';
|
||||
font-weight: bold;
|
||||
color: var(--link-hover-color);
|
||||
}
|
||||
|
||||
#changelist-filter details[open] > summary::before {
|
||||
content: '↓';
|
||||
}
|
||||
|
||||
#changelist-filter ul {
|
||||
margin: 5px 0;
|
||||
padding: 0 15px 15px;
|
||||
border-bottom: 1px solid var(--hairline-color);
|
||||
}
|
||||
|
||||
#changelist-filter ul:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
#changelist-filter li {
|
||||
list-style-type: none;
|
||||
margin-left: 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
#changelist-filter a {
|
||||
display: block;
|
||||
color: var(--body-quiet-color);
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
#changelist-filter li.selected {
|
||||
border-left: 5px solid var(--hairline-color);
|
||||
padding-left: 10px;
|
||||
margin-left: -15px;
|
||||
}
|
||||
|
||||
#changelist-filter li.selected a {
|
||||
color: var(--link-selected-fg);
|
||||
}
|
||||
|
||||
#changelist-filter a:focus, #changelist-filter a:hover,
|
||||
#changelist-filter li.selected a:focus,
|
||||
#changelist-filter li.selected a:hover {
|
||||
color: var(--link-hover-color);
|
||||
}
|
||||
|
||||
#changelist-filter #changelist-filter-clear a {
|
||||
font-size: 0.8125rem;
|
||||
padding-bottom: 10px;
|
||||
border-bottom: 1px solid var(--hairline-color);
|
||||
}
|
||||
|
||||
/* DATE DRILLDOWN */
|
||||
|
||||
.change-list .toplinks {
|
||||
display: flex;
|
||||
padding-bottom: 5px;
|
||||
flex-wrap: wrap;
|
||||
gap: 3px 17px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.change-list .toplinks a {
|
||||
font-size: 0.8125rem;
|
||||
}
|
||||
|
||||
.change-list .toplinks .date-back {
|
||||
color: var(--body-quiet-color);
|
||||
}
|
||||
|
||||
.change-list .toplinks .date-back:focus,
|
||||
.change-list .toplinks .date-back:hover {
|
||||
color: var(--link-hover-color);
|
||||
}
|
||||
|
||||
/* ACTIONS */
|
||||
|
||||
.filtered .actions {
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
#changelist table input {
|
||||
margin: 0;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
/* Once the :has() pseudo-class is supported by all browsers, the tr.selected
|
||||
selector and the JS adding the class can be removed. */
|
||||
#changelist tbody tr.selected {
|
||||
background-color: var(--selected-row);
|
||||
}
|
||||
|
||||
#changelist tbody tr:has(.action-select:checked) {
|
||||
background-color: var(--selected-row);
|
||||
}
|
||||
|
||||
#changelist .actions {
|
||||
padding: 10px;
|
||||
background: var(--body-bg);
|
||||
border-top: none;
|
||||
border-bottom: none;
|
||||
line-height: 1.5rem;
|
||||
color: var(--body-quiet-color);
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#changelist .actions span.all,
|
||||
#changelist .actions span.action-counter,
|
||||
#changelist .actions span.clear,
|
||||
#changelist .actions span.question {
|
||||
font-size: 0.8125rem;
|
||||
margin: 0 0.5em;
|
||||
}
|
||||
|
||||
#changelist .actions:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
#changelist .actions select {
|
||||
vertical-align: top;
|
||||
height: 1.5rem;
|
||||
color: var(--body-fg);
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 4px;
|
||||
font-size: 0.875rem;
|
||||
padding: 0 0 0 4px;
|
||||
margin: 0;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
#changelist .actions select:focus {
|
||||
border-color: var(--body-quiet-color);
|
||||
}
|
||||
|
||||
#changelist .actions label {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
font-size: 0.8125rem;
|
||||
}
|
||||
|
||||
#changelist .actions .button {
|
||||
font-size: 0.8125rem;
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 4px;
|
||||
background: var(--body-bg);
|
||||
box-shadow: 0 -15px 20px -10px rgba(0, 0, 0, 0.15) inset;
|
||||
cursor: pointer;
|
||||
height: 1.5rem;
|
||||
line-height: 1;
|
||||
padding: 4px 8px;
|
||||
margin: 0;
|
||||
color: var(--body-fg);
|
||||
}
|
||||
|
||||
#changelist .actions .button:focus, #changelist .actions .button:hover {
|
||||
border-color: var(--body-quiet-color);
|
||||
}
|
||||
>>>>>>> master
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
<<<<<<< HEAD
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--primary: #264b5d;
|
||||
@ -136,142 +135,3 @@ html[data-theme="light"] .theme-toggle svg.theme-icon-when-light {
|
||||
color: var(--body-fg);
|
||||
background-color: var(--body-bg);
|
||||
}
|
||||
=======
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--primary: #264b5d;
|
||||
--primary-fg: #f7f7f7;
|
||||
|
||||
--body-fg: #eeeeee;
|
||||
--body-bg: #121212;
|
||||
--body-quiet-color: #e0e0e0;
|
||||
--body-loud-color: #ffffff;
|
||||
|
||||
--breadcrumbs-link-fg: #e0e0e0;
|
||||
--breadcrumbs-bg: var(--primary);
|
||||
|
||||
--link-fg: #81d4fa;
|
||||
--link-hover-color: #4ac1f7;
|
||||
--link-selected-fg: #6f94c6;
|
||||
|
||||
--hairline-color: #272727;
|
||||
--border-color: #353535;
|
||||
|
||||
--error-fg: #e35f5f;
|
||||
--message-success-bg: #006b1b;
|
||||
--message-warning-bg: #583305;
|
||||
--message-error-bg: #570808;
|
||||
|
||||
--darkened-bg: #212121;
|
||||
--selected-bg: #1b1b1b;
|
||||
--selected-row: #00363a;
|
||||
|
||||
--close-button-bg: #333333;
|
||||
--close-button-hover-bg: #666666;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
html[data-theme="dark"] {
|
||||
--primary: #264b5d;
|
||||
--primary-fg: #f7f7f7;
|
||||
|
||||
--body-fg: #eeeeee;
|
||||
--body-bg: #121212;
|
||||
--body-quiet-color: #e0e0e0;
|
||||
--body-loud-color: #ffffff;
|
||||
|
||||
--breadcrumbs-link-fg: #e0e0e0;
|
||||
--breadcrumbs-bg: var(--primary);
|
||||
|
||||
--link-fg: #81d4fa;
|
||||
--link-hover-color: #4ac1f7;
|
||||
--link-selected-fg: #6f94c6;
|
||||
|
||||
--hairline-color: #272727;
|
||||
--border-color: #353535;
|
||||
|
||||
--error-fg: #e35f5f;
|
||||
--message-success-bg: #006b1b;
|
||||
--message-warning-bg: #583305;
|
||||
--message-error-bg: #570808;
|
||||
|
||||
--darkened-bg: #212121;
|
||||
--selected-bg: #1b1b1b;
|
||||
--selected-row: #00363a;
|
||||
|
||||
--close-button-bg: #333333;
|
||||
--close-button-hover-bg: #666666;
|
||||
}
|
||||
|
||||
/* THEME SWITCH */
|
||||
.theme-toggle {
|
||||
cursor: pointer;
|
||||
border: none;
|
||||
padding: 0;
|
||||
background: transparent;
|
||||
vertical-align: middle;
|
||||
margin-inline-start: 5px;
|
||||
margin-top: -1px;
|
||||
}
|
||||
|
||||
.theme-toggle svg {
|
||||
vertical-align: middle;
|
||||
height: 1rem;
|
||||
width: 1rem;
|
||||
display: none;
|
||||
}
|
||||
|
||||
/*
|
||||
Fully hide screen reader text so we only show the one matching the current
|
||||
theme.
|
||||
*/
|
||||
.theme-toggle .visually-hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
html[data-theme="auto"] .theme-toggle .theme-label-when-auto {
|
||||
display: block;
|
||||
}
|
||||
|
||||
html[data-theme="dark"] .theme-toggle .theme-label-when-dark {
|
||||
display: block;
|
||||
}
|
||||
|
||||
html[data-theme="light"] .theme-toggle .theme-label-when-light {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* ICONS */
|
||||
.theme-toggle svg.theme-icon-when-auto,
|
||||
.theme-toggle svg.theme-icon-when-dark,
|
||||
.theme-toggle svg.theme-icon-when-light {
|
||||
fill: var(--header-link-color);
|
||||
color: var(--header-bg);
|
||||
}
|
||||
|
||||
html[data-theme="auto"] .theme-toggle svg.theme-icon-when-auto {
|
||||
display: block;
|
||||
}
|
||||
|
||||
html[data-theme="dark"] .theme-toggle svg.theme-icon-when-dark {
|
||||
display: block;
|
||||
}
|
||||
|
||||
html[data-theme="light"] .theme-toggle svg.theme-icon-when-light {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.visually-hidden {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
clip: rect(0,0,0,0);
|
||||
white-space: nowrap;
|
||||
border: 0;
|
||||
color: var(--body-fg);
|
||||
background-color: var(--body-bg);
|
||||
}
|
||||
>>>>>>> master
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
<<<<<<< HEAD
|
||||
/* DASHBOARD */
|
||||
.dashboard td, .dashboard th {
|
||||
word-break: break-word;
|
||||
@ -28,34 +27,3 @@ ul.actionlist li {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
=======
|
||||
/* DASHBOARD */
|
||||
.dashboard td, .dashboard th {
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.dashboard .module table th {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.dashboard .module table td {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.dashboard .module table td a {
|
||||
display: block;
|
||||
padding-right: .6em;
|
||||
}
|
||||
|
||||
/* RECENT ACTIONS MODULE */
|
||||
|
||||
.module ul.actionlist {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
ul.actionlist li {
|
||||
list-style-type: none;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
>>>>>>> master
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
<<<<<<< HEAD
|
||||
@import url('widgets.css');
|
||||
|
||||
/* FORM ROWS */
|
||||
@ -529,535 +528,3 @@ form .related-widget-wrapper ul {
|
||||
.clearable-file-input input {
|
||||
margin-top: 0;
|
||||
}
|
||||
=======
|
||||
@import url('widgets.css');
|
||||
|
||||
/* FORM ROWS */
|
||||
|
||||
.form-row {
|
||||
overflow: hidden;
|
||||
padding: 10px;
|
||||
font-size: 0.8125rem;
|
||||
border-bottom: 1px solid var(--hairline-color);
|
||||
}
|
||||
|
||||
.form-row img, .form-row input {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.form-row label input[type="checkbox"] {
|
||||
margin-top: 0;
|
||||
vertical-align: 0;
|
||||
}
|
||||
|
||||
form .form-row p {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.flex-container {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.form-multiline > div {
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
/* FORM LABELS */
|
||||
|
||||
label {
|
||||
font-weight: normal;
|
||||
color: var(--body-quiet-color);
|
||||
font-size: 0.8125rem;
|
||||
}
|
||||
|
||||
.required label, label.required {
|
||||
font-weight: bold;
|
||||
color: var(--body-fg);
|
||||
}
|
||||
|
||||
/* RADIO BUTTONS */
|
||||
|
||||
form div.radiolist div {
|
||||
padding-right: 7px;
|
||||
}
|
||||
|
||||
form div.radiolist.inline div {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
form div.radiolist label {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
form div.radiolist input[type="radio"] {
|
||||
margin: -2px 4px 0 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
form ul.inline {
|
||||
margin-left: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
form ul.inline li {
|
||||
float: left;
|
||||
padding-right: 7px;
|
||||
}
|
||||
|
||||
/* ALIGNED FIELDSETS */
|
||||
|
||||
.aligned label {
|
||||
display: block;
|
||||
padding: 4px 10px 0 0;
|
||||
width: 160px;
|
||||
word-wrap: break-word;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.aligned label:not(.vCheckboxLabel):after {
|
||||
content: '';
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
height: 1.625rem;
|
||||
}
|
||||
|
||||
.aligned label + p, .aligned .checkbox-row + div.help, .aligned label + div.readonly {
|
||||
padding: 6px 0;
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
margin-left: 0;
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
|
||||
.aligned ul label {
|
||||
display: inline;
|
||||
float: none;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.aligned .form-row input {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.colMS .aligned .vLargeTextField, .colMS .aligned .vXMLLargeTextField {
|
||||
width: 350px;
|
||||
}
|
||||
|
||||
form .aligned ul {
|
||||
margin-left: 160px;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
form .aligned div.radiolist {
|
||||
display: inline-block;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
form .aligned p.help,
|
||||
form .aligned div.help {
|
||||
margin-top: 0;
|
||||
margin-left: 160px;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
form .aligned p.date div.help.timezonewarning,
|
||||
form .aligned p.datetime div.help.timezonewarning,
|
||||
form .aligned p.time div.help.timezonewarning {
|
||||
margin-left: 0;
|
||||
padding-left: 0;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
form .aligned p.help:last-child,
|
||||
form .aligned div.help:last-child {
|
||||
margin-bottom: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
form .aligned input + p.help,
|
||||
form .aligned textarea + p.help,
|
||||
form .aligned select + p.help,
|
||||
form .aligned input + div.help,
|
||||
form .aligned textarea + div.help,
|
||||
form .aligned select + div.help {
|
||||
margin-left: 160px;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
form .aligned ul li {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
form .aligned table p {
|
||||
margin-left: 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.aligned .vCheckboxLabel {
|
||||
float: none;
|
||||
width: auto;
|
||||
display: inline-block;
|
||||
vertical-align: -3px;
|
||||
padding: 0 0 5px 5px;
|
||||
}
|
||||
|
||||
.aligned .vCheckboxLabel + p.help,
|
||||
.aligned .vCheckboxLabel + div.help {
|
||||
margin-top: -4px;
|
||||
}
|
||||
|
||||
.colM .aligned .vLargeTextField, .colM .aligned .vXMLLargeTextField {
|
||||
width: 610px;
|
||||
}
|
||||
|
||||
fieldset .fieldBox {
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
/* WIDE FIELDSETS */
|
||||
|
||||
.wide label {
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
form .wide p,
|
||||
form .wide ul.errorlist,
|
||||
form .wide input + p.help,
|
||||
form .wide input + div.help {
|
||||
margin-left: 200px;
|
||||
}
|
||||
|
||||
form .wide p.help,
|
||||
form .wide div.help {
|
||||
padding-left: 50px;
|
||||
}
|
||||
|
||||
form div.help ul {
|
||||
padding-left: 0;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.colM fieldset.wide .vLargeTextField, .colM fieldset.wide .vXMLLargeTextField {
|
||||
width: 450px;
|
||||
}
|
||||
|
||||
/* COLLAPSED FIELDSETS */
|
||||
|
||||
fieldset.collapsed * {
|
||||
display: none;
|
||||
}
|
||||
|
||||
fieldset.collapsed h2, fieldset.collapsed {
|
||||
display: block;
|
||||
}
|
||||
|
||||
fieldset.collapsed {
|
||||
border: 1px solid var(--hairline-color);
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
fieldset.collapsed h2 {
|
||||
background: var(--darkened-bg);
|
||||
color: var(--body-quiet-color);
|
||||
}
|
||||
|
||||
fieldset .collapse-toggle {
|
||||
color: var(--header-link-color);
|
||||
}
|
||||
|
||||
fieldset.collapsed .collapse-toggle {
|
||||
background: transparent;
|
||||
display: inline;
|
||||
color: var(--link-fg);
|
||||
}
|
||||
|
||||
/* MONOSPACE TEXTAREAS */
|
||||
|
||||
fieldset.monospace textarea {
|
||||
font-family: var(--font-family-monospace);
|
||||
}
|
||||
|
||||
/* SUBMIT ROW */
|
||||
|
||||
.submit-row {
|
||||
padding: 12px 14px 12px;
|
||||
margin: 0 0 20px;
|
||||
background: var(--darkened-bg);
|
||||
border: 1px solid var(--hairline-color);
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
body.popup .submit-row {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.submit-row input {
|
||||
height: 2.1875rem;
|
||||
line-height: 0.9375rem;
|
||||
}
|
||||
|
||||
.submit-row input, .submit-row a {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.submit-row input.default {
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.submit-row a.deletelink {
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.submit-row a.deletelink {
|
||||
display: block;
|
||||
background: var(--delete-button-bg);
|
||||
border-radius: 4px;
|
||||
padding: 0.625rem 0.9375rem;
|
||||
height: 0.9375rem;
|
||||
line-height: 0.9375rem;
|
||||
color: var(--button-fg);
|
||||
}
|
||||
|
||||
.submit-row a.closelink {
|
||||
display: inline-block;
|
||||
background: var(--close-button-bg);
|
||||
border-radius: 4px;
|
||||
padding: 10px 15px;
|
||||
height: 0.9375rem;
|
||||
line-height: 0.9375rem;
|
||||
color: var(--button-fg);
|
||||
}
|
||||
|
||||
.submit-row a.deletelink:focus,
|
||||
.submit-row a.deletelink:hover,
|
||||
.submit-row a.deletelink:active {
|
||||
background: var(--delete-button-hover-bg);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.submit-row a.closelink:focus,
|
||||
.submit-row a.closelink:hover,
|
||||
.submit-row a.closelink:active {
|
||||
background: var(--close-button-hover-bg);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* CUSTOM FORM FIELDS */
|
||||
|
||||
.vSelectMultipleField {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.vCheckboxField {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.vDateField, .vTimeField {
|
||||
margin-right: 2px;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.vDateField {
|
||||
min-width: 6.85em;
|
||||
}
|
||||
|
||||
.vTimeField {
|
||||
min-width: 4.7em;
|
||||
}
|
||||
|
||||
.vURLField {
|
||||
width: 30em;
|
||||
}
|
||||
|
||||
.vLargeTextField, .vXMLLargeTextField {
|
||||
width: 48em;
|
||||
}
|
||||
|
||||
.flatpages-flatpage #id_content {
|
||||
height: 40.2em;
|
||||
}
|
||||
|
||||
.module table .vPositiveSmallIntegerField {
|
||||
width: 2.2em;
|
||||
}
|
||||
|
||||
.vIntegerField {
|
||||
width: 5em;
|
||||
}
|
||||
|
||||
.vBigIntegerField {
|
||||
width: 10em;
|
||||
}
|
||||
|
||||
.vForeignKeyRawIdAdminField {
|
||||
width: 5em;
|
||||
}
|
||||
|
||||
.vTextField, .vUUIDField {
|
||||
width: 20em;
|
||||
}
|
||||
|
||||
/* INLINES */
|
||||
|
||||
.inline-group {
|
||||
padding: 0;
|
||||
margin: 0 0 30px;
|
||||
}
|
||||
|
||||
.inline-group thead th {
|
||||
padding: 8px 10px;
|
||||
}
|
||||
|
||||
.inline-group .aligned label {
|
||||
width: 160px;
|
||||
}
|
||||
|
||||
.inline-related {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.inline-related h3 {
|
||||
margin: 0;
|
||||
color: var(--body-quiet-color);
|
||||
padding: 5px;
|
||||
font-size: 0.8125rem;
|
||||
background: var(--darkened-bg);
|
||||
border-top: 1px solid var(--hairline-color);
|
||||
border-bottom: 1px solid var(--hairline-color);
|
||||
}
|
||||
|
||||
.inline-related h3 span.delete {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.inline-related h3 span.delete label {
|
||||
margin-left: 2px;
|
||||
font-size: 0.6875rem;
|
||||
}
|
||||
|
||||
.inline-related fieldset {
|
||||
margin: 0;
|
||||
background: var(--body-bg);
|
||||
border: none;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.inline-related fieldset.module h3 {
|
||||
margin: 0;
|
||||
padding: 2px 5px 3px 5px;
|
||||
font-size: 0.6875rem;
|
||||
text-align: left;
|
||||
font-weight: bold;
|
||||
background: #bcd;
|
||||
color: var(--body-bg);
|
||||
}
|
||||
|
||||
.inline-group .tabular fieldset.module {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.inline-related.tabular fieldset.module table {
|
||||
width: 100%;
|
||||
overflow-x: scroll;
|
||||
}
|
||||
|
||||
.last-related fieldset {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.inline-group .tabular tr.has_original td {
|
||||
padding-top: 2em;
|
||||
}
|
||||
|
||||
.inline-group .tabular tr td.original {
|
||||
padding: 2px 0 0 0;
|
||||
width: 0;
|
||||
_position: relative;
|
||||
}
|
||||
|
||||
.inline-group .tabular th.original {
|
||||
width: 0px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.inline-group .tabular td.original p {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
height: 1.1em;
|
||||
padding: 2px 9px;
|
||||
overflow: hidden;
|
||||
font-size: 0.5625rem;
|
||||
font-weight: bold;
|
||||
color: var(--body-quiet-color);
|
||||
_width: 700px;
|
||||
}
|
||||
|
||||
.inline-group ul.tools {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.inline-group ul.tools li {
|
||||
display: inline;
|
||||
padding: 0 5px;
|
||||
}
|
||||
|
||||
.inline-group div.add-row,
|
||||
.inline-group .tabular tr.add-row td {
|
||||
color: var(--body-quiet-color);
|
||||
background: var(--darkened-bg);
|
||||
padding: 8px 10px;
|
||||
border-bottom: 1px solid var(--hairline-color);
|
||||
}
|
||||
|
||||
.inline-group .tabular tr.add-row td {
|
||||
padding: 8px 10px;
|
||||
border-bottom: 1px solid var(--hairline-color);
|
||||
}
|
||||
|
||||
.inline-group ul.tools a.add,
|
||||
.inline-group div.add-row a,
|
||||
.inline-group .tabular tr.add-row td a {
|
||||
background: url(../img/icon-addlink.svg) 0 1px no-repeat;
|
||||
padding-left: 16px;
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
|
||||
.empty-form {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* RELATED FIELD ADD ONE / LOOKUP */
|
||||
|
||||
.related-lookup {
|
||||
margin-left: 5px;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 14px;
|
||||
}
|
||||
|
||||
.related-lookup {
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
background-image: url(../img/search.svg);
|
||||
}
|
||||
|
||||
form .related-widget-wrapper ul {
|
||||
display: inline-block;
|
||||
margin-left: 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.clearable-file-input input {
|
||||
margin-top: 0;
|
||||
}
|
||||
>>>>>>> master
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
<<<<<<< HEAD
|
||||
/* LOGIN FORM */
|
||||
|
||||
.login {
|
||||
@ -60,66 +59,3 @@
|
||||
.login .password-reset-link {
|
||||
text-align: center;
|
||||
}
|
||||
=======
|
||||
/* LOGIN FORM */
|
||||
|
||||
.login {
|
||||
background: var(--darkened-bg);
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.login #header {
|
||||
height: auto;
|
||||
padding: 15px 16px;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.login #header h1 {
|
||||
font-size: 1.125rem;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.login #header h1 a {
|
||||
color: var(--header-link-color);
|
||||
}
|
||||
|
||||
.login #content {
|
||||
padding: 20px 20px 0;
|
||||
}
|
||||
|
||||
.login #container {
|
||||
background: var(--body-bg);
|
||||
border: 1px solid var(--hairline-color);
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
width: 28em;
|
||||
min-width: 300px;
|
||||
margin: 100px auto;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.login .form-row {
|
||||
padding: 4px 0;
|
||||
}
|
||||
|
||||
.login .form-row label {
|
||||
display: block;
|
||||
line-height: 2em;
|
||||
}
|
||||
|
||||
.login .form-row #id_username, .login .form-row #id_password {
|
||||
padding: 8px;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.login .submit-row {
|
||||
padding: 1em 0 0 0;
|
||||
margin: 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.login .password-reset-link {
|
||||
text-align: center;
|
||||
}
|
||||
>>>>>>> master
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
<<<<<<< HEAD
|
||||
.sticky {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
@ -143,149 +142,3 @@
|
||||
#nav-sidebar table {
|
||||
width: 100%;
|
||||
}
|
||||
=======
|
||||
.sticky {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
max-height: 100vh;
|
||||
}
|
||||
|
||||
.toggle-nav-sidebar {
|
||||
z-index: 20;
|
||||
left: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex: 0 0 23px;
|
||||
width: 23px;
|
||||
border: 0;
|
||||
border-right: 1px solid var(--hairline-color);
|
||||
background-color: var(--body-bg);
|
||||
cursor: pointer;
|
||||
font-size: 1.25rem;
|
||||
color: var(--link-fg);
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
[dir="rtl"] .toggle-nav-sidebar {
|
||||
border-left: 1px solid var(--hairline-color);
|
||||
border-right: 0;
|
||||
}
|
||||
|
||||
.toggle-nav-sidebar:hover,
|
||||
.toggle-nav-sidebar:focus {
|
||||
background-color: var(--darkened-bg);
|
||||
}
|
||||
|
||||
#nav-sidebar {
|
||||
z-index: 15;
|
||||
flex: 0 0 275px;
|
||||
left: -276px;
|
||||
margin-left: -276px;
|
||||
border-top: 1px solid transparent;
|
||||
border-right: 1px solid var(--hairline-color);
|
||||
background-color: var(--body-bg);
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
[dir="rtl"] #nav-sidebar {
|
||||
border-left: 1px solid var(--hairline-color);
|
||||
border-right: 0;
|
||||
left: 0;
|
||||
margin-left: 0;
|
||||
right: -276px;
|
||||
margin-right: -276px;
|
||||
}
|
||||
|
||||
.toggle-nav-sidebar::before {
|
||||
content: '\00BB';
|
||||
}
|
||||
|
||||
.main.shifted .toggle-nav-sidebar::before {
|
||||
content: '\00AB';
|
||||
}
|
||||
|
||||
.main > #nav-sidebar {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.main.shifted > #nav-sidebar {
|
||||
margin-left: 0;
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
[dir="rtl"] .main.shifted > #nav-sidebar {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
#nav-sidebar .module th {
|
||||
width: 100%;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
#nav-sidebar .module th,
|
||||
#nav-sidebar .module caption {
|
||||
padding-left: 16px;
|
||||
}
|
||||
|
||||
#nav-sidebar .module td {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
[dir="rtl"] #nav-sidebar .module th,
|
||||
[dir="rtl"] #nav-sidebar .module caption {
|
||||
padding-left: 8px;
|
||||
padding-right: 16px;
|
||||
}
|
||||
|
||||
#nav-sidebar .current-app .section:link,
|
||||
#nav-sidebar .current-app .section:visited {
|
||||
color: var(--header-color);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#nav-sidebar .current-model {
|
||||
background: var(--selected-row);
|
||||
}
|
||||
|
||||
.main > #nav-sidebar + .content {
|
||||
max-width: calc(100% - 23px);
|
||||
}
|
||||
|
||||
.main.shifted > #nav-sidebar + .content {
|
||||
max-width: calc(100% - 299px);
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
#nav-sidebar, #toggle-nav-sidebar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.main > #nav-sidebar + .content,
|
||||
.main.shifted > #nav-sidebar + .content {
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
#nav-filter {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
padding: 2px 5px;
|
||||
margin: 5px 0;
|
||||
border: 1px solid var(--border-color);
|
||||
background-color: var(--darkened-bg);
|
||||
color: var(--body-fg);
|
||||
}
|
||||
|
||||
#nav-filter:focus {
|
||||
border-color: var(--body-quiet-color);
|
||||
}
|
||||
|
||||
#nav-filter.no-results {
|
||||
background: var(--message-error-bg);
|
||||
}
|
||||
|
||||
#nav-sidebar table {
|
||||
width: 100%;
|
||||
}
|
||||
>>>>>>> master
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,3 @@
|
||||
<<<<<<< HEAD
|
||||
/* TABLETS */
|
||||
|
||||
@media (max-width: 1024px) {
|
||||
@ -80,86 +79,3 @@
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
=======
|
||||
/* TABLETS */
|
||||
|
||||
@media (max-width: 1024px) {
|
||||
[dir="rtl"] .colMS {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
[dir="rtl"] #user-tools {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
[dir="rtl"] #changelist .actions label {
|
||||
padding-left: 10px;
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
[dir="rtl"] #changelist .actions select {
|
||||
margin-left: 0;
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
||||
[dir="rtl"] .change-list .filtered .results,
|
||||
[dir="rtl"] .change-list .filtered .paginator,
|
||||
[dir="rtl"] .filtered #toolbar,
|
||||
[dir="rtl"] .filtered div.xfull,
|
||||
[dir="rtl"] .filtered .actions,
|
||||
[dir="rtl"] #changelist-filter {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
[dir="rtl"] .inline-group ul.tools a.add,
|
||||
[dir="rtl"] .inline-group div.add-row a,
|
||||
[dir="rtl"] .inline-group .tabular tr.add-row td a {
|
||||
padding: 8px 26px 8px 10px;
|
||||
background-position: calc(100% - 8px) 9px;
|
||||
}
|
||||
|
||||
[dir="rtl"] .related-widget-wrapper-link + .selector {
|
||||
margin-right: 0;
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
||||
[dir="rtl"] .selector .selector-filter label {
|
||||
margin-right: 0;
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
[dir="rtl"] .object-tools li {
|
||||
float: right;
|
||||
}
|
||||
|
||||
[dir="rtl"] .object-tools li + li {
|
||||
margin-left: 0;
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
||||
[dir="rtl"] .dashboard .module table td a {
|
||||
padding-left: 0;
|
||||
padding-right: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
/* MOBILE */
|
||||
|
||||
@media (max-width: 767px) {
|
||||
[dir="rtl"] .aligned .related-lookup,
|
||||
[dir="rtl"] .aligned .datetimeshortcuts {
|
||||
margin-left: 0;
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
||||
[dir="rtl"] .aligned ul,
|
||||
[dir="rtl"] form .aligned ul.errorlist {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
[dir="rtl"] #changelist-filter {
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
>>>>>>> master
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
<<<<<<< HEAD
|
||||
/* GLOBAL */
|
||||
|
||||
th {
|
||||
@ -287,293 +286,3 @@ form .form-row p.datetime {
|
||||
margin-left: inherit;
|
||||
margin-right: 2px;
|
||||
}
|
||||
=======
|
||||
/* GLOBAL */
|
||||
|
||||
th {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.module h2, .module caption {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.module ul, .module ol {
|
||||
margin-left: 0;
|
||||
margin-right: 1.5em;
|
||||
}
|
||||
|
||||
.viewlink, .addlink, .changelink {
|
||||
padding-left: 0;
|
||||
padding-right: 16px;
|
||||
background-position: 100% 1px;
|
||||
}
|
||||
|
||||
.deletelink {
|
||||
padding-left: 0;
|
||||
padding-right: 16px;
|
||||
background-position: 100% 1px;
|
||||
}
|
||||
|
||||
.object-tools {
|
||||
float: left;
|
||||
}
|
||||
|
||||
thead th:first-child,
|
||||
tfoot td:first-child {
|
||||
border-left: none;
|
||||
}
|
||||
|
||||
/* LAYOUT */
|
||||
|
||||
#user-tools {
|
||||
right: auto;
|
||||
left: 0;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
div.breadcrumbs {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
#content-main {
|
||||
float: right;
|
||||
}
|
||||
|
||||
#content-related {
|
||||
float: left;
|
||||
margin-left: -300px;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.colMS {
|
||||
margin-left: 300px;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
/* SORTABLE TABLES */
|
||||
|
||||
table thead th.sorted .sortoptions {
|
||||
float: left;
|
||||
}
|
||||
|
||||
thead th.sorted .text {
|
||||
padding-right: 0;
|
||||
padding-left: 42px;
|
||||
}
|
||||
|
||||
/* dashboard styles */
|
||||
|
||||
.dashboard .module table td a {
|
||||
padding-left: .6em;
|
||||
padding-right: 16px;
|
||||
}
|
||||
|
||||
/* changelists styles */
|
||||
|
||||
.change-list .filtered table {
|
||||
border-left: none;
|
||||
border-right: 0px none;
|
||||
}
|
||||
|
||||
#changelist-filter {
|
||||
border-left: none;
|
||||
border-right: none;
|
||||
margin-left: 0;
|
||||
margin-right: 30px;
|
||||
}
|
||||
|
||||
#changelist-filter li.selected {
|
||||
border-left: none;
|
||||
padding-left: 10px;
|
||||
margin-left: 0;
|
||||
border-right: 5px solid var(--hairline-color);
|
||||
padding-right: 10px;
|
||||
margin-right: -15px;
|
||||
}
|
||||
|
||||
#changelist table tbody td:first-child, #changelist table tbody th:first-child {
|
||||
border-right: none;
|
||||
border-left: none;
|
||||
}
|
||||
|
||||
/* FORMS */
|
||||
|
||||
.aligned label {
|
||||
padding: 0 0 3px 1em;
|
||||
}
|
||||
|
||||
.submit-row a.deletelink {
|
||||
margin-left: 0;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.vDateField, .vTimeField {
|
||||
margin-left: 2px;
|
||||
}
|
||||
|
||||
.aligned .form-row input {
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
form .aligned ul {
|
||||
margin-right: 163px;
|
||||
padding-right: 10px;
|
||||
margin-left: 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
form ul.inline li {
|
||||
float: right;
|
||||
padding-right: 0;
|
||||
padding-left: 7px;
|
||||
}
|
||||
|
||||
form .aligned p.help,
|
||||
form .aligned div.help {
|
||||
margin-right: 160px;
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
form div.help ul,
|
||||
form .aligned .checkbox-row + .help,
|
||||
form .aligned p.date div.help.timezonewarning,
|
||||
form .aligned p.datetime div.help.timezonewarning,
|
||||
form .aligned p.time div.help.timezonewarning {
|
||||
margin-right: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
form .wide p.help, form .wide div.help {
|
||||
padding-left: 0;
|
||||
padding-right: 50px;
|
||||
}
|
||||
|
||||
form .wide p,
|
||||
form .wide ul.errorlist,
|
||||
form .wide input + p.help,
|
||||
form .wide input + div.help {
|
||||
margin-right: 200px;
|
||||
margin-left: 0px;
|
||||
}
|
||||
|
||||
.submit-row {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
fieldset .fieldBox {
|
||||
margin-left: 20px;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.errorlist li {
|
||||
background-position: 100% 12px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.errornote {
|
||||
background-position: 100% 12px;
|
||||
padding: 10px 12px;
|
||||
}
|
||||
|
||||
/* WIDGETS */
|
||||
|
||||
.calendarnav-previous {
|
||||
top: 0;
|
||||
left: auto;
|
||||
right: 10px;
|
||||
background: url(../img/calendar-icons.svg) 0 -30px no-repeat;
|
||||
}
|
||||
|
||||
.calendarbox .calendarnav-previous:focus,
|
||||
.calendarbox .calendarnav-previous:hover {
|
||||
background-position: 0 -45px;
|
||||
}
|
||||
|
||||
.calendarnav-next {
|
||||
top: 0;
|
||||
right: auto;
|
||||
left: 10px;
|
||||
background: url(../img/calendar-icons.svg) 0 0 no-repeat;
|
||||
}
|
||||
|
||||
.calendarbox .calendarnav-next:focus,
|
||||
.calendarbox .calendarnav-next:hover {
|
||||
background-position: 0 -15px;
|
||||
}
|
||||
|
||||
.calendar caption, .calendarbox h2 {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.selector {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.selector .selector-filter {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.selector-add {
|
||||
background: url(../img/selector-icons.svg) 0 -64px no-repeat;
|
||||
}
|
||||
|
||||
.active.selector-add:focus, .active.selector-add:hover {
|
||||
background-position: 0 -80px;
|
||||
}
|
||||
|
||||
.selector-remove {
|
||||
background: url(../img/selector-icons.svg) 0 -96px no-repeat;
|
||||
}
|
||||
|
||||
.active.selector-remove:focus, .active.selector-remove:hover {
|
||||
background-position: 0 -112px;
|
||||
}
|
||||
|
||||
a.selector-chooseall {
|
||||
background: url(../img/selector-icons.svg) right -128px no-repeat;
|
||||
}
|
||||
|
||||
a.active.selector-chooseall:focus, a.active.selector-chooseall:hover {
|
||||
background-position: 100% -144px;
|
||||
}
|
||||
|
||||
a.selector-clearall {
|
||||
background: url(../img/selector-icons.svg) 0 -160px no-repeat;
|
||||
}
|
||||
|
||||
a.active.selector-clearall:focus, a.active.selector-clearall:hover {
|
||||
background-position: 0 -176px;
|
||||
}
|
||||
|
||||
.inline-deletelink {
|
||||
float: left;
|
||||
}
|
||||
|
||||
form .form-row p.datetime {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.related-widget-wrapper {
|
||||
float: right;
|
||||
}
|
||||
|
||||
/* MISC */
|
||||
|
||||
.inline-related h2, .inline-group h2 {
|
||||
text-align: right
|
||||
}
|
||||
|
||||
.inline-related h3 span.delete {
|
||||
padding-right: 20px;
|
||||
padding-left: inherit;
|
||||
left: 10px;
|
||||
right: inherit;
|
||||
float:left;
|
||||
}
|
||||
|
||||
.inline-related h3 span.delete label {
|
||||
margin-left: inherit;
|
||||
margin-right: 2px;
|
||||
}
|
||||
>>>>>>> master
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
<<<<<<< HEAD
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2012-2017 Kevin Brown, Igor Vaynberg, and Select2 contributors
|
||||
@ -20,26 +19,3 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
=======
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2012-2017 Kevin Brown, Igor Vaynberg, and Select2 contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
>>>>>>> master
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
<<<<<<< HEAD
|
||||
.select2-container {
|
||||
box-sizing: border-box;
|
||||
display: inline-block;
|
||||
@ -480,486 +479,3 @@
|
||||
|
||||
.select2-container--classic.select2-container--open .select2-dropdown {
|
||||
border-color: #5897fb; }
|
||||
=======
|
||||
.select2-container {
|
||||
box-sizing: border-box;
|
||||
display: inline-block;
|
||||
margin: 0;
|
||||
position: relative;
|
||||
vertical-align: middle; }
|
||||
.select2-container .select2-selection--single {
|
||||
box-sizing: border-box;
|
||||
cursor: pointer;
|
||||
display: block;
|
||||
height: 28px;
|
||||
user-select: none;
|
||||
-webkit-user-select: none; }
|
||||
.select2-container .select2-selection--single .select2-selection__rendered {
|
||||
display: block;
|
||||
padding-left: 8px;
|
||||
padding-right: 20px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap; }
|
||||
.select2-container .select2-selection--single .select2-selection__clear {
|
||||
position: relative; }
|
||||
.select2-container[dir="rtl"] .select2-selection--single .select2-selection__rendered {
|
||||
padding-right: 8px;
|
||||
padding-left: 20px; }
|
||||
.select2-container .select2-selection--multiple {
|
||||
box-sizing: border-box;
|
||||
cursor: pointer;
|
||||
display: block;
|
||||
min-height: 32px;
|
||||
user-select: none;
|
||||
-webkit-user-select: none; }
|
||||
.select2-container .select2-selection--multiple .select2-selection__rendered {
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
padding-left: 8px;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap; }
|
||||
.select2-container .select2-search--inline {
|
||||
float: left; }
|
||||
.select2-container .select2-search--inline .select2-search__field {
|
||||
box-sizing: border-box;
|
||||
border: none;
|
||||
font-size: 100%;
|
||||
margin-top: 5px;
|
||||
padding: 0; }
|
||||
.select2-container .select2-search--inline .select2-search__field::-webkit-search-cancel-button {
|
||||
-webkit-appearance: none; }
|
||||
|
||||
.select2-dropdown {
|
||||
background-color: white;
|
||||
border: 1px solid #aaa;
|
||||
border-radius: 4px;
|
||||
box-sizing: border-box;
|
||||
display: block;
|
||||
position: absolute;
|
||||
left: -100000px;
|
||||
width: 100%;
|
||||
z-index: 1051; }
|
||||
|
||||
.select2-results {
|
||||
display: block; }
|
||||
|
||||
.select2-results__options {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0; }
|
||||
|
||||
.select2-results__option {
|
||||
padding: 6px;
|
||||
user-select: none;
|
||||
-webkit-user-select: none; }
|
||||
.select2-results__option[aria-selected] {
|
||||
cursor: pointer; }
|
||||
|
||||
.select2-container--open .select2-dropdown {
|
||||
left: 0; }
|
||||
|
||||
.select2-container--open .select2-dropdown--above {
|
||||
border-bottom: none;
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0; }
|
||||
|
||||
.select2-container--open .select2-dropdown--below {
|
||||
border-top: none;
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 0; }
|
||||
|
||||
.select2-search--dropdown {
|
||||
display: block;
|
||||
padding: 4px; }
|
||||
.select2-search--dropdown .select2-search__field {
|
||||
padding: 4px;
|
||||
width: 100%;
|
||||
box-sizing: border-box; }
|
||||
.select2-search--dropdown .select2-search__field::-webkit-search-cancel-button {
|
||||
-webkit-appearance: none; }
|
||||
.select2-search--dropdown.select2-search--hide {
|
||||
display: none; }
|
||||
|
||||
.select2-close-mask {
|
||||
border: 0;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: block;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
min-height: 100%;
|
||||
min-width: 100%;
|
||||
height: auto;
|
||||
width: auto;
|
||||
opacity: 0;
|
||||
z-index: 99;
|
||||
background-color: #fff;
|
||||
filter: alpha(opacity=0); }
|
||||
|
||||
.select2-hidden-accessible {
|
||||
border: 0 !important;
|
||||
clip: rect(0 0 0 0) !important;
|
||||
-webkit-clip-path: inset(50%) !important;
|
||||
clip-path: inset(50%) !important;
|
||||
height: 1px !important;
|
||||
overflow: hidden !important;
|
||||
padding: 0 !important;
|
||||
position: absolute !important;
|
||||
width: 1px !important;
|
||||
white-space: nowrap !important; }
|
||||
|
||||
.select2-container--default .select2-selection--single {
|
||||
background-color: #fff;
|
||||
border: 1px solid #aaa;
|
||||
border-radius: 4px; }
|
||||
.select2-container--default .select2-selection--single .select2-selection__rendered {
|
||||
color: #444;
|
||||
line-height: 28px; }
|
||||
.select2-container--default .select2-selection--single .select2-selection__clear {
|
||||
cursor: pointer;
|
||||
float: right;
|
||||
font-weight: bold; }
|
||||
.select2-container--default .select2-selection--single .select2-selection__placeholder {
|
||||
color: #999; }
|
||||
.select2-container--default .select2-selection--single .select2-selection__arrow {
|
||||
height: 26px;
|
||||
position: absolute;
|
||||
top: 1px;
|
||||
right: 1px;
|
||||
width: 20px; }
|
||||
.select2-container--default .select2-selection--single .select2-selection__arrow b {
|
||||
border-color: #888 transparent transparent transparent;
|
||||
border-style: solid;
|
||||
border-width: 5px 4px 0 4px;
|
||||
height: 0;
|
||||
left: 50%;
|
||||
margin-left: -4px;
|
||||
margin-top: -2px;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
width: 0; }
|
||||
|
||||
.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__clear {
|
||||
float: left; }
|
||||
|
||||
.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__arrow {
|
||||
left: 1px;
|
||||
right: auto; }
|
||||
|
||||
.select2-container--default.select2-container--disabled .select2-selection--single {
|
||||
background-color: #eee;
|
||||
cursor: default; }
|
||||
.select2-container--default.select2-container--disabled .select2-selection--single .select2-selection__clear {
|
||||
display: none; }
|
||||
|
||||
.select2-container--default.select2-container--open .select2-selection--single .select2-selection__arrow b {
|
||||
border-color: transparent transparent #888 transparent;
|
||||
border-width: 0 4px 5px 4px; }
|
||||
|
||||
.select2-container--default .select2-selection--multiple {
|
||||
background-color: white;
|
||||
border: 1px solid #aaa;
|
||||
border-radius: 4px;
|
||||
cursor: text; }
|
||||
.select2-container--default .select2-selection--multiple .select2-selection__rendered {
|
||||
box-sizing: border-box;
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0 5px;
|
||||
width: 100%; }
|
||||
.select2-container--default .select2-selection--multiple .select2-selection__rendered li {
|
||||
list-style: none; }
|
||||
.select2-container--default .select2-selection--multiple .select2-selection__clear {
|
||||
cursor: pointer;
|
||||
float: right;
|
||||
font-weight: bold;
|
||||
margin-top: 5px;
|
||||
margin-right: 10px;
|
||||
padding: 1px; }
|
||||
.select2-container--default .select2-selection--multiple .select2-selection__choice {
|
||||
background-color: #e4e4e4;
|
||||
border: 1px solid #aaa;
|
||||
border-radius: 4px;
|
||||
cursor: default;
|
||||
float: left;
|
||||
margin-right: 5px;
|
||||
margin-top: 5px;
|
||||
padding: 0 5px; }
|
||||
.select2-container--default .select2-selection--multiple .select2-selection__choice__remove {
|
||||
color: #999;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
font-weight: bold;
|
||||
margin-right: 2px; }
|
||||
.select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover {
|
||||
color: #333; }
|
||||
|
||||
.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice, .select2-container--default[dir="rtl"] .select2-selection--multiple .select2-search--inline {
|
||||
float: right; }
|
||||
|
||||
.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice {
|
||||
margin-left: 5px;
|
||||
margin-right: auto; }
|
||||
|
||||
.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove {
|
||||
margin-left: 2px;
|
||||
margin-right: auto; }
|
||||
|
||||
.select2-container--default.select2-container--focus .select2-selection--multiple {
|
||||
border: solid black 1px;
|
||||
outline: 0; }
|
||||
|
||||
.select2-container--default.select2-container--disabled .select2-selection--multiple {
|
||||
background-color: #eee;
|
||||
cursor: default; }
|
||||
|
||||
.select2-container--default.select2-container--disabled .select2-selection__choice__remove {
|
||||
display: none; }
|
||||
|
||||
.select2-container--default.select2-container--open.select2-container--above .select2-selection--single, .select2-container--default.select2-container--open.select2-container--above .select2-selection--multiple {
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 0; }
|
||||
|
||||
.select2-container--default.select2-container--open.select2-container--below .select2-selection--single, .select2-container--default.select2-container--open.select2-container--below .select2-selection--multiple {
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0; }
|
||||
|
||||
.select2-container--default .select2-search--dropdown .select2-search__field {
|
||||
border: 1px solid #aaa; }
|
||||
|
||||
.select2-container--default .select2-search--inline .select2-search__field {
|
||||
background: transparent;
|
||||
border: none;
|
||||
outline: 0;
|
||||
box-shadow: none;
|
||||
-webkit-appearance: textfield; }
|
||||
|
||||
.select2-container--default .select2-results > .select2-results__options {
|
||||
max-height: 200px;
|
||||
overflow-y: auto; }
|
||||
|
||||
.select2-container--default .select2-results__option[role=group] {
|
||||
padding: 0; }
|
||||
|
||||
.select2-container--default .select2-results__option[aria-disabled=true] {
|
||||
color: #999; }
|
||||
|
||||
.select2-container--default .select2-results__option[aria-selected=true] {
|
||||
background-color: #ddd; }
|
||||
|
||||
.select2-container--default .select2-results__option .select2-results__option {
|
||||
padding-left: 1em; }
|
||||
.select2-container--default .select2-results__option .select2-results__option .select2-results__group {
|
||||
padding-left: 0; }
|
||||
.select2-container--default .select2-results__option .select2-results__option .select2-results__option {
|
||||
margin-left: -1em;
|
||||
padding-left: 2em; }
|
||||
.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
|
||||
margin-left: -2em;
|
||||
padding-left: 3em; }
|
||||
.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
|
||||
margin-left: -3em;
|
||||
padding-left: 4em; }
|
||||
.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
|
||||
margin-left: -4em;
|
||||
padding-left: 5em; }
|
||||
.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
|
||||
margin-left: -5em;
|
||||
padding-left: 6em; }
|
||||
|
||||
.select2-container--default .select2-results__option--highlighted[aria-selected] {
|
||||
background-color: #5897fb;
|
||||
color: white; }
|
||||
|
||||
.select2-container--default .select2-results__group {
|
||||
cursor: default;
|
||||
display: block;
|
||||
padding: 6px; }
|
||||
|
||||
.select2-container--classic .select2-selection--single {
|
||||
background-color: #f7f7f7;
|
||||
border: 1px solid #aaa;
|
||||
border-radius: 4px;
|
||||
outline: 0;
|
||||
background-image: -webkit-linear-gradient(top, white 50%, #eeeeee 100%);
|
||||
background-image: -o-linear-gradient(top, white 50%, #eeeeee 100%);
|
||||
background-image: linear-gradient(to bottom, white 50%, #eeeeee 100%);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0); }
|
||||
.select2-container--classic .select2-selection--single:focus {
|
||||
border: 1px solid #5897fb; }
|
||||
.select2-container--classic .select2-selection--single .select2-selection__rendered {
|
||||
color: #444;
|
||||
line-height: 28px; }
|
||||
.select2-container--classic .select2-selection--single .select2-selection__clear {
|
||||
cursor: pointer;
|
||||
float: right;
|
||||
font-weight: bold;
|
||||
margin-right: 10px; }
|
||||
.select2-container--classic .select2-selection--single .select2-selection__placeholder {
|
||||
color: #999; }
|
||||
.select2-container--classic .select2-selection--single .select2-selection__arrow {
|
||||
background-color: #ddd;
|
||||
border: none;
|
||||
border-left: 1px solid #aaa;
|
||||
border-top-right-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
height: 26px;
|
||||
position: absolute;
|
||||
top: 1px;
|
||||
right: 1px;
|
||||
width: 20px;
|
||||
background-image: -webkit-linear-gradient(top, #eeeeee 50%, #cccccc 100%);
|
||||
background-image: -o-linear-gradient(top, #eeeeee 50%, #cccccc 100%);
|
||||
background-image: linear-gradient(to bottom, #eeeeee 50%, #cccccc 100%);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFCCCCCC', GradientType=0); }
|
||||
.select2-container--classic .select2-selection--single .select2-selection__arrow b {
|
||||
border-color: #888 transparent transparent transparent;
|
||||
border-style: solid;
|
||||
border-width: 5px 4px 0 4px;
|
||||
height: 0;
|
||||
left: 50%;
|
||||
margin-left: -4px;
|
||||
margin-top: -2px;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
width: 0; }
|
||||
|
||||
.select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__clear {
|
||||
float: left; }
|
||||
|
||||
.select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__arrow {
|
||||
border: none;
|
||||
border-right: 1px solid #aaa;
|
||||
border-radius: 0;
|
||||
border-top-left-radius: 4px;
|
||||
border-bottom-left-radius: 4px;
|
||||
left: 1px;
|
||||
right: auto; }
|
||||
|
||||
.select2-container--classic.select2-container--open .select2-selection--single {
|
||||
border: 1px solid #5897fb; }
|
||||
.select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow {
|
||||
background: transparent;
|
||||
border: none; }
|
||||
.select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow b {
|
||||
border-color: transparent transparent #888 transparent;
|
||||
border-width: 0 4px 5px 4px; }
|
||||
|
||||
.select2-container--classic.select2-container--open.select2-container--above .select2-selection--single {
|
||||
border-top: none;
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 0;
|
||||
background-image: -webkit-linear-gradient(top, white 0%, #eeeeee 50%);
|
||||
background-image: -o-linear-gradient(top, white 0%, #eeeeee 50%);
|
||||
background-image: linear-gradient(to bottom, white 0%, #eeeeee 50%);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0); }
|
||||
|
||||
.select2-container--classic.select2-container--open.select2-container--below .select2-selection--single {
|
||||
border-bottom: none;
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
background-image: -webkit-linear-gradient(top, #eeeeee 50%, white 100%);
|
||||
background-image: -o-linear-gradient(top, #eeeeee 50%, white 100%);
|
||||
background-image: linear-gradient(to bottom, #eeeeee 50%, white 100%);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFFFFFFF', GradientType=0); }
|
||||
|
||||
.select2-container--classic .select2-selection--multiple {
|
||||
background-color: white;
|
||||
border: 1px solid #aaa;
|
||||
border-radius: 4px;
|
||||
cursor: text;
|
||||
outline: 0; }
|
||||
.select2-container--classic .select2-selection--multiple:focus {
|
||||
border: 1px solid #5897fb; }
|
||||
.select2-container--classic .select2-selection--multiple .select2-selection__rendered {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0 5px; }
|
||||
.select2-container--classic .select2-selection--multiple .select2-selection__clear {
|
||||
display: none; }
|
||||
.select2-container--classic .select2-selection--multiple .select2-selection__choice {
|
||||
background-color: #e4e4e4;
|
||||
border: 1px solid #aaa;
|
||||
border-radius: 4px;
|
||||
cursor: default;
|
||||
float: left;
|
||||
margin-right: 5px;
|
||||
margin-top: 5px;
|
||||
padding: 0 5px; }
|
||||
.select2-container--classic .select2-selection--multiple .select2-selection__choice__remove {
|
||||
color: #888;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
font-weight: bold;
|
||||
margin-right: 2px; }
|
||||
.select2-container--classic .select2-selection--multiple .select2-selection__choice__remove:hover {
|
||||
color: #555; }
|
||||
|
||||
.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice {
|
||||
float: right;
|
||||
margin-left: 5px;
|
||||
margin-right: auto; }
|
||||
|
||||
.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove {
|
||||
margin-left: 2px;
|
||||
margin-right: auto; }
|
||||
|
||||
.select2-container--classic.select2-container--open .select2-selection--multiple {
|
||||
border: 1px solid #5897fb; }
|
||||
|
||||
.select2-container--classic.select2-container--open.select2-container--above .select2-selection--multiple {
|
||||
border-top: none;
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 0; }
|
||||
|
||||
.select2-container--classic.select2-container--open.select2-container--below .select2-selection--multiple {
|
||||
border-bottom: none;
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0; }
|
||||
|
||||
.select2-container--classic .select2-search--dropdown .select2-search__field {
|
||||
border: 1px solid #aaa;
|
||||
outline: 0; }
|
||||
|
||||
.select2-container--classic .select2-search--inline .select2-search__field {
|
||||
outline: 0;
|
||||
box-shadow: none; }
|
||||
|
||||
.select2-container--classic .select2-dropdown {
|
||||
background-color: white;
|
||||
border: 1px solid transparent; }
|
||||
|
||||
.select2-container--classic .select2-dropdown--above {
|
||||
border-bottom: none; }
|
||||
|
||||
.select2-container--classic .select2-dropdown--below {
|
||||
border-top: none; }
|
||||
|
||||
.select2-container--classic .select2-results > .select2-results__options {
|
||||
max-height: 200px;
|
||||
overflow-y: auto; }
|
||||
|
||||
.select2-container--classic .select2-results__option[role=group] {
|
||||
padding: 0; }
|
||||
|
||||
.select2-container--classic .select2-results__option[aria-disabled=true] {
|
||||
color: grey; }
|
||||
|
||||
.select2-container--classic .select2-results__option--highlighted[aria-selected] {
|
||||
background-color: #3875d7;
|
||||
color: white; }
|
||||
|
||||
.select2-container--classic .select2-results__group {
|
||||
cursor: default;
|
||||
display: block;
|
||||
padding: 6px; }
|
||||
|
||||
.select2-container--classic.select2-container--open .select2-dropdown {
|
||||
border-color: #5897fb; }
|
||||
>>>>>>> master
|
||||
|
||||
File diff suppressed because one or more lines are too long
@ -1,4 +1,3 @@
|
||||
<<<<<<< HEAD
|
||||
/* SELECTOR (FILTER INTERFACE) */
|
||||
|
||||
.selector {
|
||||
@ -602,608 +601,3 @@ select + .related-widget-wrapper-link,
|
||||
width: 600px;
|
||||
height: 400px;
|
||||
}
|
||||
=======
|
||||
/* SELECTOR (FILTER INTERFACE) */
|
||||
|
||||
.selector {
|
||||
width: 800px;
|
||||
float: left;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.selector select {
|
||||
width: 380px;
|
||||
height: 17.2em;
|
||||
flex: 1 0 auto;
|
||||
}
|
||||
|
||||
.selector-available, .selector-chosen {
|
||||
width: 380px;
|
||||
text-align: center;
|
||||
margin-bottom: 5px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.selector-available h2, .selector-chosen h2 {
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 4px 4px 0 0;
|
||||
}
|
||||
|
||||
.selector-chosen .list-footer-display {
|
||||
border: 1px solid var(--border-color);
|
||||
border-top: none;
|
||||
border-radius: 0 0 4px 4px;
|
||||
margin: 0 0 10px;
|
||||
padding: 8px;
|
||||
text-align: center;
|
||||
background: var(--primary);
|
||||
color: var(--header-link-color);
|
||||
cursor: pointer;
|
||||
}
|
||||
.selector-chosen .list-footer-display__clear {
|
||||
color: var(--breadcrumbs-fg);
|
||||
}
|
||||
|
||||
.selector-chosen h2 {
|
||||
background: var(--primary);
|
||||
color: var(--header-link-color);
|
||||
}
|
||||
|
||||
.selector .selector-available h2 {
|
||||
background: var(--darkened-bg);
|
||||
color: var(--body-quiet-color);
|
||||
}
|
||||
|
||||
.selector .selector-filter {
|
||||
border: 1px solid var(--border-color);
|
||||
border-width: 0 1px;
|
||||
padding: 8px;
|
||||
color: var(--body-quiet-color);
|
||||
font-size: 0.625rem;
|
||||
margin: 0;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.selector .selector-filter label,
|
||||
.inline-group .aligned .selector .selector-filter label {
|
||||
float: left;
|
||||
margin: 7px 0 0;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.selector .selector-available input,
|
||||
.selector .selector-chosen input {
|
||||
width: 320px;
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.selector ul.selector-chooser {
|
||||
align-self: center;
|
||||
width: 22px;
|
||||
background-color: var(--selected-bg);
|
||||
border-radius: 10px;
|
||||
margin: 0 5px;
|
||||
padding: 0;
|
||||
transform: translateY(-17px);
|
||||
}
|
||||
|
||||
.selector-chooser li {
|
||||
margin: 0;
|
||||
padding: 3px;
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
.selector select {
|
||||
padding: 0 10px;
|
||||
margin: 0 0 10px;
|
||||
border-radius: 0 0 4px 4px;
|
||||
}
|
||||
.selector .selector-chosen--with-filtered select {
|
||||
margin: 0;
|
||||
border-radius: 0;
|
||||
height: 14em;
|
||||
}
|
||||
|
||||
.selector .selector-chosen:not(.selector-chosen--with-filtered) .list-footer-display {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.selector-add, .selector-remove {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
display: block;
|
||||
text-indent: -3000px;
|
||||
overflow: hidden;
|
||||
cursor: default;
|
||||
opacity: 0.55;
|
||||
}
|
||||
|
||||
.active.selector-add, .active.selector-remove {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.active.selector-add:hover, .active.selector-remove:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.selector-add {
|
||||
background: url(../img/selector-icons.svg) 0 -96px no-repeat;
|
||||
}
|
||||
|
||||
.active.selector-add:focus, .active.selector-add:hover {
|
||||
background-position: 0 -112px;
|
||||
}
|
||||
|
||||
.selector-remove {
|
||||
background: url(../img/selector-icons.svg) 0 -64px no-repeat;
|
||||
}
|
||||
|
||||
.active.selector-remove:focus, .active.selector-remove:hover {
|
||||
background-position: 0 -80px;
|
||||
}
|
||||
|
||||
a.selector-chooseall, a.selector-clearall {
|
||||
display: inline-block;
|
||||
height: 16px;
|
||||
text-align: left;
|
||||
margin: 1px auto 3px;
|
||||
overflow: hidden;
|
||||
font-weight: bold;
|
||||
line-height: 16px;
|
||||
color: var(--body-quiet-color);
|
||||
text-decoration: none;
|
||||
opacity: 0.55;
|
||||
}
|
||||
|
||||
a.active.selector-chooseall:focus, a.active.selector-clearall:focus,
|
||||
a.active.selector-chooseall:hover, a.active.selector-clearall:hover {
|
||||
color: var(--link-fg);
|
||||
}
|
||||
|
||||
a.active.selector-chooseall, a.active.selector-clearall {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
a.active.selector-chooseall:hover, a.active.selector-clearall:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
a.selector-chooseall {
|
||||
padding: 0 18px 0 0;
|
||||
background: url(../img/selector-icons.svg) right -160px no-repeat;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
a.active.selector-chooseall:focus, a.active.selector-chooseall:hover {
|
||||
background-position: 100% -176px;
|
||||
}
|
||||
|
||||
a.selector-clearall {
|
||||
padding: 0 0 0 18px;
|
||||
background: url(../img/selector-icons.svg) 0 -128px no-repeat;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
a.active.selector-clearall:focus, a.active.selector-clearall:hover {
|
||||
background-position: 0 -144px;
|
||||
}
|
||||
|
||||
/* STACKED SELECTORS */
|
||||
|
||||
.stacked {
|
||||
float: left;
|
||||
width: 490px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.stacked select {
|
||||
width: 480px;
|
||||
height: 10.1em;
|
||||
}
|
||||
|
||||
.stacked .selector-available, .stacked .selector-chosen {
|
||||
width: 480px;
|
||||
}
|
||||
|
||||
.stacked .selector-available {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.stacked .selector-available input {
|
||||
width: 422px;
|
||||
}
|
||||
|
||||
.stacked ul.selector-chooser {
|
||||
height: 22px;
|
||||
width: 50px;
|
||||
margin: 0 0 10px 40%;
|
||||
background-color: #eee;
|
||||
border-radius: 10px;
|
||||
transform: none;
|
||||
}
|
||||
|
||||
.stacked .selector-chooser li {
|
||||
float: left;
|
||||
padding: 3px 3px 3px 5px;
|
||||
}
|
||||
|
||||
.stacked .selector-chooseall, .stacked .selector-clearall {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.stacked .selector-add {
|
||||
background: url(../img/selector-icons.svg) 0 -32px no-repeat;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.stacked .active.selector-add {
|
||||
background-position: 0 -32px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.stacked .active.selector-add:focus, .stacked .active.selector-add:hover {
|
||||
background-position: 0 -48px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.stacked .selector-remove {
|
||||
background: url(../img/selector-icons.svg) 0 0 no-repeat;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.stacked .active.selector-remove {
|
||||
background-position: 0 0px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.stacked .active.selector-remove:focus, .stacked .active.selector-remove:hover {
|
||||
background-position: 0 -16px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.selector .help-icon {
|
||||
background: url(../img/icon-unknown.svg) 0 0 no-repeat;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
margin: -2px 0 0 2px;
|
||||
width: 13px;
|
||||
height: 13px;
|
||||
}
|
||||
|
||||
.selector .selector-chosen .help-icon {
|
||||
background: url(../img/icon-unknown-alt.svg) 0 0 no-repeat;
|
||||
}
|
||||
|
||||
.selector .search-label-icon {
|
||||
background: url(../img/search.svg) 0 0 no-repeat;
|
||||
display: inline-block;
|
||||
height: 1.125rem;
|
||||
width: 1.125rem;
|
||||
}
|
||||
|
||||
/* DATE AND TIME */
|
||||
|
||||
p.datetime {
|
||||
line-height: 20px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
color: var(--body-quiet-color);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.datetime span {
|
||||
white-space: nowrap;
|
||||
font-weight: normal;
|
||||
font-size: 0.6875rem;
|
||||
color: var(--body-quiet-color);
|
||||
}
|
||||
|
||||
.datetime input, .form-row .datetime input.vDateField, .form-row .datetime input.vTimeField {
|
||||
margin-left: 5px;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
table p.datetime {
|
||||
font-size: 0.6875rem;
|
||||
margin-left: 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.datetimeshortcuts .clock-icon, .datetimeshortcuts .date-icon {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.datetimeshortcuts .clock-icon {
|
||||
background: url(../img/icon-clock.svg) 0 0 no-repeat;
|
||||
}
|
||||
|
||||
.datetimeshortcuts a:focus .clock-icon,
|
||||
.datetimeshortcuts a:hover .clock-icon {
|
||||
background-position: 0 -16px;
|
||||
}
|
||||
|
||||
.datetimeshortcuts .date-icon {
|
||||
background: url(../img/icon-calendar.svg) 0 0 no-repeat;
|
||||
top: -1px;
|
||||
}
|
||||
|
||||
.datetimeshortcuts a:focus .date-icon,
|
||||
.datetimeshortcuts a:hover .date-icon {
|
||||
background-position: 0 -16px;
|
||||
}
|
||||
|
||||
.timezonewarning {
|
||||
font-size: 0.6875rem;
|
||||
color: var(--body-quiet-color);
|
||||
}
|
||||
|
||||
/* URL */
|
||||
|
||||
p.url {
|
||||
line-height: 20px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
color: var(--body-quiet-color);
|
||||
font-size: 0.6875rem;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.url a {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
/* FILE UPLOADS */
|
||||
|
||||
p.file-upload {
|
||||
line-height: 20px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
color: var(--body-quiet-color);
|
||||
font-size: 0.6875rem;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.file-upload a {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.file-upload .deletelink {
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
span.clearable-file-input label {
|
||||
color: var(--body-fg);
|
||||
font-size: 0.6875rem;
|
||||
display: inline;
|
||||
float: none;
|
||||
}
|
||||
|
||||
/* CALENDARS & CLOCKS */
|
||||
|
||||
.calendarbox, .clockbox {
|
||||
margin: 5px auto;
|
||||
font-size: 0.75rem;
|
||||
width: 19em;
|
||||
text-align: center;
|
||||
background: var(--body-bg);
|
||||
color: var(--body-fg);
|
||||
border: 1px solid var(--hairline-color);
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.15);
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.clockbox {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.calendar {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.calendar table {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border-collapse: collapse;
|
||||
background: white;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.calendar caption, .calendarbox h2 {
|
||||
margin: 0;
|
||||
text-align: center;
|
||||
border-top: none;
|
||||
font-weight: 700;
|
||||
font-size: 0.75rem;
|
||||
color: #333;
|
||||
background: var(--accent);
|
||||
}
|
||||
|
||||
.calendar th {
|
||||
padding: 8px 5px;
|
||||
background: var(--darkened-bg);
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
font-weight: 400;
|
||||
font-size: 0.75rem;
|
||||
text-align: center;
|
||||
color: var(--body-quiet-color);
|
||||
}
|
||||
|
||||
.calendar td {
|
||||
font-weight: 400;
|
||||
font-size: 0.75rem;
|
||||
text-align: center;
|
||||
padding: 0;
|
||||
border-top: 1px solid var(--hairline-color);
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.calendar td.selected a {
|
||||
background: var(--primary);
|
||||
color: var(--button-fg);
|
||||
}
|
||||
|
||||
.calendar td.nonday {
|
||||
background: var(--darkened-bg);
|
||||
}
|
||||
|
||||
.calendar td.today a {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.calendar td a, .timelist a {
|
||||
display: block;
|
||||
font-weight: 400;
|
||||
padding: 6px;
|
||||
text-decoration: none;
|
||||
color: var(--body-quiet-color);
|
||||
}
|
||||
|
||||
.calendar td a:focus, .timelist a:focus,
|
||||
.calendar td a:hover, .timelist a:hover {
|
||||
background: var(--primary);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.calendar td a:active, .timelist a:active {
|
||||
background: var(--header-bg);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.calendarnav {
|
||||
font-size: 0.625rem;
|
||||
text-align: center;
|
||||
color: #ccc;
|
||||
margin: 0;
|
||||
padding: 1px 3px;
|
||||
}
|
||||
|
||||
.calendarnav a:link, #calendarnav a:visited,
|
||||
#calendarnav a:focus, #calendarnav a:hover {
|
||||
color: var(--body-quiet-color);
|
||||
}
|
||||
|
||||
.calendar-shortcuts {
|
||||
background: var(--body-bg);
|
||||
color: var(--body-quiet-color);
|
||||
font-size: 0.6875rem;
|
||||
line-height: 0.6875rem;
|
||||
border-top: 1px solid var(--hairline-color);
|
||||
padding: 8px 0;
|
||||
}
|
||||
|
||||
.calendarbox .calendarnav-previous, .calendarbox .calendarnav-next {
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
text-indent: -9999px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.calendarnav-previous {
|
||||
left: 10px;
|
||||
background: url(../img/calendar-icons.svg) 0 0 no-repeat;
|
||||
}
|
||||
|
||||
.calendarbox .calendarnav-previous:focus,
|
||||
.calendarbox .calendarnav-previous:hover {
|
||||
background-position: 0 -15px;
|
||||
}
|
||||
|
||||
.calendarnav-next {
|
||||
right: 10px;
|
||||
background: url(../img/calendar-icons.svg) 0 -30px no-repeat;
|
||||
}
|
||||
|
||||
.calendarbox .calendarnav-next:focus,
|
||||
.calendarbox .calendarnav-next:hover {
|
||||
background-position: 0 -45px;
|
||||
}
|
||||
|
||||
.calendar-cancel {
|
||||
margin: 0;
|
||||
padding: 4px 0;
|
||||
font-size: 0.75rem;
|
||||
background: #eee;
|
||||
border-top: 1px solid var(--border-color);
|
||||
color: var(--body-fg);
|
||||
}
|
||||
|
||||
.calendar-cancel:focus, .calendar-cancel:hover {
|
||||
background: #ddd;
|
||||
}
|
||||
|
||||
.calendar-cancel a {
|
||||
color: black;
|
||||
display: block;
|
||||
}
|
||||
|
||||
ul.timelist, .timelist li {
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.timelist a {
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
/* EDIT INLINE */
|
||||
|
||||
.inline-deletelink {
|
||||
float: right;
|
||||
text-indent: -9999px;
|
||||
background: url(../img/inline-delete.svg) 0 0 no-repeat;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
border: 0px none;
|
||||
}
|
||||
|
||||
.inline-deletelink:focus, .inline-deletelink:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* RELATED WIDGET WRAPPER */
|
||||
.related-widget-wrapper {
|
||||
float: left; /* display properly in form rows with multiple fields */
|
||||
overflow: hidden; /* clear floated contents */
|
||||
}
|
||||
|
||||
.related-widget-wrapper-link {
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
.related-widget-wrapper-link:link {
|
||||
opacity: .8;
|
||||
}
|
||||
|
||||
.related-widget-wrapper-link:link:focus,
|
||||
.related-widget-wrapper-link:link:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
select + .related-widget-wrapper-link,
|
||||
.related-widget-wrapper-link + .related-widget-wrapper-link {
|
||||
margin-left: 7px;
|
||||
}
|
||||
|
||||
/* GIS MAPS */
|
||||
.dj_map {
|
||||
width: 600px;
|
||||
height: 400px;
|
||||
}
|
||||
>>>>>>> master
|
||||
|
||||
@ -1,462 +0,0 @@
|
||||
/*
|
||||
* article.css
|
||||
* Styles for CKEditor 5 rendered content inside .content-card
|
||||
* and for the article detail page layout.
|
||||
*
|
||||
* Scope: all rules are under .content-card .card-content
|
||||
* so they never leak into the rest of the site.
|
||||
*/
|
||||
|
||||
/* ===== ARTICLE PAGE LAYOUT ===== */
|
||||
|
||||
.article-meta {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1.5rem;
|
||||
flex-wrap: wrap;
|
||||
font-size: 0.9rem;
|
||||
color: var(--text-light);
|
||||
margin-bottom: 2rem;
|
||||
padding-bottom: 1.5rem;
|
||||
border-bottom: 1px solid var(--border-light);
|
||||
}
|
||||
|
||||
.article-meta span {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.4rem;
|
||||
}
|
||||
|
||||
.article-tags {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.5rem;
|
||||
margin: 1.5rem 0;
|
||||
}
|
||||
|
||||
.article-tag {
|
||||
display: inline-block;
|
||||
padding: 0.25rem 0.75rem;
|
||||
background: var(--bg-tertiary);
|
||||
border: 1px solid var(--border-light);
|
||||
border-radius: var(--radius-sm);
|
||||
font-size: 0.8rem;
|
||||
color: var(--text-secondary);
|
||||
text-decoration: none;
|
||||
transition: var(--transition);
|
||||
}
|
||||
|
||||
.article-tag:hover {
|
||||
background: var(--primary);
|
||||
color: white;
|
||||
border-color: var(--primary);
|
||||
}
|
||||
|
||||
/* ===== CKEDITOR 5 CONTENT ===== */
|
||||
|
||||
.content-card .card-content {
|
||||
font-size: 1.05rem;
|
||||
line-height: 1.8;
|
||||
color: var(--text-primary);
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
/* --- Headings --- */
|
||||
|
||||
.content-card .card-content h2,
|
||||
.content-card .card-content h3,
|
||||
.content-card .card-content h4,
|
||||
.content-card .card-content h5,
|
||||
.content-card .card-content h6 {
|
||||
font-weight: 700;
|
||||
line-height: 1.3;
|
||||
margin-top: 2rem;
|
||||
margin-bottom: 0.75rem;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.content-card .card-content h2 {
|
||||
font-size: 1.75rem;
|
||||
padding-bottom: 0.5rem;
|
||||
border-bottom: 2px solid var(--border-light);
|
||||
}
|
||||
|
||||
.content-card .card-content h3 {
|
||||
font-size: 1.375rem;
|
||||
padding-left: 0.75rem;
|
||||
border-left: 4px solid var(--primary);
|
||||
}
|
||||
|
||||
.content-card .card-content h4 {
|
||||
font-size: 1.125rem;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
/* --- Paragraphs --- */
|
||||
|
||||
.content-card .card-content p {
|
||||
margin-bottom: 1.25rem;
|
||||
}
|
||||
|
||||
.content-card .card-content p:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
/* --- Links --- */
|
||||
|
||||
.content-card .card-content a {
|
||||
color: var(--primary);
|
||||
text-decoration: underline;
|
||||
text-decoration-color: rgba(255, 107, 0, 0.4);
|
||||
text-underline-offset: 3px;
|
||||
transition: var(--transition);
|
||||
}
|
||||
|
||||
.content-card .card-content a:hover {
|
||||
color: var(--primary-dark);
|
||||
text-decoration-color: var(--primary-dark);
|
||||
}
|
||||
|
||||
/* --- Lists --- */
|
||||
|
||||
.content-card .card-content ul,
|
||||
.content-card .card-content ol {
|
||||
margin: 0 0 1.25rem 0;
|
||||
padding-left: 1.75rem;
|
||||
}
|
||||
|
||||
.content-card .card-content ul {
|
||||
list-style: none;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.content-card .card-content ul li {
|
||||
position: relative;
|
||||
padding-left: 1.5rem;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.content-card .card-content ul li::before {
|
||||
content: '▸';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
color: var(--primary);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.content-card .card-content ol li {
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.content-card .card-content ul ul,
|
||||
.content-card .card-content ol ol,
|
||||
.content-card .card-content ul ol,
|
||||
.content-card .card-content ol ul {
|
||||
margin-top: 0.5rem;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
/* --- Blockquote --- */
|
||||
|
||||
.content-card .card-content blockquote {
|
||||
margin: 1.5rem 0;
|
||||
padding: 1.25rem 1.5rem;
|
||||
border-left: 4px solid var(--primary);
|
||||
background: var(--bg-secondary);
|
||||
border-radius: 0 var(--radius-md) var(--radius-md) 0;
|
||||
color: var(--text-secondary);
|
||||
font-style: italic;
|
||||
font-size: 1.05rem;
|
||||
}
|
||||
|
||||
.content-card .card-content blockquote p:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
/* --- Inline code (not inside pre) --- */
|
||||
/*
|
||||
* High specificity is fine here because this selector explicitly
|
||||
* excludes pre > code, so it never touches hljs blocks.
|
||||
*/
|
||||
|
||||
.content-card .card-content :not(pre) > code {
|
||||
font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
|
||||
font-size: 0.875em;
|
||||
background: var(--bg-tertiary);
|
||||
color: var(--primary-dark);
|
||||
padding: 0.15em 0.4em;
|
||||
border-radius: 4px;
|
||||
border: 1px solid var(--border-light);
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
/* --- Code blocks (CKEditor generates <pre><code class="hljs">) --- */
|
||||
/*
|
||||
* ALL pre and pre code rules use :where() — zero specificity.
|
||||
* This guarantees hljs always wins on colors, background, and padding.
|
||||
*
|
||||
* Responsibility split:
|
||||
* article.css → layout only: margin, border-radius, overflow, shadow
|
||||
* hljs CSS → everything visual: background, color, padding, font-size
|
||||
*
|
||||
* font-size:0 on pre prevents inherited line-height:1.8 from inflating
|
||||
* the spacing between lines (line-height is computed from font-size,
|
||||
* so zeroing it on the wrapper element neutralises the inheritance).
|
||||
* font-size is restored on pre code.
|
||||
*/
|
||||
|
||||
:where(.content-card .card-content) pre {
|
||||
margin: 1.5rem 0;
|
||||
padding: 0; /* hljs sets padding:1em on code.hljs — don't double it */
|
||||
border-radius: var(--radius-md);
|
||||
overflow-x: auto;
|
||||
box-shadow: var(--shadow-md);
|
||||
font-size: 0; /* neutralise inherited line-height */
|
||||
line-height: 1;
|
||||
background: none; /* hljs controls background (#fff or #282c34) */
|
||||
}
|
||||
|
||||
:where(.content-card .card-content) pre code {
|
||||
font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
|
||||
font-size: 0.9rem; /* restore font-size for hljs to work from */
|
||||
line-height: 1.5;
|
||||
word-break: normal;
|
||||
white-space: pre;
|
||||
/* NO color, NO background, NO padding — hljs owns these */
|
||||
}
|
||||
|
||||
/* --- Tables --- */
|
||||
|
||||
.content-card .card-content .table-wrapper,
|
||||
.content-card .card-content figure.table {
|
||||
overflow-x: auto;
|
||||
margin: 1.5rem 0;
|
||||
border-radius: var(--radius-md);
|
||||
box-shadow: var(--shadow-sm);
|
||||
}
|
||||
|
||||
.content-card .card-content table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
|
||||
.content-card .card-content th {
|
||||
background: var(--bg-secondary);
|
||||
font-weight: 700;
|
||||
text-align: left;
|
||||
padding: 0.875rem 1rem;
|
||||
border-bottom: 2px solid var(--border-medium);
|
||||
color: var(--text-primary);
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.content-card .card-content td {
|
||||
padding: 0.75rem 1rem;
|
||||
border-bottom: 1px solid var(--border-light);
|
||||
color: var(--text-secondary);
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.content-card .card-content tr:last-child td {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.content-card .card-content tbody tr:hover td {
|
||||
background: var(--bg-secondary);
|
||||
}
|
||||
|
||||
/* CKEditor 5 table with header row class */
|
||||
.content-card .card-content table.ck-table-resized th,
|
||||
.content-card .card-content table.ck-table-resized td {
|
||||
border: 1px solid var(--border-light);
|
||||
}
|
||||
|
||||
/* --- Images (CKEditor wraps in <figure class="image">) --- */
|
||||
|
||||
.content-card .card-content figure.image {
|
||||
margin: 1.5rem auto;
|
||||
text-align: center;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.content-card .card-content figure.image img,
|
||||
.content-card .card-content img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
border-radius: var(--radius-md);
|
||||
box-shadow: var(--shadow-md);
|
||||
cursor: pointer; /* triggers the click-to-enlarge modal */
|
||||
}
|
||||
|
||||
.content-card .card-content figure.image figcaption {
|
||||
margin-top: 0.5rem;
|
||||
font-size: 0.875rem;
|
||||
color: var(--text-light);
|
||||
font-style: italic;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* CKEditor alignment classes */
|
||||
.content-card .card-content figure.image.image-style-align-left {
|
||||
float: left;
|
||||
margin: 0.5rem 1.5rem 1rem 0;
|
||||
max-width: 45%;
|
||||
}
|
||||
|
||||
.content-card .card-content figure.image.image-style-align-right {
|
||||
float: right;
|
||||
margin: 0.5rem 0 1rem 1.5rem;
|
||||
max-width: 45%;
|
||||
}
|
||||
|
||||
/* Clearfix after floated images */
|
||||
.content-card .card-content::after {
|
||||
content: '';
|
||||
display: table;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
/* --- Horizontal rule --- */
|
||||
|
||||
.content-card .card-content hr {
|
||||
border: none;
|
||||
height: 2px;
|
||||
background: linear-gradient(90deg, transparent, var(--border-medium), transparent);
|
||||
margin: 2rem 0;
|
||||
}
|
||||
|
||||
/* --- Alert/info boxes (CKEditor custom classes if used) --- */
|
||||
|
||||
.content-card .card-content .info-box {
|
||||
padding: 1rem 1.25rem;
|
||||
border-radius: var(--radius-md);
|
||||
margin: 1.5rem 0;
|
||||
border-left: 4px solid var(--accent);
|
||||
background: rgba(0, 168, 255, 0.08);
|
||||
color: var(--text-secondary);
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
|
||||
/* ===== COMMENTS SECTION ===== */
|
||||
|
||||
.comments-section {
|
||||
margin-top: 3rem;
|
||||
}
|
||||
|
||||
.comments-section h3 {
|
||||
font-size: 1.5rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 1.5rem;
|
||||
color: var(--text-primary);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
.comment-card {
|
||||
background: var(--bg-secondary);
|
||||
border-radius: var(--radius-lg);
|
||||
padding: 1.25rem 1.5rem;
|
||||
margin-bottom: 1rem;
|
||||
border: 1px solid var(--border-light);
|
||||
border-left: 3px solid var(--secondary);
|
||||
}
|
||||
|
||||
.comment-author {
|
||||
font-weight: 600;
|
||||
color: var(--text-primary);
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
|
||||
.comment-date {
|
||||
font-size: 0.8rem;
|
||||
color: var(--text-light);
|
||||
margin-left: 0.75rem;
|
||||
}
|
||||
|
||||
.comment-body {
|
||||
margin-top: 0.75rem;
|
||||
color: var(--text-secondary);
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.comment-form-card {
|
||||
background: var(--bg-card);
|
||||
border-radius: var(--radius-xl);
|
||||
padding: 2rem;
|
||||
box-shadow: var(--shadow-md);
|
||||
border: 1px solid var(--border-light);
|
||||
margin-top: 2rem;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.comment-form-card::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 4px;
|
||||
background: var(--gradient-secondary);
|
||||
border-radius: var(--radius-xl) var(--radius-xl) 0 0;
|
||||
}
|
||||
|
||||
.comment-form-card h4 {
|
||||
font-size: 1.25rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 1.5rem;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
/* ===== RESPONSIVE ===== */
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.content-card .card-content h2 {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
.content-card .card-content h3 {
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
.content-card .card-content figure.image.image-style-align-left,
|
||||
.content-card .card-content figure.image.image-style-align-right {
|
||||
float: none;
|
||||
max-width: 100%;
|
||||
margin: 1rem auto;
|
||||
}
|
||||
|
||||
/* :where() keeps specificity at zero so hljs still wins on mobile */
|
||||
:where(.content-card .card-content) pre {
|
||||
box-shadow: none;
|
||||
margin: 1rem 0;
|
||||
}
|
||||
|
||||
.content-card .card-content th,
|
||||
.content-card .card-content td {
|
||||
padding: 0.6rem 0.75rem;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
.article-meta {
|
||||
gap: 1rem;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.content-card .card-content {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.content-card .card-content h2 {
|
||||
font-size: 1.375rem;
|
||||
}
|
||||
|
||||
.content-card .card-content h3 {
|
||||
font-size: 1.125rem;
|
||||
}
|
||||
}
|
||||
@ -1,139 +0,0 @@
|
||||
/* Основная типографика */
|
||||
.article-content {
|
||||
font-family: 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
||||
line-height: 1.6;
|
||||
color: #333;
|
||||
max-width: 800px; /* при необходимости */
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.article-content h1,
|
||||
.article-content h2,
|
||||
.article-content h3,
|
||||
.article-content h4,
|
||||
.article-content h5,
|
||||
.article-content h6 {
|
||||
margin-top: 1.5em;
|
||||
margin-bottom: 0.5em;
|
||||
font-weight: 600;
|
||||
line-height: 1.25;
|
||||
}
|
||||
|
||||
.article-content p {
|
||||
margin-bottom: 1.2em;
|
||||
}
|
||||
|
||||
.article-content blockquote {
|
||||
border-left: 4px solid #ddd;
|
||||
padding-left: 1em;
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
font-style: italic;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.article-content pre {
|
||||
background: #f5f5f5;
|
||||
padding: 1em;
|
||||
border-radius: 4px;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.article-content code {
|
||||
background: #f0f0f0;
|
||||
padding: 0.2em 0.4em;
|
||||
border-radius: 3px;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
/* Таблицы */
|
||||
.article-content table {
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
.article-content th,
|
||||
.article-content td {
|
||||
border: 1px solid #ddd;
|
||||
padding: 8px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.article-content th {
|
||||
background-color: #f8f8f8;
|
||||
}
|
||||
|
||||
/* Изображения */
|
||||
.article-content figure.image {
|
||||
display: inline-block;
|
||||
margin: 1em 0;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.article-content figure.image img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
/* Выравнивание изображений (классы, используемые CKEditor 5) */
|
||||
.article-content .image-style-align-left {
|
||||
float: left;
|
||||
margin-right: 1.5em;
|
||||
margin-bottom: 1em;
|
||||
max-width: 50%;
|
||||
}
|
||||
|
||||
.article-content .image-style-align-right {
|
||||
float: right;
|
||||
margin-left: 1.5em;
|
||||
margin-bottom: 1em;
|
||||
max-width: 50%;
|
||||
}
|
||||
|
||||
.article-content .image-style-align-center {
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
/* Подписи к изображениям (если используются) */
|
||||
.article-content figure.image figcaption {
|
||||
text-align: center;
|
||||
font-size: 0.9em;
|
||||
color: #666;
|
||||
margin-top: 0.3em;
|
||||
}
|
||||
|
||||
/* Встроенные медиа (видео) */
|
||||
.article-content .media {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
padding-bottom: 56.25%; /* 16:9 */
|
||||
height: 0;
|
||||
margin: 1.5em 0;
|
||||
}
|
||||
|
||||
.article-content .media iframe {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
/* Списки */
|
||||
.article-content ul,
|
||||
.article-content ol {
|
||||
padding-left: 2em;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
/* Горизонтальная линия */
|
||||
.article-content hr {
|
||||
border: none;
|
||||
border-top: 2px solid #eee;
|
||||
margin: 2em 0;
|
||||
}
|
||||
@ -914,6 +914,14 @@ body {
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.product-configs {
|
||||
color: var(--text-secondary);
|
||||
font-size: 1.25rem;
|
||||
font-weight: 500;
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
/* ===== FOOTER ===== */
|
||||
.footer {
|
||||
background: var(--footer-bg);
|
||||
@ -1665,6 +1673,11 @@ body {
|
||||
padding: 0 1rem;
|
||||
}
|
||||
|
||||
.product-configs {
|
||||
font-size: 1.125rem;
|
||||
padding: 0 1rem;
|
||||
}
|
||||
|
||||
.grid-2 {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 1.5rem;
|
||||
|
||||
@ -16,9 +16,17 @@ const CallbackModal = {
|
||||
}, 5000);
|
||||
},
|
||||
|
||||
open() {
|
||||
open(productTitle) {
|
||||
const modal = document.getElementById(this.modalId);
|
||||
if (modal) {
|
||||
|
||||
if (productTitle) {
|
||||
const questionField = modal.querySelector('#id_question');
|
||||
if (questionField) {
|
||||
questionField.value = `Запрос цены по ПП "${productTitle}"`;
|
||||
}
|
||||
}
|
||||
|
||||
modal.style.display = 'block';
|
||||
const floatingBtn = document.getElementById(this.floatingBtnId);
|
||||
if (floatingBtn && this.shown) {
|
||||
|
||||
30
programmer/static/programmer/js/profile.js
Normal file
30
programmer/static/programmer/js/profile.js
Normal file
@ -0,0 +1,30 @@
|
||||
// programmer/static/programmer/js/profile.js
|
||||
function openModalContent(el) {
|
||||
const url = el.dataset.url;
|
||||
const title = el.querySelector('h4').innerText;
|
||||
const modal = document.getElementById('contentModal');
|
||||
const body = document.getElementById('contentModalBody');
|
||||
const titleEl = document.getElementById('contentModalTitle');
|
||||
titleEl.textContent = title;
|
||||
body.innerHTML = '<p>Загрузка...</p>';
|
||||
modal.style.display = 'block';
|
||||
fetch(url)
|
||||
.then(response => response.text())
|
||||
.then(html => {
|
||||
body.innerHTML = html;
|
||||
})
|
||||
.catch(() => {
|
||||
body.innerHTML = '<p style="color:red;">Ошибка загрузки. Попробуйте позже.</p>';
|
||||
});
|
||||
}
|
||||
|
||||
function closeContentModal() {
|
||||
document.getElementById('contentModal').style.display = 'none';
|
||||
}
|
||||
// Закрытие по клику на фон и ESC
|
||||
document.addEventListener('click', function(e) {
|
||||
if (e.target === document.getElementById('contentModal')) closeContentModal();
|
||||
});
|
||||
document.addEventListener('keydown', function(e) {
|
||||
if (e.key === 'Escape') closeContentModal();
|
||||
});
|
||||
@ -393,30 +393,32 @@
|
||||
<form method="post" action="{% url 'callback' %}" id="callbackForm">
|
||||
{% csrf_token %}
|
||||
|
||||
<input type="hidden" name="next" value="{{ request.path }}">
|
||||
|
||||
<div class="form-group">
|
||||
<label for="id_name">Имя *</label>
|
||||
{{ form.name }}
|
||||
{{ callback_form.name }}
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="id_phone">Телефон *</label>
|
||||
{{ form.phone }}
|
||||
{{ callback_form.phone }}
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="id_email">Электронная почта</label>
|
||||
{{ form.email }}
|
||||
{{ callback_form.email }}
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="id_question">Ваш вопрос</label>
|
||||
{{ form.question }}
|
||||
{{ callback_form.question }}
|
||||
</div>
|
||||
|
||||
{% if form.captcha %}
|
||||
<div class="form-group">
|
||||
<label for="id_captcha">Защитный код *</label>
|
||||
{{ form.captcha }}
|
||||
{{ callback_form.captcha }}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
@ -430,6 +432,19 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Универсальное модальное окно -->
|
||||
<div id="contentModal" class="modal">
|
||||
<div class="modal-content" style="max-width: 700px;">
|
||||
<div class="modal-header">
|
||||
<h3 id="contentModalTitle">Заголовок</h3>
|
||||
<button class="modal-close" onclick="closeContentModal()">×</button>
|
||||
</div>
|
||||
<div class="modal-body" id="contentModalBody">
|
||||
<!-- сюда подгружается содержимое -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Плавающая кнопка -->
|
||||
<div id="floatingButton" class="floating-btn" style="position: fixed; bottom: 30px; right: 30px; z-index: 10000; display: none;">
|
||||
<button onclick="CallbackModal.open()" class="btn btn-primary pulse">🎯 Получить консультацию</button>
|
||||
|
||||
80
programmer/templates/programmer/includes/my_callbacks.html
Normal file
80
programmer/templates/programmer/includes/my_callbacks.html
Normal file
@ -0,0 +1,80 @@
|
||||
<style>
|
||||
.status-badge {
|
||||
display: inline-block;
|
||||
padding: 0.25rem 0.75rem;
|
||||
border-radius: 20px;
|
||||
font-size: 0.8rem;
|
||||
font-weight: 600;
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
.status-badge.new { background: #dc3545; color: #fff; }
|
||||
.status-badge.read { background: #28a745; color: #fff; }
|
||||
.status-badge.processed { background: #17a2b8; color: #fff; }
|
||||
.status-badge.unprocessed { background: #ffc107; color: #212529; }
|
||||
.status-badge.sent { background: #6c757d; color: #fff; }
|
||||
.list-item {
|
||||
padding: 0.75rem 0;
|
||||
border-bottom: 1px solid var(--border-light);
|
||||
}
|
||||
.list-item:last-child { border-bottom: none; }
|
||||
.list-item .meta { font-size: 0.9rem; color: var(--text-light); }
|
||||
</style>
|
||||
|
||||
<h3>📞 Мои заявки на звонок</h3>
|
||||
{% if callbacks %}
|
||||
{% for cb in callbacks %}
|
||||
<div class="list-item">
|
||||
<div>
|
||||
<strong>{{ cb.name }}</strong>
|
||||
<span class="status-badge {% if cb.is_read %}read{% else %}new{% endif %}">
|
||||
{% if cb.is_read %}✅ Прочитано{% else %}🆕 Новое{% endif %}
|
||||
</span>
|
||||
<span class="status-badge {% if cb.is_processed %}processed{% else %}unprocessed{% endif %}">
|
||||
{% if cb.is_processed %}✅ Обработано{% else %}⏳ В обработке{% endif %}
|
||||
</span>
|
||||
</div>
|
||||
<div class="meta">
|
||||
{{ cb.time_create|date:"d.m.Y H:i" }} •
|
||||
📞 {{ cb.phone }} •
|
||||
✉️ {{ cb.email|default:"email не указан" }}
|
||||
{% if cb.question %}
|
||||
<br><span style="font-style:italic;">{{ cb.question|truncatechars:80 }}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<p>Заявок пока нет.</p>
|
||||
{% endif %}
|
||||
|
||||
<hr>
|
||||
|
||||
<h3>🛒 Мои заказы</h3>
|
||||
{% if orders %}
|
||||
{% for order in orders %}
|
||||
<div class="list-item">
|
||||
<div>
|
||||
<strong>{{ order.product.title }}</strong>
|
||||
<span class="status-badge {% if order.is_processed %}processed{% else %}unprocessed{% endif %}">
|
||||
{% if order.is_processed %}✅ Обработан{% else %}⏳ В обработке{% endif %}
|
||||
</span>
|
||||
{% if order.notification_sent %}
|
||||
<span class="status-badge sent">📨 Уведомление отправлено</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="meta">
|
||||
{{ order.created_at|date:"d.m.Y H:i" }} •
|
||||
📞 {{ order.phone }} •
|
||||
✉️ {{ order.email }}
|
||||
{% if order.configuration %}
|
||||
<br>⚙️ Конфигурация: {{ order.configuration.name }}
|
||||
{% endif %}
|
||||
{% if order.comment %}
|
||||
<br><span style="font-style:italic;">{{ order.comment|truncatechars:80 }}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<p>Заказов пока нет.</p>
|
||||
{% endif %}
|
||||
59
programmer/templates/programmer/includes/my_comments.html
Normal file
59
programmer/templates/programmer/includes/my_comments.html
Normal file
@ -0,0 +1,59 @@
|
||||
<style>
|
||||
.comment-status {
|
||||
display: inline-block;
|
||||
padding: 0.2rem 0.6rem;
|
||||
border-radius: 12px;
|
||||
font-size: 0.8rem;
|
||||
font-weight: 600;
|
||||
margin-left: 0.5rem;
|
||||
}
|
||||
.comment-status.moderation {
|
||||
background: #ffc107;
|
||||
color: #212529;
|
||||
}
|
||||
.comment-status.approved {
|
||||
background: #28a745;
|
||||
color: #fff;
|
||||
}
|
||||
.list-item {
|
||||
padding: 0.75rem 0;
|
||||
border-bottom: 1px solid var(--border-light);
|
||||
}
|
||||
.list-item:last-child { border-bottom: none; }
|
||||
.list-item .meta { font-size: 0.9rem; color: var(--text-light); }
|
||||
.list-item .article-link {
|
||||
font-weight: 600;
|
||||
color: var(--primary);
|
||||
text-decoration: none;
|
||||
transition: color 0.2s;
|
||||
}
|
||||
.list-item .article-link:hover {
|
||||
color: var(--primary-dark);
|
||||
text-decoration: underline;
|
||||
}
|
||||
</style>
|
||||
|
||||
<h3>💬 Мои комментарии</h3>
|
||||
{% if comments %}
|
||||
{% for comment in comments %}
|
||||
<div class="list-item">
|
||||
<div>
|
||||
<a href="{{ comment.article.get_absolute_url }}" class="article-link">
|
||||
{{ comment.article.title }}
|
||||
</a>
|
||||
{% if not comment.is_moderated %}
|
||||
<span class="comment-status moderation">⏳ На модерации</span>
|
||||
{% else %}
|
||||
<span class="comment-status approved">✅ Одобрен</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="meta">
|
||||
{{ comment.time_create|date:"d.m.Y H:i" }}
|
||||
<br>
|
||||
{{ comment.content|truncatechars:150 }}
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<p>Вы ещё не оставили ни одного комментария.</p>
|
||||
{% endif %}
|
||||
@ -0,0 +1,25 @@
|
||||
<h3>🔔 Настройки уведомлений</h3>
|
||||
<form id="notif-form">
|
||||
{% csrf_token %}
|
||||
<label>
|
||||
<input type="checkbox" name="notify_new_articles" {% if profile.notify_new_articles %}checked{% endif %}>
|
||||
Уведомлять о новых статьях
|
||||
</label><br>
|
||||
<label>
|
||||
<input type="checkbox" name="notify_new_products" {% if profile.notify_new_products %}checked{% endif %}>
|
||||
Уведомлять о новых продуктах
|
||||
</label><br>
|
||||
<button type="submit" class="btn btn-primary">Сохранить</button>
|
||||
</form>
|
||||
<script>
|
||||
document.getElementById('notif-form').addEventListener('submit', function(e) {
|
||||
e.preventDefault();
|
||||
fetch('{% url "notification_settings" %}', {
|
||||
method: 'POST',
|
||||
body: new FormData(this),
|
||||
headers: { 'X-CSRFToken': document.querySelector('[name=csrfmiddlewaretoken]').value }
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => { if (data.status === 'ok') alert('Настройки сохранены!'); });
|
||||
});
|
||||
</script>
|
||||
@ -1,5 +1,6 @@
|
||||
{% extends 'programmer/base.html' %}
|
||||
{% load django_bootstrap5 %}
|
||||
{% load static %}
|
||||
|
||||
{% block content %}
|
||||
<div class="page-header">
|
||||
@ -31,21 +32,22 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="content-card mt-3">
|
||||
<h3>Мои действия</h3>
|
||||
<div class="skills-grid">
|
||||
<div class="skill-category">
|
||||
<div class="skills-grid">
|
||||
<div class="skill-category" data-url="{% url 'my_callbacks' %}" onclick="openModalContent(this)">
|
||||
<h4>📋 Мои заявки</h4>
|
||||
<p>Просмотр истории обращений</p>
|
||||
</div>
|
||||
<div class="skill-category">
|
||||
<div class="skill-category" data-url="{% url 'my_comments' %}" onclick="openModalContent(this)">
|
||||
<h4>💬 Мои комментарии</h4>
|
||||
<p>Управление комментариями к статьям</p>
|
||||
</div>
|
||||
<div class="skill-category">
|
||||
<div class="skill-category" data-url="{% url 'notification_settings' %}" onclick="openModalContent(this)">
|
||||
<h4>🔔 Настройки уведомлений</h4>
|
||||
<p>Email-рассылка и оповещения</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_js %}
|
||||
<script src="{% static 'programmer/js/profile.js' %}"></script>
|
||||
{% endblock %}
|
||||
@ -35,6 +35,9 @@ urlpatterns = [
|
||||
path('privacy/', PrivacyPolicyView.as_view(), name='privacy'),
|
||||
path('yandex_cdc16c33291495b9.html/', yandex_html, name='yandex_cdc16c33291495b9'),
|
||||
path('requisites/', RequisitesPageView.as_view(), name='requisites'),
|
||||
path('profile/callbacks/', views.my_callbacks, name='my_callbacks'),
|
||||
path('profile/comments/', views.my_comments, name='my_comments'),
|
||||
path('profile/notifications/', views.notification_settings, name='notification_settings'),
|
||||
]
|
||||
|
||||
|
||||
|
||||
@ -104,3 +104,191 @@ def send_multiple_callback_notifications(callbacks):
|
||||
if connection:
|
||||
connection.close()
|
||||
return 0
|
||||
|
||||
|
||||
# ===== Уведомления о заказах =====
|
||||
|
||||
def send_order_notification(order):
|
||||
"""
|
||||
Отправляет уведомление о новом заказе:
|
||||
- администратору (на ADMIN_EMAILS)
|
||||
- клиенту (на email из заказа, если указан)
|
||||
Возвращает True, если хотя бы одно письмо отправлено.
|
||||
"""
|
||||
try:
|
||||
if not all([settings.EMAIL_HOST_USER, settings.EMAIL_HOST_PASSWORD]):
|
||||
logger.error("Email settings are not configured properly")
|
||||
return False
|
||||
|
||||
admin_sent = False
|
||||
client_sent = False
|
||||
|
||||
# Письмо администратору
|
||||
subject_admin = f'🛒 Новый заказ #{order.id} от {order.name}'
|
||||
html_admin = render_to_string('products/emails/order_admin.html', {
|
||||
'order': order,
|
||||
'product': order.product,
|
||||
'configuration': order.configuration,
|
||||
'site_url': settings.ALLOWED_HOSTS[0] if settings.ALLOWED_HOSTS else 'localhost',
|
||||
})
|
||||
plain_admin = strip_tags(html_admin)
|
||||
|
||||
send_mail(
|
||||
subject=subject_admin,
|
||||
message=plain_admin,
|
||||
from_email=settings.DEFAULT_FROM_EMAIL,
|
||||
recipient_list=settings.ADMIN_EMAILS,
|
||||
html_message=html_admin,
|
||||
fail_silently=False,
|
||||
)
|
||||
admin_sent = True
|
||||
logger.info(f"Order admin notification sent for order #{order.id}")
|
||||
|
||||
# Письмо клиенту (если email указан)
|
||||
if order.email:
|
||||
subject_client = f'✅ Ваш заказ #{order.id} на {order.product.title} принят'
|
||||
html_client = render_to_string('products/emails/order_client.html', {
|
||||
'order': order,
|
||||
'product': order.product,
|
||||
'configuration': order.configuration,
|
||||
'site_url': settings.ALLOWED_HOSTS[0] if settings.ALLOWED_HOSTS else 'localhost',
|
||||
})
|
||||
plain_client = strip_tags(html_client)
|
||||
|
||||
send_mail(
|
||||
subject=subject_client,
|
||||
message=plain_client,
|
||||
from_email=settings.DEFAULT_FROM_EMAIL,
|
||||
recipient_list=[order.email],
|
||||
html_message=html_client,
|
||||
fail_silently=False,
|
||||
)
|
||||
client_sent = True
|
||||
logger.info(f"Order client notification sent to {order.email} for order #{order.id}")
|
||||
|
||||
return admin_sent or client_sent
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error sending order notification for order #{order.id}: {e}")
|
||||
return False
|
||||
|
||||
|
||||
def send_multiple_order_notifications(orders):
|
||||
"""
|
||||
Отправляет уведомления для нескольких заказов, используя одно SMTP-соединение.
|
||||
Возвращает количество успешно отправленных заказов.
|
||||
"""
|
||||
if not orders:
|
||||
return 0
|
||||
|
||||
connection = get_connection()
|
||||
try:
|
||||
connection.open()
|
||||
count = 0
|
||||
for order in orders:
|
||||
try:
|
||||
# Администратору
|
||||
subject_admin = f'🛒 Новый заказ #{order.id} от {order.name}'
|
||||
html_admin = render_to_string('products/emails/order_admin.html', {
|
||||
'order': order,
|
||||
'product': order.product,
|
||||
'configuration': order.configuration,
|
||||
'site_url': settings.ALLOWED_HOSTS[0] if settings.ALLOWED_HOSTS else 'localhost',
|
||||
})
|
||||
plain_admin = strip_tags(html_admin)
|
||||
send_mail(
|
||||
subject=subject_admin,
|
||||
message=plain_admin,
|
||||
from_email=settings.DEFAULT_FROM_EMAIL,
|
||||
recipient_list=settings.ADMIN_EMAILS,
|
||||
html_message=html_admin,
|
||||
connection=connection,
|
||||
fail_silently=False,
|
||||
)
|
||||
|
||||
# Клиенту
|
||||
if order.email:
|
||||
subject_client = f'✅ Ваш заказ #{order.id} на {order.product.title} принят'
|
||||
html_client = render_to_string('products/emails/order_client.html', {
|
||||
'order': order,
|
||||
'product': order.product,
|
||||
'configuration': order.configuration,
|
||||
'site_url': settings.ALLOWED_HOSTS[0] if settings.ALLOWED_HOSTS else 'localhost',
|
||||
})
|
||||
plain_client = strip_tags(html_client)
|
||||
send_mail(
|
||||
subject=subject_client,
|
||||
message=plain_client,
|
||||
from_email=settings.DEFAULT_FROM_EMAIL,
|
||||
recipient_list=[order.email],
|
||||
html_message=html_client,
|
||||
connection=connection,
|
||||
fail_silently=False,
|
||||
)
|
||||
|
||||
count += 1
|
||||
logger.info(f"Order notifications sent for order #{order.id}")
|
||||
except Exception as e:
|
||||
logger.error(f"Error sending order notifications for order #{order.id}: {e}")
|
||||
connection.close()
|
||||
return count
|
||||
except Exception as e:
|
||||
logger.error(f"Connection error in send_multiple_order_notifications: {e}")
|
||||
if connection:
|
||||
connection.close()
|
||||
return 0
|
||||
|
||||
|
||||
def send_test_order_email():
|
||||
"""Тестовая отправка письма для проверки настроек почты."""
|
||||
try:
|
||||
send_mail(
|
||||
subject='📧 Test Order Email',
|
||||
message='This is a test email for order notifications.',
|
||||
from_email=settings.DEFAULT_FROM_EMAIL,
|
||||
recipient_list=settings.ADMIN_EMAILS,
|
||||
fail_silently=False,
|
||||
)
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.error(f"Test order email failed: {e}")
|
||||
return False
|
||||
|
||||
|
||||
# Асинхронная отправка
|
||||
|
||||
def send_order_notification_async(order):
|
||||
"""Выбирает способ отправки в зависимости от DEBUG."""
|
||||
if settings.DEBUG:
|
||||
# Используем background-tasks
|
||||
from .tasks import send_order_notification_background
|
||||
send_order_notification_background(order.id)
|
||||
return True # задача поставлена в очередь
|
||||
else:
|
||||
# Используем Celery
|
||||
try:
|
||||
from .tasks import send_order_notification_celery
|
||||
send_order_notification_celery.delay(order.id)
|
||||
return True
|
||||
except (ImportError, AttributeError):
|
||||
# fallback на синхронную отправку
|
||||
from .email_notifications import send_order_notification
|
||||
return send_order_notification(order)
|
||||
|
||||
|
||||
def send_multiple_order_notifications_async(orders):
|
||||
if settings.DEBUG:
|
||||
from .tasks import send_multiple_order_notifications_background
|
||||
order_ids = list(orders.values_list('id', flat=True))
|
||||
send_multiple_order_notifications_background(order_ids)
|
||||
return len(order_ids)
|
||||
else:
|
||||
try:
|
||||
from .tasks import send_multiple_order_notifications_celery
|
||||
order_ids = list(orders.values_list('id', flat=True))
|
||||
send_multiple_order_notifications_celery.delay(order_ids)
|
||||
return len(order_ids)
|
||||
except (ImportError, AttributeError):
|
||||
from .email_notifications import send_multiple_order_notifications
|
||||
return send_multiple_order_notifications(orders)
|
||||
|
||||
|
||||
56
programmer/utils/tasks.py
Normal file
56
programmer/utils/tasks.py
Normal file
@ -0,0 +1,56 @@
|
||||
from background_task import background
|
||||
from django.conf import settings
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@background(schedule=0)
|
||||
def send_order_notification_background(order_id):
|
||||
"""Асинхронная отправка уведомлений о заказе через background-tasks."""
|
||||
from .email_notifications import send_order_notification
|
||||
from products.models import Order
|
||||
try:
|
||||
order = Order.objects.select_related('product', 'configuration').get(id=order_id)
|
||||
success = send_order_notification(order)
|
||||
if success:
|
||||
order.notification_sent = True
|
||||
order.save(update_fields=['notification_sent'])
|
||||
return success
|
||||
except Order.DoesNotExist:
|
||||
logger.error(f"Order #{order_id} not found")
|
||||
return False
|
||||
|
||||
@background(schedule=0)
|
||||
def send_multiple_order_notifications_background(order_ids):
|
||||
"""Отправка уведомлений для нескольких заказов."""
|
||||
from .email_notifications import send_multiple_order_notifications
|
||||
from products.models import Order
|
||||
orders = Order.objects.filter(id__in=order_ids)
|
||||
return send_multiple_order_notifications(orders)
|
||||
|
||||
try:
|
||||
from celery import shared_task
|
||||
except ImportError:
|
||||
shared_task = None
|
||||
|
||||
if shared_task is not None:
|
||||
@shared_task
|
||||
def send_order_notification_celery(order_id):
|
||||
from .email_notifications import send_order_notification
|
||||
from products.models import Order
|
||||
try:
|
||||
order = Order.objects.select_related('product', 'configuration').get(id=order_id)
|
||||
success = send_order_notification(order)
|
||||
if success:
|
||||
order.notification_sent = True
|
||||
order.save(update_fields=['notification_sent'])
|
||||
return success
|
||||
except Order.DoesNotExist:
|
||||
return False
|
||||
|
||||
@shared_task
|
||||
def send_multiple_order_notifications_celery(order_ids):
|
||||
from .email_notifications import send_multiple_order_notifications
|
||||
from products.models import Order
|
||||
orders = Order.objects.filter(id__in=order_ids)
|
||||
return send_multiple_order_notifications(orders)
|
||||
@ -10,6 +10,7 @@ from django.shortcuts import render, redirect
|
||||
from django.contrib import messages
|
||||
from .forms import CallbackForm, ProfileForm, UserEditForm, RegistrationForm
|
||||
from django.utils import timezone
|
||||
from django.urls import reverse
|
||||
from datetime import timedelta
|
||||
from django.db.models import Count, QuerySet
|
||||
from django.contrib.auth.decorators import login_required, user_passes_test
|
||||
@ -19,6 +20,9 @@ from .mixins import PageViewTrackingMixin, MenuContextMixin, BreadcrumbMixin
|
||||
from .services import get_published_queryset, track_page_view
|
||||
from typing import Any, Dict, Type
|
||||
from django.template.loader import render_to_string
|
||||
from django.utils.http import url_has_allowed_host_and_scheme
|
||||
from blog.models import Comment
|
||||
from products.models import Order
|
||||
import os
|
||||
|
||||
|
||||
@ -392,6 +396,10 @@ def callback_request(request: HttpRequest) -> HttpResponse:
|
||||
if 'captcha' in form.fields:
|
||||
del form.fields['captcha']
|
||||
|
||||
next_url = request.POST.get('next', '')
|
||||
if not next_url or not url_has_allowed_host_and_scheme(next_url, allowed_hosts={request.get_host()}):
|
||||
next_url = reverse('home')
|
||||
|
||||
if form.is_valid():
|
||||
# Сохраняем заявку
|
||||
callback = form.save()
|
||||
@ -402,7 +410,7 @@ def callback_request(request: HttpRequest) -> HttpResponse:
|
||||
|
||||
messages.success(
|
||||
request,
|
||||
'✅ Ваша заявка успешно отправлена! Я свяжусь с вами в ближайшее время.'
|
||||
'✅ Ваша заявка успешно отправлена! Мы свяжемся с вами в ближайшее время.'
|
||||
)
|
||||
else:
|
||||
# Собираем все ошибки формы
|
||||
@ -414,7 +422,7 @@ def callback_request(request: HttpRequest) -> HttpResponse:
|
||||
f'❌ Ошибка в поле "{field_label}": {error}'
|
||||
)
|
||||
|
||||
return redirect('home')
|
||||
return redirect(next_url)
|
||||
|
||||
|
||||
|
||||
@ -478,3 +486,29 @@ def robots_txt(request):
|
||||
def yandex_html(request: HttpRequest) -> HttpResponse:
|
||||
"""Отдает yandex_cdc16c33291495b9.html."""
|
||||
return render(request, 'programmer/yandex_cdc16c33291495b9.html', content_type='text/html')
|
||||
|
||||
@login_required
|
||||
def my_callbacks(request):
|
||||
callbacks = CallbackRequest.objects.filter(email=request.user.email).order_by('-time_create')
|
||||
# Можно также фильтровать по телефону, если он заполнен в профиле, но email — универсальнее.
|
||||
orders = Order.objects.filter(email=request.user.email).order_by('-created_at') # если поле есть
|
||||
return render(request, 'programmer/includes/my_callbacks.html', {
|
||||
'callbacks': callbacks,
|
||||
'orders': orders,
|
||||
})
|
||||
|
||||
@login_required
|
||||
def my_comments(request):
|
||||
comments = Comment.objects.filter(user=request.user).select_related('article').order_by('-time_create')
|
||||
return render(request, 'programmer/includes/my_comments.html', {'comments': comments})
|
||||
|
||||
@login_required
|
||||
def notification_settings(request):
|
||||
profile = request.user.profile
|
||||
if request.method == 'POST':
|
||||
# обработка формы (можно через AJAX POST)
|
||||
profile.notify_new_articles = request.POST.get('notify_new_articles') == 'on'
|
||||
profile.notify_new_products = request.POST.get('notify_new_products') == 'on'
|
||||
profile.save()
|
||||
return JsonResponse({'status': 'ok'})
|
||||
return render(request, 'programmer/includes/notification_settings.html', {'profile': profile})
|
||||
|
||||
@ -11,3 +11,4 @@ django_ckeditor_5
|
||||
django-allauth
|
||||
django-simple-captcha
|
||||
django-turnstile
|
||||
celery
|
||||
@ -1,4 +1,3 @@
|
||||
<<<<<<< HEAD
|
||||
select.admin-autocomplete {
|
||||
width: 20em;
|
||||
}
|
||||
@ -274,280 +273,3 @@ select.admin-autocomplete {
|
||||
display: block;
|
||||
padding: 6px;
|
||||
}
|
||||
=======
|
||||
select.admin-autocomplete {
|
||||
width: 20em;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete.select2-container {
|
||||
min-height: 30px;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete .select2-selection--single,
|
||||
.select2-container--admin-autocomplete .select2-selection--multiple {
|
||||
min-height: 30px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete.select2-container--focus .select2-selection,
|
||||
.select2-container--admin-autocomplete.select2-container--open .select2-selection {
|
||||
border-color: var(--body-quiet-color);
|
||||
min-height: 30px;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete.select2-container--focus .select2-selection.select2-selection--single,
|
||||
.select2-container--admin-autocomplete.select2-container--open .select2-selection.select2-selection--single {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete.select2-container--focus .select2-selection.select2-selection--multiple,
|
||||
.select2-container--admin-autocomplete.select2-container--open .select2-selection.select2-selection--multiple {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete .select2-selection--single {
|
||||
background-color: var(--body-bg);
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete .select2-selection--single .select2-selection__rendered {
|
||||
color: var(--body-fg);
|
||||
line-height: 30px;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete .select2-selection--single .select2-selection__clear {
|
||||
cursor: pointer;
|
||||
float: right;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete .select2-selection--single .select2-selection__placeholder {
|
||||
color: var(--body-quiet-color);
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete .select2-selection--single .select2-selection__arrow {
|
||||
height: 26px;
|
||||
position: absolute;
|
||||
top: 1px;
|
||||
right: 1px;
|
||||
width: 20px;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete .select2-selection--single .select2-selection__arrow b {
|
||||
border-color: #888 transparent transparent transparent;
|
||||
border-style: solid;
|
||||
border-width: 5px 4px 0 4px;
|
||||
height: 0;
|
||||
left: 50%;
|
||||
margin-left: -4px;
|
||||
margin-top: -2px;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
width: 0;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete[dir="rtl"] .select2-selection--single .select2-selection__clear {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete[dir="rtl"] .select2-selection--single .select2-selection__arrow {
|
||||
left: 1px;
|
||||
right: auto;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete.select2-container--disabled .select2-selection--single {
|
||||
background-color: var(--darkened-bg);
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete.select2-container--disabled .select2-selection--single .select2-selection__clear {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete.select2-container--open .select2-selection--single .select2-selection__arrow b {
|
||||
border-color: transparent transparent #888 transparent;
|
||||
border-width: 0 4px 5px 4px;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete .select2-selection--multiple {
|
||||
background-color: var(--body-bg);
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 4px;
|
||||
cursor: text;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete .select2-selection--multiple .select2-selection__rendered {
|
||||
box-sizing: border-box;
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0 10px 5px 5px;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete .select2-selection--multiple .select2-selection__rendered li {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete .select2-selection--multiple .select2-selection__placeholder {
|
||||
color: var(--body-quiet-color);
|
||||
margin-top: 5px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete .select2-selection--multiple .select2-selection__clear {
|
||||
cursor: pointer;
|
||||
float: right;
|
||||
font-weight: bold;
|
||||
margin: 5px;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete .select2-selection--multiple .select2-selection__choice {
|
||||
background-color: var(--darkened-bg);
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 4px;
|
||||
cursor: default;
|
||||
float: left;
|
||||
margin-right: 5px;
|
||||
margin-top: 5px;
|
||||
padding: 0 5px;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete .select2-selection--multiple .select2-selection__choice__remove {
|
||||
color: var(--body-quiet-color);
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
font-weight: bold;
|
||||
margin-right: 2px;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete .select2-selection--multiple .select2-selection__choice__remove:hover {
|
||||
color: var(--body-fg);
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete[dir="rtl"] .select2-selection--multiple .select2-selection__choice, .select2-container--admin-autocomplete[dir="rtl"] .select2-selection--multiple .select2-selection__placeholder, .select2-container--admin-autocomplete[dir="rtl"] .select2-selection--multiple .select2-search--inline {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete[dir="rtl"] .select2-selection--multiple .select2-selection__choice {
|
||||
margin-left: 5px;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove {
|
||||
margin-left: 2px;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete.select2-container--focus .select2-selection--multiple {
|
||||
border: solid var(--body-quiet-color) 1px;
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete.select2-container--disabled .select2-selection--multiple {
|
||||
background-color: var(--darkened-bg);
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete.select2-container--disabled .select2-selection__choice__remove {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete.select2-container--open.select2-container--above .select2-selection--single, .select2-container--admin-autocomplete.select2-container--open.select2-container--above .select2-selection--multiple {
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 0;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete.select2-container--open.select2-container--below .select2-selection--single, .select2-container--admin-autocomplete.select2-container--open.select2-container--below .select2-selection--multiple {
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete .select2-search--dropdown {
|
||||
background: var(--darkened-bg);
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete .select2-search--dropdown .select2-search__field {
|
||||
background: var(--body-bg);
|
||||
color: var(--body-fg);
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete .select2-search--inline .select2-search__field {
|
||||
background: transparent;
|
||||
color: var(--body-fg);
|
||||
border: none;
|
||||
outline: 0;
|
||||
box-shadow: none;
|
||||
-webkit-appearance: textfield;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete .select2-results > .select2-results__options {
|
||||
max-height: 200px;
|
||||
overflow-y: auto;
|
||||
color: var(--body-fg);
|
||||
background: var(--body-bg);
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete .select2-results__option[role=group] {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete .select2-results__option[aria-disabled=true] {
|
||||
color: var(--body-quiet-color);
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete .select2-results__option[aria-selected=true] {
|
||||
background-color: var(--selected-bg);
|
||||
color: var(--body-fg);
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete .select2-results__option .select2-results__option {
|
||||
padding-left: 1em;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete .select2-results__option .select2-results__option .select2-results__group {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete .select2-results__option .select2-results__option .select2-results__option {
|
||||
margin-left: -1em;
|
||||
padding-left: 2em;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
|
||||
margin-left: -2em;
|
||||
padding-left: 3em;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
|
||||
margin-left: -3em;
|
||||
padding-left: 4em;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
|
||||
margin-left: -4em;
|
||||
padding-left: 5em;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
|
||||
margin-left: -5em;
|
||||
padding-left: 6em;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete .select2-results__option--highlighted[aria-selected] {
|
||||
background-color: var(--primary);
|
||||
color: var(--primary-fg);
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete .select2-results__group {
|
||||
cursor: default;
|
||||
display: block;
|
||||
padding: 6px;
|
||||
}
|
||||
>>>>>>> master
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,3 @@
|
||||
<<<<<<< HEAD
|
||||
/* CHANGELISTS */
|
||||
|
||||
#changelist {
|
||||
@ -327,333 +326,3 @@
|
||||
#changelist .actions .button:focus, #changelist .actions .button:hover {
|
||||
border-color: var(--body-quiet-color);
|
||||
}
|
||||
=======
|
||||
/* CHANGELISTS */
|
||||
|
||||
#changelist {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
#changelist .changelist-form-container {
|
||||
flex: 1 1 auto;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
#changelist table {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.change-list .hiddenfields { display:none; }
|
||||
|
||||
.change-list .filtered table {
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
.change-list .filtered {
|
||||
min-height: 400px;
|
||||
}
|
||||
|
||||
.change-list .filtered .results, .change-list .filtered .paginator,
|
||||
.filtered #toolbar, .filtered div.xfull {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.change-list .filtered table tbody th {
|
||||
padding-right: 1em;
|
||||
}
|
||||
|
||||
#changelist-form .results {
|
||||
overflow-x: auto;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#changelist .toplinks {
|
||||
border-bottom: 1px solid var(--hairline-color);
|
||||
}
|
||||
|
||||
#changelist .paginator {
|
||||
color: var(--body-quiet-color);
|
||||
border-bottom: 1px solid var(--hairline-color);
|
||||
background: var(--body-bg);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* CHANGELIST TABLES */
|
||||
|
||||
#changelist table thead th {
|
||||
padding: 0;
|
||||
white-space: nowrap;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
#changelist table thead th.action-checkbox-column {
|
||||
width: 1.5em;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#changelist table tbody td.action-checkbox {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#changelist table tfoot {
|
||||
color: var(--body-quiet-color);
|
||||
}
|
||||
|
||||
/* TOOLBAR */
|
||||
|
||||
#toolbar {
|
||||
padding: 8px 10px;
|
||||
margin-bottom: 15px;
|
||||
border-top: 1px solid var(--hairline-color);
|
||||
border-bottom: 1px solid var(--hairline-color);
|
||||
background: var(--darkened-bg);
|
||||
color: var(--body-quiet-color);
|
||||
}
|
||||
|
||||
#toolbar form input {
|
||||
border-radius: 4px;
|
||||
font-size: 0.875rem;
|
||||
padding: 5px;
|
||||
color: var(--body-fg);
|
||||
}
|
||||
|
||||
#toolbar #searchbar {
|
||||
height: 1.1875rem;
|
||||
border: 1px solid var(--border-color);
|
||||
padding: 2px 5px;
|
||||
margin: 0;
|
||||
vertical-align: top;
|
||||
font-size: 0.8125rem;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
#toolbar #searchbar:focus {
|
||||
border-color: var(--body-quiet-color);
|
||||
}
|
||||
|
||||
#toolbar form input[type="submit"] {
|
||||
border: 1px solid var(--border-color);
|
||||
font-size: 0.8125rem;
|
||||
padding: 4px 8px;
|
||||
margin: 0;
|
||||
vertical-align: middle;
|
||||
background: var(--body-bg);
|
||||
box-shadow: 0 -15px 20px -10px rgba(0, 0, 0, 0.15) inset;
|
||||
cursor: pointer;
|
||||
color: var(--body-fg);
|
||||
}
|
||||
|
||||
#toolbar form input[type="submit"]:focus,
|
||||
#toolbar form input[type="submit"]:hover {
|
||||
border-color: var(--body-quiet-color);
|
||||
}
|
||||
|
||||
#changelist-search img {
|
||||
vertical-align: middle;
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
#changelist-search .help {
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
/* FILTER COLUMN */
|
||||
|
||||
#changelist-filter {
|
||||
flex: 0 0 240px;
|
||||
order: 1;
|
||||
background: var(--darkened-bg);
|
||||
border-left: none;
|
||||
margin: 0 0 0 30px;
|
||||
}
|
||||
|
||||
#changelist-filter h2 {
|
||||
font-size: 0.875rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
padding: 5px 15px;
|
||||
margin-bottom: 12px;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
#changelist-filter h3,
|
||||
#changelist-filter details summary {
|
||||
font-weight: 400;
|
||||
padding: 0 15px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
#changelist-filter details summary > * {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
#changelist-filter details > summary {
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
#changelist-filter details > summary::-webkit-details-marker {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#changelist-filter details > summary::before {
|
||||
content: '→';
|
||||
font-weight: bold;
|
||||
color: var(--link-hover-color);
|
||||
}
|
||||
|
||||
#changelist-filter details[open] > summary::before {
|
||||
content: '↓';
|
||||
}
|
||||
|
||||
#changelist-filter ul {
|
||||
margin: 5px 0;
|
||||
padding: 0 15px 15px;
|
||||
border-bottom: 1px solid var(--hairline-color);
|
||||
}
|
||||
|
||||
#changelist-filter ul:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
#changelist-filter li {
|
||||
list-style-type: none;
|
||||
margin-left: 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
#changelist-filter a {
|
||||
display: block;
|
||||
color: var(--body-quiet-color);
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
#changelist-filter li.selected {
|
||||
border-left: 5px solid var(--hairline-color);
|
||||
padding-left: 10px;
|
||||
margin-left: -15px;
|
||||
}
|
||||
|
||||
#changelist-filter li.selected a {
|
||||
color: var(--link-selected-fg);
|
||||
}
|
||||
|
||||
#changelist-filter a:focus, #changelist-filter a:hover,
|
||||
#changelist-filter li.selected a:focus,
|
||||
#changelist-filter li.selected a:hover {
|
||||
color: var(--link-hover-color);
|
||||
}
|
||||
|
||||
#changelist-filter #changelist-filter-clear a {
|
||||
font-size: 0.8125rem;
|
||||
padding-bottom: 10px;
|
||||
border-bottom: 1px solid var(--hairline-color);
|
||||
}
|
||||
|
||||
/* DATE DRILLDOWN */
|
||||
|
||||
.change-list .toplinks {
|
||||
display: flex;
|
||||
padding-bottom: 5px;
|
||||
flex-wrap: wrap;
|
||||
gap: 3px 17px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.change-list .toplinks a {
|
||||
font-size: 0.8125rem;
|
||||
}
|
||||
|
||||
.change-list .toplinks .date-back {
|
||||
color: var(--body-quiet-color);
|
||||
}
|
||||
|
||||
.change-list .toplinks .date-back:focus,
|
||||
.change-list .toplinks .date-back:hover {
|
||||
color: var(--link-hover-color);
|
||||
}
|
||||
|
||||
/* ACTIONS */
|
||||
|
||||
.filtered .actions {
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
#changelist table input {
|
||||
margin: 0;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
/* Once the :has() pseudo-class is supported by all browsers, the tr.selected
|
||||
selector and the JS adding the class can be removed. */
|
||||
#changelist tbody tr.selected {
|
||||
background-color: var(--selected-row);
|
||||
}
|
||||
|
||||
#changelist tbody tr:has(.action-select:checked) {
|
||||
background-color: var(--selected-row);
|
||||
}
|
||||
|
||||
#changelist .actions {
|
||||
padding: 10px;
|
||||
background: var(--body-bg);
|
||||
border-top: none;
|
||||
border-bottom: none;
|
||||
line-height: 1.5rem;
|
||||
color: var(--body-quiet-color);
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#changelist .actions span.all,
|
||||
#changelist .actions span.action-counter,
|
||||
#changelist .actions span.clear,
|
||||
#changelist .actions span.question {
|
||||
font-size: 0.8125rem;
|
||||
margin: 0 0.5em;
|
||||
}
|
||||
|
||||
#changelist .actions:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
#changelist .actions select {
|
||||
vertical-align: top;
|
||||
height: 1.5rem;
|
||||
color: var(--body-fg);
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 4px;
|
||||
font-size: 0.875rem;
|
||||
padding: 0 0 0 4px;
|
||||
margin: 0;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
#changelist .actions select:focus {
|
||||
border-color: var(--body-quiet-color);
|
||||
}
|
||||
|
||||
#changelist .actions label {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
font-size: 0.8125rem;
|
||||
}
|
||||
|
||||
#changelist .actions .button {
|
||||
font-size: 0.8125rem;
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 4px;
|
||||
background: var(--body-bg);
|
||||
box-shadow: 0 -15px 20px -10px rgba(0, 0, 0, 0.15) inset;
|
||||
cursor: pointer;
|
||||
height: 1.5rem;
|
||||
line-height: 1;
|
||||
padding: 4px 8px;
|
||||
margin: 0;
|
||||
color: var(--body-fg);
|
||||
}
|
||||
|
||||
#changelist .actions .button:focus, #changelist .actions .button:hover {
|
||||
border-color: var(--body-quiet-color);
|
||||
}
|
||||
>>>>>>> master
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
<<<<<<< HEAD
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--primary: #264b5d;
|
||||
@ -136,142 +135,3 @@ html[data-theme="light"] .theme-toggle svg.theme-icon-when-light {
|
||||
color: var(--body-fg);
|
||||
background-color: var(--body-bg);
|
||||
}
|
||||
=======
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--primary: #264b5d;
|
||||
--primary-fg: #f7f7f7;
|
||||
|
||||
--body-fg: #eeeeee;
|
||||
--body-bg: #121212;
|
||||
--body-quiet-color: #e0e0e0;
|
||||
--body-loud-color: #ffffff;
|
||||
|
||||
--breadcrumbs-link-fg: #e0e0e0;
|
||||
--breadcrumbs-bg: var(--primary);
|
||||
|
||||
--link-fg: #81d4fa;
|
||||
--link-hover-color: #4ac1f7;
|
||||
--link-selected-fg: #6f94c6;
|
||||
|
||||
--hairline-color: #272727;
|
||||
--border-color: #353535;
|
||||
|
||||
--error-fg: #e35f5f;
|
||||
--message-success-bg: #006b1b;
|
||||
--message-warning-bg: #583305;
|
||||
--message-error-bg: #570808;
|
||||
|
||||
--darkened-bg: #212121;
|
||||
--selected-bg: #1b1b1b;
|
||||
--selected-row: #00363a;
|
||||
|
||||
--close-button-bg: #333333;
|
||||
--close-button-hover-bg: #666666;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
html[data-theme="dark"] {
|
||||
--primary: #264b5d;
|
||||
--primary-fg: #f7f7f7;
|
||||
|
||||
--body-fg: #eeeeee;
|
||||
--body-bg: #121212;
|
||||
--body-quiet-color: #e0e0e0;
|
||||
--body-loud-color: #ffffff;
|
||||
|
||||
--breadcrumbs-link-fg: #e0e0e0;
|
||||
--breadcrumbs-bg: var(--primary);
|
||||
|
||||
--link-fg: #81d4fa;
|
||||
--link-hover-color: #4ac1f7;
|
||||
--link-selected-fg: #6f94c6;
|
||||
|
||||
--hairline-color: #272727;
|
||||
--border-color: #353535;
|
||||
|
||||
--error-fg: #e35f5f;
|
||||
--message-success-bg: #006b1b;
|
||||
--message-warning-bg: #583305;
|
||||
--message-error-bg: #570808;
|
||||
|
||||
--darkened-bg: #212121;
|
||||
--selected-bg: #1b1b1b;
|
||||
--selected-row: #00363a;
|
||||
|
||||
--close-button-bg: #333333;
|
||||
--close-button-hover-bg: #666666;
|
||||
}
|
||||
|
||||
/* THEME SWITCH */
|
||||
.theme-toggle {
|
||||
cursor: pointer;
|
||||
border: none;
|
||||
padding: 0;
|
||||
background: transparent;
|
||||
vertical-align: middle;
|
||||
margin-inline-start: 5px;
|
||||
margin-top: -1px;
|
||||
}
|
||||
|
||||
.theme-toggle svg {
|
||||
vertical-align: middle;
|
||||
height: 1rem;
|
||||
width: 1rem;
|
||||
display: none;
|
||||
}
|
||||
|
||||
/*
|
||||
Fully hide screen reader text so we only show the one matching the current
|
||||
theme.
|
||||
*/
|
||||
.theme-toggle .visually-hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
html[data-theme="auto"] .theme-toggle .theme-label-when-auto {
|
||||
display: block;
|
||||
}
|
||||
|
||||
html[data-theme="dark"] .theme-toggle .theme-label-when-dark {
|
||||
display: block;
|
||||
}
|
||||
|
||||
html[data-theme="light"] .theme-toggle .theme-label-when-light {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* ICONS */
|
||||
.theme-toggle svg.theme-icon-when-auto,
|
||||
.theme-toggle svg.theme-icon-when-dark,
|
||||
.theme-toggle svg.theme-icon-when-light {
|
||||
fill: var(--header-link-color);
|
||||
color: var(--header-bg);
|
||||
}
|
||||
|
||||
html[data-theme="auto"] .theme-toggle svg.theme-icon-when-auto {
|
||||
display: block;
|
||||
}
|
||||
|
||||
html[data-theme="dark"] .theme-toggle svg.theme-icon-when-dark {
|
||||
display: block;
|
||||
}
|
||||
|
||||
html[data-theme="light"] .theme-toggle svg.theme-icon-when-light {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.visually-hidden {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
clip: rect(0,0,0,0);
|
||||
white-space: nowrap;
|
||||
border: 0;
|
||||
color: var(--body-fg);
|
||||
background-color: var(--body-bg);
|
||||
}
|
||||
>>>>>>> master
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
<<<<<<< HEAD
|
||||
/* DASHBOARD */
|
||||
.dashboard td, .dashboard th {
|
||||
word-break: break-word;
|
||||
@ -28,34 +27,3 @@ ul.actionlist li {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
=======
|
||||
/* DASHBOARD */
|
||||
.dashboard td, .dashboard th {
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.dashboard .module table th {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.dashboard .module table td {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.dashboard .module table td a {
|
||||
display: block;
|
||||
padding-right: .6em;
|
||||
}
|
||||
|
||||
/* RECENT ACTIONS MODULE */
|
||||
|
||||
.module ul.actionlist {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
ul.actionlist li {
|
||||
list-style-type: none;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
>>>>>>> master
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
<<<<<<< HEAD
|
||||
@import url('widgets.css');
|
||||
|
||||
/* FORM ROWS */
|
||||
@ -529,535 +528,3 @@ form .related-widget-wrapper ul {
|
||||
.clearable-file-input input {
|
||||
margin-top: 0;
|
||||
}
|
||||
=======
|
||||
@import url('widgets.css');
|
||||
|
||||
/* FORM ROWS */
|
||||
|
||||
.form-row {
|
||||
overflow: hidden;
|
||||
padding: 10px;
|
||||
font-size: 0.8125rem;
|
||||
border-bottom: 1px solid var(--hairline-color);
|
||||
}
|
||||
|
||||
.form-row img, .form-row input {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.form-row label input[type="checkbox"] {
|
||||
margin-top: 0;
|
||||
vertical-align: 0;
|
||||
}
|
||||
|
||||
form .form-row p {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.flex-container {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.form-multiline > div {
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
/* FORM LABELS */
|
||||
|
||||
label {
|
||||
font-weight: normal;
|
||||
color: var(--body-quiet-color);
|
||||
font-size: 0.8125rem;
|
||||
}
|
||||
|
||||
.required label, label.required {
|
||||
font-weight: bold;
|
||||
color: var(--body-fg);
|
||||
}
|
||||
|
||||
/* RADIO BUTTONS */
|
||||
|
||||
form div.radiolist div {
|
||||
padding-right: 7px;
|
||||
}
|
||||
|
||||
form div.radiolist.inline div {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
form div.radiolist label {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
form div.radiolist input[type="radio"] {
|
||||
margin: -2px 4px 0 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
form ul.inline {
|
||||
margin-left: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
form ul.inline li {
|
||||
float: left;
|
||||
padding-right: 7px;
|
||||
}
|
||||
|
||||
/* ALIGNED FIELDSETS */
|
||||
|
||||
.aligned label {
|
||||
display: block;
|
||||
padding: 4px 10px 0 0;
|
||||
width: 160px;
|
||||
word-wrap: break-word;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.aligned label:not(.vCheckboxLabel):after {
|
||||
content: '';
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
height: 1.625rem;
|
||||
}
|
||||
|
||||
.aligned label + p, .aligned .checkbox-row + div.help, .aligned label + div.readonly {
|
||||
padding: 6px 0;
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
margin-left: 0;
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
|
||||
.aligned ul label {
|
||||
display: inline;
|
||||
float: none;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.aligned .form-row input {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.colMS .aligned .vLargeTextField, .colMS .aligned .vXMLLargeTextField {
|
||||
width: 350px;
|
||||
}
|
||||
|
||||
form .aligned ul {
|
||||
margin-left: 160px;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
form .aligned div.radiolist {
|
||||
display: inline-block;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
form .aligned p.help,
|
||||
form .aligned div.help {
|
||||
margin-top: 0;
|
||||
margin-left: 160px;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
form .aligned p.date div.help.timezonewarning,
|
||||
form .aligned p.datetime div.help.timezonewarning,
|
||||
form .aligned p.time div.help.timezonewarning {
|
||||
margin-left: 0;
|
||||
padding-left: 0;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
form .aligned p.help:last-child,
|
||||
form .aligned div.help:last-child {
|
||||
margin-bottom: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
form .aligned input + p.help,
|
||||
form .aligned textarea + p.help,
|
||||
form .aligned select + p.help,
|
||||
form .aligned input + div.help,
|
||||
form .aligned textarea + div.help,
|
||||
form .aligned select + div.help {
|
||||
margin-left: 160px;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
form .aligned ul li {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
form .aligned table p {
|
||||
margin-left: 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.aligned .vCheckboxLabel {
|
||||
float: none;
|
||||
width: auto;
|
||||
display: inline-block;
|
||||
vertical-align: -3px;
|
||||
padding: 0 0 5px 5px;
|
||||
}
|
||||
|
||||
.aligned .vCheckboxLabel + p.help,
|
||||
.aligned .vCheckboxLabel + div.help {
|
||||
margin-top: -4px;
|
||||
}
|
||||
|
||||
.colM .aligned .vLargeTextField, .colM .aligned .vXMLLargeTextField {
|
||||
width: 610px;
|
||||
}
|
||||
|
||||
fieldset .fieldBox {
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
/* WIDE FIELDSETS */
|
||||
|
||||
.wide label {
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
form .wide p,
|
||||
form .wide ul.errorlist,
|
||||
form .wide input + p.help,
|
||||
form .wide input + div.help {
|
||||
margin-left: 200px;
|
||||
}
|
||||
|
||||
form .wide p.help,
|
||||
form .wide div.help {
|
||||
padding-left: 50px;
|
||||
}
|
||||
|
||||
form div.help ul {
|
||||
padding-left: 0;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.colM fieldset.wide .vLargeTextField, .colM fieldset.wide .vXMLLargeTextField {
|
||||
width: 450px;
|
||||
}
|
||||
|
||||
/* COLLAPSED FIELDSETS */
|
||||
|
||||
fieldset.collapsed * {
|
||||
display: none;
|
||||
}
|
||||
|
||||
fieldset.collapsed h2, fieldset.collapsed {
|
||||
display: block;
|
||||
}
|
||||
|
||||
fieldset.collapsed {
|
||||
border: 1px solid var(--hairline-color);
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
fieldset.collapsed h2 {
|
||||
background: var(--darkened-bg);
|
||||
color: var(--body-quiet-color);
|
||||
}
|
||||
|
||||
fieldset .collapse-toggle {
|
||||
color: var(--header-link-color);
|
||||
}
|
||||
|
||||
fieldset.collapsed .collapse-toggle {
|
||||
background: transparent;
|
||||
display: inline;
|
||||
color: var(--link-fg);
|
||||
}
|
||||
|
||||
/* MONOSPACE TEXTAREAS */
|
||||
|
||||
fieldset.monospace textarea {
|
||||
font-family: var(--font-family-monospace);
|
||||
}
|
||||
|
||||
/* SUBMIT ROW */
|
||||
|
||||
.submit-row {
|
||||
padding: 12px 14px 12px;
|
||||
margin: 0 0 20px;
|
||||
background: var(--darkened-bg);
|
||||
border: 1px solid var(--hairline-color);
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
body.popup .submit-row {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.submit-row input {
|
||||
height: 2.1875rem;
|
||||
line-height: 0.9375rem;
|
||||
}
|
||||
|
||||
.submit-row input, .submit-row a {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.submit-row input.default {
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.submit-row a.deletelink {
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.submit-row a.deletelink {
|
||||
display: block;
|
||||
background: var(--delete-button-bg);
|
||||
border-radius: 4px;
|
||||
padding: 0.625rem 0.9375rem;
|
||||
height: 0.9375rem;
|
||||
line-height: 0.9375rem;
|
||||
color: var(--button-fg);
|
||||
}
|
||||
|
||||
.submit-row a.closelink {
|
||||
display: inline-block;
|
||||
background: var(--close-button-bg);
|
||||
border-radius: 4px;
|
||||
padding: 10px 15px;
|
||||
height: 0.9375rem;
|
||||
line-height: 0.9375rem;
|
||||
color: var(--button-fg);
|
||||
}
|
||||
|
||||
.submit-row a.deletelink:focus,
|
||||
.submit-row a.deletelink:hover,
|
||||
.submit-row a.deletelink:active {
|
||||
background: var(--delete-button-hover-bg);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.submit-row a.closelink:focus,
|
||||
.submit-row a.closelink:hover,
|
||||
.submit-row a.closelink:active {
|
||||
background: var(--close-button-hover-bg);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* CUSTOM FORM FIELDS */
|
||||
|
||||
.vSelectMultipleField {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.vCheckboxField {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.vDateField, .vTimeField {
|
||||
margin-right: 2px;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.vDateField {
|
||||
min-width: 6.85em;
|
||||
}
|
||||
|
||||
.vTimeField {
|
||||
min-width: 4.7em;
|
||||
}
|
||||
|
||||
.vURLField {
|
||||
width: 30em;
|
||||
}
|
||||
|
||||
.vLargeTextField, .vXMLLargeTextField {
|
||||
width: 48em;
|
||||
}
|
||||
|
||||
.flatpages-flatpage #id_content {
|
||||
height: 40.2em;
|
||||
}
|
||||
|
||||
.module table .vPositiveSmallIntegerField {
|
||||
width: 2.2em;
|
||||
}
|
||||
|
||||
.vIntegerField {
|
||||
width: 5em;
|
||||
}
|
||||
|
||||
.vBigIntegerField {
|
||||
width: 10em;
|
||||
}
|
||||
|
||||
.vForeignKeyRawIdAdminField {
|
||||
width: 5em;
|
||||
}
|
||||
|
||||
.vTextField, .vUUIDField {
|
||||
width: 20em;
|
||||
}
|
||||
|
||||
/* INLINES */
|
||||
|
||||
.inline-group {
|
||||
padding: 0;
|
||||
margin: 0 0 30px;
|
||||
}
|
||||
|
||||
.inline-group thead th {
|
||||
padding: 8px 10px;
|
||||
}
|
||||
|
||||
.inline-group .aligned label {
|
||||
width: 160px;
|
||||
}
|
||||
|
||||
.inline-related {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.inline-related h3 {
|
||||
margin: 0;
|
||||
color: var(--body-quiet-color);
|
||||
padding: 5px;
|
||||
font-size: 0.8125rem;
|
||||
background: var(--darkened-bg);
|
||||
border-top: 1px solid var(--hairline-color);
|
||||
border-bottom: 1px solid var(--hairline-color);
|
||||
}
|
||||
|
||||
.inline-related h3 span.delete {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.inline-related h3 span.delete label {
|
||||
margin-left: 2px;
|
||||
font-size: 0.6875rem;
|
||||
}
|
||||
|
||||
.inline-related fieldset {
|
||||
margin: 0;
|
||||
background: var(--body-bg);
|
||||
border: none;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.inline-related fieldset.module h3 {
|
||||
margin: 0;
|
||||
padding: 2px 5px 3px 5px;
|
||||
font-size: 0.6875rem;
|
||||
text-align: left;
|
||||
font-weight: bold;
|
||||
background: #bcd;
|
||||
color: var(--body-bg);
|
||||
}
|
||||
|
||||
.inline-group .tabular fieldset.module {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.inline-related.tabular fieldset.module table {
|
||||
width: 100%;
|
||||
overflow-x: scroll;
|
||||
}
|
||||
|
||||
.last-related fieldset {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.inline-group .tabular tr.has_original td {
|
||||
padding-top: 2em;
|
||||
}
|
||||
|
||||
.inline-group .tabular tr td.original {
|
||||
padding: 2px 0 0 0;
|
||||
width: 0;
|
||||
_position: relative;
|
||||
}
|
||||
|
||||
.inline-group .tabular th.original {
|
||||
width: 0px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.inline-group .tabular td.original p {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
height: 1.1em;
|
||||
padding: 2px 9px;
|
||||
overflow: hidden;
|
||||
font-size: 0.5625rem;
|
||||
font-weight: bold;
|
||||
color: var(--body-quiet-color);
|
||||
_width: 700px;
|
||||
}
|
||||
|
||||
.inline-group ul.tools {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.inline-group ul.tools li {
|
||||
display: inline;
|
||||
padding: 0 5px;
|
||||
}
|
||||
|
||||
.inline-group div.add-row,
|
||||
.inline-group .tabular tr.add-row td {
|
||||
color: var(--body-quiet-color);
|
||||
background: var(--darkened-bg);
|
||||
padding: 8px 10px;
|
||||
border-bottom: 1px solid var(--hairline-color);
|
||||
}
|
||||
|
||||
.inline-group .tabular tr.add-row td {
|
||||
padding: 8px 10px;
|
||||
border-bottom: 1px solid var(--hairline-color);
|
||||
}
|
||||
|
||||
.inline-group ul.tools a.add,
|
||||
.inline-group div.add-row a,
|
||||
.inline-group .tabular tr.add-row td a {
|
||||
background: url(../img/icon-addlink.svg) 0 1px no-repeat;
|
||||
padding-left: 16px;
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
|
||||
.empty-form {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* RELATED FIELD ADD ONE / LOOKUP */
|
||||
|
||||
.related-lookup {
|
||||
margin-left: 5px;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 14px;
|
||||
}
|
||||
|
||||
.related-lookup {
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
background-image: url(../img/search.svg);
|
||||
}
|
||||
|
||||
form .related-widget-wrapper ul {
|
||||
display: inline-block;
|
||||
margin-left: 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.clearable-file-input input {
|
||||
margin-top: 0;
|
||||
}
|
||||
>>>>>>> master
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
<<<<<<< HEAD
|
||||
/* LOGIN FORM */
|
||||
|
||||
.login {
|
||||
@ -60,66 +59,3 @@
|
||||
.login .password-reset-link {
|
||||
text-align: center;
|
||||
}
|
||||
=======
|
||||
/* LOGIN FORM */
|
||||
|
||||
.login {
|
||||
background: var(--darkened-bg);
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.login #header {
|
||||
height: auto;
|
||||
padding: 15px 16px;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.login #header h1 {
|
||||
font-size: 1.125rem;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.login #header h1 a {
|
||||
color: var(--header-link-color);
|
||||
}
|
||||
|
||||
.login #content {
|
||||
padding: 20px 20px 0;
|
||||
}
|
||||
|
||||
.login #container {
|
||||
background: var(--body-bg);
|
||||
border: 1px solid var(--hairline-color);
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
width: 28em;
|
||||
min-width: 300px;
|
||||
margin: 100px auto;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.login .form-row {
|
||||
padding: 4px 0;
|
||||
}
|
||||
|
||||
.login .form-row label {
|
||||
display: block;
|
||||
line-height: 2em;
|
||||
}
|
||||
|
||||
.login .form-row #id_username, .login .form-row #id_password {
|
||||
padding: 8px;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.login .submit-row {
|
||||
padding: 1em 0 0 0;
|
||||
margin: 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.login .password-reset-link {
|
||||
text-align: center;
|
||||
}
|
||||
>>>>>>> master
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
<<<<<<< HEAD
|
||||
.sticky {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
@ -143,149 +142,3 @@
|
||||
#nav-sidebar table {
|
||||
width: 100%;
|
||||
}
|
||||
=======
|
||||
.sticky {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
max-height: 100vh;
|
||||
}
|
||||
|
||||
.toggle-nav-sidebar {
|
||||
z-index: 20;
|
||||
left: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex: 0 0 23px;
|
||||
width: 23px;
|
||||
border: 0;
|
||||
border-right: 1px solid var(--hairline-color);
|
||||
background-color: var(--body-bg);
|
||||
cursor: pointer;
|
||||
font-size: 1.25rem;
|
||||
color: var(--link-fg);
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
[dir="rtl"] .toggle-nav-sidebar {
|
||||
border-left: 1px solid var(--hairline-color);
|
||||
border-right: 0;
|
||||
}
|
||||
|
||||
.toggle-nav-sidebar:hover,
|
||||
.toggle-nav-sidebar:focus {
|
||||
background-color: var(--darkened-bg);
|
||||
}
|
||||
|
||||
#nav-sidebar {
|
||||
z-index: 15;
|
||||
flex: 0 0 275px;
|
||||
left: -276px;
|
||||
margin-left: -276px;
|
||||
border-top: 1px solid transparent;
|
||||
border-right: 1px solid var(--hairline-color);
|
||||
background-color: var(--body-bg);
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
[dir="rtl"] #nav-sidebar {
|
||||
border-left: 1px solid var(--hairline-color);
|
||||
border-right: 0;
|
||||
left: 0;
|
||||
margin-left: 0;
|
||||
right: -276px;
|
||||
margin-right: -276px;
|
||||
}
|
||||
|
||||
.toggle-nav-sidebar::before {
|
||||
content: '\00BB';
|
||||
}
|
||||
|
||||
.main.shifted .toggle-nav-sidebar::before {
|
||||
content: '\00AB';
|
||||
}
|
||||
|
||||
.main > #nav-sidebar {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.main.shifted > #nav-sidebar {
|
||||
margin-left: 0;
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
[dir="rtl"] .main.shifted > #nav-sidebar {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
#nav-sidebar .module th {
|
||||
width: 100%;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
#nav-sidebar .module th,
|
||||
#nav-sidebar .module caption {
|
||||
padding-left: 16px;
|
||||
}
|
||||
|
||||
#nav-sidebar .module td {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
[dir="rtl"] #nav-sidebar .module th,
|
||||
[dir="rtl"] #nav-sidebar .module caption {
|
||||
padding-left: 8px;
|
||||
padding-right: 16px;
|
||||
}
|
||||
|
||||
#nav-sidebar .current-app .section:link,
|
||||
#nav-sidebar .current-app .section:visited {
|
||||
color: var(--header-color);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#nav-sidebar .current-model {
|
||||
background: var(--selected-row);
|
||||
}
|
||||
|
||||
.main > #nav-sidebar + .content {
|
||||
max-width: calc(100% - 23px);
|
||||
}
|
||||
|
||||
.main.shifted > #nav-sidebar + .content {
|
||||
max-width: calc(100% - 299px);
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
#nav-sidebar, #toggle-nav-sidebar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.main > #nav-sidebar + .content,
|
||||
.main.shifted > #nav-sidebar + .content {
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
#nav-filter {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
padding: 2px 5px;
|
||||
margin: 5px 0;
|
||||
border: 1px solid var(--border-color);
|
||||
background-color: var(--darkened-bg);
|
||||
color: var(--body-fg);
|
||||
}
|
||||
|
||||
#nav-filter:focus {
|
||||
border-color: var(--body-quiet-color);
|
||||
}
|
||||
|
||||
#nav-filter.no-results {
|
||||
background: var(--message-error-bg);
|
||||
}
|
||||
|
||||
#nav-sidebar table {
|
||||
width: 100%;
|
||||
}
|
||||
>>>>>>> master
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,3 @@
|
||||
<<<<<<< HEAD
|
||||
/* TABLETS */
|
||||
|
||||
@media (max-width: 1024px) {
|
||||
@ -80,86 +79,3 @@
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
=======
|
||||
/* TABLETS */
|
||||
|
||||
@media (max-width: 1024px) {
|
||||
[dir="rtl"] .colMS {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
[dir="rtl"] #user-tools {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
[dir="rtl"] #changelist .actions label {
|
||||
padding-left: 10px;
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
[dir="rtl"] #changelist .actions select {
|
||||
margin-left: 0;
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
||||
[dir="rtl"] .change-list .filtered .results,
|
||||
[dir="rtl"] .change-list .filtered .paginator,
|
||||
[dir="rtl"] .filtered #toolbar,
|
||||
[dir="rtl"] .filtered div.xfull,
|
||||
[dir="rtl"] .filtered .actions,
|
||||
[dir="rtl"] #changelist-filter {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
[dir="rtl"] .inline-group ul.tools a.add,
|
||||
[dir="rtl"] .inline-group div.add-row a,
|
||||
[dir="rtl"] .inline-group .tabular tr.add-row td a {
|
||||
padding: 8px 26px 8px 10px;
|
||||
background-position: calc(100% - 8px) 9px;
|
||||
}
|
||||
|
||||
[dir="rtl"] .related-widget-wrapper-link + .selector {
|
||||
margin-right: 0;
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
||||
[dir="rtl"] .selector .selector-filter label {
|
||||
margin-right: 0;
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
[dir="rtl"] .object-tools li {
|
||||
float: right;
|
||||
}
|
||||
|
||||
[dir="rtl"] .object-tools li + li {
|
||||
margin-left: 0;
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
||||
[dir="rtl"] .dashboard .module table td a {
|
||||
padding-left: 0;
|
||||
padding-right: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
/* MOBILE */
|
||||
|
||||
@media (max-width: 767px) {
|
||||
[dir="rtl"] .aligned .related-lookup,
|
||||
[dir="rtl"] .aligned .datetimeshortcuts {
|
||||
margin-left: 0;
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
||||
[dir="rtl"] .aligned ul,
|
||||
[dir="rtl"] form .aligned ul.errorlist {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
[dir="rtl"] #changelist-filter {
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
>>>>>>> master
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
<<<<<<< HEAD
|
||||
/* GLOBAL */
|
||||
|
||||
th {
|
||||
@ -287,293 +286,3 @@ form .form-row p.datetime {
|
||||
margin-left: inherit;
|
||||
margin-right: 2px;
|
||||
}
|
||||
=======
|
||||
/* GLOBAL */
|
||||
|
||||
th {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.module h2, .module caption {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.module ul, .module ol {
|
||||
margin-left: 0;
|
||||
margin-right: 1.5em;
|
||||
}
|
||||
|
||||
.viewlink, .addlink, .changelink {
|
||||
padding-left: 0;
|
||||
padding-right: 16px;
|
||||
background-position: 100% 1px;
|
||||
}
|
||||
|
||||
.deletelink {
|
||||
padding-left: 0;
|
||||
padding-right: 16px;
|
||||
background-position: 100% 1px;
|
||||
}
|
||||
|
||||
.object-tools {
|
||||
float: left;
|
||||
}
|
||||
|
||||
thead th:first-child,
|
||||
tfoot td:first-child {
|
||||
border-left: none;
|
||||
}
|
||||
|
||||
/* LAYOUT */
|
||||
|
||||
#user-tools {
|
||||
right: auto;
|
||||
left: 0;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
div.breadcrumbs {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
#content-main {
|
||||
float: right;
|
||||
}
|
||||
|
||||
#content-related {
|
||||
float: left;
|
||||
margin-left: -300px;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.colMS {
|
||||
margin-left: 300px;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
/* SORTABLE TABLES */
|
||||
|
||||
table thead th.sorted .sortoptions {
|
||||
float: left;
|
||||
}
|
||||
|
||||
thead th.sorted .text {
|
||||
padding-right: 0;
|
||||
padding-left: 42px;
|
||||
}
|
||||
|
||||
/* dashboard styles */
|
||||
|
||||
.dashboard .module table td a {
|
||||
padding-left: .6em;
|
||||
padding-right: 16px;
|
||||
}
|
||||
|
||||
/* changelists styles */
|
||||
|
||||
.change-list .filtered table {
|
||||
border-left: none;
|
||||
border-right: 0px none;
|
||||
}
|
||||
|
||||
#changelist-filter {
|
||||
border-left: none;
|
||||
border-right: none;
|
||||
margin-left: 0;
|
||||
margin-right: 30px;
|
||||
}
|
||||
|
||||
#changelist-filter li.selected {
|
||||
border-left: none;
|
||||
padding-left: 10px;
|
||||
margin-left: 0;
|
||||
border-right: 5px solid var(--hairline-color);
|
||||
padding-right: 10px;
|
||||
margin-right: -15px;
|
||||
}
|
||||
|
||||
#changelist table tbody td:first-child, #changelist table tbody th:first-child {
|
||||
border-right: none;
|
||||
border-left: none;
|
||||
}
|
||||
|
||||
/* FORMS */
|
||||
|
||||
.aligned label {
|
||||
padding: 0 0 3px 1em;
|
||||
}
|
||||
|
||||
.submit-row a.deletelink {
|
||||
margin-left: 0;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.vDateField, .vTimeField {
|
||||
margin-left: 2px;
|
||||
}
|
||||
|
||||
.aligned .form-row input {
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
form .aligned ul {
|
||||
margin-right: 163px;
|
||||
padding-right: 10px;
|
||||
margin-left: 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
form ul.inline li {
|
||||
float: right;
|
||||
padding-right: 0;
|
||||
padding-left: 7px;
|
||||
}
|
||||
|
||||
form .aligned p.help,
|
||||
form .aligned div.help {
|
||||
margin-right: 160px;
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
form div.help ul,
|
||||
form .aligned .checkbox-row + .help,
|
||||
form .aligned p.date div.help.timezonewarning,
|
||||
form .aligned p.datetime div.help.timezonewarning,
|
||||
form .aligned p.time div.help.timezonewarning {
|
||||
margin-right: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
form .wide p.help, form .wide div.help {
|
||||
padding-left: 0;
|
||||
padding-right: 50px;
|
||||
}
|
||||
|
||||
form .wide p,
|
||||
form .wide ul.errorlist,
|
||||
form .wide input + p.help,
|
||||
form .wide input + div.help {
|
||||
margin-right: 200px;
|
||||
margin-left: 0px;
|
||||
}
|
||||
|
||||
.submit-row {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
fieldset .fieldBox {
|
||||
margin-left: 20px;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.errorlist li {
|
||||
background-position: 100% 12px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.errornote {
|
||||
background-position: 100% 12px;
|
||||
padding: 10px 12px;
|
||||
}
|
||||
|
||||
/* WIDGETS */
|
||||
|
||||
.calendarnav-previous {
|
||||
top: 0;
|
||||
left: auto;
|
||||
right: 10px;
|
||||
background: url(../img/calendar-icons.svg) 0 -30px no-repeat;
|
||||
}
|
||||
|
||||
.calendarbox .calendarnav-previous:focus,
|
||||
.calendarbox .calendarnav-previous:hover {
|
||||
background-position: 0 -45px;
|
||||
}
|
||||
|
||||
.calendarnav-next {
|
||||
top: 0;
|
||||
right: auto;
|
||||
left: 10px;
|
||||
background: url(../img/calendar-icons.svg) 0 0 no-repeat;
|
||||
}
|
||||
|
||||
.calendarbox .calendarnav-next:focus,
|
||||
.calendarbox .calendarnav-next:hover {
|
||||
background-position: 0 -15px;
|
||||
}
|
||||
|
||||
.calendar caption, .calendarbox h2 {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.selector {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.selector .selector-filter {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.selector-add {
|
||||
background: url(../img/selector-icons.svg) 0 -64px no-repeat;
|
||||
}
|
||||
|
||||
.active.selector-add:focus, .active.selector-add:hover {
|
||||
background-position: 0 -80px;
|
||||
}
|
||||
|
||||
.selector-remove {
|
||||
background: url(../img/selector-icons.svg) 0 -96px no-repeat;
|
||||
}
|
||||
|
||||
.active.selector-remove:focus, .active.selector-remove:hover {
|
||||
background-position: 0 -112px;
|
||||
}
|
||||
|
||||
a.selector-chooseall {
|
||||
background: url(../img/selector-icons.svg) right -128px no-repeat;
|
||||
}
|
||||
|
||||
a.active.selector-chooseall:focus, a.active.selector-chooseall:hover {
|
||||
background-position: 100% -144px;
|
||||
}
|
||||
|
||||
a.selector-clearall {
|
||||
background: url(../img/selector-icons.svg) 0 -160px no-repeat;
|
||||
}
|
||||
|
||||
a.active.selector-clearall:focus, a.active.selector-clearall:hover {
|
||||
background-position: 0 -176px;
|
||||
}
|
||||
|
||||
.inline-deletelink {
|
||||
float: left;
|
||||
}
|
||||
|
||||
form .form-row p.datetime {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.related-widget-wrapper {
|
||||
float: right;
|
||||
}
|
||||
|
||||
/* MISC */
|
||||
|
||||
.inline-related h2, .inline-group h2 {
|
||||
text-align: right
|
||||
}
|
||||
|
||||
.inline-related h3 span.delete {
|
||||
padding-right: 20px;
|
||||
padding-left: inherit;
|
||||
left: 10px;
|
||||
right: inherit;
|
||||
float:left;
|
||||
}
|
||||
|
||||
.inline-related h3 span.delete label {
|
||||
margin-left: inherit;
|
||||
margin-right: 2px;
|
||||
}
|
||||
>>>>>>> master
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
<<<<<<< HEAD
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2012-2017 Kevin Brown, Igor Vaynberg, and Select2 contributors
|
||||
@ -20,26 +19,3 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
=======
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2012-2017 Kevin Brown, Igor Vaynberg, and Select2 contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
>>>>>>> master
|
||||
|
||||
484
static/admin/css/vendor/select2/select2.css
vendored
484
static/admin/css/vendor/select2/select2.css
vendored
@ -1,4 +1,3 @@
|
||||
<<<<<<< HEAD
|
||||
.select2-container {
|
||||
box-sizing: border-box;
|
||||
display: inline-block;
|
||||
@ -480,486 +479,3 @@
|
||||
|
||||
.select2-container--classic.select2-container--open .select2-dropdown {
|
||||
border-color: #5897fb; }
|
||||
=======
|
||||
.select2-container {
|
||||
box-sizing: border-box;
|
||||
display: inline-block;
|
||||
margin: 0;
|
||||
position: relative;
|
||||
vertical-align: middle; }
|
||||
.select2-container .select2-selection--single {
|
||||
box-sizing: border-box;
|
||||
cursor: pointer;
|
||||
display: block;
|
||||
height: 28px;
|
||||
user-select: none;
|
||||
-webkit-user-select: none; }
|
||||
.select2-container .select2-selection--single .select2-selection__rendered {
|
||||
display: block;
|
||||
padding-left: 8px;
|
||||
padding-right: 20px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap; }
|
||||
.select2-container .select2-selection--single .select2-selection__clear {
|
||||
position: relative; }
|
||||
.select2-container[dir="rtl"] .select2-selection--single .select2-selection__rendered {
|
||||
padding-right: 8px;
|
||||
padding-left: 20px; }
|
||||
.select2-container .select2-selection--multiple {
|
||||
box-sizing: border-box;
|
||||
cursor: pointer;
|
||||
display: block;
|
||||
min-height: 32px;
|
||||
user-select: none;
|
||||
-webkit-user-select: none; }
|
||||
.select2-container .select2-selection--multiple .select2-selection__rendered {
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
padding-left: 8px;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap; }
|
||||
.select2-container .select2-search--inline {
|
||||
float: left; }
|
||||
.select2-container .select2-search--inline .select2-search__field {
|
||||
box-sizing: border-box;
|
||||
border: none;
|
||||
font-size: 100%;
|
||||
margin-top: 5px;
|
||||
padding: 0; }
|
||||
.select2-container .select2-search--inline .select2-search__field::-webkit-search-cancel-button {
|
||||
-webkit-appearance: none; }
|
||||
|
||||
.select2-dropdown {
|
||||
background-color: white;
|
||||
border: 1px solid #aaa;
|
||||
border-radius: 4px;
|
||||
box-sizing: border-box;
|
||||
display: block;
|
||||
position: absolute;
|
||||
left: -100000px;
|
||||
width: 100%;
|
||||
z-index: 1051; }
|
||||
|
||||
.select2-results {
|
||||
display: block; }
|
||||
|
||||
.select2-results__options {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0; }
|
||||
|
||||
.select2-results__option {
|
||||
padding: 6px;
|
||||
user-select: none;
|
||||
-webkit-user-select: none; }
|
||||
.select2-results__option[aria-selected] {
|
||||
cursor: pointer; }
|
||||
|
||||
.select2-container--open .select2-dropdown {
|
||||
left: 0; }
|
||||
|
||||
.select2-container--open .select2-dropdown--above {
|
||||
border-bottom: none;
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0; }
|
||||
|
||||
.select2-container--open .select2-dropdown--below {
|
||||
border-top: none;
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 0; }
|
||||
|
||||
.select2-search--dropdown {
|
||||
display: block;
|
||||
padding: 4px; }
|
||||
.select2-search--dropdown .select2-search__field {
|
||||
padding: 4px;
|
||||
width: 100%;
|
||||
box-sizing: border-box; }
|
||||
.select2-search--dropdown .select2-search__field::-webkit-search-cancel-button {
|
||||
-webkit-appearance: none; }
|
||||
.select2-search--dropdown.select2-search--hide {
|
||||
display: none; }
|
||||
|
||||
.select2-close-mask {
|
||||
border: 0;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: block;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
min-height: 100%;
|
||||
min-width: 100%;
|
||||
height: auto;
|
||||
width: auto;
|
||||
opacity: 0;
|
||||
z-index: 99;
|
||||
background-color: #fff;
|
||||
filter: alpha(opacity=0); }
|
||||
|
||||
.select2-hidden-accessible {
|
||||
border: 0 !important;
|
||||
clip: rect(0 0 0 0) !important;
|
||||
-webkit-clip-path: inset(50%) !important;
|
||||
clip-path: inset(50%) !important;
|
||||
height: 1px !important;
|
||||
overflow: hidden !important;
|
||||
padding: 0 !important;
|
||||
position: absolute !important;
|
||||
width: 1px !important;
|
||||
white-space: nowrap !important; }
|
||||
|
||||
.select2-container--default .select2-selection--single {
|
||||
background-color: #fff;
|
||||
border: 1px solid #aaa;
|
||||
border-radius: 4px; }
|
||||
.select2-container--default .select2-selection--single .select2-selection__rendered {
|
||||
color: #444;
|
||||
line-height: 28px; }
|
||||
.select2-container--default .select2-selection--single .select2-selection__clear {
|
||||
cursor: pointer;
|
||||
float: right;
|
||||
font-weight: bold; }
|
||||
.select2-container--default .select2-selection--single .select2-selection__placeholder {
|
||||
color: #999; }
|
||||
.select2-container--default .select2-selection--single .select2-selection__arrow {
|
||||
height: 26px;
|
||||
position: absolute;
|
||||
top: 1px;
|
||||
right: 1px;
|
||||
width: 20px; }
|
||||
.select2-container--default .select2-selection--single .select2-selection__arrow b {
|
||||
border-color: #888 transparent transparent transparent;
|
||||
border-style: solid;
|
||||
border-width: 5px 4px 0 4px;
|
||||
height: 0;
|
||||
left: 50%;
|
||||
margin-left: -4px;
|
||||
margin-top: -2px;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
width: 0; }
|
||||
|
||||
.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__clear {
|
||||
float: left; }
|
||||
|
||||
.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__arrow {
|
||||
left: 1px;
|
||||
right: auto; }
|
||||
|
||||
.select2-container--default.select2-container--disabled .select2-selection--single {
|
||||
background-color: #eee;
|
||||
cursor: default; }
|
||||
.select2-container--default.select2-container--disabled .select2-selection--single .select2-selection__clear {
|
||||
display: none; }
|
||||
|
||||
.select2-container--default.select2-container--open .select2-selection--single .select2-selection__arrow b {
|
||||
border-color: transparent transparent #888 transparent;
|
||||
border-width: 0 4px 5px 4px; }
|
||||
|
||||
.select2-container--default .select2-selection--multiple {
|
||||
background-color: white;
|
||||
border: 1px solid #aaa;
|
||||
border-radius: 4px;
|
||||
cursor: text; }
|
||||
.select2-container--default .select2-selection--multiple .select2-selection__rendered {
|
||||
box-sizing: border-box;
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0 5px;
|
||||
width: 100%; }
|
||||
.select2-container--default .select2-selection--multiple .select2-selection__rendered li {
|
||||
list-style: none; }
|
||||
.select2-container--default .select2-selection--multiple .select2-selection__clear {
|
||||
cursor: pointer;
|
||||
float: right;
|
||||
font-weight: bold;
|
||||
margin-top: 5px;
|
||||
margin-right: 10px;
|
||||
padding: 1px; }
|
||||
.select2-container--default .select2-selection--multiple .select2-selection__choice {
|
||||
background-color: #e4e4e4;
|
||||
border: 1px solid #aaa;
|
||||
border-radius: 4px;
|
||||
cursor: default;
|
||||
float: left;
|
||||
margin-right: 5px;
|
||||
margin-top: 5px;
|
||||
padding: 0 5px; }
|
||||
.select2-container--default .select2-selection--multiple .select2-selection__choice__remove {
|
||||
color: #999;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
font-weight: bold;
|
||||
margin-right: 2px; }
|
||||
.select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover {
|
||||
color: #333; }
|
||||
|
||||
.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice, .select2-container--default[dir="rtl"] .select2-selection--multiple .select2-search--inline {
|
||||
float: right; }
|
||||
|
||||
.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice {
|
||||
margin-left: 5px;
|
||||
margin-right: auto; }
|
||||
|
||||
.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove {
|
||||
margin-left: 2px;
|
||||
margin-right: auto; }
|
||||
|
||||
.select2-container--default.select2-container--focus .select2-selection--multiple {
|
||||
border: solid black 1px;
|
||||
outline: 0; }
|
||||
|
||||
.select2-container--default.select2-container--disabled .select2-selection--multiple {
|
||||
background-color: #eee;
|
||||
cursor: default; }
|
||||
|
||||
.select2-container--default.select2-container--disabled .select2-selection__choice__remove {
|
||||
display: none; }
|
||||
|
||||
.select2-container--default.select2-container--open.select2-container--above .select2-selection--single, .select2-container--default.select2-container--open.select2-container--above .select2-selection--multiple {
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 0; }
|
||||
|
||||
.select2-container--default.select2-container--open.select2-container--below .select2-selection--single, .select2-container--default.select2-container--open.select2-container--below .select2-selection--multiple {
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0; }
|
||||
|
||||
.select2-container--default .select2-search--dropdown .select2-search__field {
|
||||
border: 1px solid #aaa; }
|
||||
|
||||
.select2-container--default .select2-search--inline .select2-search__field {
|
||||
background: transparent;
|
||||
border: none;
|
||||
outline: 0;
|
||||
box-shadow: none;
|
||||
-webkit-appearance: textfield; }
|
||||
|
||||
.select2-container--default .select2-results > .select2-results__options {
|
||||
max-height: 200px;
|
||||
overflow-y: auto; }
|
||||
|
||||
.select2-container--default .select2-results__option[role=group] {
|
||||
padding: 0; }
|
||||
|
||||
.select2-container--default .select2-results__option[aria-disabled=true] {
|
||||
color: #999; }
|
||||
|
||||
.select2-container--default .select2-results__option[aria-selected=true] {
|
||||
background-color: #ddd; }
|
||||
|
||||
.select2-container--default .select2-results__option .select2-results__option {
|
||||
padding-left: 1em; }
|
||||
.select2-container--default .select2-results__option .select2-results__option .select2-results__group {
|
||||
padding-left: 0; }
|
||||
.select2-container--default .select2-results__option .select2-results__option .select2-results__option {
|
||||
margin-left: -1em;
|
||||
padding-left: 2em; }
|
||||
.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
|
||||
margin-left: -2em;
|
||||
padding-left: 3em; }
|
||||
.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
|
||||
margin-left: -3em;
|
||||
padding-left: 4em; }
|
||||
.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
|
||||
margin-left: -4em;
|
||||
padding-left: 5em; }
|
||||
.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
|
||||
margin-left: -5em;
|
||||
padding-left: 6em; }
|
||||
|
||||
.select2-container--default .select2-results__option--highlighted[aria-selected] {
|
||||
background-color: #5897fb;
|
||||
color: white; }
|
||||
|
||||
.select2-container--default .select2-results__group {
|
||||
cursor: default;
|
||||
display: block;
|
||||
padding: 6px; }
|
||||
|
||||
.select2-container--classic .select2-selection--single {
|
||||
background-color: #f7f7f7;
|
||||
border: 1px solid #aaa;
|
||||
border-radius: 4px;
|
||||
outline: 0;
|
||||
background-image: -webkit-linear-gradient(top, white 50%, #eeeeee 100%);
|
||||
background-image: -o-linear-gradient(top, white 50%, #eeeeee 100%);
|
||||
background-image: linear-gradient(to bottom, white 50%, #eeeeee 100%);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0); }
|
||||
.select2-container--classic .select2-selection--single:focus {
|
||||
border: 1px solid #5897fb; }
|
||||
.select2-container--classic .select2-selection--single .select2-selection__rendered {
|
||||
color: #444;
|
||||
line-height: 28px; }
|
||||
.select2-container--classic .select2-selection--single .select2-selection__clear {
|
||||
cursor: pointer;
|
||||
float: right;
|
||||
font-weight: bold;
|
||||
margin-right: 10px; }
|
||||
.select2-container--classic .select2-selection--single .select2-selection__placeholder {
|
||||
color: #999; }
|
||||
.select2-container--classic .select2-selection--single .select2-selection__arrow {
|
||||
background-color: #ddd;
|
||||
border: none;
|
||||
border-left: 1px solid #aaa;
|
||||
border-top-right-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
height: 26px;
|
||||
position: absolute;
|
||||
top: 1px;
|
||||
right: 1px;
|
||||
width: 20px;
|
||||
background-image: -webkit-linear-gradient(top, #eeeeee 50%, #cccccc 100%);
|
||||
background-image: -o-linear-gradient(top, #eeeeee 50%, #cccccc 100%);
|
||||
background-image: linear-gradient(to bottom, #eeeeee 50%, #cccccc 100%);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFCCCCCC', GradientType=0); }
|
||||
.select2-container--classic .select2-selection--single .select2-selection__arrow b {
|
||||
border-color: #888 transparent transparent transparent;
|
||||
border-style: solid;
|
||||
border-width: 5px 4px 0 4px;
|
||||
height: 0;
|
||||
left: 50%;
|
||||
margin-left: -4px;
|
||||
margin-top: -2px;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
width: 0; }
|
||||
|
||||
.select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__clear {
|
||||
float: left; }
|
||||
|
||||
.select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__arrow {
|
||||
border: none;
|
||||
border-right: 1px solid #aaa;
|
||||
border-radius: 0;
|
||||
border-top-left-radius: 4px;
|
||||
border-bottom-left-radius: 4px;
|
||||
left: 1px;
|
||||
right: auto; }
|
||||
|
||||
.select2-container--classic.select2-container--open .select2-selection--single {
|
||||
border: 1px solid #5897fb; }
|
||||
.select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow {
|
||||
background: transparent;
|
||||
border: none; }
|
||||
.select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow b {
|
||||
border-color: transparent transparent #888 transparent;
|
||||
border-width: 0 4px 5px 4px; }
|
||||
|
||||
.select2-container--classic.select2-container--open.select2-container--above .select2-selection--single {
|
||||
border-top: none;
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 0;
|
||||
background-image: -webkit-linear-gradient(top, white 0%, #eeeeee 50%);
|
||||
background-image: -o-linear-gradient(top, white 0%, #eeeeee 50%);
|
||||
background-image: linear-gradient(to bottom, white 0%, #eeeeee 50%);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0); }
|
||||
|
||||
.select2-container--classic.select2-container--open.select2-container--below .select2-selection--single {
|
||||
border-bottom: none;
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
background-image: -webkit-linear-gradient(top, #eeeeee 50%, white 100%);
|
||||
background-image: -o-linear-gradient(top, #eeeeee 50%, white 100%);
|
||||
background-image: linear-gradient(to bottom, #eeeeee 50%, white 100%);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFFFFFFF', GradientType=0); }
|
||||
|
||||
.select2-container--classic .select2-selection--multiple {
|
||||
background-color: white;
|
||||
border: 1px solid #aaa;
|
||||
border-radius: 4px;
|
||||
cursor: text;
|
||||
outline: 0; }
|
||||
.select2-container--classic .select2-selection--multiple:focus {
|
||||
border: 1px solid #5897fb; }
|
||||
.select2-container--classic .select2-selection--multiple .select2-selection__rendered {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0 5px; }
|
||||
.select2-container--classic .select2-selection--multiple .select2-selection__clear {
|
||||
display: none; }
|
||||
.select2-container--classic .select2-selection--multiple .select2-selection__choice {
|
||||
background-color: #e4e4e4;
|
||||
border: 1px solid #aaa;
|
||||
border-radius: 4px;
|
||||
cursor: default;
|
||||
float: left;
|
||||
margin-right: 5px;
|
||||
margin-top: 5px;
|
||||
padding: 0 5px; }
|
||||
.select2-container--classic .select2-selection--multiple .select2-selection__choice__remove {
|
||||
color: #888;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
font-weight: bold;
|
||||
margin-right: 2px; }
|
||||
.select2-container--classic .select2-selection--multiple .select2-selection__choice__remove:hover {
|
||||
color: #555; }
|
||||
|
||||
.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice {
|
||||
float: right;
|
||||
margin-left: 5px;
|
||||
margin-right: auto; }
|
||||
|
||||
.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove {
|
||||
margin-left: 2px;
|
||||
margin-right: auto; }
|
||||
|
||||
.select2-container--classic.select2-container--open .select2-selection--multiple {
|
||||
border: 1px solid #5897fb; }
|
||||
|
||||
.select2-container--classic.select2-container--open.select2-container--above .select2-selection--multiple {
|
||||
border-top: none;
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 0; }
|
||||
|
||||
.select2-container--classic.select2-container--open.select2-container--below .select2-selection--multiple {
|
||||
border-bottom: none;
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0; }
|
||||
|
||||
.select2-container--classic .select2-search--dropdown .select2-search__field {
|
||||
border: 1px solid #aaa;
|
||||
outline: 0; }
|
||||
|
||||
.select2-container--classic .select2-search--inline .select2-search__field {
|
||||
outline: 0;
|
||||
box-shadow: none; }
|
||||
|
||||
.select2-container--classic .select2-dropdown {
|
||||
background-color: white;
|
||||
border: 1px solid transparent; }
|
||||
|
||||
.select2-container--classic .select2-dropdown--above {
|
||||
border-bottom: none; }
|
||||
|
||||
.select2-container--classic .select2-dropdown--below {
|
||||
border-top: none; }
|
||||
|
||||
.select2-container--classic .select2-results > .select2-results__options {
|
||||
max-height: 200px;
|
||||
overflow-y: auto; }
|
||||
|
||||
.select2-container--classic .select2-results__option[role=group] {
|
||||
padding: 0; }
|
||||
|
||||
.select2-container--classic .select2-results__option[aria-disabled=true] {
|
||||
color: grey; }
|
||||
|
||||
.select2-container--classic .select2-results__option--highlighted[aria-selected] {
|
||||
background-color: #3875d7;
|
||||
color: white; }
|
||||
|
||||
.select2-container--classic .select2-results__group {
|
||||
cursor: default;
|
||||
display: block;
|
||||
padding: 6px; }
|
||||
|
||||
.select2-container--classic.select2-container--open .select2-dropdown {
|
||||
border-color: #5897fb; }
|
||||
>>>>>>> master
|
||||
|
||||
File diff suppressed because one or more lines are too long
@ -1,4 +1,3 @@
|
||||
<<<<<<< HEAD
|
||||
/* SELECTOR (FILTER INTERFACE) */
|
||||
|
||||
.selector {
|
||||
@ -602,608 +601,3 @@ select + .related-widget-wrapper-link,
|
||||
width: 600px;
|
||||
height: 400px;
|
||||
}
|
||||
=======
|
||||
/* SELECTOR (FILTER INTERFACE) */
|
||||
|
||||
.selector {
|
||||
width: 800px;
|
||||
float: left;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.selector select {
|
||||
width: 380px;
|
||||
height: 17.2em;
|
||||
flex: 1 0 auto;
|
||||
}
|
||||
|
||||
.selector-available, .selector-chosen {
|
||||
width: 380px;
|
||||
text-align: center;
|
||||
margin-bottom: 5px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.selector-available h2, .selector-chosen h2 {
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 4px 4px 0 0;
|
||||
}
|
||||
|
||||
.selector-chosen .list-footer-display {
|
||||
border: 1px solid var(--border-color);
|
||||
border-top: none;
|
||||
border-radius: 0 0 4px 4px;
|
||||
margin: 0 0 10px;
|
||||
padding: 8px;
|
||||
text-align: center;
|
||||
background: var(--primary);
|
||||
color: var(--header-link-color);
|
||||
cursor: pointer;
|
||||
}
|
||||
.selector-chosen .list-footer-display__clear {
|
||||
color: var(--breadcrumbs-fg);
|
||||
}
|
||||
|
||||
.selector-chosen h2 {
|
||||
background: var(--primary);
|
||||
color: var(--header-link-color);
|
||||
}
|
||||
|
||||
.selector .selector-available h2 {
|
||||
background: var(--darkened-bg);
|
||||
color: var(--body-quiet-color);
|
||||
}
|
||||
|
||||
.selector .selector-filter {
|
||||
border: 1px solid var(--border-color);
|
||||
border-width: 0 1px;
|
||||
padding: 8px;
|
||||
color: var(--body-quiet-color);
|
||||
font-size: 0.625rem;
|
||||
margin: 0;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.selector .selector-filter label,
|
||||
.inline-group .aligned .selector .selector-filter label {
|
||||
float: left;
|
||||
margin: 7px 0 0;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.selector .selector-available input,
|
||||
.selector .selector-chosen input {
|
||||
width: 320px;
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.selector ul.selector-chooser {
|
||||
align-self: center;
|
||||
width: 22px;
|
||||
background-color: var(--selected-bg);
|
||||
border-radius: 10px;
|
||||
margin: 0 5px;
|
||||
padding: 0;
|
||||
transform: translateY(-17px);
|
||||
}
|
||||
|
||||
.selector-chooser li {
|
||||
margin: 0;
|
||||
padding: 3px;
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
.selector select {
|
||||
padding: 0 10px;
|
||||
margin: 0 0 10px;
|
||||
border-radius: 0 0 4px 4px;
|
||||
}
|
||||
.selector .selector-chosen--with-filtered select {
|
||||
margin: 0;
|
||||
border-radius: 0;
|
||||
height: 14em;
|
||||
}
|
||||
|
||||
.selector .selector-chosen:not(.selector-chosen--with-filtered) .list-footer-display {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.selector-add, .selector-remove {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
display: block;
|
||||
text-indent: -3000px;
|
||||
overflow: hidden;
|
||||
cursor: default;
|
||||
opacity: 0.55;
|
||||
}
|
||||
|
||||
.active.selector-add, .active.selector-remove {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.active.selector-add:hover, .active.selector-remove:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.selector-add {
|
||||
background: url(../img/selector-icons.svg) 0 -96px no-repeat;
|
||||
}
|
||||
|
||||
.active.selector-add:focus, .active.selector-add:hover {
|
||||
background-position: 0 -112px;
|
||||
}
|
||||
|
||||
.selector-remove {
|
||||
background: url(../img/selector-icons.svg) 0 -64px no-repeat;
|
||||
}
|
||||
|
||||
.active.selector-remove:focus, .active.selector-remove:hover {
|
||||
background-position: 0 -80px;
|
||||
}
|
||||
|
||||
a.selector-chooseall, a.selector-clearall {
|
||||
display: inline-block;
|
||||
height: 16px;
|
||||
text-align: left;
|
||||
margin: 1px auto 3px;
|
||||
overflow: hidden;
|
||||
font-weight: bold;
|
||||
line-height: 16px;
|
||||
color: var(--body-quiet-color);
|
||||
text-decoration: none;
|
||||
opacity: 0.55;
|
||||
}
|
||||
|
||||
a.active.selector-chooseall:focus, a.active.selector-clearall:focus,
|
||||
a.active.selector-chooseall:hover, a.active.selector-clearall:hover {
|
||||
color: var(--link-fg);
|
||||
}
|
||||
|
||||
a.active.selector-chooseall, a.active.selector-clearall {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
a.active.selector-chooseall:hover, a.active.selector-clearall:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
a.selector-chooseall {
|
||||
padding: 0 18px 0 0;
|
||||
background: url(../img/selector-icons.svg) right -160px no-repeat;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
a.active.selector-chooseall:focus, a.active.selector-chooseall:hover {
|
||||
background-position: 100% -176px;
|
||||
}
|
||||
|
||||
a.selector-clearall {
|
||||
padding: 0 0 0 18px;
|
||||
background: url(../img/selector-icons.svg) 0 -128px no-repeat;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
a.active.selector-clearall:focus, a.active.selector-clearall:hover {
|
||||
background-position: 0 -144px;
|
||||
}
|
||||
|
||||
/* STACKED SELECTORS */
|
||||
|
||||
.stacked {
|
||||
float: left;
|
||||
width: 490px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.stacked select {
|
||||
width: 480px;
|
||||
height: 10.1em;
|
||||
}
|
||||
|
||||
.stacked .selector-available, .stacked .selector-chosen {
|
||||
width: 480px;
|
||||
}
|
||||
|
||||
.stacked .selector-available {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.stacked .selector-available input {
|
||||
width: 422px;
|
||||
}
|
||||
|
||||
.stacked ul.selector-chooser {
|
||||
height: 22px;
|
||||
width: 50px;
|
||||
margin: 0 0 10px 40%;
|
||||
background-color: #eee;
|
||||
border-radius: 10px;
|
||||
transform: none;
|
||||
}
|
||||
|
||||
.stacked .selector-chooser li {
|
||||
float: left;
|
||||
padding: 3px 3px 3px 5px;
|
||||
}
|
||||
|
||||
.stacked .selector-chooseall, .stacked .selector-clearall {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.stacked .selector-add {
|
||||
background: url(../img/selector-icons.svg) 0 -32px no-repeat;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.stacked .active.selector-add {
|
||||
background-position: 0 -32px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.stacked .active.selector-add:focus, .stacked .active.selector-add:hover {
|
||||
background-position: 0 -48px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.stacked .selector-remove {
|
||||
background: url(../img/selector-icons.svg) 0 0 no-repeat;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.stacked .active.selector-remove {
|
||||
background-position: 0 0px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.stacked .active.selector-remove:focus, .stacked .active.selector-remove:hover {
|
||||
background-position: 0 -16px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.selector .help-icon {
|
||||
background: url(../img/icon-unknown.svg) 0 0 no-repeat;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
margin: -2px 0 0 2px;
|
||||
width: 13px;
|
||||
height: 13px;
|
||||
}
|
||||
|
||||
.selector .selector-chosen .help-icon {
|
||||
background: url(../img/icon-unknown-alt.svg) 0 0 no-repeat;
|
||||
}
|
||||
|
||||
.selector .search-label-icon {
|
||||
background: url(../img/search.svg) 0 0 no-repeat;
|
||||
display: inline-block;
|
||||
height: 1.125rem;
|
||||
width: 1.125rem;
|
||||
}
|
||||
|
||||
/* DATE AND TIME */
|
||||
|
||||
p.datetime {
|
||||
line-height: 20px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
color: var(--body-quiet-color);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.datetime span {
|
||||
white-space: nowrap;
|
||||
font-weight: normal;
|
||||
font-size: 0.6875rem;
|
||||
color: var(--body-quiet-color);
|
||||
}
|
||||
|
||||
.datetime input, .form-row .datetime input.vDateField, .form-row .datetime input.vTimeField {
|
||||
margin-left: 5px;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
table p.datetime {
|
||||
font-size: 0.6875rem;
|
||||
margin-left: 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.datetimeshortcuts .clock-icon, .datetimeshortcuts .date-icon {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.datetimeshortcuts .clock-icon {
|
||||
background: url(../img/icon-clock.svg) 0 0 no-repeat;
|
||||
}
|
||||
|
||||
.datetimeshortcuts a:focus .clock-icon,
|
||||
.datetimeshortcuts a:hover .clock-icon {
|
||||
background-position: 0 -16px;
|
||||
}
|
||||
|
||||
.datetimeshortcuts .date-icon {
|
||||
background: url(../img/icon-calendar.svg) 0 0 no-repeat;
|
||||
top: -1px;
|
||||
}
|
||||
|
||||
.datetimeshortcuts a:focus .date-icon,
|
||||
.datetimeshortcuts a:hover .date-icon {
|
||||
background-position: 0 -16px;
|
||||
}
|
||||
|
||||
.timezonewarning {
|
||||
font-size: 0.6875rem;
|
||||
color: var(--body-quiet-color);
|
||||
}
|
||||
|
||||
/* URL */
|
||||
|
||||
p.url {
|
||||
line-height: 20px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
color: var(--body-quiet-color);
|
||||
font-size: 0.6875rem;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.url a {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
/* FILE UPLOADS */
|
||||
|
||||
p.file-upload {
|
||||
line-height: 20px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
color: var(--body-quiet-color);
|
||||
font-size: 0.6875rem;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.file-upload a {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.file-upload .deletelink {
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
span.clearable-file-input label {
|
||||
color: var(--body-fg);
|
||||
font-size: 0.6875rem;
|
||||
display: inline;
|
||||
float: none;
|
||||
}
|
||||
|
||||
/* CALENDARS & CLOCKS */
|
||||
|
||||
.calendarbox, .clockbox {
|
||||
margin: 5px auto;
|
||||
font-size: 0.75rem;
|
||||
width: 19em;
|
||||
text-align: center;
|
||||
background: var(--body-bg);
|
||||
color: var(--body-fg);
|
||||
border: 1px solid var(--hairline-color);
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.15);
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.clockbox {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.calendar {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.calendar table {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border-collapse: collapse;
|
||||
background: white;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.calendar caption, .calendarbox h2 {
|
||||
margin: 0;
|
||||
text-align: center;
|
||||
border-top: none;
|
||||
font-weight: 700;
|
||||
font-size: 0.75rem;
|
||||
color: #333;
|
||||
background: var(--accent);
|
||||
}
|
||||
|
||||
.calendar th {
|
||||
padding: 8px 5px;
|
||||
background: var(--darkened-bg);
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
font-weight: 400;
|
||||
font-size: 0.75rem;
|
||||
text-align: center;
|
||||
color: var(--body-quiet-color);
|
||||
}
|
||||
|
||||
.calendar td {
|
||||
font-weight: 400;
|
||||
font-size: 0.75rem;
|
||||
text-align: center;
|
||||
padding: 0;
|
||||
border-top: 1px solid var(--hairline-color);
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.calendar td.selected a {
|
||||
background: var(--primary);
|
||||
color: var(--button-fg);
|
||||
}
|
||||
|
||||
.calendar td.nonday {
|
||||
background: var(--darkened-bg);
|
||||
}
|
||||
|
||||
.calendar td.today a {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.calendar td a, .timelist a {
|
||||
display: block;
|
||||
font-weight: 400;
|
||||
padding: 6px;
|
||||
text-decoration: none;
|
||||
color: var(--body-quiet-color);
|
||||
}
|
||||
|
||||
.calendar td a:focus, .timelist a:focus,
|
||||
.calendar td a:hover, .timelist a:hover {
|
||||
background: var(--primary);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.calendar td a:active, .timelist a:active {
|
||||
background: var(--header-bg);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.calendarnav {
|
||||
font-size: 0.625rem;
|
||||
text-align: center;
|
||||
color: #ccc;
|
||||
margin: 0;
|
||||
padding: 1px 3px;
|
||||
}
|
||||
|
||||
.calendarnav a:link, #calendarnav a:visited,
|
||||
#calendarnav a:focus, #calendarnav a:hover {
|
||||
color: var(--body-quiet-color);
|
||||
}
|
||||
|
||||
.calendar-shortcuts {
|
||||
background: var(--body-bg);
|
||||
color: var(--body-quiet-color);
|
||||
font-size: 0.6875rem;
|
||||
line-height: 0.6875rem;
|
||||
border-top: 1px solid var(--hairline-color);
|
||||
padding: 8px 0;
|
||||
}
|
||||
|
||||
.calendarbox .calendarnav-previous, .calendarbox .calendarnav-next {
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
text-indent: -9999px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.calendarnav-previous {
|
||||
left: 10px;
|
||||
background: url(../img/calendar-icons.svg) 0 0 no-repeat;
|
||||
}
|
||||
|
||||
.calendarbox .calendarnav-previous:focus,
|
||||
.calendarbox .calendarnav-previous:hover {
|
||||
background-position: 0 -15px;
|
||||
}
|
||||
|
||||
.calendarnav-next {
|
||||
right: 10px;
|
||||
background: url(../img/calendar-icons.svg) 0 -30px no-repeat;
|
||||
}
|
||||
|
||||
.calendarbox .calendarnav-next:focus,
|
||||
.calendarbox .calendarnav-next:hover {
|
||||
background-position: 0 -45px;
|
||||
}
|
||||
|
||||
.calendar-cancel {
|
||||
margin: 0;
|
||||
padding: 4px 0;
|
||||
font-size: 0.75rem;
|
||||
background: #eee;
|
||||
border-top: 1px solid var(--border-color);
|
||||
color: var(--body-fg);
|
||||
}
|
||||
|
||||
.calendar-cancel:focus, .calendar-cancel:hover {
|
||||
background: #ddd;
|
||||
}
|
||||
|
||||
.calendar-cancel a {
|
||||
color: black;
|
||||
display: block;
|
||||
}
|
||||
|
||||
ul.timelist, .timelist li {
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.timelist a {
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
/* EDIT INLINE */
|
||||
|
||||
.inline-deletelink {
|
||||
float: right;
|
||||
text-indent: -9999px;
|
||||
background: url(../img/inline-delete.svg) 0 0 no-repeat;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
border: 0px none;
|
||||
}
|
||||
|
||||
.inline-deletelink:focus, .inline-deletelink:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* RELATED WIDGET WRAPPER */
|
||||
.related-widget-wrapper {
|
||||
float: left; /* display properly in form rows with multiple fields */
|
||||
overflow: hidden; /* clear floated contents */
|
||||
}
|
||||
|
||||
.related-widget-wrapper-link {
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
.related-widget-wrapper-link:link {
|
||||
opacity: .8;
|
||||
}
|
||||
|
||||
.related-widget-wrapper-link:link:focus,
|
||||
.related-widget-wrapper-link:link:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
select + .related-widget-wrapper-link,
|
||||
.related-widget-wrapper-link + .related-widget-wrapper-link {
|
||||
margin-left: 7px;
|
||||
}
|
||||
|
||||
/* GIS MAPS */
|
||||
.dj_map {
|
||||
width: 600px;
|
||||
height: 400px;
|
||||
}
|
||||
>>>>>>> master
|
||||
|
||||
@ -1,462 +1,90 @@
|
||||
/*
|
||||
* article.css
|
||||
* Styles for CKEditor 5 rendered content inside .content-card
|
||||
* and for the article detail page layout.
|
||||
*
|
||||
* Scope: all rules are under .content-card .card-content
|
||||
* so they never leak into the rest of the site.
|
||||
*/
|
||||
|
||||
/* ===== ARTICLE PAGE LAYOUT ===== */
|
||||
|
||||
.article-meta {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1.5rem;
|
||||
flex-wrap: wrap;
|
||||
font-size: 0.9rem;
|
||||
color: var(--text-light);
|
||||
margin-bottom: 2rem;
|
||||
padding-bottom: 1.5rem;
|
||||
border-bottom: 1px solid var(--border-light);
|
||||
}
|
||||
|
||||
.article-meta span {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.4rem;
|
||||
}
|
||||
|
||||
.article-tags {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.5rem;
|
||||
margin: 1.5rem 0;
|
||||
}
|
||||
|
||||
.article-tag {
|
||||
display: inline-block;
|
||||
padding: 0.25rem 0.75rem;
|
||||
background: var(--bg-tertiary);
|
||||
border: 1px solid var(--border-light);
|
||||
border-radius: var(--radius-sm);
|
||||
font-size: 0.8rem;
|
||||
color: var(--text-secondary);
|
||||
text-decoration: none;
|
||||
transition: var(--transition);
|
||||
}
|
||||
|
||||
.article-tag:hover {
|
||||
background: var(--primary);
|
||||
color: white;
|
||||
border-color: var(--primary);
|
||||
}
|
||||
|
||||
/* ===== CKEDITOR 5 CONTENT ===== */
|
||||
|
||||
.content-card .card-content {
|
||||
font-size: 1.05rem;
|
||||
line-height: 1.8;
|
||||
color: var(--text-primary);
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
/* --- Headings --- */
|
||||
|
||||
.content-card .card-content h2,
|
||||
.content-card .card-content h3,
|
||||
.content-card .card-content h4,
|
||||
.content-card .card-content h5,
|
||||
.content-card .card-content h6 {
|
||||
font-weight: 700;
|
||||
line-height: 1.3;
|
||||
margin-top: 2rem;
|
||||
margin-bottom: 0.75rem;
|
||||
/* Стили для содержимого статьи */
|
||||
.article-content {
|
||||
font-size: 1rem;
|
||||
line-height: 1.6;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.content-card .card-content h2 {
|
||||
font-size: 1.75rem;
|
||||
padding-bottom: 0.5rem;
|
||||
border-bottom: 2px solid var(--border-light);
|
||||
.article-content h1,
|
||||
.article-content h2,
|
||||
.article-content h3,
|
||||
.article-content h4,
|
||||
.article-content h5,
|
||||
.article-content h6 {
|
||||
margin-top: 1.5em;
|
||||
margin-bottom: 0.75em;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.content-card .card-content h3 {
|
||||
font-size: 1.375rem;
|
||||
padding-left: 0.75rem;
|
||||
border-left: 4px solid var(--primary);
|
||||
}
|
||||
|
||||
.content-card .card-content h4 {
|
||||
font-size: 1.125rem;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
/* --- Paragraphs --- */
|
||||
|
||||
.content-card .card-content p {
|
||||
margin-bottom: 1.25rem;
|
||||
}
|
||||
|
||||
.content-card .card-content p:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
/* --- Links --- */
|
||||
|
||||
.content-card .card-content a {
|
||||
color: var(--primary);
|
||||
text-decoration: underline;
|
||||
text-decoration-color: rgba(255, 107, 0, 0.4);
|
||||
text-underline-offset: 3px;
|
||||
transition: var(--transition);
|
||||
}
|
||||
|
||||
.content-card .card-content a:hover {
|
||||
color: var(--primary-dark);
|
||||
text-decoration-color: var(--primary-dark);
|
||||
}
|
||||
|
||||
/* --- Lists --- */
|
||||
|
||||
.content-card .card-content ul,
|
||||
.content-card .card-content ol {
|
||||
margin: 0 0 1.25rem 0;
|
||||
padding-left: 1.75rem;
|
||||
}
|
||||
|
||||
.content-card .card-content ul {
|
||||
list-style: none;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.content-card .card-content ul li {
|
||||
position: relative;
|
||||
padding-left: 1.5rem;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.content-card .card-content ul li::before {
|
||||
content: '▸';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
color: var(--primary);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.content-card .card-content ol li {
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.content-card .card-content ul ul,
|
||||
.content-card .card-content ol ol,
|
||||
.content-card .card-content ul ol,
|
||||
.content-card .card-content ol ul {
|
||||
margin-top: 0.5rem;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
/* --- Blockquote --- */
|
||||
|
||||
.content-card .card-content blockquote {
|
||||
margin: 1.5rem 0;
|
||||
padding: 1.25rem 1.5rem;
|
||||
.article-content h1 { font-size: 2rem; }
|
||||
.article-content h2 { font-size: 1.75rem; }
|
||||
.article-content h3 { font-size: 1.5rem; }
|
||||
|
||||
.article-content p {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.article-content ul,
|
||||
.article-content ol {
|
||||
margin-bottom: 1rem;
|
||||
padding-left: 2rem;
|
||||
}
|
||||
|
||||
.article-content li {
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
|
||||
.article-content blockquote {
|
||||
border-left: 4px solid var(--primary);
|
||||
padding: 0.5rem 1rem;
|
||||
background: var(--bg-secondary);
|
||||
border-radius: 0 var(--radius-md) var(--radius-md) 0;
|
||||
color: var(--text-secondary);
|
||||
margin: 1rem 0;
|
||||
font-style: italic;
|
||||
font-size: 1.05rem;
|
||||
}
|
||||
|
||||
.content-card .card-content blockquote p:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
/* --- Inline code (not inside pre) --- */
|
||||
/*
|
||||
* High specificity is fine here because this selector explicitly
|
||||
* excludes pre > code, so it never touches hljs blocks.
|
||||
*/
|
||||
|
||||
.content-card .card-content :not(pre) > code {
|
||||
font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
|
||||
font-size: 0.875em;
|
||||
background: var(--bg-tertiary);
|
||||
color: var(--primary-dark);
|
||||
padding: 0.15em 0.4em;
|
||||
border-radius: 4px;
|
||||
border: 1px solid var(--border-light);
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
/* --- Code blocks (CKEditor generates <pre><code class="hljs">) --- */
|
||||
/*
|
||||
* ALL pre and pre code rules use :where() — zero specificity.
|
||||
* This guarantees hljs always wins on colors, background, and padding.
|
||||
*
|
||||
* Responsibility split:
|
||||
* article.css → layout only: margin, border-radius, overflow, shadow
|
||||
* hljs CSS → everything visual: background, color, padding, font-size
|
||||
*
|
||||
* font-size:0 on pre prevents inherited line-height:1.8 from inflating
|
||||
* the spacing between lines (line-height is computed from font-size,
|
||||
* so zeroing it on the wrapper element neutralises the inheritance).
|
||||
* font-size is restored on pre code.
|
||||
*/
|
||||
|
||||
:where(.content-card .card-content) pre {
|
||||
margin: 1.5rem 0;
|
||||
padding: 0; /* hljs sets padding:1em on code.hljs — don't double it */
|
||||
border-radius: var(--radius-md);
|
||||
overflow-x: auto;
|
||||
box-shadow: var(--shadow-md);
|
||||
font-size: 0; /* neutralise inherited line-height */
|
||||
line-height: 1;
|
||||
background: none; /* hljs controls background (#fff or #282c34) */
|
||||
}
|
||||
|
||||
:where(.content-card .card-content) pre code {
|
||||
font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
|
||||
font-size: 0.9rem; /* restore font-size for hljs to work from */
|
||||
line-height: 1.5;
|
||||
word-break: normal;
|
||||
white-space: pre;
|
||||
/* NO color, NO background, NO padding — hljs owns these */
|
||||
}
|
||||
|
||||
/* --- Tables --- */
|
||||
|
||||
.content-card .card-content .table-wrapper,
|
||||
.content-card .card-content figure.table {
|
||||
overflow-x: auto;
|
||||
margin: 1.5rem 0;
|
||||
border-radius: var(--radius-md);
|
||||
box-shadow: var(--shadow-sm);
|
||||
}
|
||||
|
||||
.content-card .card-content table {
|
||||
.article-content table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
font-size: 0.95rem;
|
||||
margin: 1rem 0;
|
||||
}
|
||||
|
||||
.content-card .card-content th {
|
||||
background: var(--bg-secondary);
|
||||
font-weight: 700;
|
||||
text-align: left;
|
||||
padding: 0.875rem 1rem;
|
||||
border-bottom: 2px solid var(--border-medium);
|
||||
color: var(--text-primary);
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.content-card .card-content td {
|
||||
padding: 0.75rem 1rem;
|
||||
border-bottom: 1px solid var(--border-light);
|
||||
color: var(--text-secondary);
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.content-card .card-content tr:last-child td {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.content-card .card-content tbody tr:hover td {
|
||||
background: var(--bg-secondary);
|
||||
}
|
||||
|
||||
/* CKEditor 5 table with header row class */
|
||||
.content-card .card-content table.ck-table-resized th,
|
||||
.content-card .card-content table.ck-table-resized td {
|
||||
.article-content th,
|
||||
.article-content td {
|
||||
border: 1px solid var(--border-light);
|
||||
padding: 0.5rem;
|
||||
}
|
||||
|
||||
/* --- Images (CKEditor wraps in <figure class="image">) --- */
|
||||
|
||||
.content-card .card-content figure.image {
|
||||
margin: 1.5rem auto;
|
||||
text-align: center;
|
||||
max-width: 100%;
|
||||
.article-content th {
|
||||
background: var(--bg-secondary);
|
||||
}
|
||||
|
||||
.content-card .card-content figure.image img,
|
||||
.content-card .card-content img {
|
||||
.article-content img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
border-radius: var(--radius-md);
|
||||
box-shadow: var(--shadow-md);
|
||||
cursor: pointer; /* triggers the click-to-enlarge modal */
|
||||
}
|
||||
|
||||
.content-card .card-content figure.image figcaption {
|
||||
margin-top: 0.5rem;
|
||||
font-size: 0.875rem;
|
||||
color: var(--text-light);
|
||||
font-style: italic;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* CKEditor alignment classes */
|
||||
.content-card .card-content figure.image.image-style-align-left {
|
||||
float: left;
|
||||
margin: 0.5rem 1.5rem 1rem 0;
|
||||
max-width: 45%;
|
||||
}
|
||||
|
||||
.content-card .card-content figure.image.image-style-align-right {
|
||||
float: right;
|
||||
margin: 0.5rem 0 1rem 1.5rem;
|
||||
max-width: 45%;
|
||||
}
|
||||
|
||||
/* Clearfix after floated images */
|
||||
.content-card .card-content::after {
|
||||
content: '';
|
||||
display: table;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
/* --- Horizontal rule --- */
|
||||
|
||||
.content-card .card-content hr {
|
||||
border: none;
|
||||
height: 2px;
|
||||
background: linear-gradient(90deg, transparent, var(--border-medium), transparent);
|
||||
margin: 2rem 0;
|
||||
}
|
||||
|
||||
/* --- Alert/info boxes (CKEditor custom classes if used) --- */
|
||||
|
||||
.content-card .card-content .info-box {
|
||||
padding: 1rem 1.25rem;
|
||||
border-radius: var(--radius-md);
|
||||
margin: 1.5rem 0;
|
||||
border-left: 4px solid var(--accent);
|
||||
background: rgba(0, 168, 255, 0.08);
|
||||
color: var(--text-secondary);
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
|
||||
/* ===== COMMENTS SECTION ===== */
|
||||
|
||||
.comments-section {
|
||||
margin-top: 3rem;
|
||||
}
|
||||
|
||||
.comments-section h3 {
|
||||
font-size: 1.5rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 1.5rem;
|
||||
color: var(--text-primary);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
.comment-card {
|
||||
background: var(--bg-secondary);
|
||||
border-radius: var(--radius-lg);
|
||||
padding: 1.25rem 1.5rem;
|
||||
margin-bottom: 1rem;
|
||||
border: 1px solid var(--border-light);
|
||||
border-left: 3px solid var(--secondary);
|
||||
}
|
||||
|
||||
.comment-author {
|
||||
font-weight: 600;
|
||||
color: var(--text-primary);
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
|
||||
.comment-date {
|
||||
font-size: 0.8rem;
|
||||
color: var(--text-light);
|
||||
margin-left: 0.75rem;
|
||||
}
|
||||
|
||||
.comment-body {
|
||||
margin-top: 0.75rem;
|
||||
color: var(--text-secondary);
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.comment-form-card {
|
||||
background: var(--bg-card);
|
||||
border-radius: var(--radius-xl);
|
||||
padding: 2rem;
|
||||
box-shadow: var(--shadow-md);
|
||||
border: 1px solid var(--border-light);
|
||||
margin-top: 2rem;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.comment-form-card::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 4px;
|
||||
background: var(--gradient-secondary);
|
||||
border-radius: var(--radius-xl) var(--radius-xl) 0 0;
|
||||
}
|
||||
|
||||
.comment-form-card h4 {
|
||||
font-size: 1.25rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 1.5rem;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
/* ===== RESPONSIVE ===== */
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.content-card .card-content h2 {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
.content-card .card-content h3 {
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
.content-card .card-content figure.image.image-style-align-left,
|
||||
.content-card .card-content figure.image.image-style-align-right {
|
||||
float: none;
|
||||
max-width: 100%;
|
||||
margin: 1rem auto;
|
||||
}
|
||||
|
||||
/* :where() keeps specificity at zero so hljs still wins on mobile */
|
||||
:where(.content-card .card-content) pre {
|
||||
box-shadow: none;
|
||||
margin: 1rem 0;
|
||||
}
|
||||
|
||||
.content-card .card-content th,
|
||||
.content-card .card-content td {
|
||||
padding: 0.6rem 0.75rem;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
.article-meta {
|
||||
gap: 1rem;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.content-card .card-content {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.content-card .card-content h2 {
|
||||
font-size: 1.375rem;
|
||||
}
|
||||
|
||||
.content-card .card-content h3 {
|
||||
font-size: 1.125rem;
|
||||
}
|
||||
.article-content pre {
|
||||
background: #2d2d2d;
|
||||
color: #ccc;
|
||||
padding: 1rem;
|
||||
border-radius: 4px;
|
||||
overflow-x: auto;
|
||||
margin: 1rem 0;
|
||||
}
|
||||
|
||||
.article-content code {
|
||||
font-family: 'Courier New', monospace;
|
||||
background: #2d2d2d;
|
||||
color: #ccc;
|
||||
padding: 0.2rem 0.4rem;
|
||||
border-radius: 3px;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
.article-content pre code {
|
||||
padding: 0;
|
||||
background: none;
|
||||
color: inherit;
|
||||
}
|
||||
237
static/products/css/ck_content.css
Normal file
237
static/products/css/ck_content.css
Normal file
@ -0,0 +1,237 @@
|
||||
/*
|
||||
* ck_content.css — общие стили для CKEditor-контента
|
||||
* Используется в блоге (.article-content) и в продуктах (.product-description).
|
||||
* Подключать вместо article_content.css / product_content.css.
|
||||
*
|
||||
* Размещение: static/core/css/ck_content.css (или аналогичное shared-место)
|
||||
*/
|
||||
|
||||
/* ===== Базовый контейнер ===== */
|
||||
.article-content,
|
||||
.product-description {
|
||||
font-size: 1rem;
|
||||
line-height: 1.7;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
/* ===== Заголовки ===== */
|
||||
.article-content h1, .product-description h1,
|
||||
.article-content h2, .product-description h2,
|
||||
.article-content h3, .product-description h3,
|
||||
.article-content h4, .product-description h4,
|
||||
.article-content h5, .product-description h5,
|
||||
.article-content h6, .product-description h6 {
|
||||
margin-top: 1.5em;
|
||||
margin-bottom: 0.5em;
|
||||
font-weight: 600;
|
||||
line-height: 1.25;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
.article-content h1, .product-description h1 { font-size: 2rem; }
|
||||
.article-content h2, .product-description h2 { font-size: 1.75rem; }
|
||||
.article-content h3, .product-description h3 { font-size: 1.5rem; }
|
||||
.article-content h4, .product-description h4 { font-size: 1.25rem; }
|
||||
.article-content h5, .product-description h5 { font-size: 1.1rem; }
|
||||
.article-content h6, .product-description h6 { font-size: 1rem; }
|
||||
|
||||
/* ===== Абзацы ===== */
|
||||
.article-content p,
|
||||
.product-description p {
|
||||
margin-bottom: 1.2em;
|
||||
}
|
||||
|
||||
/* ===== Списки ===== */
|
||||
.article-content ul, .product-description ul,
|
||||
.article-content ol, .product-description ol {
|
||||
margin-bottom: 1rem;
|
||||
padding-left: 2rem;
|
||||
}
|
||||
.article-content li,
|
||||
.product-description li {
|
||||
margin-bottom: 0.3rem;
|
||||
}
|
||||
|
||||
/* ===== Цитаты ===== */
|
||||
.article-content blockquote,
|
||||
.product-description blockquote {
|
||||
border-left: 4px solid var(--primary);
|
||||
padding: 0.5rem 1rem;
|
||||
background: var(--bg-secondary);
|
||||
margin: 1.25rem 0;
|
||||
font-style: italic;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
/* ===== Горизонтальная линия ===== */
|
||||
.article-content hr,
|
||||
.product-description hr {
|
||||
border: none;
|
||||
border-top: 2px solid var(--border-light);
|
||||
margin: 2em 0;
|
||||
}
|
||||
|
||||
/* ===== Таблицы ===== */
|
||||
.article-content table,
|
||||
.product-description table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin: 1.25rem 0;
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
.article-content th, .product-description th,
|
||||
.article-content td, .product-description td {
|
||||
border: 1px solid var(--border-light);
|
||||
padding: 0.6rem 0.8rem;
|
||||
text-align: left;
|
||||
}
|
||||
.article-content th,
|
||||
.product-description th {
|
||||
background: var(--bg-secondary);
|
||||
color: var(--text-primary);
|
||||
font-weight: 600;
|
||||
}
|
||||
.article-content tr:nth-child(even),
|
||||
.product-description tr:nth-child(even) {
|
||||
background: var(--bg-secondary);
|
||||
}
|
||||
|
||||
/* ===== Изображения ===== */
|
||||
.article-content img,
|
||||
.product-description img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
margin: 1rem 0;
|
||||
border-radius: var(--radius-sm, 4px);
|
||||
}
|
||||
|
||||
/* CKEditor 5: figure.image */
|
||||
.article-content figure.image,
|
||||
.product-description figure.image {
|
||||
display: inline-block;
|
||||
margin: 1em 0;
|
||||
max-width: 100%;
|
||||
}
|
||||
.article-content figure.image img,
|
||||
.product-description figure.image img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
.article-content figure.image figcaption,
|
||||
.product-description figure.image figcaption {
|
||||
text-align: center;
|
||||
font-size: 0.88em;
|
||||
color: var(--text-light);
|
||||
margin-top: 0.4em;
|
||||
}
|
||||
|
||||
/* Выравнивание изображений (классы CKEditor 5) */
|
||||
.article-content .image-style-align-left,
|
||||
.product-description .image-style-align-left {
|
||||
float: left;
|
||||
margin-right: 1.5em;
|
||||
margin-bottom: 1em;
|
||||
max-width: 50%;
|
||||
}
|
||||
.article-content .image-style-align-right,
|
||||
.product-description .image-style-align-right {
|
||||
float: right;
|
||||
margin-left: 1.5em;
|
||||
margin-bottom: 1em;
|
||||
max-width: 50%;
|
||||
}
|
||||
.article-content .image-style-align-center,
|
||||
.product-description .image-style-align-center {
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
/* clearfix после float-изображений */
|
||||
.article-content::after,
|
||||
.product-description::after {
|
||||
content: '';
|
||||
display: table;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
/* ===== Встроенное видео (iframe/media) ===== */
|
||||
.article-content .media,
|
||||
.product-description .media {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
padding-bottom: 56.25%; /* 16:9 */
|
||||
height: 0;
|
||||
margin: 1.5em 0;
|
||||
}
|
||||
.article-content .media iframe,
|
||||
.product-description .media iframe {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: 0;
|
||||
border-radius: var(--radius-sm, 4px);
|
||||
}
|
||||
|
||||
/* ===== Блоки кода ===== */
|
||||
.article-content pre,
|
||||
.product-description pre {
|
||||
background: #1e1e1e;
|
||||
color: #d4d4d4;
|
||||
padding: 1rem 1.25rem;
|
||||
border-radius: var(--radius-sm, 4px);
|
||||
overflow-x: auto;
|
||||
margin: 1rem 0;
|
||||
font-size: 0.9em;
|
||||
line-height: 1.5;
|
||||
}
|
||||
.article-content code,
|
||||
.product-description code {
|
||||
font-family: 'Cascadia Code', 'Fira Code', 'Courier New', monospace;
|
||||
background: var(--bg-secondary);
|
||||
color: var(--primary);
|
||||
padding: 0.15rem 0.4rem;
|
||||
border-radius: 3px;
|
||||
font-size: 0.88em;
|
||||
}
|
||||
.article-content pre code,
|
||||
.product-description pre code {
|
||||
padding: 0;
|
||||
background: none;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
/* ===== Ссылки внутри контента ===== */
|
||||
.article-content a,
|
||||
.product-description a {
|
||||
color: var(--primary);
|
||||
text-decoration: underline;
|
||||
text-underline-offset: 3px;
|
||||
transition: opacity 0.15s;
|
||||
}
|
||||
.article-content a:hover,
|
||||
.product-description a:hover {
|
||||
opacity: 0.75;
|
||||
}
|
||||
|
||||
/* ===== Адаптивность ===== */
|
||||
@media (max-width: 600px) {
|
||||
.article-content .image-style-align-left,
|
||||
.article-content .image-style-align-right,
|
||||
.product-description .image-style-align-left,
|
||||
.product-description .image-style-align-right {
|
||||
float: none;
|
||||
max-width: 100%;
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
.article-content table,
|
||||
.product-description table {
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
}
|
||||
|
||||
290
static/products/css/products.css
Normal file
290
static/products/css/products.css
Normal file
@ -0,0 +1,290 @@
|
||||
/*
|
||||
* products.css — layout и компоненты страниц продуктов.
|
||||
* Типографика CKEditor-контента вынесена в ck_content.css.
|
||||
*/
|
||||
|
||||
/* ===== Сетка продуктов ===== */
|
||||
.products-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
|
||||
gap: 1.5rem;
|
||||
margin-top: 1.5rem;
|
||||
}
|
||||
|
||||
/* ===== Карточка продукта ===== */
|
||||
.product-card {
|
||||
background: var(--bg-card);
|
||||
border-radius: var(--radius-lg);
|
||||
box-shadow: var(--shadow-md);
|
||||
border: 1px solid var(--border-light);
|
||||
transition: var(--transition);
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.product-card:hover {
|
||||
transform: translateY(-4px);
|
||||
box-shadow: var(--shadow-lg);
|
||||
}
|
||||
|
||||
.product-image {
|
||||
width: 100%;
|
||||
height: 180px;
|
||||
object-fit: cover;
|
||||
}
|
||||
.product-image-placeholder {
|
||||
width: 100%;
|
||||
height: 180px;
|
||||
background: var(--bg-secondary);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: var(--text-light);
|
||||
font-size: 2rem;
|
||||
}
|
||||
.product-image-placeholder::after {
|
||||
content: '📦';
|
||||
}
|
||||
|
||||
.product-info {
|
||||
padding: 1rem;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.product-info h3 {
|
||||
margin: 0 0 0.5rem 0;
|
||||
font-size: 1.1rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
.product-info h3 a {
|
||||
color: var(--text-primary);
|
||||
text-decoration: none;
|
||||
transition: color 0.15s;
|
||||
}
|
||||
.product-info h3 a:hover {
|
||||
color: var(--primary);
|
||||
}
|
||||
|
||||
.product-short {
|
||||
color: var(--text-secondary);
|
||||
font-size: 0.9rem;
|
||||
margin-bottom: 0.75rem;
|
||||
flex: 1;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.product-meta {
|
||||
font-size: 0.8rem;
|
||||
color: var(--text-light);
|
||||
margin-bottom: 0.75rem;
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.product-category,
|
||||
.product-configs {
|
||||
background: var(--bg-secondary);
|
||||
padding: 0.15rem 0.5rem;
|
||||
border-radius: var(--radius-sm);
|
||||
border: 1px solid var(--border-light);
|
||||
}
|
||||
|
||||
/* ===== Цена ===== */
|
||||
.product-price-block {
|
||||
margin-top: auto;
|
||||
}
|
||||
.product-price {
|
||||
font-size: 1.2rem;
|
||||
font-weight: 700;
|
||||
color: var(--primary);
|
||||
}
|
||||
|
||||
.price-restricted {
|
||||
background: var(--bg-secondary);
|
||||
padding: 0.6rem;
|
||||
border-radius: var(--radius-sm);
|
||||
text-align: center;
|
||||
}
|
||||
.price-text {
|
||||
display: block;
|
||||
margin-bottom: 0.5rem;
|
||||
font-size: 0.85rem;
|
||||
color: var(--text-light);
|
||||
}
|
||||
.price-actions {
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
justify-content: center;
|
||||
}
|
||||
.btn-small {
|
||||
padding: 0.4rem 0.8rem;
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
/* ===== Фильтры ===== */
|
||||
.filters-bar {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 1rem;
|
||||
margin-bottom: 1.5rem;
|
||||
align-items: center;
|
||||
}
|
||||
.filter-group {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.5rem;
|
||||
align-items: center;
|
||||
}
|
||||
.filter-group > span {
|
||||
font-size: 0.85rem;
|
||||
color: var(--text-light);
|
||||
font-weight: 500;
|
||||
}
|
||||
.filter-btn {
|
||||
padding: 0.3rem 0.8rem;
|
||||
border-radius: var(--radius-sm);
|
||||
background: var(--bg-secondary);
|
||||
color: var(--text-secondary);
|
||||
text-decoration: none;
|
||||
font-size: 0.85rem;
|
||||
border: 1px solid var(--border-light);
|
||||
transition: var(--transition);
|
||||
white-space: nowrap;
|
||||
}
|
||||
.filter-btn.active,
|
||||
.filter-btn:hover {
|
||||
background: var(--primary);
|
||||
color: white;
|
||||
border-color: var(--primary);
|
||||
}
|
||||
|
||||
/* ===== Детальная страница ===== */
|
||||
.product-detail {
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.product-header {
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
.product-header h1 {
|
||||
font-size: 2rem;
|
||||
margin-bottom: 0.5rem;
|
||||
color: var(--text-primary);
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.product-meta-detail {
|
||||
display: flex;
|
||||
gap: 0.75rem;
|
||||
color: var(--text-light);
|
||||
font-size: 0.875rem;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.product-detail-image {
|
||||
width: 100%;
|
||||
max-height: 420px;
|
||||
object-fit: cover;
|
||||
border-radius: var(--radius-md);
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
/* Контент CKEditor — max-width задан на .product-detail, не здесь */
|
||||
.product-description {
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
/* ===== Блок цены (детальная) ===== */
|
||||
.product-price-block-detail {
|
||||
margin: 2rem 0;
|
||||
text-align: center;
|
||||
}
|
||||
.product-price-large {
|
||||
font-size: 2rem;
|
||||
font-weight: 700;
|
||||
color: var(--primary);
|
||||
display: block;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.price-restricted-detail {
|
||||
background: var(--bg-secondary);
|
||||
padding: 1.5rem;
|
||||
border-radius: var(--radius-md);
|
||||
border: 1px solid var(--border-light);
|
||||
}
|
||||
.price-restricted-detail p {
|
||||
margin-bottom: 1rem;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.product-back {
|
||||
margin-top: 2rem;
|
||||
padding-top: 1.5rem;
|
||||
border-top: 1px solid var(--border-light);
|
||||
}
|
||||
|
||||
/* ===== Пагинация ===== */
|
||||
.pagination {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 0.4rem;
|
||||
margin-top: 2.5rem;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.pagination a,
|
||||
.pagination span {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-width: 2.2rem;
|
||||
padding: 0.45rem 0.7rem;
|
||||
border-radius: var(--radius-sm);
|
||||
background: var(--bg-secondary);
|
||||
color: var(--text-secondary);
|
||||
text-decoration: none;
|
||||
font-size: 0.9rem;
|
||||
border: 1px solid var(--border-light);
|
||||
transition: var(--transition);
|
||||
}
|
||||
.pagination a:hover {
|
||||
background: var(--primary);
|
||||
color: white;
|
||||
border-color: var(--primary);
|
||||
}
|
||||
.pagination .current {
|
||||
background: var(--primary);
|
||||
color: white;
|
||||
font-weight: 600;
|
||||
border-color: var(--primary);
|
||||
}
|
||||
.pagination .disabled {
|
||||
opacity: 0.45;
|
||||
cursor: default;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* ===== Адаптивность ===== */
|
||||
@media (max-width: 768px) {
|
||||
.product-header h1 {
|
||||
font-size: 1.6rem;
|
||||
}
|
||||
.product-price-large {
|
||||
font-size: 1.6rem;
|
||||
}
|
||||
}
|
||||
@media (max-width: 480px) {
|
||||
.products-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
.price-actions {
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
}
|
||||
.filters-bar {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
}
|
||||
}
|
||||
@ -914,6 +914,14 @@ body {
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.product-configs {
|
||||
color: var(--text-secondary);
|
||||
font-size: 1.25rem;
|
||||
font-weight: 500;
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
/* ===== FOOTER ===== */
|
||||
.footer {
|
||||
background: var(--footer-bg);
|
||||
@ -1665,6 +1673,11 @@ body {
|
||||
padding: 0 1rem;
|
||||
}
|
||||
|
||||
.product-configs {
|
||||
font-size: 1.125rem;
|
||||
padding: 0 1rem;
|
||||
}
|
||||
|
||||
.grid-2 {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 1.5rem;
|
||||
|
||||
@ -16,9 +16,17 @@ const CallbackModal = {
|
||||
}, 5000);
|
||||
},
|
||||
|
||||
open() {
|
||||
open(productTitle) {
|
||||
const modal = document.getElementById(this.modalId);
|
||||
if (modal) {
|
||||
|
||||
if (productTitle) {
|
||||
const questionField = modal.querySelector('#id_question');
|
||||
if (questionField) {
|
||||
questionField.value = `Запрос цены по ПП "${productTitle}"`;
|
||||
}
|
||||
}
|
||||
|
||||
modal.style.display = 'block';
|
||||
const floatingBtn = document.getElementById(this.floatingBtnId);
|
||||
if (floatingBtn && this.shown) {
|
||||
|
||||
30
static/programmer/js/profile.js
Normal file
30
static/programmer/js/profile.js
Normal file
@ -0,0 +1,30 @@
|
||||
// programmer/static/programmer/js/profile.js
|
||||
function openModalContent(el) {
|
||||
const url = el.dataset.url;
|
||||
const title = el.querySelector('h4').innerText;
|
||||
const modal = document.getElementById('contentModal');
|
||||
const body = document.getElementById('contentModalBody');
|
||||
const titleEl = document.getElementById('contentModalTitle');
|
||||
titleEl.textContent = title;
|
||||
body.innerHTML = '<p>Загрузка...</p>';
|
||||
modal.style.display = 'block';
|
||||
fetch(url)
|
||||
.then(response => response.text())
|
||||
.then(html => {
|
||||
body.innerHTML = html;
|
||||
})
|
||||
.catch(() => {
|
||||
body.innerHTML = '<p style="color:red;">Ошибка загрузки. Попробуйте позже.</p>';
|
||||
});
|
||||
}
|
||||
|
||||
function closeContentModal() {
|
||||
document.getElementById('contentModal').style.display = 'none';
|
||||
}
|
||||
// Закрытие по клику на фон и ESC
|
||||
document.addEventListener('click', function(e) {
|
||||
if (e.target === document.getElementById('contentModal')) closeContentModal();
|
||||
});
|
||||
document.addEventListener('keydown', function(e) {
|
||||
if (e.key === 'Escape') closeContentModal();
|
||||
});
|
||||
Loading…
x
Reference in New Issue
Block a user